Merge branch '3.0' into fix/TD-23549
This commit is contained in:
commit
99d6c5cfa0
|
@ -18,7 +18,7 @@
|
|||
注意:修改文档的分支要以`docs/`为开头,以免进行不必要的测试。
|
||||
4. 创建pull request,将自己的分支合并到开发分支`3.0`,我们开发团队将尽快审核。
|
||||
|
||||
如遇任何问题,请添加官方微信TDengineECO。我们的团队会帮忙解决。
|
||||
如遇任何问题,请添加官方微信 tdengine1。我们的团队会帮忙解决。
|
||||
|
||||
## 给贡献者的礼品
|
||||
|
||||
|
@ -48,4 +48,4 @@ TDengine 社区致力于让更多的开发者理解和使用它。
|
|||
|
||||
## 联系我们
|
||||
|
||||
如果您有什么问题需要解决,或者有什么问题需要解答,可以添加微信:TDengineECO
|
||||
如果您有什么问题需要解决,或者有什么问题需要解答,可以添加微信:tdengine1。
|
||||
|
|
14
README-CN.md
14
README-CN.md
|
@ -52,7 +52,7 @@ TDengine 还提供一组辅助工具软件 taosTools,目前它包含 taosBench
|
|||
### Ubuntu 18.04 及以上版本 & Debian:
|
||||
|
||||
```bash
|
||||
sudo apt-get install -y gcc cmake build-essential git libssl-dev libgflags2.2 libgflags-dev
|
||||
sudo apt-get install -y gcc cmake build-essential git libssl-dev libgflags2.2 libgflags-dev libgeos-dev
|
||||
```
|
||||
|
||||
#### 为 taos-tools 安装编译需要的软件
|
||||
|
@ -68,14 +68,14 @@ sudo apt install build-essential libjansson-dev libsnappy-dev liblzma-dev libz-d
|
|||
```bash
|
||||
sudo yum install epel-release
|
||||
sudo yum update
|
||||
sudo yum install -y gcc gcc-c++ make cmake3 git openssl-devel
|
||||
sudo yum install -y gcc gcc-c++ make cmake3 git openssl-devel geos geos-devel
|
||||
sudo ln -sf /usr/bin/cmake3 /usr/bin/cmake
|
||||
```
|
||||
|
||||
### CentOS 8 & Fedora
|
||||
### CentOS 8/Fedora/Rocky Linux
|
||||
|
||||
```bash
|
||||
sudo dnf install -y gcc gcc-c++ make cmake epel-release git openssl-devel
|
||||
sudo dnf install -y gcc gcc-c++ make cmake epel-release git openssl-devel geos geos-devel
|
||||
```
|
||||
|
||||
#### 在 CentOS 上构建 taosTools 安装依赖软件
|
||||
|
@ -88,7 +88,7 @@ sudo dnf install -y gcc gcc-c++ make cmake epel-release git openssl-devel
|
|||
sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libatomic-static libstdc++-static openssl-devel
|
||||
```
|
||||
|
||||
#### CentOS 8/Rocky Linux
|
||||
#### CentOS 8/Fedora/Rocky Linux
|
||||
|
||||
```
|
||||
sudo yum install -y epel-release
|
||||
|
@ -101,7 +101,7 @@ sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson
|
|||
|
||||
若 powertools 安装失败,可以尝试改用:
|
||||
```
|
||||
sudo yum config-manager --set-enabled Powertools
|
||||
sudo yum config-manager --set-enabled powertools
|
||||
```
|
||||
|
||||
#### CentOS + devtoolset
|
||||
|
@ -117,7 +117,7 @@ scl enable devtoolset-9 -- bash
|
|||
### macOS
|
||||
|
||||
```
|
||||
brew install argp-standalone pkgconfig
|
||||
brew install argp-standalone pkgconfig geos
|
||||
```
|
||||
|
||||
### 设置 golang 开发环境
|
||||
|
|
12
README.md
12
README.md
|
@ -60,7 +60,7 @@ To build TDengine, use [CMake](https://cmake.org/) 3.0.2 or higher versions in t
|
|||
### Ubuntu 18.04 and above or Debian
|
||||
|
||||
```bash
|
||||
sudo apt-get install -y gcc cmake build-essential git libssl-dev libgflags2.2 libgflags-dev
|
||||
sudo apt-get install -y gcc cmake build-essential git libssl-dev libgflags2.2 libgflags-dev libgeos-dev
|
||||
```
|
||||
|
||||
#### Install build dependencies for taosTools
|
||||
|
@ -76,14 +76,14 @@ sudo apt install build-essential libjansson-dev libsnappy-dev liblzma-dev libz-d
|
|||
```bash
|
||||
sudo yum install epel-release
|
||||
sudo yum update
|
||||
sudo yum install -y gcc gcc-c++ make cmake3 git openssl-devel
|
||||
sudo yum install -y gcc gcc-c++ make cmake3 git openssl-devel geos geos-devel
|
||||
sudo ln -sf /usr/bin/cmake3 /usr/bin/cmake
|
||||
```
|
||||
|
||||
### CentOS 8 & Fedora
|
||||
### CentOS 8/Fedora/Rocky Linux
|
||||
|
||||
```bash
|
||||
sudo dnf install -y gcc gcc-c++ make cmake epel-release git openssl-devel
|
||||
sudo dnf install -y gcc gcc-c++ make cmake epel-release git openssl-devel geos geos-devel
|
||||
```
|
||||
|
||||
#### Install build dependencies for taosTools on CentOS
|
||||
|
@ -94,7 +94,7 @@ sudo dnf install -y gcc gcc-c++ make cmake epel-release git openssl-devel
|
|||
sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libatomic-static libstdc++-static openssl-devel
|
||||
```
|
||||
|
||||
#### CentOS 8/Rocky Linux
|
||||
#### CentOS 8/Fedora/Rocky Linux
|
||||
|
||||
```
|
||||
sudo yum install -y epel-release
|
||||
|
@ -124,7 +124,7 @@ scl enable devtoolset-9 -- bash
|
|||
### macOS
|
||||
|
||||
```
|
||||
brew install argp-standalone pkgconfig
|
||||
brew install argp-standalone pkgconfig geos
|
||||
```
|
||||
|
||||
### Setup golang environment
|
||||
|
|
|
@ -123,8 +123,8 @@ ELSE ()
|
|||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -O3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-reserved-user-defined-literal -Wno-literal-suffix -Werror=return-type -fPIC -O3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k")
|
||||
ELSE ()
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reserved-user-defined-literal -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -g3 -gdwarf-2 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reserved-user-defined-literal -g3 -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k")
|
||||
ENDIF ()
|
||||
|
||||
# disable all assert
|
||||
|
|
|
@ -64,12 +64,25 @@ IF(${TD_WINDOWS})
|
|||
ON
|
||||
)
|
||||
|
||||
MESSAGE("build geos Win32")
|
||||
option(
|
||||
BUILD_GEOS
|
||||
"If build geos on Windows"
|
||||
ON
|
||||
)
|
||||
|
||||
ELSEIF (TD_DARWIN_64)
|
||||
IF(${BUILD_TEST})
|
||||
add_definitions(-DCOMPILER_SUPPORTS_CXX13)
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
option(
|
||||
BUILD_GEOS
|
||||
"If build geos on Windows"
|
||||
OFF
|
||||
)
|
||||
|
||||
option(
|
||||
BUILD_SHARED_LIBS
|
||||
""
|
||||
|
|
|
@ -56,7 +56,17 @@ IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin
|
|||
|
||||
SET(TD_DARWIN TRUE)
|
||||
SET(OSTYPE "macOS")
|
||||
execute_process(COMMAND geos-config --cflags OUTPUT_VARIABLE GEOS_CFLAGS)
|
||||
execute_process(COMMAND geos-config --ldflags OUTPUT_VARIABLE GEOS_LDFLAGS)
|
||||
string(SUBSTRING ${GEOS_CFLAGS} 2 -1 GEOS_CFLAGS)
|
||||
string(REGEX REPLACE "\n" "" GEOS_CFLAGS ${GEOS_CFLAGS})
|
||||
string(SUBSTRING ${GEOS_LDFLAGS} 2 -1 GEOS_LDFLAGS)
|
||||
string(REGEX REPLACE "\n" "" GEOS_LDFLAGS ${GEOS_LDFLAGS})
|
||||
MESSAGE("GEOS_CFLAGS "${GEOS_CFLAGS})
|
||||
MESSAGE("GEOS_LDFLAGS "${GEOS_LDFLAGS})
|
||||
ADD_DEFINITIONS("-DDARWIN -Wno-tautological-pointer-compare")
|
||||
INCLUDE_DIRECTORIES(${GEOS_CFLAGS})
|
||||
LINK_DIRECTORIES(${GEOS_LDFLAGS})
|
||||
|
||||
IF (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64")
|
||||
MESSAGE("Current system arch is arm64")
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
IF (DEFINED VERNUMBER)
|
||||
SET(TD_VER_NUMBER ${VERNUMBER})
|
||||
ELSE ()
|
||||
SET(TD_VER_NUMBER "3.0.4.1")
|
||||
SET(TD_VER_NUMBER "3.0.4.3")
|
||||
ENDIF ()
|
||||
|
||||
IF (DEFINED VERCOMPATIBLE)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
# geos
|
||||
ExternalProject_Add(geos
|
||||
GIT_REPOSITORY https://github.com/libgeos/geos.git
|
||||
GIT_TAG 3.11.2
|
||||
SOURCE_DIR "${TD_CONTRIB_DIR}/geos"
|
||||
BINARY_DIR ""
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
|
@ -2,6 +2,7 @@
|
|||
# stub
|
||||
ExternalProject_Add(stub
|
||||
GIT_REPOSITORY https://github.com/coolxv/cpp-stub.git
|
||||
GIT_TAG 5e903b8e
|
||||
GIT_SUBMODULES "src"
|
||||
SOURCE_DIR "${TD_CONTRIB_DIR}/cpp-stub"
|
||||
BINARY_DIR "${TD_CONTRIB_DIR}/cpp-stub/src"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# taosadapter
|
||||
ExternalProject_Add(taosadapter
|
||||
GIT_REPOSITORY https://github.com/taosdata/taosadapter.git
|
||||
GIT_TAG 565ca21
|
||||
GIT_TAG 3.0
|
||||
SOURCE_DIR "${TD_SOURCE_DIR}/tools/taosadapter"
|
||||
BINARY_DIR ""
|
||||
#BUILD_IN_SOURCE TRUE
|
||||
|
|
|
@ -134,6 +134,11 @@ if(${BUILD_ADDR2LINE})
|
|||
endif(NOT ${TD_WINDOWS})
|
||||
endif(${BUILD_ADDR2LINE})
|
||||
|
||||
# geos
|
||||
if(${BUILD_GEOS})
|
||||
cat("${TD_SUPPORT_DIR}/geos_CMakeLists.txt.in" ${CONTRIB_TMP_FILE})
|
||||
endif()
|
||||
|
||||
# download dependencies
|
||||
configure_file(${CONTRIB_TMP_FILE} "${TD_CONTRIB_DIR}/deps-download/CMakeLists.txt")
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
|
||||
|
@ -226,11 +231,16 @@ if(${BUILD_WITH_ROCKSDB})
|
|||
if(${TD_LINUX})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=maybe-uninitialized -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=unused-function -Wno-errno=unused-private-field -Wno-error=unused-result")
|
||||
endif(${TD_LINUX})
|
||||
MESSAGE(STATUS "CXXXX STATUS CONFIG: " ${CMAKE_CXX_FLAGS})
|
||||
|
||||
if(${TD_DARWIN})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=maybe-uninitialized")
|
||||
endif(${TD_DARWIN})
|
||||
|
||||
if (${TD_DARWIN_ARM64})
|
||||
set(HAS_ARMV8_CRC true)
|
||||
endif(${TD_DARWIN_ARM64})
|
||||
|
||||
if (${TD_WINDOWS})
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244 /wd4819")
|
||||
endif(${TD_WINDOWS})
|
||||
|
@ -243,7 +253,7 @@ if(${BUILD_WITH_ROCKSDB})
|
|||
endif(${TD_DARWIN})
|
||||
|
||||
if(${TD_WINDOWS})
|
||||
option(WITH_JNI "" ON)
|
||||
option(WITH_JNI "" OFF)
|
||||
endif(${TD_WINDOWS})
|
||||
|
||||
if(${TD_WINDOWS})
|
||||
|
@ -255,7 +265,7 @@ if(${BUILD_WITH_ROCKSDB})
|
|||
option(WITH_FALLOCATE "" OFF)
|
||||
option(WITH_JEMALLOC "" OFF)
|
||||
option(WITH_GFLAGS "" OFF)
|
||||
option(PORTABLE "" ON)
|
||||
option(PORTABLE "" OFF)
|
||||
option(WITH_LIBURING "" OFF)
|
||||
option(FAIL_ON_WARNINGS OFF)
|
||||
|
||||
|
@ -263,8 +273,11 @@ if(${BUILD_WITH_ROCKSDB})
|
|||
option(WITH_BENCHMARK_TOOLS "" OFF)
|
||||
option(WITH_TOOLS "" OFF)
|
||||
option(WITH_LIBURING "" OFF)
|
||||
|
||||
IF (TD_LINUX)
|
||||
option(ROCKSDB_BUILD_SHARED "Build shared versions of the RocksDB libraries" ON)
|
||||
ELSE()
|
||||
option(ROCKSDB_BUILD_SHARED "Build shared versions of the RocksDB libraries" OFF)
|
||||
ENDIF()
|
||||
add_subdirectory(rocksdb EXCLUDE_FROM_ALL)
|
||||
target_include_directories(
|
||||
rocksdb
|
||||
|
@ -470,6 +483,15 @@ if(${BUILD_ADDR2LINE})
|
|||
endif(NOT ${TD_WINDOWS})
|
||||
endif(${BUILD_ADDR2LINE})
|
||||
|
||||
# geos
|
||||
if(${BUILD_GEOS})
|
||||
option(BUILD_SHARED_LIBS "Build GEOS with shared libraries" OFF)
|
||||
add_subdirectory(geos EXCLUDE_FROM_ALL)
|
||||
target_include_directories(
|
||||
geos_c
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/geos/include>
|
||||
)
|
||||
endif(${BUILD_GEOS})
|
||||
|
||||
# ================================================================================================
|
||||
# Build test
|
||||
|
|
|
@ -4,7 +4,7 @@ if(${BUILD_DOCS})
|
|||
find_package(Doxygen)
|
||||
if (DOXYGEN_FOUND)
|
||||
# Build the doc
|
||||
set(DOXYGEN_IN ${TD_SOURCE_DIR}/docs/Doxyfile.in)
|
||||
set(DOXYGEN_IN ${TD_SOURCE_DIR}/docs/doxgen/Doxyfile.in)
|
||||
set(DOXYGEN_OUT ${CMAKE_BINARY_DIR}/Doxyfile)
|
||||
|
||||
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
|
||||
|
|
|
@ -83,7 +83,7 @@ If `maven` is used to manage the projects, what needs to be done is only adding
|
|||
<dependency>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.2.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
|
|
@ -285,10 +285,10 @@ You configure the following parameters when creating a consumer:
|
|||
|
||||
| Parameter | Type | Description | Remarks |
|
||||
| :----------------------------: | :-----: | -------------------------------------------------------- | ------------------------------------------- |
|
||||
| `td.connect.ip` | string | Used in establishing a connection; same as `taos_connect` | Only valid for establishing native connection |
|
||||
| `td.connect.user` | string | Used in establishing a connection; same as `taos_connect` | Only valid for establishing native connection |
|
||||
| `td.connect.pass` | string | Used in establishing a connection; same as `taos_connect` | Only valid for establishing native connection |
|
||||
| `td.connect.port` | string | Used in establishing a connection; same as `taos_connect` | Only valid for establishing native connection |
|
||||
| `td.connect.ip` | string | IP address of the server side | |
|
||||
| `td.connect.user` | string | User Name | |
|
||||
| `td.connect.pass` | string | Password | |
|
||||
| `td.connect.port` | string | Port of the server side | |
|
||||
| `group.id` | string | Consumer group ID; consumers with the same ID are in the same group | **Required**. Maximum length: 192. |
|
||||
| `client.id` | string | Client ID | Maximum length: 192. |
|
||||
| `auto.offset.reset` | enum | Initial offset for the consumer group | Specify `earliest`, `latest`, or `none`(default) |
|
||||
|
@ -325,6 +325,7 @@ Java programs use the following parameters:
|
|||
|
||||
| Parameter | Type | Description | Remarks |
|
||||
| ----------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `td.connect.type` | string | connection type: "jni" means native connection, "ws" means websocket connection, the default is "jni" |
|
||||
| `bootstrap.servers` | string |Connection address, such as `localhost:6030` |
|
||||
| `value.deserializer` | string | Value deserializer; to use this method, implement the `com.taosdata.jdbc.tmq.Deserializer` interface or inherit the `com.taosdata.jdbc.tmq.ReferenceDeserializer` type |
|
||||
| `value.deserializer.encoding` | string | Specify the encoding for string deserialization | |
|
||||
|
@ -399,22 +400,6 @@ from taos.tmq import Consumer
|
|||
consumer = Consumer({"group.id": "local", "td.connect.ip": "127.0.0.1"})
|
||||
```
|
||||
|
||||
Python programs use the following parameters:
|
||||
|
||||
| Parameter | Type | Description | Remarks |
|
||||
|:---------:|:----:|:-----------:|:-------:|
|
||||
| `td.connect.ip` | string | Used in establishing a connection||
|
||||
| `td.connect.user` | string | Used in establishing a connection||
|
||||
| `td.connect.pass` | string | Used in establishing a connection||
|
||||
| `td.connect.port` | string | Used in establishing a connection||
|
||||
| `group.id` | string | Consumer group ID; consumers with the same ID are in the same group | **Required**. Maximum length: 192 |
|
||||
| `client.id` | string | Client ID | Maximum length: 192 |
|
||||
| `msg.with.table.name` | string | Specify whether to deserialize table names from messages | pecify `true` or `false` |
|
||||
| `enable.auto.commit` | string | Commit automatically | pecify `true` or `false` |
|
||||
| `auto.commit.interval.ms` | string | Interval for automatic commits, in milliseconds | |
|
||||
| `auto.offset.reset` | string | Initial offset for the consumer group | Specify `earliest`, `latest`, or `none`(default) |
|
||||
| `enable.heartbeat.background` | string | Backend heartbeat; if enabled, the consumer does not go offline even if it has not polled for a long time | Specify `true` or `false` |
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="Node.JS" value="Node.JS">
|
||||
|
|
|
@ -270,15 +270,81 @@ select max_vol(vol1,vol2,vol3,deviceid) from battery;
|
|||
|
||||
## Implement a UDF in Python
|
||||
|
||||
### Prepare Environment
|
||||
|
||||
1. Prepare Python Environment
|
||||
|
||||
Please follow standard procedure of python environment preparation.
|
||||
|
||||
2. Install Python package `taospyudf`
|
||||
|
||||
```shell
|
||||
pip3 install taospyudf
|
||||
```
|
||||
|
||||
During this process, some C++ code needs to be compiled. So it's required to have `cmake` and `gcc` on your system. The compiled `libtaospyudf.so` will be automatically copied to `/usr/local/lib` path. If you are not root user, please use `sudo`. After installation is done, please check using the command below.
|
||||
|
||||
```shell
|
||||
root@slave11 ~/udf $ ls -l /usr/local/lib/libtaos*
|
||||
-rw-r--r-- 1 root root 671344 May 24 22:54 /usr/local/lib/libtaospyudf.so
|
||||
```
|
||||
|
||||
Then execute the command below.
|
||||
|
||||
```shell
|
||||
ldconfig
|
||||
```
|
||||
|
||||
3. If you want to utilize some 3rd party python packages in your Python UDF, please set configuration parameter `UdfdLdLibPath` to the value of `PYTHONPATH` before starting `taosd`.
|
||||
|
||||
4. Launch `taosd` service
|
||||
|
||||
Please refer to [Get Started](../../get-started)
|
||||
|
||||
### Interface definition
|
||||
|
||||
#### Introduction to Interface
|
||||
|
||||
Implement the specified interface functions when implementing a UDF in Python.
|
||||
- implement `process` function for the scalar UDF.
|
||||
- implement `start`, `reduce`, `finish` for the aggregate UDF.
|
||||
- implement `init` for initialization and `destroy` for termination.
|
||||
|
||||
### Implement a Scalar UDF in Python
|
||||
#### Scalar UDF Interface
|
||||
|
||||
The implementation of a scalar UDF is described as follows:
|
||||
|
||||
```Python
|
||||
def process(input: datablock) -> tuple[output_type]:
|
||||
```
|
||||
|
||||
Description: this function prcesses datablock, which is the input; you can use datablock.data(row, col) to access the python object at location(row,col); the output is a tuple object consisted of objects of type outputtype
|
||||
|
||||
#### Aggregate UDF Interface
|
||||
|
||||
The implementation of an aggregate function is described as follows:
|
||||
|
||||
```Python
|
||||
def start() -> bytes:
|
||||
def reduce(inputs: datablock, buf: bytes) -> bytes
|
||||
def finish(buf: bytes) -> output_type:
|
||||
```
|
||||
|
||||
Description: first the start() is invoked to generate the initial result `buffer`; then the input data is divided into multiple row blocks, and reduce() is invoked for each block `inputs` and current intermediate result `buf`; finally finish() is invoked to generate the final result from intermediate `buf`, the final result can only contains 0 or 1 data.
|
||||
|
||||
#### Initialization and Cleanup Interface
|
||||
|
||||
```python
|
||||
def init()
|
||||
def destroy()
|
||||
```
|
||||
|
||||
Description: init() does the work of initialization before processing any data; destroy() does the work of cleanup after the data is processed.
|
||||
|
||||
### Python UDF Template
|
||||
|
||||
#### Scalar Template
|
||||
|
||||
```Python
|
||||
def init():
|
||||
# initialization
|
||||
|
@ -290,9 +356,9 @@ def process(input: datablock) -> tuple[output_type]:
|
|||
# return tuple object consisted of object of type outputtype
|
||||
```
|
||||
|
||||
### Implement an Aggregate UDF in Python
|
||||
Note:process() must be implemeted, init() and destroy() must be defined too but they can do nothing.
|
||||
|
||||
The implementation of an aggregate function is described as follows:
|
||||
#### Aggregate Template
|
||||
|
||||
```Python
|
||||
def init():
|
||||
|
@ -304,40 +370,14 @@ def start() -> bytes:
|
|||
def reduce(inputs: datablock, buf: bytes) -> bytes
|
||||
# deserialize buf to state
|
||||
# reduce the inputs and state into new_state.
|
||||
# use inputs.data(i,j) to access python ojbect of location(i,j)
|
||||
# use inputs.data(i,j) to access python object of location(i,j)
|
||||
# serialize new_state into new_state_bytes
|
||||
return new_state_bytes
|
||||
def finish(buf: bytes) -> output_type:
|
||||
#return obj of type outputtype
|
||||
```
|
||||
|
||||
### Python UDF Interface Definition
|
||||
|
||||
#### Scalar interface
|
||||
```Python
|
||||
def process(input: datablock) -> tuple[output_type]:
|
||||
```
|
||||
- `input` is a data block two-dimension matrix-like object, of which method `data(row, col)` returns the Python object located at location (`row`, `col`)
|
||||
- return a Python tuple object, of which each item is a Python object of type `output_type`
|
||||
|
||||
#### Aggregate Interface
|
||||
```Python
|
||||
def start() -> bytes:
|
||||
def reduce(input: datablock, buf: bytes) -> bytes
|
||||
def finish(buf: bytes) -> output_type:
|
||||
```
|
||||
|
||||
- first `start()` is called to return the initial result in type `bytes`
|
||||
- then the input data are divided into multiple data blocks and for each block `input`, `reduce` is called with the data block `input` and the current result `buf` bytes and generates a new intermediate result buffer.
|
||||
- finally, the `finish` function is called on the intermediate result `buf` and outputs 0 or 1 data of type `output_type`
|
||||
|
||||
|
||||
#### Initialization and Cleanup Interface
|
||||
```Python
|
||||
def init()
|
||||
def destroy()
|
||||
```
|
||||
Implement `init` for initialization and `destroy` for termination.
|
||||
Note: aggregate UDF requires init(), destroy(), start(), reduce() and finish() to be impemented. start() generates the initial result in buffer, then the input data is divided into multiple row data blocks, reduce() is invoked for each data block `inputs` and intermediate `buf`, finally finish() is invoked to generate final result from the intermediate result `buf`.
|
||||
|
||||
### Data Mapping between TDengine SQL and Python UDF
|
||||
|
||||
|
@ -353,15 +393,463 @@ The following table describes the mapping between TDengine SQL data type and Pyt
|
|||
|TIMESTAMP | int |
|
||||
|JSON and other types | Not Supported |
|
||||
|
||||
### Installing Python UDF
|
||||
1. Install Python package `taospyudf` that executes Python UDF
|
||||
```bash
|
||||
sudo pip install taospyudf
|
||||
ldconfig
|
||||
```
|
||||
2. If PYTHONPATH is needed to find Python packages when the Python UDF executes, include the PYTHONPATH contents into the udfdLdLibPath variable of the taos.cfg configuration file
|
||||
### Development Guide
|
||||
|
||||
In this section we will demonstrate 5 examples of developing UDF in Python language. In this guide, you will learn the development skills from easy case to hard case, the examples include:
|
||||
1. A scalar function which accepts only one integer as input and outputs ln(n^2 + 1)。
|
||||
2. A scalar function which accepts n integers, like(x1, x2, ..., xn)and output the sum of the product of each input and its sequence number, i.e. x1 + 2 * x2 + ... + n * xn。
|
||||
3. A scalar function which accepts a timestamp and output the next closest Sunday of the timestamp. In this case, we will demonstrate how to use 3rd party library `moment`.
|
||||
4. An aggregate function which calculates the difference between the maximum and the minimum of a specific column, i.e. same functionality of built-in spread().
|
||||
|
||||
In the guide, some debugging skills of using Python UDF will be explained too.
|
||||
|
||||
We assume you are using Linux system and already have TDengine 3.0.4.0+ and Python 3.x.
|
||||
|
||||
Note:**You can't use print() function to output log inside a UDF, you have to write the log to a specific file or use logging module of Python.**
|
||||
|
||||
#### Sample 1: Simplest UDF
|
||||
|
||||
This scalar UDF accepts an integer as input and output ln(n^2 + 1).
|
||||
|
||||
Firstly, please compose a Python source code file in your system and save it, e.g. `/root/udf/myfun.py`, the code is like below.
|
||||
|
||||
```python
|
||||
from math import log
|
||||
|
||||
def init():
|
||||
pass
|
||||
|
||||
def destroy():
|
||||
pass
|
||||
|
||||
def process(block):
|
||||
rows, _ = block.shape()
|
||||
return [log(block.data(i, 0) ** 2 + 1) for i in range(rows)]
|
||||
```
|
||||
|
||||
This program consists of 3 functions, init() and destroy() do nothing, but they have to be defined even though there is nothing to do in them because they are critical parts of a python UDF. The most important function is process(), which accepts a data block and the data block object has two methods:
|
||||
1. shape() returns the number of rows and the number of columns of the data block
|
||||
2. data(i, j) returns the value at (i,j) in the block
|
||||
|
||||
The output of the process() function of a scalar UDF returns exactly same number of data as the number of input rows. We will ignore the number of columns because we just want to compute on the first column.
|
||||
|
||||
Then, we create the UDF using the SQL command below.
|
||||
|
||||
```sql
|
||||
create function myfun as '/root/udf/myfun.py' outputtype double language 'Python'
|
||||
```
|
||||
|
||||
Here is the output example, it may change a little depending on your version being used.
|
||||
|
||||
```shell
|
||||
taos> create function myfun as '/root/udf/myfun.py' outputtype double language 'Python';
|
||||
Create OK, 0 row(s) affected (0.005202s)
|
||||
```
|
||||
|
||||
Then, we used the `show` command to prove the creation of the UDF is successful.
|
||||
|
||||
```text
|
||||
taos> show functions;
|
||||
name |
|
||||
=================================
|
||||
myfun |
|
||||
Query OK, 1 row(s) in set (0.005767s)
|
||||
```
|
||||
|
||||
Next, we can try to test the function. Before executing the UDF, we need to prepare some data using the command below in TDengine CLI.
|
||||
|
||||
```sql
|
||||
create database test;
|
||||
create table t(ts timestamp, v1 int, v2 int, v3 int);
|
||||
insert into t values('2023-05-01 12:13:14', 1, 2, 3);
|
||||
insert into t values('2023-05-03 08:09:10', 2, 3, 4);
|
||||
insert into t values('2023-05-10 07:06:05', 3, 4, 5);
|
||||
```
|
||||
|
||||
Execute the UDF to test it:
|
||||
|
||||
```sql
|
||||
taos> select myfun(v1, v2) from t;
|
||||
|
||||
DB error: udf function execution failure (0.011088s)
|
||||
```
|
||||
|
||||
Unfortunately, the UDF execution failed. We need to check the log `udfd` daemon to find out why.
|
||||
|
||||
```shell
|
||||
tail -10 /var/log/taos/udfd.log
|
||||
```
|
||||
|
||||
Below is the output.
|
||||
|
||||
```text
|
||||
05/24 22:46:28.733545 01665799 UDF ERROR can not load library libtaospyudf.so. error: operation not permitted
|
||||
05/24 22:46:28.733561 01665799 UDF ERROR can not load python plugin. lib path libtaospyudf.so
|
||||
```
|
||||
|
||||
From the error message we can find out that `libtaospyudf.so` was not loaded successfully. Please refer to the [Prepare Environment] section.
|
||||
|
||||
After correcting environment issues, execute the UDF:
|
||||
|
||||
```sql
|
||||
taos> select myfun(v1) from t;
|
||||
myfun(v1) |
|
||||
============================
|
||||
0.693147181 |
|
||||
1.609437912 |
|
||||
2.302585093 |
|
||||
```
|
||||
|
||||
Now, we have finished the first PDF in Python, and learned some basic debugging skills.
|
||||
|
||||
#### Sample 2: Abnormal Processing
|
||||
|
||||
The `myfun` UDF example in sample 1 has passed, but it has two drawbacks.
|
||||
|
||||
1. It the program accepts only one column of data as input, but it doesn't throw exception if you passes multiple columns.
|
||||
|
||||
```sql
|
||||
taos> select myfun(v1, v2) from t;
|
||||
myfun(v1, v2) |
|
||||
============================
|
||||
0.693147181 |
|
||||
1.609437912 |
|
||||
2.302585093 |
|
||||
```
|
||||
|
||||
2. `null` value is not processed. We expect the program to throw exception and terminate if `null` is passed as input.
|
||||
|
||||
So, we try to optimize the process() function as below.
|
||||
|
||||
```python
|
||||
def process(block):
|
||||
rows, cols = block.shape()
|
||||
if cols > 1:
|
||||
raise Exception(f"require 1 parameter but given {cols}")
|
||||
return [ None if block.data(i, 0) is None else log(block.data(i, 0) ** 2 + 1) for i in range(rows)]
|
||||
```
|
||||
|
||||
The update the UDF with command below.
|
||||
|
||||
```sql
|
||||
create or replace function myfun as '/root/udf/myfun.py' outputtype double language 'Python';
|
||||
```
|
||||
|
||||
At this time, if we pass two arguments to `myfun`, the execution would fail.
|
||||
|
||||
```sql
|
||||
taos> select myfun(v1, v2) from t;
|
||||
|
||||
DB error: udf function execution failure (0.014643s)
|
||||
```
|
||||
|
||||
However, the exception is not shown to end user, but displayed in the log file `/var/log/taos/taospyudf.log`
|
||||
|
||||
```text
|
||||
2023-05-24 23:21:06.790 ERROR [1666188] [doPyUdfScalarProc@507] call pyUdfScalar proc function. context 0x7faade26d180. error: Exception: require 1 parameter but given 2
|
||||
|
||||
At:
|
||||
/var/lib/taos//.udf/myfun_3_1884e1281d9.py(12): process
|
||||
|
||||
```
|
||||
|
||||
Now, we have learned how to update a UDF and check the log of a UDF.
|
||||
|
||||
Note: Prior to TDengine 3.0.5.0 (excluding), updating a UDF requires to restart `taosd` service. After 3.0.5.0, restarting is not required.
|
||||
|
||||
#### Sample 3: UDF with n arguments
|
||||
|
||||
A UDF which accepts n intergers, likee (x1, x2, ..., xn) and output the sum of the product of each value and its sequence number: 1 * x1 + 2 * x2 + ... + n * xn. If there is `null` in the input, then the result is `null`. The difference from sample 1 is that it can accept any number of columns as input and process each column. Assume the program is written in /root/udf/nsum.py:
|
||||
|
||||
```python
|
||||
def init():
|
||||
pass
|
||||
|
||||
|
||||
def destroy():
|
||||
pass
|
||||
|
||||
|
||||
def process(block):
|
||||
rows, cols = block.shape()
|
||||
result = []
|
||||
for i in range(rows):
|
||||
total = 0
|
||||
for j in range(cols):
|
||||
v = block.data(i, j)
|
||||
if v is None:
|
||||
total = None
|
||||
break
|
||||
total += (j + 1) * block.data(i, j)
|
||||
result.append(total)
|
||||
return result
|
||||
```
|
||||
|
||||
Crate and test the UDF:
|
||||
|
||||
```sql
|
||||
create function nsum as '/root/udf/nsum.py' outputtype double language 'Python';
|
||||
```
|
||||
|
||||
```sql
|
||||
taos> insert into t values('2023-05-25 09:09:15', 6, null, 8);
|
||||
Insert OK, 1 row(s) affected (0.003675s)
|
||||
|
||||
taos> select ts, v1, v2, v3, nsum(v1, v2, v3) from t;
|
||||
ts | v1 | v2 | v3 | nsum(v1, v2, v3) |
|
||||
================================================================================================
|
||||
2023-05-01 12:13:14.000 | 1 | 2 | 3 | 14.000000000 |
|
||||
2023-05-03 08:09:10.000 | 2 | 3 | 4 | 20.000000000 |
|
||||
2023-05-10 07:06:05.000 | 3 | 4 | 5 | 26.000000000 |
|
||||
2023-05-25 09:09:15.000 | 6 | NULL | 8 | NULL |
|
||||
Query OK, 4 row(s) in set (0.010653s)
|
||||
```
|
||||
|
||||
#### Sample 4: Utilize 3rd party package
|
||||
|
||||
A UDF which accepts a timestamp and output the next closed Sunday. This sample requires to use third party package `moment`, you need to install it firslty.
|
||||
|
||||
```shell
|
||||
pip3 install moment
|
||||
```
|
||||
|
||||
Then compose the Python code in /root/udf/nextsunday.py
|
||||
|
||||
```python
|
||||
import moment
|
||||
|
||||
|
||||
def init():
|
||||
pass
|
||||
|
||||
|
||||
def destroy():
|
||||
pass
|
||||
|
||||
|
||||
def process(block):
|
||||
rows, cols = block.shape()
|
||||
if cols > 1:
|
||||
raise Exception("require only 1 parameter")
|
||||
if not type(block.data(0, 0)) is int:
|
||||
raise Exception("type error")
|
||||
return [moment.unix(block.data(i, 0)).replace(weekday=7).format('YYYY-MM-DD')
|
||||
for i in range(rows)]
|
||||
```
|
||||
|
||||
UDF framework will map the TDengine timestamp to Python int type, so this function only accepts an integer representing millisecond. process() firstly validates the parameters, then use `moment` to replace the time, format the result and output.
|
||||
|
||||
Create and test the UDF.
|
||||
|
||||
```sql
|
||||
create function nextsunday as '/root/udf/nextsunday.py' outputtype binary(10) language 'Python';
|
||||
```
|
||||
|
||||
If your `taosd` is started using `systemd`, you may encounter the error below. Next we will show how to debug.
|
||||
|
||||
```sql
|
||||
taos> select ts, nextsunday(ts) from t;
|
||||
|
||||
DB error: udf function execution failure (1.123615s)
|
||||
```
|
||||
|
||||
```shell
|
||||
tail -20 taospyudf.log
|
||||
2023-05-25 11:42:34.541 ERROR [1679419] [PyUdf::PyUdf@217] py udf load module failure. error ModuleNotFoundError: No module named 'moment'
|
||||
```
|
||||
|
||||
This is because `moment` doesn't exist in the default library search path of python UDF, please check the log file `taosdpyudf.log`.
|
||||
|
||||
```shell
|
||||
grep 'sys path' taospyudf.log | tail -1
|
||||
```
|
||||
|
||||
```text
|
||||
2023-05-25 10:58:48.554 INFO [1679419] [doPyOpen@592] python sys path: ['', '/lib/python38.zip', '/lib/python3.8', '/lib/python3.8/lib-dynload', '/lib/python3/dist-packages', '/var/lib/taos//.udf']
|
||||
```
|
||||
|
||||
You may find that the default library search path is `/lib/python3/dist-packages` (just for example, it may be different in your system), but `moment` is installed to `/usr/local/lib/python3.8/dist-packages` (for example, it may be different in your system). Then we change the library search path of python UDF.
|
||||
|
||||
Check `sys.path`, which must include the packages you install with pip3 command previously, as shown below:
|
||||
|
||||
```python
|
||||
>>> import sys
|
||||
>>> ":".join(sys.path)
|
||||
'/usr/lib/python3.8:/usr/lib/python3.8/lib-dynload:/usr/local/lib/python3.8/dist-packages:/usr/lib/python3/dist-packages'
|
||||
```
|
||||
|
||||
Copy the output and edit /var/taos/taos.cfg to add below configuration parameter.
|
||||
|
||||
```shell
|
||||
UdfdLdLibPath /usr/lib/python3.8:/usr/lib/python3.8/lib-dynload:/usr/local/lib/python3.8/dist-packages:/usr/lib/python3/dist-packages
|
||||
```
|
||||
|
||||
Save it, then restart `taosd`, using `systemctl restart taosd`, and test again, it will succeed this time.
|
||||
|
||||
Note: If your cluster consists of multiple `taosd` instances, you have to repeat same process for each of them.
|
||||
|
||||
```sql
|
||||
taos> select ts, nextsunday(ts) from t;
|
||||
ts | nextsunday(ts) |
|
||||
===========================================
|
||||
2023-05-01 12:13:14.000 | 2023-05-07 |
|
||||
2023-05-03 08:09:10.000 | 2023-05-07 |
|
||||
2023-05-10 07:06:05.000 | 2023-05-14 |
|
||||
2023-05-25 09:09:15.000 | 2023-05-28 |
|
||||
Query OK, 4 row(s) in set (1.011474s)
|
||||
```
|
||||
|
||||
#### Sample 5: Aggregate Function
|
||||
|
||||
An aggregate function which calculates the difference of the maximum and the minimum in a column. An aggregate funnction takes multiple rows as input and output only one data. The execution process of an aggregate UDF is like map-reduce, the framework divides the input into multiple parts, each mapper processes one block and the reducer aggregates the result of the mappers. The reduce() of Python UDF has the functionality of both map() and reduce(). The reduce() takes two arguments: the data to be processed; and the result of other tasks executing reduce(). For exmaple, assume the code is in `/root/udf/myspread.py`.
|
||||
|
||||
```python
|
||||
import io
|
||||
import math
|
||||
import pickle
|
||||
|
||||
LOG_FILE: io.TextIOBase = None
|
||||
|
||||
|
||||
def init():
|
||||
global LOG_FILE
|
||||
LOG_FILE = open("/var/log/taos/spread.log", "wt")
|
||||
log("init function myspead success")
|
||||
|
||||
|
||||
def log(o):
|
||||
LOG_FILE.write(str(o) + '\n')
|
||||
|
||||
|
||||
def destroy():
|
||||
log("close log file: spread.log")
|
||||
LOG_FILE.close()
|
||||
|
||||
|
||||
def start():
|
||||
return pickle.dumps((-math.inf, math.inf))
|
||||
|
||||
|
||||
def reduce(block, buf):
|
||||
max_number, min_number = pickle.loads(buf)
|
||||
log(f"initial max_number={max_number}, min_number={min_number}")
|
||||
rows, _ = block.shape()
|
||||
for i in range(rows):
|
||||
v = block.data(i, 0)
|
||||
if v > max_number:
|
||||
log(f"max_number={v}")
|
||||
max_number = v
|
||||
if v < min_number:
|
||||
log(f"min_number={v}")
|
||||
min_number = v
|
||||
return pickle.dumps((max_number, min_number))
|
||||
|
||||
|
||||
def finish(buf):
|
||||
max_number, min_number = pickle.loads(buf)
|
||||
return max_number - min_number
|
||||
```
|
||||
|
||||
In this example, we implemented an aggregate function, and added some logging.
|
||||
1. init() opens a file for logging
|
||||
2. log() is the function for logging, it converts the input object to string and output with an end of line
|
||||
3. destroy() closes the log file \
|
||||
4. start() returns the initial buffer for storing the intermediate result
|
||||
5. reduce() processes each daa block and aggregates the result
|
||||
6. finish() converts the final buffer() to final result\
|
||||
|
||||
Create the UDF.
|
||||
|
||||
```sql
|
||||
create or replace aggregate function myspread as '/root/udf/myspread.py' outputtype double bufsize 128 language 'Python';
|
||||
```
|
||||
|
||||
This SQL command has two important different points from the command creating scalar UDF.
|
||||
1. keyword `aggregate` is used
|
||||
2. keyword `bufsize` is used to specify the memory size for storing the intermediate result. In this example, the result is 32 bytes, but we specified 128 bytes for `bufsize`. You can use the `python` CLI to print actual size.
|
||||
|
||||
```python
|
||||
>>> len(pickle.dumps((12345.6789, 23456789.9877)))
|
||||
32
|
||||
```
|
||||
|
||||
Test this function, you can see the result is same as built-in spread() function. \
|
||||
|
||||
```sql
|
||||
taos> select myspread(v1) from t;
|
||||
myspread(v1) |
|
||||
============================
|
||||
5.000000000 |
|
||||
Query OK, 1 row(s) in set (0.013486s)
|
||||
|
||||
taos> select spread(v1) from t;
|
||||
spread(v1) |
|
||||
============================
|
||||
5.000000000 |
|
||||
Query OK, 1 row(s) in set (0.005501s)
|
||||
```
|
||||
|
||||
At last, check the log file, we can see that the reduce() function is executed 3 times, max value is updated 3 times and min value is updated only one time.
|
||||
|
||||
```shell
|
||||
root@slave11 /var/log/taos $ cat spread.log
|
||||
init function myspead success
|
||||
initial max_number=-inf, min_number=inf
|
||||
max_number=1
|
||||
min_number=1
|
||||
initial max_number=1, min_number=1
|
||||
max_number=2
|
||||
max_number=3
|
||||
initial max_number=3, min_number=1
|
||||
max_number=6
|
||||
close log file: spread.log
|
||||
```
|
||||
|
||||
### SQL Commands
|
||||
|
||||
1. Create Scalar UDF
|
||||
|
||||
```sql
|
||||
CREATE FUNCTION function_name AS library_path OUTPUTTYPE output_type LANGUAGE 'Python';
|
||||
```
|
||||
|
||||
2. Create Aggregate UDF
|
||||
|
||||
```sql
|
||||
CREATE AGGREGATE FUNCTION function_name library_path OUTPUTTYPE output_type LANGUAGE 'Python';
|
||||
```
|
||||
|
||||
3. Update Scalar UDF
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE FUNCTION function_name AS OUTPUTTYPE int LANGUAGE 'Python';
|
||||
```
|
||||
|
||||
4. Update Aggregate UDF
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE AGGREGATE FUNCTION function_name AS OUTPUTTYPE BUFSIZE buf_size int LANGUAGE 'Python';
|
||||
```
|
||||
|
||||
Note: If keyword `AGGREGATE` used, the UDF will be treated as aggregate UDF despite what it was before; Similarly, if there is no keyword `aggregate`, the UDF will be treated as scalar function despite what it was before.
|
||||
|
||||
5. Show the UDF
|
||||
|
||||
The version of a UDF is increased by one every time it's updated.
|
||||
|
||||
```sql
|
||||
select * from ins_functions \G;
|
||||
```
|
||||
|
||||
6. Show and Drop existing UDF
|
||||
|
||||
```sql
|
||||
SHOW functions;
|
||||
DROP FUNCTION function_name;
|
||||
```
|
||||
|
||||
### More Python UDF Samples
|
||||
|
||||
### Python UDF Sample Code
|
||||
#### Scalar Function [pybitand](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pybitand.py)
|
||||
|
||||
The `pybitand` function implements bitwise addition for multiple columns. If there is only one column, the column is returned. The `pybitand` function ignores null values.
|
||||
|
@ -377,7 +865,7 @@ The `pybitand` function implements bitwise addition for multiple columns. If the
|
|||
|
||||
#### Aggregate Function [pyl2norm](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pyl2norm.py)
|
||||
|
||||
The `pyl2norm` function finds the second-order norm for all data in the input column. This squares the values, takes a cumulative sum, and finds the square root.
|
||||
The `pyl2norm` function finds the second-order norm for all data in the input columns. This squares the values, takes a cumulative sum, and finds the square root.
|
||||
<details>
|
||||
<summary>pyl2norm.py</summary>
|
||||
|
||||
|
@ -387,5 +875,16 @@ The `pyl2norm` function finds the second-order norm for all data in the input co
|
|||
|
||||
</details>
|
||||
|
||||
#### Aggregate Function [pycumsum](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pycumsum.py)
|
||||
|
||||
The `pycumsum` function finds the cumulative sum for all data in the input columns.
|
||||
<details>
|
||||
<summary>pycumsum.py</summary>
|
||||
|
||||
```c
|
||||
{{#include tests/script/sh/pycumsum.py}}
|
||||
```
|
||||
|
||||
</details>
|
||||
## Manage and Use UDF
|
||||
You need to add UDF to TDengine before using it in SQL queries. For more information about how to manage UDF and how to invoke UDF, please see [Manage and Use UDF](../12-taos-sql/26-udf.md).
|
||||
|
|
|
@ -42,7 +42,6 @@ In TDengine, the data types below can be used when specifying a column or tag.
|
|||
| 14 | NCHAR | User Defined | Multi-byte string that can include multi byte characters like Chinese characters. Each character of NCHAR type consumes 4 bytes storage. The string value should be quoted with single quotes. Literal single quote inside the string must be preceded with backslash, like `\'`. The length must be specified when defining a column or tag of NCHAR type, for example nchar(10) means it can store at most 10 characters of nchar type and will consume fixed storage of 40 bytes. An error will be reported if the string value exceeds the length defined. |
|
||||
| 15 | JSON | | JSON type can only be used on tags. A tag of json type is excluded with any other tags of any other type. |
|
||||
| 16 | VARCHAR | User-defined | Alias of BINARY |
|
||||
|
||||
:::note
|
||||
|
||||
- Only ASCII visible characters are suggested to be used in a column or tag of BINARY type. Multi-byte characters must be stored in NCHAR type.
|
||||
|
|
|
@ -867,10 +867,16 @@ FIRST(expr)
|
|||
### INTERP
|
||||
|
||||
```sql
|
||||
INTERP(expr)
|
||||
INTERP(expr [, ignore_null_values])
|
||||
|
||||
ignore_null_values: {
|
||||
0
|
||||
| 1
|
||||
}
|
||||
```
|
||||
|
||||
**Description**: The value that matches the specified timestamp range is returned, if existing; or an interpolation value is returned.
|
||||
**Description**: The value that matches the specified timestamp range is returned, if existing; or an interpolation value is returned. The value of `ignore_null_values` can be 0 or 1, 1 means null values are ignored. The default value of this parameter is 0.
|
||||
|
||||
|
||||
**Return value type**: Same as the column being operated upon
|
||||
|
||||
|
@ -1002,8 +1008,7 @@ SAMPLE(expr, k)
|
|||
|
||||
**More explanations**:
|
||||
|
||||
This function cannot be used in expression calculation.
|
||||
- Must be used with `PARTITION BY tbname` when it's used on a STable to force the result on each single timeline
|
||||
- This function cannot be used in expression calculation.
|
||||
|
||||
|
||||
### TAIL
|
||||
|
@ -1082,7 +1087,6 @@ CSUM(expr)
|
|||
|
||||
- Arithmetic operation can't be performed on the result of `csum` function
|
||||
- Can only be used with aggregate functions This function can be used with supertables and standard tables.
|
||||
- Must be used with `PARTITION BY tbname` when it's used on a STable to force the result on each single timeline
|
||||
|
||||
|
||||
### DERIVATIVE
|
||||
|
@ -1106,7 +1110,6 @@ ignore_negative: {
|
|||
|
||||
**More explanation**:
|
||||
|
||||
- It can be used together with `PARTITION BY tbname` against a STable.
|
||||
- It can be used together with a selected column. For example: select \_rowts, DERIVATIVE() from.
|
||||
|
||||
### DIFF
|
||||
|
@ -1169,7 +1172,6 @@ MAVG(expr, k)
|
|||
|
||||
- Arithmetic operation can't be performed on the result of `MAVG`.
|
||||
- Can only be used with data columns, can't be used with tags. - Can't be used with aggregate functions.
|
||||
- Must be used with `PARTITION BY tbname` when it's used on a STable to force the result on each single timeline
|
||||
|
||||
|
||||
### STATECOUNT
|
||||
|
@ -1195,7 +1197,6 @@ STATECOUNT(expr, oper, val)
|
|||
|
||||
**More explanations**:
|
||||
|
||||
- Must be used together with `PARTITION BY tbname` when it's used on a STable to force the result into each single timeline]
|
||||
- Can't be used with window operation, like interval/state_window/session_window
|
||||
|
||||
|
||||
|
@ -1223,7 +1224,6 @@ STATEDURATION(expr, oper, val, unit)
|
|||
|
||||
**More explanations**:
|
||||
|
||||
- Must be used together with `PARTITION BY tbname` when it's used on a STable to force the result into each single timeline]
|
||||
- Can't be used with window operation, like interval/state_window/session_window
|
||||
|
||||
|
||||
|
@ -1241,7 +1241,6 @@ TWA(expr)
|
|||
|
||||
**Applicable table types**: standard tables and supertables
|
||||
|
||||
- Must be used together with `PARTITION BY tbname` to force the result into each single timeline.
|
||||
|
||||
|
||||
## System Information Functions
|
||||
|
|
|
@ -17,7 +17,7 @@ CREATE [OR REPLACE] FUNCTION function_name AS library_path OUTPUTTYPE output_typ
|
|||
```
|
||||
- OR REPLACE: if the UDF exists, the UDF properties are modified
|
||||
- function_name: The scalar function name to be used in the SQL statement
|
||||
- LANGUAGE 'C|Python': the programming language of UDF. Now C or Python is supported. If this clause is omitted, C is assumed as the programming language.
|
||||
- LANGUAGE 'C|Python': the programming language of UDF. Now C or Python (v3.7+) is supported. If this clause is omitted, C is assumed as the programming language.
|
||||
- library_path: For C programming language, The absolute path of the DLL file including the name of the shared object file (.so). For Python programming language, the absolute path of the Python UDF script. The path must be quoted with single or double quotes.
|
||||
- output_type: The data type of the results of the UDF.
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ You can use below command to setup Grafana alert notification.
|
|||
An existing Grafana Notification Channel can be specified with parameter `-E`, the notifier uid of the channel can be obtained by `curl -u admin:admin localhost:3000/api/alert-notifications |jq`
|
||||
|
||||
```bash
|
||||
sudo ./TDinsight.sh -a http://localhost:6041 -u root -p taosdata -E <notifier uid>
|
||||
./TDinsight.sh -a http://localhost:6041 -u root -p taosdata -E <notifier uid>
|
||||
```
|
||||
|
||||
Launch `TDinsight.sh` with the command above and restart Grafana, then open Dashboard `http://localhost:3000/d/tdinsight`.
|
||||
|
@ -274,7 +274,7 @@ The data of tdinsight dashboard is stored in `log` database (default. You can ch
|
|||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||metric value|
|
||||
|gauge|DOUBLE||metric value|
|
||||
|client\_ip|NCHAR|TAG|client ip|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|request\_method|NCHAR|TAG|request method|
|
||||
|
@ -288,7 +288,7 @@ The data of tdinsight dashboard is stored in `log` database (default. You can ch
|
|||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||metric value|
|
||||
|gauge|DOUBLE||metric value|
|
||||
|client\_ip|NCHAR|TAG|client ip|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|request\_method|NCHAR|TAG|request method|
|
||||
|
@ -302,7 +302,7 @@ The data of tdinsight dashboard is stored in `log` database (default. You can ch
|
|||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||metric value|
|
||||
|gauge|DOUBLE||metric value|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|
||||
### taosadapter\_restful\_http\_request\_summary\_milliseconds table
|
||||
|
@ -330,7 +330,7 @@ The data of tdinsight dashboard is stored in `log` database (default. You can ch
|
|||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||metric value|
|
||||
|gauge|DOUBLE||metric value|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|
||||
### taosadapter\_system\_cpu\_percent table
|
||||
|
@ -340,6 +340,6 @@ The data of tdinsight dashboard is stored in `log` database (default. You can ch
|
|||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||mertic value|
|
||||
|gauge|DOUBLE||mertic value|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|
||||
|
|
|
@ -959,6 +959,7 @@ The preceding example uses the SQL statement `select ts, speed from speed_table`
|
|||
|
||||
```java
|
||||
Properties config = new Properties();
|
||||
config.setProperty("bootstrap.servers", "localhost:6030");
|
||||
config.setProperty("enable.auto.commit", "true");
|
||||
config.setProperty("group.id", "group1");
|
||||
config.setProperty("value.deserializer", "com.taosdata.jdbc.tmq.ConsumerTest.ResultDeserializer");
|
||||
|
@ -966,12 +967,14 @@ config.setProperty("value.deserializer", "com.taosdata.jdbc.tmq.ConsumerTest.Res
|
|||
TaosConsumer consumer = new TaosConsumer<>(config);
|
||||
```
|
||||
|
||||
- bootstrap.servers: `ip:port` where the TDengine server is located, or `ip:port` where the taosAdapter is located if WebSocket connection is used.
|
||||
- enable.auto.commit: Specifies whether to commit automatically.
|
||||
- group.id: consumer: Specifies the group that the consumer is in.
|
||||
- value.deserializer: To deserialize the results, you can inherit `com.taosdata.jdbc.tmq.ReferenceDeserializer` and specify the result set bean. You can also inherit `com.taosdata.jdbc.tmq.Deserializer` and perform custom deserialization based on the SQL result set.
|
||||
- td.connect.type: Specifies the type connect with TDengine, `jni` or `WebSocket`. default is `jni`
|
||||
- httpConnectTimeout: WebSocket connection timeout in milliseconds, the default value is 5000 ms. It only takes effect when using WebSocket type.
|
||||
- messageWaitTimeout: socket timeout in milliseconds, the default value is 10000 ms. It only takes effect when using WebSocket type.
|
||||
- httpPoolSize: Maximum number of concurrent requests on the a connection。It only takes effect when using WebSocket type.
|
||||
- For more information, see [Consumer Parameters](../../../develop/tmq).
|
||||
|
||||
#### Subscribe to consume data
|
||||
|
@ -1015,10 +1018,20 @@ public abstract class ConsumerLoop {
|
|||
|
||||
public ConsumerLoop() throws SQLException {
|
||||
Properties config = new Properties();
|
||||
config.setProperty("td.connect.type", "jni");
|
||||
config.setProperty("bootstrap.servers", "localhost:6030");
|
||||
config.setProperty("td.connect.user", "root");
|
||||
config.setProperty("td.connect.pass", "taosdata");
|
||||
config.setProperty("auto.offset.reset", "earliest");
|
||||
config.setProperty("msg.with.table.name", "true");
|
||||
config.setProperty("enable.auto.commit", "true");
|
||||
config.setProperty("auto.commit.interval.ms", "1000");
|
||||
config.setProperty("group.id", "group1");
|
||||
config.setProperty("client.id", "1");
|
||||
config.setProperty("value.deserializer", "com.taosdata.jdbc.tmq.ConsumerTest.ConsumerLoop$ResultDeserializer");
|
||||
config.setProperty("value.deserializer.encoding", "UTF-8");
|
||||
config.setProperty("experimental.snapshot.enable", "true");
|
||||
|
||||
|
||||
this.consumer = new TaosConsumer<>(config);
|
||||
this.topics = Collections.singletonList("topic_speed");
|
||||
|
@ -1090,12 +1103,19 @@ public abstract class ConsumerLoop {
|
|||
|
||||
public ConsumerLoop() throws SQLException {
|
||||
Properties config = new Properties();
|
||||
config.setProperty("bootstrap.servers", "localhost:6041");
|
||||
config.setProperty("td.connect.type", "ws");
|
||||
config.setProperty("bootstrap.servers", "localhost:6041");
|
||||
config.setProperty("td.connect.user", "root");
|
||||
config.setProperty("td.connect.pass", "taosdata");
|
||||
config.setProperty("auto.offset.reset", "earliest");
|
||||
config.setProperty("msg.with.table.name", "true");
|
||||
config.setProperty("enable.auto.commit", "true");
|
||||
config.setProperty("auto.commit.interval.ms", "1000");
|
||||
config.setProperty("group.id", "group2");
|
||||
config.setProperty("client.id", "1");
|
||||
config.setProperty("value.deserializer", "com.taosdata.jdbc.tmq.ConsumerTest.ConsumerLoop$ResultDeserializer");
|
||||
config.setProperty("value.deserializer.encoding", "UTF-8");
|
||||
config.setProperty("experimental.snapshot.enable", "true");
|
||||
|
||||
this.consumer = new TaosConsumer<>(config);
|
||||
this.topics = Collections.singletonList("topic_speed");
|
||||
|
|
|
@ -362,7 +362,7 @@ By using the optional req_id parameter, you can specify a request ID that can be
|
|||
|
||||
##### TaosConnection class
|
||||
|
||||
The `TaosConnection` class contains both an implementation of the PEP249 Connection interface (e.g., the `cursor()` method and the `close()` method) and many extensions (e.g., the `execute()`, `query()`, `schemaless_insert()`, and `subscribe()` methods).
|
||||
As the way to connect introduced above but add `req_id` argument.
|
||||
|
||||
```python title="execute method"
|
||||
{{#include docs/examples/python/connection_usage_native_reference_with_req_id.py:insert}}
|
||||
|
@ -372,13 +372,9 @@ The `TaosConnection` class contains both an implementation of the PEP249 Connect
|
|||
{{#include docs/examples/python/connection_usage_native_reference_with_req_id.py:query}}
|
||||
```
|
||||
|
||||
:::tip
|
||||
The queried results can only be fetched once. For example, only one of `fetch_all()` and `fetch_all_into_dict()` can be used in the example above. Repeated fetches will result in an empty list.
|
||||
:::
|
||||
|
||||
##### Use of TaosResult class
|
||||
|
||||
In the above example of using the `TaosConnection` class, we have shown two ways to get the result of a query: `fetch_all()` and `fetch_all_into_dict()`. In addition, `TaosResult` also provides methods to iterate through the result set by rows (`rows_iter`) or by data blocks (`blocks_iter`). Using these two methods will be more efficient in scenarios where the query has a large amount of data.
|
||||
As the way to fetch data introduced above but add `req_id` argument.
|
||||
|
||||
```python title="blocks_iter method"
|
||||
{{#include docs/examples/python/result_set_with_req_id_examples.py}}
|
||||
|
@ -391,17 +387,12 @@ The `TaosConnection` class and the `TaosResult` class already implement all the
|
|||
{{#include docs/examples/python/cursor_usage_native_reference_with_req_id.py}}
|
||||
```
|
||||
|
||||
:::note
|
||||
The TaosCursor class uses native connections for write and query operations. In a client-side multi-threaded scenario, this cursor instance must remain thread exclusive and cannot be shared across threads for use, otherwise, it will result in errors in the returned results.
|
||||
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="rest" label="REST connection">
|
||||
|
||||
##### Use of TaosRestCursor class
|
||||
|
||||
The `TaosRestCursor` class is an implementation of the PEP249 Cursor interface.
|
||||
As the way to connect introduced above but add `req_id` argument.
|
||||
|
||||
```python title="Use of TaosRestCursor"
|
||||
{{#include docs/examples/python/connect_rest_with_req_id_examples.py:basic}}
|
||||
|
@ -421,8 +412,11 @@ The `RestClient` class is a direct wrapper for the [REST API](/reference/rest-ap
|
|||
For a more detailed description of the `sql()` method, please refer to [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html).
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="websocket" label="WebSocket connection">
|
||||
|
||||
As the way to connect introduced above but add `req_id` argument.
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/connect_websocket_with_req_id_examples.py:basic}}
|
||||
```
|
||||
|
|
|
@ -62,7 +62,7 @@ The different database framework specifications for various programming language
|
|||
| **Regular Query** | Support | Support | Support | Support | Support | Support |
|
||||
| **Parameter Binding** | Not Supported | Not Supported | Support | Support | Not Supported | Support |
|
||||
| **Subscription (TMQ) ** | Supported | Support | Support | Not Supported | Not Supported | Support |
|
||||
| **Schemaless** | Supported | Not Supported | Not Supported | Not Supported | Not Supported | Not Supported |
|
||||
| **Schemaless** | Not Supported | Not Supported | Not Supported | Not Supported | Not Supported | Not Supported |
|
||||
| **Bulk Pulling (based on WebSocket) ** | Support | Support | Support | Support | Support | Support |
|
||||
| **DataFrame** | Not Supported | Support | Not Supported | Not Supported | Not Supported | Not Supported |
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@ curl --no-progress-meter -u admin:admin http://localhost:3000/api/alert-notifica
|
|||
Use the `uid` value obtained above as `-E` input.
|
||||
|
||||
```bash
|
||||
sudo ./TDinsight.sh -a http://tdengine:6041 -u root1 -p pass5ord -E existing-notifier
|
||||
./TDinsight.sh -a http://tdengine:6041 -u root1 -p pass5ord -E existing-notifier
|
||||
```
|
||||
|
||||
If you want to monitor multiple TDengine clusters, you need to set up numerous TDinsight dashboards. Setting up non-default TDinsight requires some changes: the `-n` `-i` `-t` options need to be changed to non-default names, and `-N` and `-L` should also be changed if using the built-in SMS alerting feature.
|
||||
|
|
|
@ -46,7 +46,7 @@ The parameters described in this document by the effect that they have on the sy
|
|||
### firstEp
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------------------------------------------------- |
|
||||
| ---------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | The end point of the first dnode in the cluster to be connected to when `taosd` or `taos` is started |
|
||||
| Default | localhost:6030 |
|
||||
|
@ -54,7 +54,7 @@ The parameters described in this document by the effect that they have on the sy
|
|||
### secondEp
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------------------------------------------------------------------------- |
|
||||
| ---------- | ---------------------------------------------------------------------------------------------------------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | The end point of the second dnode to be connected to if the firstEp is not available when `taosd` or `taos` is started |
|
||||
| Default | None |
|
||||
|
@ -71,7 +71,7 @@ The parameters described in this document by the effect that they have on the sy
|
|||
### serverPort
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ----------------------------------------------------------------------------------------------------------------------- |
|
||||
| ------------- | ----------------------------------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | The port for external access after `taosd` is started |
|
||||
| Default Value | 6030 |
|
||||
|
@ -80,12 +80,12 @@ The parameters described in this document by the effect that they have on the sy
|
|||
- Ensure that your firewall rules do not block TCP port 6042 on any host in the cluster. Below table describes the ports used by TDengine in details.
|
||||
:::
|
||||
| Protocol | Default Port | Description | How to configure |
|
||||
| :------- | :----------- | :----------------------------------------------- | :--------------------------------------------------------------------------------------------- |
|
||||
| :------- | :----------- | :-------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------- |
|
||||
| TCP | 6030 | Communication between client and server. In a multi-node cluster, communication between nodes. serverPort |
|
||||
| TCP | 6041 | REST connection between client and server | Prior to 2.4.0.0: serverPort+11; After 2.4.0.0 refer to [taosAdapter](/reference/taosadapter/) |
|
||||
| TCP | 6043 | Service Port of taosKeeper | The parameter of taosKeeper |
|
||||
| TCP | 6044 | Data access port for StatsD | Configurable through taosAdapter parameters.
|
||||
| UDP | 6045 | Data access for statsd | Configurable through taosAdapter parameters.
|
||||
| TCP | 6044 | Data access port for StatsD | Configurable through taosAdapter parameters. |
|
||||
| UDP | 6045 | Data access for statsd | Configurable through taosAdapter parameters. |
|
||||
| TCP | 6060 | Port of Monitoring Service in Enterprise version | |
|
||||
|
||||
### maxShellConns
|
||||
|
@ -97,6 +97,24 @@ The parameters described in this document by the effect that they have on the sy
|
|||
| Value Range | 10-50000000 |
|
||||
| Default Value | 5000 |
|
||||
|
||||
### numOfRpcSessions
|
||||
|
||||
| Attribute | Description |
|
||||
| ------------- | ------------------------------------------ |
|
||||
| Applicable | Client/Server |
|
||||
| Meaning | The maximum number of connection to create |
|
||||
| Value Range | 100-100000 |
|
||||
| Default Value | 10000 |
|
||||
|
||||
### timeToGetAvailableConn
|
||||
|
||||
| Attribute | Description |
|
||||
| ------------- | ---------------------------------------------- |
|
||||
| Applicable | Client/Server |
|
||||
| Meaning | The maximum waiting time to get available conn |
|
||||
| Value Range | 10-50000000(ms) |
|
||||
| Default Value | 500000 |
|
||||
|
||||
## Monitoring Parameters
|
||||
|
||||
:::note
|
||||
|
@ -105,16 +123,16 @@ Please note the `taoskeeper` needs to be installed and running to create the `lo
|
|||
### monitor
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Applicable | Server only |
|
||||
| Meaning | The switch for monitoring inside server. The main object of monitoring is to collect information about load on physical nodes, including CPU usage, memory usage, disk usage, and network bandwidth. Monitoring information is sent over HTTP to the taosKeeper service specified by `monitorFqdn` and `monitorProt`.
|
||||
| Meaning | The switch for monitoring inside server. The main object of monitoring is to collect information about load on physical nodes, including CPU usage, memory usage, disk usage, and network bandwidth. Monitoring information is sent over HTTP to the taosKeeper service specified by `monitorFqdn` and `monitorProt`. |
|
||||
| Value Range | 0: monitoring disabled, 1: monitoring enabled |
|
||||
| Default | 0 |
|
||||
|
||||
### monitorFqdn
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------------- |
|
||||
| ---------- | ------------------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | FQDN of taosKeeper monitoring service |
|
||||
| Default | None |
|
||||
|
@ -122,7 +140,7 @@ Please note the `taoskeeper` needs to be installed and running to create the `lo
|
|||
### monitorPort
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | --------------------------- |
|
||||
| ------------- | ------------------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Port of taosKeeper monitoring service |
|
||||
| Default Value | 6043 |
|
||||
|
@ -130,7 +148,7 @@ Please note the `taoskeeper` needs to be installed and running to create the `lo
|
|||
### monitorInterval
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------------------------------- |
|
||||
| ------------- | ------------------------------------------ |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | The interval of collecting system workload |
|
||||
| Unit | second |
|
||||
|
@ -140,7 +158,7 @@ Please note the `taoskeeper` needs to be installed and running to create the `lo
|
|||
### telemetryReporting
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ---------------------------------------- |
|
||||
| ------------- | ---------------------------------------------------------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Switch for allowing TDengine to collect and report service usage information |
|
||||
| Value Range | 0: Not allowed; 1: Allowed |
|
||||
|
@ -148,9 +166,9 @@ Please note the `taoskeeper` needs to be installed and running to create the `lo
|
|||
### crashReporting
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------------------------------- |
|
||||
| ------------- | ---------------------------------------------------------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning |Switch for allowing TDengine to collect and report crash related information |
|
||||
| Meaning | Switch for allowing TDengine to collect and report crash related information |
|
||||
| Value Range | 0,1 0: Not allowed; 1: allowed |
|
||||
| Default Value | 1 |
|
||||
|
||||
|
@ -160,7 +178,7 @@ Please note the `taoskeeper` needs to be installed and running to create the `lo
|
|||
### queryPolicy
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ----------------------------- |
|
||||
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Applicable | Client only |
|
||||
| Meaning | Execution policy for query statements |
|
||||
| Unit | None |
|
||||
|
@ -170,17 +188,17 @@ Please note the `taoskeeper` needs to be installed and running to create the `lo
|
|||
### querySmaOptimize
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------- |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Applicable | Client only |
|
||||
| Meaning | SMA index optimization policy |
|
||||
| Unit | None |
|
||||
| Default Value | 0 |
|
||||
| Notes |0: Disable SMA indexing and perform all queries on non-indexed data; 1: Enable SMA indexing and perform queries from suitable statements on precomputation results.|
|
||||
| Notes | 0: Disable SMA indexing and perform all queries on non-indexed data; 1: Enable SMA indexing and perform queries from suitable statements on precomputation results. |
|
||||
|
||||
### countAlwaysReturnValue
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------------------- |
|
||||
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Applicable | Server only |
|
||||
| Meaning | count()/hyperloglog() return value or not if the input data is empty or NULL |
|
||||
| Vlue Range | 0: Return empty line, 1: Return 0 |
|
||||
|
@ -190,7 +208,7 @@ Please note the `taoskeeper` needs to be installed and running to create the `lo
|
|||
### maxNumOfDistinctRes
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------------------- |
|
||||
| ------------- | -------------------------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | The maximum number of distinct rows returned |
|
||||
| Value Range | [100,000 - 100,000,000] |
|
||||
|
@ -199,7 +217,7 @@ Please note the `taoskeeper` needs to be installed and running to create the `lo
|
|||
### keepColumnName
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------------------- |
|
||||
| ------------- | --------------------------------------------------------------------------------------------------------------- |
|
||||
| Applicable | Client only |
|
||||
| Meaning | When the Last, First, LastRow function is queried, whether the returned column name contains the function name. |
|
||||
| Value Range | 0 means including the function name, 1 means not including the function name. |
|
||||
|
@ -210,7 +228,7 @@ Please note the `taoskeeper` needs to be installed and running to create the `lo
|
|||
### timezone
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------------------ |
|
||||
| ------------- | ------------------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | TimeZone |
|
||||
| Default Value | TimeZone configured in the host |
|
||||
|
@ -315,7 +333,7 @@ The charset that takes effect is UTF-8.
|
|||
### dataDir
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------------------------------ |
|
||||
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | All data files are stored in this directory |
|
||||
| Default Value | /var/lib/taos |
|
||||
|
@ -324,7 +342,7 @@ The charset that takes effect is UTF-8.
|
|||
### tempDir
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------------------------------ |
|
||||
| ---------- | ---------------------------------------------------------------------------------- |
|
||||
| Applicable | Server only |
|
||||
| Meaning | The directory where to put all the temporary files generated during system running |
|
||||
| Default | /tmp |
|
||||
|
@ -332,7 +350,7 @@ The charset that takes effect is UTF-8.
|
|||
### minimalTmpDirGB
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------------------------------------ |
|
||||
| ------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | When the available disk space in tmpDir is below this threshold, writing to tmpDir is suspended |
|
||||
| Unit | GB |
|
||||
|
@ -341,7 +359,7 @@ The charset that takes effect is UTF-8.
|
|||
### minimalDataDirGB
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------------------------------------ |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | When the available disk space in dataDir is below this threshold, writing to dataDir is suspended |
|
||||
| Unit | GB |
|
||||
|
@ -352,7 +370,7 @@ The charset that takes effect is UTF-8.
|
|||
### supportVnodes
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | --------------------------- |
|
||||
| ------------- | ---------------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Maximum number of vnodes per dnode |
|
||||
| Value Range | 0-4096 |
|
||||
|
@ -374,7 +392,7 @@ The charset that takes effect is UTF-8.
|
|||
### logDir
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------------------------------------- |
|
||||
| ------------- | ----------------------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | The directory for writing log files |
|
||||
| Default Value | /var/log/taos |
|
||||
|
@ -382,7 +400,7 @@ The charset that takes effect is UTF-8.
|
|||
### minimalLogDirGB
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------------------------------- |
|
||||
| ------------- | -------------------------------------------------------------------------------------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | When the available disk space in logDir is below this threshold, writing to log files is suspended |
|
||||
| Unit | GB |
|
||||
|
@ -391,7 +409,7 @@ The charset that takes effect is UTF-8.
|
|||
### numOfLogLines
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ---------------------------- |
|
||||
| ------------- | ------------------------------------------ |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | Maximum number of lines in single log file |
|
||||
| Default Value | 10000000 |
|
||||
|
@ -399,7 +417,7 @@ The charset that takes effect is UTF-8.
|
|||
### asyncLog
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------- |
|
||||
| ------------- | ---------------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | The mode of writing log file |
|
||||
| Value Range | 0: sync way; 1: async way |
|
||||
|
@ -408,7 +426,7 @@ The charset that takes effect is UTF-8.
|
|||
### logKeepDays
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ----------------------------------------------------------------------------------- |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | The number of days for log files to be kept |
|
||||
| Unit | day |
|
||||
|
@ -418,7 +436,7 @@ The charset that takes effect is UTF-8.
|
|||
### debugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------------------------------------------------------------------------------------- |
|
||||
| ------------- | --------------------------------------------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | Log level |
|
||||
| Value Range | 131: INFO/WARNING/ERROR; 135: plus DEBUG; 143: plus TRACE |
|
||||
|
@ -427,7 +445,7 @@ The charset that takes effect is UTF-8.
|
|||
### tmrDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------- |
|
||||
| ------------- | ------------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | Log level of timer module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -436,7 +454,7 @@ The charset that takes effect is UTF-8.
|
|||
### uDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ---------------------- |
|
||||
| ------------- | -------------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | Log level of common module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -445,7 +463,7 @@ The charset that takes effect is UTF-8.
|
|||
### rpcDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------- |
|
||||
| ------------- | ----------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | Log level of rpc module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -454,7 +472,7 @@ The charset that takes effect is UTF-8.
|
|||
### jniDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------ |
|
||||
| ------------- | ----------------------- |
|
||||
| Applicable | Client Only |
|
||||
| Meaning | Log level of jni module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -463,7 +481,7 @@ The charset that takes effect is UTF-8.
|
|||
### qDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------- |
|
||||
| ------------- | ------------------------- |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | Log level of query module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -472,7 +490,7 @@ The charset that takes effect is UTF-8.
|
|||
### cDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | --------------------- |
|
||||
| ------------- | ------------------- |
|
||||
| Applicable | Client Only |
|
||||
| Meaning | Log level of Client |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -481,7 +499,7 @@ The charset that takes effect is UTF-8.
|
|||
### dDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------- |
|
||||
| ------------- | ------------------ |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Log level of dnode |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -490,7 +508,7 @@ The charset that takes effect is UTF-8.
|
|||
### vDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------- |
|
||||
| ------------- | ------------------ |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Log level of vnode |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -499,7 +517,7 @@ The charset that takes effect is UTF-8.
|
|||
### mDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------- |
|
||||
| ------------- | ------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Log level of mnode module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -508,7 +526,7 @@ The charset that takes effect is UTF-8.
|
|||
### wDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------ |
|
||||
| ------------- | ----------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Log level of WAL module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -517,7 +535,7 @@ The charset that takes effect is UTF-8.
|
|||
### sDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------- |
|
||||
| ------------- | ------------------------ |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | Log level of sync module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -526,7 +544,7 @@ The charset that takes effect is UTF-8.
|
|||
### tsdbDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------- |
|
||||
| ------------- | ------------------------ |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Log level of TSDB module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -535,7 +553,7 @@ The charset that takes effect is UTF-8.
|
|||
### tqDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ----------------- |
|
||||
| ------------- | ---------------------- |
|
||||
| Applicable | Server only |
|
||||
| Meaning | Log level of TQ module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -544,7 +562,7 @@ The charset that takes effect is UTF-8.
|
|||
### fsDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ----------------- |
|
||||
| ------------- | ---------------------- |
|
||||
| Applicable | Server only |
|
||||
| Meaning | Log level of FS module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -553,7 +571,7 @@ The charset that takes effect is UTF-8.
|
|||
### udfDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------ |
|
||||
| ------------- | ----------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Log level of UDF module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -562,7 +580,7 @@ The charset that takes effect is UTF-8.
|
|||
### smaDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------ |
|
||||
| ------------- | ----------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Log level of SMA module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -571,7 +589,7 @@ The charset that takes effect is UTF-8.
|
|||
### idxDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | -------------------- |
|
||||
| ------------- | ------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Log level of index module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -580,7 +598,7 @@ The charset that takes effect is UTF-8.
|
|||
### tdbDebugFlag
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------ |
|
||||
| ------------- | ----------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Log level of TDB module |
|
||||
| Value Range | same as debugFlag |
|
||||
|
@ -591,7 +609,7 @@ The charset that takes effect is UTF-8.
|
|||
### smlChildTableName
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------------- |
|
||||
| ------------- | ------------------------------------------ |
|
||||
| Applicable | Client only |
|
||||
| Meaning | Custom subtable name for schemaless writes |
|
||||
| Type | String |
|
||||
|
@ -600,7 +618,7 @@ The charset that takes effect is UTF-8.
|
|||
### smlTagName
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------------------------ |
|
||||
| ------------- | ------------------------------------------------------------- |
|
||||
| Applicable | Client only |
|
||||
| Meaning | Default tag for schemaless writes without tag value specified |
|
||||
| Type | String |
|
||||
|
@ -609,9 +627,9 @@ The charset that takes effect is UTF-8.
|
|||
### smlDataFormat
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ----------------------------- |
|
||||
| ----------- | ----------------------------------------------------------------------------------- |
|
||||
| Applicable | Client only |
|
||||
| Meaning | Whether schemaless columns are consistently ordered, depat, discarded since 3.0.3.0|
|
||||
| Meaning | Whether schemaless columns are consistently ordered, depat, discarded since 3.0.3.0 |
|
||||
| Value Range | 0: not consistent; 1: consistent. |
|
||||
| Default | 0 |
|
||||
|
||||
|
@ -620,7 +638,7 @@ The charset that takes effect is UTF-8.
|
|||
### compressMsgSize
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ----------------------------- |
|
||||
| ----------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| Applicable | Both Client and Server side |
|
||||
| Meaning | Whether RPC message is compressed |
|
||||
| Value Range | -1: none message is compressed; 0: all messages are compressed; N (N>0): messages exceeding N bytes are compressed |
|
||||
|
@ -632,7 +650,7 @@ The charset that takes effect is UTF-8.
|
|||
### enableCoreFile
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| Applicable | Server and Client |
|
||||
| Meaning | Whether to generate core file when server crashes |
|
||||
| Value Range | 0: false, 1: true |
|
||||
|
@ -642,7 +660,7 @@ The charset that takes effect is UTF-8.
|
|||
### enableScience
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| ------------- | ------------------------------------------------------------- |
|
||||
| Applicable | Only taos-CLI client |
|
||||
| Meaning | Whether to show float and double with the scientific notation |
|
||||
| Value Range | 0: false, 1: true |
|
||||
|
@ -652,7 +670,7 @@ The charset that takes effect is UTF-8.
|
|||
### udf
|
||||
|
||||
| Attribute | Description |
|
||||
| -------- | ------------------ |
|
||||
| ------------- | ---------------------------------- |
|
||||
| Applicable | Server Only |
|
||||
| Meaning | Whether the UDF service is enabled |
|
||||
| Value Range | 0: disable UDF; 1: enabled UDF |
|
||||
|
@ -662,7 +680,7 @@ The charset that takes effect is UTF-8.
|
|||
## 3.0 Parameters
|
||||
|
||||
| # | **Parameter** | **Applicable to 2.x ** | **Applicable to 3.0 ** | Current behavior in 3.0 |
|
||||
| --- | :---------------------: | --------------- | --------------- | ------------------------------------------------- |
|
||||
| --- | :--------------------: | ---------------------- | ---------------------------- | ----------------------- |
|
||||
| 1 | firstEp | Yes | Yes | |
|
||||
| 2 | secondEp | Yes | Yes | |
|
||||
| 3 | fqdn | Yes | Yes | |
|
||||
|
|
|
@ -10,6 +10,10 @@ For TDengine 2.x installation packages by version, please visit [here](https://w
|
|||
|
||||
import Release from "/components/ReleaseV3";
|
||||
|
||||
## 3.0.4.2
|
||||
|
||||
<Release type="tdengine" version="3.0.4.2" />
|
||||
|
||||
## 3.0.4.1
|
||||
|
||||
<Release type="tdengine" version="3.0.4.1" />
|
||||
|
|
|
@ -78,7 +78,8 @@ int printRow(char *str, TAOS_ROW row, TAOS_FIELD *fields, int numFields) {
|
|||
} break;
|
||||
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
|
||||
memcpy(str + len, row[i], charLen);
|
||||
len += charLen;
|
||||
|
|
|
@ -76,7 +76,8 @@ int printRow(char *str, TAOS_ROW row, TAOS_FIELD *fields, int numFields) {
|
|||
} break;
|
||||
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
|
||||
memcpy(str + len, row[i], charLen);
|
||||
len += charLen;
|
||||
|
|
|
@ -6,39 +6,32 @@ import java.sql.Connection;
|
|||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class StmtInsertExample {
|
||||
private static ArrayList<Long> tsToLongArray(String ts) {
|
||||
ArrayList<Long> result = new ArrayList<>();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(ts, formatter);
|
||||
result.add(localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli());
|
||||
return result;
|
||||
}
|
||||
private static String datePattern = "yyyy-MM-dd HH:mm:ss.SSS";
|
||||
private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern(datePattern);
|
||||
|
||||
private static <T> ArrayList<T> toArray(T v) {
|
||||
ArrayList<T> result = new ArrayList<>();
|
||||
result.add(v);
|
||||
return result;
|
||||
private static List<String> getRawData(int size) {
|
||||
SimpleDateFormat format = new SimpleDateFormat(datePattern);
|
||||
List<String> result = new ArrayList<>();
|
||||
long current = System.currentTimeMillis();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < size; i++) {
|
||||
String time = format.format(current + i);
|
||||
int id = random.nextInt(10);
|
||||
result.add("d" + id + "," + time + ",10.30000,219,0.31000,California.SanFrancisco,2");
|
||||
}
|
||||
|
||||
private static List<String> getRawData() {
|
||||
return Arrays.asList(
|
||||
"d1001,2018-10-03 14:38:05.000,10.30000,219,0.31000,California.SanFrancisco,2",
|
||||
"d1001,2018-10-03 14:38:15.000,12.60000,218,0.33000,California.SanFrancisco,2",
|
||||
"d1001,2018-10-03 14:38:16.800,12.30000,221,0.31000,California.SanFrancisco,2",
|
||||
"d1002,2018-10-03 14:38:16.650,10.30000,218,0.25000,California.SanFrancisco,3",
|
||||
"d1003,2018-10-03 14:38:05.500,11.80000,221,0.28000,California.LosAngeles,2",
|
||||
"d1003,2018-10-03 14:38:16.600,13.40000,223,0.29000,California.LosAngeles,2",
|
||||
"d1004,2018-10-03 14:38:05.000,10.80000,223,0.29000,California.LosAngeles,3",
|
||||
"d1004,2018-10-03 14:38:06.500,11.50000,221,0.35000,California.LosAngeles,3"
|
||||
);
|
||||
return result.stream()
|
||||
.sorted(Comparator.comparing(s -> s.split(",")[0])).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Connection getConnection() throws SQLException {
|
||||
|
@ -48,9 +41,9 @@ public class StmtInsertExample {
|
|||
|
||||
private static void createTable(Connection conn) throws SQLException {
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.execute("CREATE DATABASE power KEEP 3650");
|
||||
stmt.executeUpdate("USE power");
|
||||
stmt.execute("CREATE STABLE meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) " +
|
||||
stmt.execute("CREATE DATABASE if not exists power KEEP 3650");
|
||||
stmt.executeUpdate("use power");
|
||||
stmt.execute("CREATE STABLE if not exists meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) " +
|
||||
"TAGS (location BINARY(64), groupId INT)");
|
||||
}
|
||||
}
|
||||
|
@ -58,21 +51,54 @@ public class StmtInsertExample {
|
|||
private static void insertData() throws SQLException {
|
||||
try (Connection conn = getConnection()) {
|
||||
createTable(conn);
|
||||
String psql = "INSERT INTO ? USING meters TAGS(?, ?) VALUES(?, ?, ?, ?)";
|
||||
String psql = "INSERT INTO ? USING power.meters TAGS(?, ?) VALUES(?, ?, ?, ?)";
|
||||
try (TSDBPreparedStatement pst = (TSDBPreparedStatement) conn.prepareStatement(psql)) {
|
||||
for (String line : getRawData()) {
|
||||
String tableName = null;
|
||||
ArrayList<Long> ts = new ArrayList<>();
|
||||
ArrayList<Float> current = new ArrayList<>();
|
||||
ArrayList<Integer> voltage = new ArrayList<>();
|
||||
ArrayList<Float> phase = new ArrayList<>();
|
||||
for (String line : getRawData(100000)) {
|
||||
String[] ps = line.split(",");
|
||||
if (tableName == null) {
|
||||
// bind table name and tags
|
||||
tableName = "power." + ps[0];
|
||||
pst.setTableName(ps[0]);
|
||||
pst.setTagString(0, ps[5]);
|
||||
pst.setTagInt(1, Integer.valueOf(ps[6]));
|
||||
// bind values
|
||||
pst.setTimestamp(0, tsToLongArray(ps[1])); //ps[1] looks like: 2018-10-03 14:38:05.000
|
||||
pst.setFloat(1, toArray(Float.valueOf(ps[2])));
|
||||
pst.setInt(2, toArray(Integer.valueOf(ps[3])));
|
||||
pst.setFloat(3, toArray(Float.valueOf(ps[4])));
|
||||
} else {
|
||||
if (!tableName.equals(ps[0])) {
|
||||
pst.setTimestamp(0, ts);
|
||||
pst.setFloat(1, current);
|
||||
pst.setInt(2, voltage);
|
||||
pst.setFloat(3, phase);
|
||||
pst.columnDataAddBatch();
|
||||
pst.columnDataExecuteBatch();
|
||||
|
||||
// bind table name and tags
|
||||
tableName = ps[0];
|
||||
pst.setTableName(ps[0]);
|
||||
pst.setTagString(0, ps[5]);
|
||||
pst.setTagInt(1, Integer.valueOf(ps[6]));
|
||||
ts.clear();
|
||||
current.clear();
|
||||
voltage.clear();
|
||||
phase.clear();
|
||||
}
|
||||
}
|
||||
// bind values
|
||||
// ps[1] looks like: 2018-10-03 14:38:05.000
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(ps[1], formatter);
|
||||
ts.add(localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli());
|
||||
current.add(Float.valueOf(ps[2]));
|
||||
voltage.add(Integer.valueOf(ps[3]));
|
||||
phase.add(Float.valueOf(ps[4]));
|
||||
}
|
||||
pst.setTimestamp(0, ts);
|
||||
pst.setFloat(1, current);
|
||||
pst.setInt(2, voltage);
|
||||
pst.setFloat(3, phase);
|
||||
pst.columnDataAddBatch();
|
||||
pst.columnDataExecuteBatch();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,20 +53,28 @@ public class SubscribeDemo {
|
|||
|
||||
// create consumer
|
||||
Properties properties = new Properties();
|
||||
properties.getProperty(TMQConstants.CONNECT_TYPE, "jni");
|
||||
properties.setProperty(TMQConstants.BOOTSTRAP_SERVERS, "127.0.0.1:6030");
|
||||
properties.setProperty(TMQConstants.CONNECT_USER, "root");
|
||||
properties.setProperty(TMQConstants.CONNECT_PASS, "taosdata");
|
||||
properties.setProperty(TMQConstants.MSG_WITH_TABLE_NAME, "true");
|
||||
properties.setProperty(TMQConstants.ENABLE_AUTO_COMMIT, "true");
|
||||
properties.setProperty(TMQConstants.GROUP_ID, "test");
|
||||
properties.setProperty(TMQConstants.AUTO_COMMIT_INTERVAL, "1000");
|
||||
properties.setProperty(TMQConstants.GROUP_ID, "test1");
|
||||
properties.setProperty(TMQConstants.CLIENT_ID, "1");
|
||||
properties.setProperty(TMQConstants.AUTO_OFFSET_RESET, "earliest");
|
||||
properties.setProperty(TMQConstants.VALUE_DESERIALIZER,
|
||||
"com.taos.example.MetersDeserializer");
|
||||
properties.setProperty(TMQConstants.VALUE_DESERIALIZER_ENCODING, "UTF-8");
|
||||
properties.setProperty(TMQConstants.EXPERIMENTAL_SNAPSHOT_ENABLE, "true");
|
||||
|
||||
// poll data
|
||||
try (TaosConsumer<Meters> consumer = new TaosConsumer<>(properties)) {
|
||||
consumer.subscribe(Collections.singletonList(TOPIC));
|
||||
while (!shutdown.get()) {
|
||||
ConsumerRecords<Meters> meters = consumer.poll(Duration.ofMillis(100));
|
||||
for (ConsumerRecord<Meters> recode : meters) {
|
||||
Meters meter = recode.value();
|
||||
for (ConsumerRecord<Meters> r : meters) {
|
||||
Meters meter = r.value();
|
||||
System.out.println(meter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.taos.example;
|
||||
|
||||
import com.taosdata.jdbc.tmq.ConsumerRecord;
|
||||
import com.taosdata.jdbc.tmq.ConsumerRecords;
|
||||
import com.taosdata.jdbc.tmq.TMQConstants;
|
||||
import com.taosdata.jdbc.tmq.TaosConsumer;
|
||||
|
@ -54,18 +55,26 @@ public class WebsocketSubscribeDemo {
|
|||
Properties properties = new Properties();
|
||||
properties.setProperty(TMQConstants.BOOTSTRAP_SERVERS, "127.0.0.1:6041");
|
||||
properties.setProperty(TMQConstants.CONNECT_TYPE, "ws");
|
||||
properties.setProperty(TMQConstants.CONNECT_USER, "root");
|
||||
properties.setProperty(TMQConstants.CONNECT_PASS, "taosdata");
|
||||
properties.setProperty(TMQConstants.AUTO_OFFSET_RESET, "earliest");
|
||||
properties.setProperty(TMQConstants.MSG_WITH_TABLE_NAME, "true");
|
||||
properties.setProperty(TMQConstants.ENABLE_AUTO_COMMIT, "true");
|
||||
properties.setProperty(TMQConstants.GROUP_ID, "test");
|
||||
properties.setProperty(TMQConstants.AUTO_COMMIT_INTERVAL, "1000");
|
||||
properties.setProperty(TMQConstants.GROUP_ID, "test2");
|
||||
properties.setProperty(TMQConstants.CLIENT_ID, "1");
|
||||
properties.setProperty(TMQConstants.VALUE_DESERIALIZER,
|
||||
"com.taos.example.MetersDeserializer");
|
||||
properties.setProperty(TMQConstants.VALUE_DESERIALIZER_ENCODING, "UTF-8");
|
||||
properties.setProperty(TMQConstants.EXPERIMENTAL_SNAPSHOT_ENABLE, "true");
|
||||
|
||||
// poll data
|
||||
try (TaosConsumer<Meters> consumer = new TaosConsumer<>(properties)) {
|
||||
consumer.subscribe(Collections.singletonList(TOPIC));
|
||||
while (!shutdown.get()) {
|
||||
ConsumerRecords<Meters> meters = consumer.poll(Duration.ofMillis(100));
|
||||
for (Meters meter : meters) {
|
||||
for (ConsumerRecord<Meters> r : meters) {
|
||||
Meters meter = (Meters) r.value();
|
||||
System.out.println(meter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速
|
|||
<dependency>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.2.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
|
|
@ -285,10 +285,10 @@ CREATE TOPIC topic_name AS DATABASE db_name;
|
|||
|
||||
| 参数名称 | 类型 | 参数说明 | 备注 |
|
||||
| :----------------------------: | :-----: | -------------------------------------------------------- | ------------------------------------------- |
|
||||
| `td.connect.ip` | string | 用于创建连接,同 `taos_connect` | 仅用于建立原生连接 |
|
||||
| `td.connect.user` | string | 用于创建连接,同 `taos_connect` | 仅用于建立原生连接 |
|
||||
| `td.connect.pass` | string | 用于创建连接,同 `taos_connect` | 仅用于建立原生连接 |
|
||||
| `td.connect.port` | integer | 用于创建连接,同 `taos_connect` | 仅用于建立原生连接 |
|
||||
| `td.connect.ip` | string | 服务端的 IP 地址 | |
|
||||
| `td.connect.user` | string | 用户名 | |
|
||||
| `td.connect.pass` | string | 密码 | |
|
||||
| `td.connect.port` | integer | 服务端的端口号 | |
|
||||
| `group.id` | string | 消费组 ID,同一消费组共享消费进度 | **必填项**。最大长度:192。 |
|
||||
| `client.id` | string | 客户端 ID | 最大长度:192。 |
|
||||
| `auto.offset.reset` | enum | 消费组订阅的初始位置 | <br />`earliest`: default;从头开始订阅; <br/>`latest`: 仅从最新数据开始订阅; <br/>`none`: 没有提交的 offset 无法订阅 |
|
||||
|
@ -321,10 +321,11 @@ tmq_conf_destroy(conf);
|
|||
</TabItem>
|
||||
<TabItem value="java" label="Java">
|
||||
|
||||
对于 Java 程序,使用如下配置项:
|
||||
对于 Java 程序,还可以使用如下配置项:
|
||||
|
||||
| 参数名称 | 类型 | 参数说明 |
|
||||
| ----------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `td.connect.type` | string | 连接类型,"jni" 指原生连接,"ws" 指 websocket 连接,默认值为 "jni" |
|
||||
| `bootstrap.servers` | string | 连接地址,如 `localhost:6030` |
|
||||
| `value.deserializer` | string | 值解析方法,使用此方法应实现 `com.taosdata.jdbc.tmq.Deserializer` 接口或继承 `com.taosdata.jdbc.tmq.ReferenceDeserializer` 类 |
|
||||
| `value.deserializer.encoding` | string | 指定字符串解析的字符集 | |
|
||||
|
@ -401,21 +402,6 @@ from taos.tmq import Consumer
|
|||
consumer = Consumer({"group.id": "local", "td.connect.ip": "127.0.0.1"})
|
||||
```
|
||||
|
||||
其中,`configs` 为 dict 类型,传递创建 Consumer 的参数。可以配置的参数有:
|
||||
|
||||
| 参数名称 | 类型 | 参数说明 | 备注 |
|
||||
|:------:|:----:|:-------:|:---:|
|
||||
| `td.connect.ip` | string | 用于创建连接||
|
||||
| `td.connect.user` | string | 用于创建连接||
|
||||
| `td.connect.pass` | string | 用于创建连接||
|
||||
| `td.connect.port` | string | 用于创建连接||
|
||||
| `group.id` | string | 消费组 ID,同一消费组共享消费进度 | **必填项**。最大长度:192 |
|
||||
| `client.id` | string | 客户端 ID | 最大长度:192 |
|
||||
| `msg.with.table.name` | string | 是否允许从消息中解析表名,不适用于列订阅 | 合法值:`true`, `false` |
|
||||
| `enable.auto.commit` | string | 启用自动提交 | 合法值:`true`, `false` |
|
||||
| `auto.commit.interval.ms` | string | 以毫秒为单位的自动提交时间间隔 | 默认值:5000 ms |
|
||||
| `auto.offset.reset` | string | 消费组订阅的初始位置 | 可选:`earliest`(default), `latest`, `none` |
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="Node.JS" value="Node.JS">
|
||||
|
|
|
@ -271,26 +271,90 @@ select max_vol(vol1,vol2,vol3,deviceid) from battery;
|
|||
|
||||
## 用 Python 语言实现 UDF
|
||||
|
||||
### 准备环境
|
||||
|
||||
1. 准备好 Python 运行环境
|
||||
|
||||
2. 安装 Python 包 `taospyudf`
|
||||
|
||||
```shell
|
||||
pip3 install taospyudf
|
||||
```
|
||||
|
||||
安装过程中会编译 C++ 源码,因此系统上要有 cmake 和 gcc。编译生成的 libtaospyudf.so 文件自动会被复制到 /usr/local/lib/ 目录,因此如果是非 root 用户,安装时需加 sudo。安装完可以检查这个目录是否有了这个文件:
|
||||
|
||||
```shell
|
||||
root@slave11 ~/udf $ ls -l /usr/local/lib/libtaos*
|
||||
-rw-r--r-- 1 root root 671344 May 24 22:54 /usr/local/lib/libtaospyudf.so
|
||||
```
|
||||
|
||||
然后执行命令
|
||||
```shell
|
||||
ldconfig
|
||||
```
|
||||
|
||||
3. 如果 Python UDF 程序执行时,通过 PYTHONPATH 引用其它的包,可以设置 taos.cfg 的 UdfdLdLibPath 变量为PYTHONPATH的内容
|
||||
|
||||
4. 启动 `taosd` 服务
|
||||
细节请参考 [快速开始](../../get-started)
|
||||
|
||||
### 接口定义
|
||||
|
||||
#### 接口概述
|
||||
|
||||
使用 Python 语言实现 UDF 时,需要实现规定的接口函数
|
||||
- 标量函数需要实现标量接口函数 process 。
|
||||
- 聚合函数需要实现聚合接口函数 start ,reduce ,finish。
|
||||
- 如果需要初始化,实现 init;如果需要清理工作,实现 destroy。
|
||||
|
||||
### 用 Python 实现标量函数
|
||||
#### 标量函数接口
|
||||
```Python
|
||||
def process(input: datablock) -> tuple[output_type]:
|
||||
```
|
||||
|
||||
说明:
|
||||
- input:datablock 类似二维矩阵,通过成员方法 data(row,col)返回位于 row 行,col 列的 python 对象
|
||||
- 返回值是一个 Python 对象元组,每个元素类型为输出类型。
|
||||
|
||||
#### 聚合函数接口
|
||||
```Python
|
||||
def start() -> bytes:
|
||||
def reduce(inputs: datablock, buf: bytes) -> bytes
|
||||
def finish(buf: bytes) -> output_type:
|
||||
```
|
||||
|
||||
说明:
|
||||
- 首先调用 start 生成最初结果 buffer
|
||||
- 然后输入数据会被分为多个行数据块,对每个数据块 inputs 和当前中间结果 buf 调用 reduce,得到新的中间结果
|
||||
- 最后再调用 finish 从中间结果 buf 产生最终输出,最终输出只能含 0 或 1 条数据。
|
||||
|
||||
#### 初始化和销毁接口
|
||||
```Python
|
||||
def init()
|
||||
def destroy()
|
||||
```
|
||||
|
||||
说明:
|
||||
- init 完成初始化工作
|
||||
- destroy 完成清理工作
|
||||
|
||||
### Python UDF 函数模板
|
||||
|
||||
#### 标量函数实现模板
|
||||
|
||||
标量函数实现模版如下
|
||||
|
||||
```Python
|
||||
def init():
|
||||
# initialization
|
||||
def destroy():
|
||||
# destroy
|
||||
def process(input: datablock) -> tuple[output_type]:
|
||||
# process input datablock,
|
||||
# datablock.data(row, col) is to access the python object in location(row,col)
|
||||
# return tuple object consisted of object of type outputtype
|
||||
```
|
||||
|
||||
### 用 Python 实现聚合函数
|
||||
注意:定义标题函数最重要是要实现 process 函数,同时必须定义 init 和 destroy 函数即使什么都不做
|
||||
|
||||
#### 聚合函数实现模板
|
||||
|
||||
聚合函数实现模版如下
|
||||
```Python
|
||||
|
@ -303,41 +367,16 @@ def start() -> bytes:
|
|||
def reduce(inputs: datablock, buf: bytes) -> bytes
|
||||
# deserialize buf to state
|
||||
# reduce the inputs and state into new_state.
|
||||
# use inputs.data(i,j) to access python ojbect of location(i,j)
|
||||
# use inputs.data(i,j) to access python object of location(i,j)
|
||||
# serialize new_state into new_state_bytes
|
||||
return new_state_bytes
|
||||
def finish(buf: bytes) -> output_type:
|
||||
#return obj of type outputtype
|
||||
```
|
||||
|
||||
### Python UDF 接口函数定义
|
||||
注意:定义聚合函数最重要是要实现 start, reduce 和 finish,且必须定义 init 和 destroy 函数。start 生成最初结果 buffer,然后输入数据会被分为多个行数据块,对每个数据块 inputs 和当前中间结果 buf 调用 reduce,得到新的中间结果,最后再调用 finish 从中间结果 buf 产生最终输出。
|
||||
|
||||
#### 标量函数接口
|
||||
```Python
|
||||
def process(input: datablock) -> tuple[output_type]:
|
||||
```
|
||||
- input:datablock 类似二维矩阵,通过成员方法 data(row,col)返回位于 row 行,col 列的 python 对象
|
||||
- 返回值是一个 Python 对象元组,每个元素类型为输出类型。
|
||||
|
||||
#### 聚合函数接口
|
||||
```Python
|
||||
def start() -> bytes:
|
||||
def reduce(inputs: datablock, buf: bytes) -> bytes
|
||||
def finish(buf: bytes) -> output_type:
|
||||
```
|
||||
|
||||
首先调用 start 生成最初结果 buffer,然后输入数据会被分为多个行数据块,对每个数据块 inputs 和当前中间结果 buf 调用 reduce,得到新的中间结果,最后再调用 finish 从中间结果 buf 产生最终输出,最终输出只能含 0 或 1 条数据。
|
||||
|
||||
|
||||
#### 初始化和销毁接口
|
||||
```Python
|
||||
def init()
|
||||
def destroy()
|
||||
```
|
||||
|
||||
其中 init 完成初始化工作。 destroy 完成清理工作。如果没有初始化工作,无需定义 init 函数。如果没有清理工作,无需定义 destroy 函数。
|
||||
|
||||
### Python 和 TDengine之间的数据类型映射
|
||||
### 数据类型映射
|
||||
|
||||
下表描述了TDengine SQL数据类型和Python数据类型的映射。任何类型的NULL值都映射成Python的None值。
|
||||
|
||||
|
@ -351,15 +390,461 @@ def destroy()
|
|||
|TIMESTAMP | int |
|
||||
|JSON and other types | 不支持 |
|
||||
|
||||
### Python UDF 环境的安装
|
||||
1. 安装 taospyudf 包。此包执行Python UDF程序。
|
||||
```bash
|
||||
sudo pip install taospyudf
|
||||
ldconfig
|
||||
```
|
||||
2. 如果 Python UDF 程序执行时,通过 PYTHONPATH 引用其它的包,可以设置 taos.cfg 的 UdfdLdLibPath 变量为PYTHONPATH的内容
|
||||
### 开发指南
|
||||
|
||||
### Python UDF 示例代码
|
||||
本文内容由浅入深包括 4 个示例程序:
|
||||
1. 定义一个只接收一个整数的标量函数: 输入 n, 输出 ln(n^2 + 1)。
|
||||
2. 定义一个接收 n 个整数的标量函数, 输入 (x1, x2, ..., xn), 输出每个值和它们的序号的乘积的和: x1 + 2 * x2 + ... + n * xn。
|
||||
3. 定义一个标量函数,输入一个时间戳,输出距离这个时间最近的下一个周日。完成这个函数要用到第三方库 moment。我们在这个示例中讲解使用第三方库的注意事项。
|
||||
4. 定义一个聚合函数,计算某一列最大值和最小值的差, 也就是实现 TDengien 内置的 spread 函数。
|
||||
同时也包含大量实用的 debug 技巧。
|
||||
本文假设你用的是 Linux 系统,且已安装好了 TDengine 3.0.4.0+ 和 Python 3.x。
|
||||
|
||||
注意:**UDF 内无法通过 print 函数输出日志,需要自己写文件或用 python 内置的 logging 库写文件**。
|
||||
|
||||
#### 最简单的 UDF
|
||||
|
||||
编写一个只接收一个整数的 UDF 函数: 输入 n, 输出 ln(n^2 + 1)。
|
||||
首先编写一个 Python 文件,存在系统某个目录,比如 /root/udf/myfun.py 内容如下
|
||||
|
||||
```python
|
||||
from math import log
|
||||
|
||||
def init():
|
||||
pass
|
||||
|
||||
def destroy():
|
||||
pass
|
||||
|
||||
def process(block):
|
||||
rows, _ = block.shape()
|
||||
return [log(block.data(i, 0) ** 2 + 1) for i in range(rows)]
|
||||
```
|
||||
|
||||
这个文件包含 3 个函数, init 和 destroy 都是空函数,它们是 UDF 的生命周期函数,即使什么都不做也要定义。最关键的是 process 函数, 它接受一个数据块,这个数据块对象有两个方法:
|
||||
1. shape() 返回数据块的行数和列数
|
||||
2. data(i, j) 返回 i 行 j 列的数据
|
||||
标量函数的 process 方法传人的数据块有多少行,就需要返回多少个数据。上述代码中我们忽略的列数,因为我们只想对每行的第一个数做计算。
|
||||
接下来我们创建对应的 UDF 函数,在 TDengine CLI 中执行下面语句:
|
||||
|
||||
```sql
|
||||
create function myfun as '/root/udf/myfun.py' outputtype double language 'Python'
|
||||
```
|
||||
其输出如下
|
||||
|
||||
```shell
|
||||
taos> create function myfun as '/root/udf/myfun.py' outputtype double language 'Python';
|
||||
Create OK, 0 row(s) affected (0.005202s)
|
||||
```
|
||||
|
||||
看起来很顺利,接下来 show 一下系统中所有的自定义函数,确认创建成功:
|
||||
|
||||
```text
|
||||
taos> show functions;
|
||||
name |
|
||||
=================================
|
||||
myfun |
|
||||
Query OK, 1 row(s) in set (0.005767s)
|
||||
```
|
||||
|
||||
接下来就来测试一下这个函数,测试之前先执行下面的 SQL 命令,制造些测试数据,在 TDengine CLI 中执行下述命令
|
||||
|
||||
```sql
|
||||
create database test;
|
||||
create table t(ts timestamp, v1 int, v2 int, v3 int);
|
||||
insert into t values('2023-05-01 12:13:14', 1, 2, 3);
|
||||
insert into t values('2023-05-03 08:09:10', 2, 3, 4);
|
||||
insert into t values('2023-05-10 07:06:05', 3, 4, 5);
|
||||
```
|
||||
|
||||
测试 myfun 函数:
|
||||
|
||||
```sql
|
||||
taos> select myfun(v1, v2) from t;
|
||||
|
||||
DB error: udf function execution failure (0.011088s)
|
||||
```
|
||||
|
||||
不幸的是执行失败了,什么原因呢?
|
||||
查看 udfd 进程的日志
|
||||
|
||||
```shell
|
||||
tail -10 /var/log/taos/udfd.log
|
||||
```
|
||||
|
||||
发现以下错误信息:
|
||||
|
||||
```text
|
||||
05/24 22:46:28.733545 01665799 UDF ERROR can not load library libtaospyudf.so. error: operation not permitted
|
||||
05/24 22:46:28.733561 01665799 UDF ERROR can not load python plugin. lib path libtaospyudf.so
|
||||
```
|
||||
|
||||
错误很明确:没有加载到 Python 插件 libtaospyudf.so,如果遇到此错误,请参考前面的准备环境一节。
|
||||
|
||||
修复环境错误后再次执行,如下:
|
||||
|
||||
```sql
|
||||
taos> select myfun(v1) from t;
|
||||
myfun(v1) |
|
||||
============================
|
||||
0.693147181 |
|
||||
1.609437912 |
|
||||
2.302585093 |
|
||||
```
|
||||
|
||||
至此,我们完成了第一个 UDF 😊,并学会了简单的 debug 方法。
|
||||
|
||||
#### 示例二:异常处理
|
||||
|
||||
上面的 myfun 虽然测试测试通过了,但是有两个缺点:
|
||||
|
||||
1. 这个标量函数只接受 1 列数据作为输入,如果用户传入了多列也不会抛异常。
|
||||
|
||||
```sql
|
||||
taos> select myfun(v1, v2) from t;
|
||||
myfun(v1, v2) |
|
||||
============================
|
||||
0.693147181 |
|
||||
1.609437912 |
|
||||
2.302585093 |
|
||||
```
|
||||
|
||||
2. 没有处理 null 值。我们期望如果输入有 null,则会抛异常终止执行。
|
||||
因此 process 函数改进如下:
|
||||
|
||||
```python
|
||||
def process(block):
|
||||
rows, cols = block.shape()
|
||||
if cols > 1:
|
||||
raise Exception(f"require 1 parameter but given {cols}")
|
||||
return [ None if block.data(i, 0) is None else log(block.data(i, 0) ** 2 + 1) for i in range(rows)]
|
||||
```
|
||||
|
||||
然后执行下面的语句更新已有的 UDF:
|
||||
|
||||
```sql
|
||||
create or replace function myfun as '/root/udf/myfun.py' outputtype double language 'Python';
|
||||
```
|
||||
|
||||
再传入 myfun 两个参数,就会执行失败了
|
||||
|
||||
```sql
|
||||
taos> select myfun(v1, v2) from t;
|
||||
|
||||
DB error: udf function execution failure (0.014643s)
|
||||
```
|
||||
|
||||
但遗憾的是我们自定义的异常信息没有展示给用户,而是在插件的日志文件 /var/log/taos/taospyudf.log 中:
|
||||
|
||||
```text
|
||||
2023-05-24 23:21:06.790 ERROR [1666188] [doPyUdfScalarProc@507] call pyUdfScalar proc function. context 0x7faade26d180. error: Exception: require 1 parameter but given 2
|
||||
|
||||
At:
|
||||
/var/lib/taos//.udf/myfun_3_1884e1281d9.py(12): process
|
||||
|
||||
```
|
||||
|
||||
至此,我们学会了如何更新 UDF,并查看 UDF 输出的错误日志。
|
||||
(注:如果 UDF 更新后未生效,在 TDengine 3.0.5.0 以前(不含)的版本中需要重启 taosd,在 3.0.5.0 及之后的版本中不需要重启 taosd 即可生效。)
|
||||
|
||||
#### 示例三: 接收 n 个参数的 UDF
|
||||
|
||||
编写一个 UDF:输入(x1, x2, ..., xn), 输出每个值和它们的序号的乘积的和: 1 * x1 + 2 * x2 + ... + n * xn。如果 x1 至 xn 中包含 null,则结果为 null。
|
||||
这个示例与示例一的区别是,可以接受任意多列作为输入,且要处理每一列的值。编写 UDF 文件 /root/udf/nsum.py:
|
||||
|
||||
```python
|
||||
def init():
|
||||
pass
|
||||
|
||||
|
||||
def destroy():
|
||||
pass
|
||||
|
||||
|
||||
def process(block):
|
||||
rows, cols = block.shape()
|
||||
result = []
|
||||
for i in range(rows):
|
||||
total = 0
|
||||
for j in range(cols):
|
||||
v = block.data(i, j)
|
||||
if v is None:
|
||||
total = None
|
||||
break
|
||||
total += (j + 1) * block.data(i, j)
|
||||
result.append(total)
|
||||
return result
|
||||
```
|
||||
|
||||
创建 UDF:
|
||||
|
||||
```sql
|
||||
create function nsum as '/root/udf/nsum.py' outputtype double language 'Python';
|
||||
```
|
||||
|
||||
测试 UDF:
|
||||
|
||||
```sql
|
||||
taos> insert into t values('2023-05-25 09:09:15', 6, null, 8);
|
||||
Insert OK, 1 row(s) affected (0.003675s)
|
||||
|
||||
taos> select ts, v1, v2, v3, nsum(v1, v2, v3) from t;
|
||||
ts | v1 | v2 | v3 | nsum(v1, v2, v3) |
|
||||
================================================================================================
|
||||
2023-05-01 12:13:14.000 | 1 | 2 | 3 | 14.000000000 |
|
||||
2023-05-03 08:09:10.000 | 2 | 3 | 4 | 20.000000000 |
|
||||
2023-05-10 07:06:05.000 | 3 | 4 | 5 | 26.000000000 |
|
||||
2023-05-25 09:09:15.000 | 6 | NULL | 8 | NULL |
|
||||
Query OK, 4 row(s) in set (0.010653s)
|
||||
```
|
||||
|
||||
#### 示例四:使用第三方库
|
||||
|
||||
编写一个 UDF,输入一个时间戳,输出距离这个时间最近的下一个周日。比如今天是 2023-05-25, 则下一个周日是 2023-05-28。
|
||||
完成这个函数要用到第三方库 momen。先安装这个库:
|
||||
|
||||
```shell
|
||||
pip3 install moment
|
||||
```
|
||||
|
||||
然后编写 UDF 文件 /root/udf/nextsunday.py
|
||||
|
||||
```python
|
||||
import moment
|
||||
|
||||
|
||||
def init():
|
||||
pass
|
||||
|
||||
|
||||
def destroy():
|
||||
pass
|
||||
|
||||
|
||||
def process(block):
|
||||
rows, cols = block.shape()
|
||||
if cols > 1:
|
||||
raise Exception("require only 1 parameter")
|
||||
if not type(block.data(0, 0)) is int:
|
||||
raise Exception("type error")
|
||||
return [moment.unix(block.data(i, 0)).replace(weekday=7).format('YYYY-MM-DD')
|
||||
for i in range(rows)]
|
||||
```
|
||||
|
||||
UDF 框架会将 TDengine 的 timestamp 类型映射为 Python 的 int 类型,所以这个函数只接受一个表示毫秒数的整数。process 方法先做参数检查,然后用 moment 包替换时间的星期为星期日,最后格式化输出。输出的字符串长度是固定的10个字符长,因此可以这样创建 UDF 函数:
|
||||
|
||||
```sql
|
||||
create function nextsunday as '/root/udf/nextsunday.py' outputtype binary(10) language 'Python';
|
||||
```
|
||||
|
||||
此时测试函数,如果你是用 systemctl 启动的 taosd,肯定会遇到错误:
|
||||
|
||||
```sql
|
||||
taos> select ts, nextsunday(ts) from t;
|
||||
|
||||
DB error: udf function execution failure (1.123615s)
|
||||
```
|
||||
|
||||
```shell
|
||||
tail -20 taospyudf.log
|
||||
2023-05-25 11:42:34.541 ERROR [1679419] [PyUdf::PyUdf@217] py udf load module failure. error ModuleNotFoundError: No module named 'moment'
|
||||
```
|
||||
|
||||
这是因为 “moment” 所在位置不在 python udf 插件默认的库搜索路径中。怎么确认这一点呢?通过以下命令搜索 taospyudf.log:
|
||||
|
||||
```shell
|
||||
grep 'sys path' taospyudf.log | tail -1
|
||||
```
|
||||
|
||||
输出如下
|
||||
|
||||
```text
|
||||
2023-05-25 10:58:48.554 INFO [1679419] [doPyOpen@592] python sys path: ['', '/lib/python38.zip', '/lib/python3.8', '/lib/python3.8/lib-dynload', '/lib/python3/dist-packages', '/var/lib/taos//.udf']
|
||||
```
|
||||
|
||||
发现 python udf 插件默认搜索的第三方库安装路径是: /lib/python3/dist-packages,而 moment 默认安装到了 /usr/local/lib/python3.8/dist-packages。下面我们修改 python udf 插件默认的库搜索路径。
|
||||
先打开 python3 命令行,查看当前的 sys.path
|
||||
|
||||
```python
|
||||
>>> import sys
|
||||
>>> ":".join(sys.path)
|
||||
'/usr/lib/python3.8:/usr/lib/python3.8/lib-dynload:/usr/local/lib/python3.8/dist-packages:/usr/lib/python3/dist-packages'
|
||||
```
|
||||
|
||||
复制上面脚本的输出的字符串,然后编辑 /var/taos/taos.cfg 加入以下配置:
|
||||
|
||||
```shell
|
||||
UdfdLdLibPath /usr/lib/python3.8:/usr/lib/python3.8/lib-dynload:/usr/local/lib/python3.8/dist-packages:/usr/lib/python3/dist-packages
|
||||
```
|
||||
|
||||
保存后执行 systemctl restart taosd, 再测试就不报错了:
|
||||
|
||||
```sql
|
||||
taos> select ts, nextsunday(ts) from t;
|
||||
ts | nextsunday(ts) |
|
||||
===========================================
|
||||
2023-05-01 12:13:14.000 | 2023-05-07 |
|
||||
2023-05-03 08:09:10.000 | 2023-05-07 |
|
||||
2023-05-10 07:06:05.000 | 2023-05-14 |
|
||||
2023-05-25 09:09:15.000 | 2023-05-28 |
|
||||
Query OK, 4 row(s) in set (1.011474s)
|
||||
```
|
||||
|
||||
#### 示例五:聚合函数
|
||||
|
||||
编写一个聚合函数,计算某一列最大值和最小值的差。
|
||||
聚合函数与标量函数的区别是:标量函数是多行输入对应多个输出,聚合函数是多行输入对应一个输出。聚合函数的执行过程有点像经典的 map-reduce 框架的执行过程,框架把数据分成若干块,每个 mapper 处理一个块,reducer 再把 mapper 的结果做聚合。不一样的地方在于,对于 TDengine Python UDF 中的 reduce 函数既有 map 的功能又有 reduce 的功能。reduce 函数接受两个参数:一个是自己要处理的数据,一个是别的任务执行 reduce 函数的处理结果。如下面的示例 /root/udf/myspread.py:
|
||||
|
||||
```python
|
||||
import io
|
||||
import math
|
||||
import pickle
|
||||
|
||||
LOG_FILE: io.TextIOBase = None
|
||||
|
||||
|
||||
def init():
|
||||
global LOG_FILE
|
||||
LOG_FILE = open("/var/log/taos/spread.log", "wt")
|
||||
log("init function myspead success")
|
||||
|
||||
|
||||
def log(o):
|
||||
LOG_FILE.write(str(o) + '\n')
|
||||
|
||||
|
||||
def destroy():
|
||||
log("close log file: spread.log")
|
||||
LOG_FILE.close()
|
||||
|
||||
|
||||
def start():
|
||||
return pickle.dumps((-math.inf, math.inf))
|
||||
|
||||
|
||||
def reduce(block, buf):
|
||||
max_number, min_number = pickle.loads(buf)
|
||||
log(f"initial max_number={max_number}, min_number={min_number}")
|
||||
rows, _ = block.shape()
|
||||
for i in range(rows):
|
||||
v = block.data(i, 0)
|
||||
if v > max_number:
|
||||
log(f"max_number={v}")
|
||||
max_number = v
|
||||
if v < min_number:
|
||||
log(f"min_number={v}")
|
||||
min_number = v
|
||||
return pickle.dumps((max_number, min_number))
|
||||
|
||||
|
||||
def finish(buf):
|
||||
max_number, min_number = pickle.loads(buf)
|
||||
return max_number - min_number
|
||||
```
|
||||
|
||||
在这个示例中我们不光定义了一个聚合函数,还添加记录执行日志的功能,讲解如下:
|
||||
1. init 函数不再是空函数,而是打开了一个文件用于写执行日志
|
||||
2. log 函数是记录日志的工具,自动将传入的对象转成字符串,加换行符输出
|
||||
3. destroy 函数用来在执行结束关闭文件
|
||||
4. start 返回了初始的 buffer,用来存聚合函数的中间结果,我们把最大值初始化为负无穷大,最小值初始化为正无穷大
|
||||
5. reduce 处理每个数据块并聚合结果
|
||||
6. finish 函数将最终的 buffer 转换成最终的输出
|
||||
执行下面的 SQL语句创建对应的 UDF:
|
||||
|
||||
```sql
|
||||
create or replace aggregate function myspread as '/root/udf/myspread.py' outputtype double bufsize 128 language 'Python';
|
||||
```
|
||||
|
||||
这个 SQL 语句与创建标量函数的 SQL 语句有两个重要区别:
|
||||
1. 增加了 aggregate 关键字
|
||||
2. 增加了 bufsize 关键字,用来指定存储中间结果的内存大小,这个数值可以大于实际使用的数值。本例中间结果是两个浮点数组成的 tuple,序列化后实际占用大小只有 32 个字节,但指定的 bufsize 是128,可以用 python 命令行打印实际占用的字节数
|
||||
|
||||
```python
|
||||
>>> len(pickle.dumps((12345.6789, 23456789.9877)))
|
||||
32
|
||||
```
|
||||
|
||||
测试这个函数,可以看到 myspread 的输出结果和内置的 spread 函数的输出结果是一致的。
|
||||
|
||||
```sql
|
||||
taos> select myspread(v1) from t;
|
||||
myspread(v1) |
|
||||
============================
|
||||
5.000000000 |
|
||||
Query OK, 1 row(s) in set (0.013486s)
|
||||
|
||||
taos> select spread(v1) from t;
|
||||
spread(v1) |
|
||||
============================
|
||||
5.000000000 |
|
||||
Query OK, 1 row(s) in set (0.005501s)
|
||||
```
|
||||
|
||||
最后,查看我们自己打印的执行日志,从日志可以看出,reduce 函数被执行了 3 次。执行过程中 max 值被更新了 4 次, min 值只被更新 1 次。
|
||||
|
||||
```shell
|
||||
root@slave11 /var/log/taos $ cat spread.log
|
||||
init function myspead success
|
||||
initial max_number=-inf, min_number=inf
|
||||
max_number=1
|
||||
min_number=1
|
||||
initial max_number=1, min_number=1
|
||||
max_number=2
|
||||
max_number=3
|
||||
initial max_number=3, min_number=1
|
||||
max_number=6
|
||||
close log file: spread.log
|
||||
```
|
||||
|
||||
通过这个示例,我们学会了如何定义聚合函数,并打印自定义的日志信息。
|
||||
|
||||
### SQL 命令
|
||||
|
||||
1. 创建标量函数的语法
|
||||
|
||||
```sql
|
||||
CREATE FUNCTION function_name AS library_path OUTPUTTYPE output_type LANGUAGE 'Python';
|
||||
```
|
||||
|
||||
2. 创建聚合函数的语法
|
||||
|
||||
```sql
|
||||
CREATE AGGREGATE FUNCTION function_name library_path OUTPUTTYPE output_type LANGUAGE 'Python';
|
||||
```
|
||||
|
||||
3. 更新标量函数
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE FUNCTION function_name AS OUTPUTTYPE int LANGUAGE 'Python';
|
||||
```
|
||||
|
||||
4. 更新聚合函数
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE AGGREGATE FUNCTION function_name AS OUTPUTTYPE BUFSIZE buf_size int LANGUAGE 'Python';
|
||||
```
|
||||
|
||||
注意:如果加了 “AGGREGATE” 关键字,更新之后函数将被当作聚合函数,无论之前是什么类型的函数。相反,如果没有加 “AGGREGATE” 关键字,更新之后的函数将被当作标量函数,无论之前是什么类型的函数。
|
||||
|
||||
5. 查看函数信息
|
||||
|
||||
同名的 UDF 每更新一次,版本号会增加 1。
|
||||
|
||||
```sql
|
||||
select * from ins_functions \G;
|
||||
```
|
||||
|
||||
6. 查看和删除已有的 UDF
|
||||
|
||||
```sql
|
||||
SHOW functions;
|
||||
DROP FUNCTION function_name;
|
||||
```
|
||||
|
||||
|
||||
上面的命令可以查看 UDF 的完整信息
|
||||
|
||||
### 更多 Python UDF 示例代码
|
||||
#### 标量函数示例 [pybitand](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pybitand.py)
|
||||
|
||||
pybitand 实现多列的按位与功能。如果只有一列,返回这一列。pybitand 忽略空值。
|
||||
|
@ -386,6 +871,17 @@ pyl2norm 实现了输入列的所有数据的二阶范数,即对每个数据
|
|||
|
||||
</details>
|
||||
|
||||
#### 聚合函数示例 [pycumsum](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pycumsum.py)
|
||||
|
||||
pycumsum 使用 numpy 计算输入列所有数据的累积和。
|
||||
<details>
|
||||
<summary>pycumsum.py</summary>
|
||||
|
||||
```c
|
||||
{{#include tests/script/sh/pycumsum.py}}
|
||||
```
|
||||
|
||||
</details>
|
||||
## 管理和使用 UDF
|
||||
在使用 UDF 之前需要先将其加入到 TDengine 系统中。关于如何管理和使用 UDF,请参考[管理和使用 UDF](../12-taos-sql/26-udf.md)
|
||||
|
||||
|
|
|
@ -962,6 +962,7 @@ statement.executeUpdate("create topic if not exists topic_speed as select ts, sp
|
|||
|
||||
```java
|
||||
Properties config = new Properties();
|
||||
config.setProperty("bootstrap.servers", "localhost:6030");
|
||||
config.setProperty("enable.auto.commit", "true");
|
||||
config.setProperty("group.id", "group1");
|
||||
config.setProperty("value.deserializer", "com.taosdata.jdbc.tmq.ConsumerTest.ResultDeserializer");
|
||||
|
@ -969,12 +970,14 @@ config.setProperty("value.deserializer", "com.taosdata.jdbc.tmq.ConsumerTest.Res
|
|||
TaosConsumer consumer = new TaosConsumer<>(config);
|
||||
```
|
||||
|
||||
- bootstrap.servers: TDengine 服务端所在的`ip:port`,如果使用 WebSocket 连接,则为 taosAdapter 所在的`ip:port`。
|
||||
- enable.auto.commit: 是否允许自动提交。
|
||||
- group.id: consumer: 所在的 group。
|
||||
- value.deserializer: 结果集反序列化方法,可以继承 `com.taosdata.jdbc.tmq.ReferenceDeserializer`,并指定结果集 bean,实现反序列化。也可以继承 `com.taosdata.jdbc.tmq.Deserializer`,根据 SQL 的 resultSet 自定义反序列化方式。
|
||||
- td.connect.type: 连接方式。jni:表示使用动态库连接的方式,ws/WebSocket:表示使用 WebSocket 进行数据通信。默认为 jni 方式。
|
||||
- httpConnectTimeout:创建连接超时参数,单位 ms,默认为 5000 ms。仅在 WebSocket 连接下有效。
|
||||
- messageWaitTimeout:数据传输超时参数,单位 ms,默认为 10000 ms。仅在 WebSocket 连接下有效。
|
||||
- httpConnectTimeout: 创建连接超时参数,单位 ms,默认为 5000 ms。仅在 WebSocket 连接下有效。
|
||||
- messageWaitTimeout: 数据传输超时参数,单位 ms,默认为 10000 ms。仅在 WebSocket 连接下有效。
|
||||
- httpPoolSize: 同一个连接下最大并行请求数。仅在 WebSocket 连接下有效。
|
||||
其他参数请参考:[Consumer 参数列表](../../../develop/tmq#创建-consumer-以及consumer-group)
|
||||
|
||||
#### 订阅消费数据
|
||||
|
@ -1016,10 +1019,19 @@ public abstract class ConsumerLoop {
|
|||
|
||||
public ConsumerLoop() throws SQLException {
|
||||
Properties config = new Properties();
|
||||
config.setProperty("td.connect.type", "jni");
|
||||
config.setProperty("bootstrap.servers", "localhost:6030");
|
||||
config.setProperty("td.connect.user", "root");
|
||||
config.setProperty("td.connect.pass", "taosdata");
|
||||
config.setProperty("auto.offset.reset", "earliest");
|
||||
config.setProperty("msg.with.table.name", "true");
|
||||
config.setProperty("enable.auto.commit", "true");
|
||||
config.setProperty("auto.commit.interval.ms", "1000");
|
||||
config.setProperty("group.id", "group1");
|
||||
config.setProperty("client.id", "1");
|
||||
config.setProperty("value.deserializer", "com.taosdata.jdbc.tmq.ConsumerTest.ConsumerLoop$ResultDeserializer");
|
||||
config.setProperty("value.deserializer.encoding", "UTF-8");
|
||||
config.setProperty("experimental.snapshot.enable", "true");
|
||||
|
||||
this.consumer = new TaosConsumer<>(config);
|
||||
this.topics = Collections.singletonList("topic_speed");
|
||||
|
@ -1093,12 +1105,19 @@ public abstract class ConsumerLoop {
|
|||
|
||||
public ConsumerLoop() throws SQLException {
|
||||
Properties config = new Properties();
|
||||
config.setProperty("bootstrap.servers", "localhost:6041");
|
||||
config.setProperty("td.connect.type", "ws");
|
||||
config.setProperty("bootstrap.servers", "localhost:6041");
|
||||
config.setProperty("td.connect.user", "root");
|
||||
config.setProperty("td.connect.pass", "taosdata");
|
||||
config.setProperty("auto.offset.reset", "earliest");
|
||||
config.setProperty("msg.with.table.name", "true");
|
||||
config.setProperty("enable.auto.commit", "true");
|
||||
config.setProperty("auto.commit.interval.ms", "1000");
|
||||
config.setProperty("group.id", "group2");
|
||||
config.setProperty("client.id", "1");
|
||||
config.setProperty("value.deserializer", "com.taosdata.jdbc.tmq.ConsumerTest.ConsumerLoop$ResultDeserializer");
|
||||
config.setProperty("value.deserializer.encoding", "UTF-8");
|
||||
config.setProperty("experimental.snapshot.enable", "true");
|
||||
|
||||
this.consumer = new TaosConsumer<>(config);
|
||||
this.topics = Collections.singletonList("topic_speed");
|
||||
|
|
|
@ -362,7 +362,7 @@ TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线
|
|||
|
||||
##### TaosConnection 类的使用
|
||||
|
||||
`TaosConnection` 类既包含对 PEP249 Connection 接口的实现(如:`cursor`方法和 `close` 方法),也包含很多扩展功能(如: `execute`、 `query`、`schemaless_insert` 和 `subscribe` 方法。
|
||||
类似上文介绍的使用方法,增加 `req_id` 参数。
|
||||
|
||||
```python title="execute 方法"
|
||||
{{#include docs/examples/python/connection_usage_native_reference_with_req_id.py:insert}}
|
||||
|
@ -372,13 +372,9 @@ TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线
|
|||
{{#include docs/examples/python/connection_usage_native_reference_with_req_id.py:query}}
|
||||
```
|
||||
|
||||
:::tip
|
||||
查询结果只能获取一次。比如上面的示例中 `fetch_all()` 和 `fetch_all_into_dict()` 只能用一个。重复获取得到的结果为空列表。
|
||||
:::
|
||||
|
||||
##### TaosResult 类的使用
|
||||
|
||||
上面 `TaosConnection` 类的使用示例中,我们已经展示了两种获取查询结果的方法: `fetch_all()` 和 `fetch_all_into_dict()`。除此之外 `TaosResult` 还提供了按行迭代(`rows_iter`)或按数据块迭代(`blocks_iter`)结果集的方法。在查询数据量较大的场景,使用这两个方法会更高效。
|
||||
类似上文介绍的使用方法,增加 `req_id` 参数。
|
||||
|
||||
```python title="blocks_iter 方法"
|
||||
{{#include docs/examples/python/result_set_with_req_id_examples.py}}
|
||||
|
@ -391,14 +387,11 @@ TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线
|
|||
{{#include docs/examples/python/cursor_usage_native_reference_with_req_id.py}}
|
||||
```
|
||||
|
||||
:::note
|
||||
TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线程的场景下,这个游标实例必须保持线程独享,不能跨线程共享使用,否则会导致返回结果出现错误。
|
||||
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="rest" label="REST 连接">
|
||||
|
||||
类似上文介绍的使用方法,增加 `req_id` 参数。
|
||||
|
||||
##### TaosRestCursor 类的使用
|
||||
|
||||
`TaosRestCursor` 类是对 PEP249 Cursor 接口的实现。
|
||||
|
@ -420,8 +413,11 @@ TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线
|
|||
|
||||
对于 `sql()` 方法更详细的介绍, 请参考 [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html)。
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="websocket" label="WebSocket 连接">
|
||||
|
||||
类似上文介绍的使用方法,增加 `req_id` 参数。
|
||||
|
||||
```python
|
||||
{{#include docs/examples/python/connect_websocket_with_req_id_examples.py:basic}}
|
||||
```
|
||||
|
|
|
@ -45,7 +45,7 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器
|
|||
| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||
| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||
| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||
| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||
| **数据订阅(TMQ)** | 暂不支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||
| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||
| **DataFrame** | 不支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 |
|
||||
|
||||
|
|
|
@ -121,6 +121,8 @@ alter_database_option: {
|
|||
| WAL_LEVEL value
|
||||
| WAL_FSYNC_PERIOD value
|
||||
| KEEP value
|
||||
| WAL_RETENTION_PERIOD value
|
||||
| WAL_RETENTION_SIZE value
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -869,10 +869,15 @@ FIRST(expr)
|
|||
### INTERP
|
||||
|
||||
```sql
|
||||
INTERP(expr)
|
||||
INTERP(expr [, ignore_null_values])
|
||||
|
||||
ignore_null_values: {
|
||||
0
|
||||
| 1
|
||||
}
|
||||
```
|
||||
|
||||
**功能说明**:返回指定时间截面指定列的记录值或插值。
|
||||
**功能说明**:返回指定时间截面指定列的记录值或插值。ignore_null_values 参数的值可以是 0 或 1,为 1 时表示忽略 NULL 值, 缺省值为0。
|
||||
|
||||
**返回数据类型**:同字段类型。
|
||||
|
||||
|
@ -996,7 +1001,6 @@ SAMPLE(expr, k)
|
|||
**使用说明**:
|
||||
|
||||
- 不能参与表达式计算;该函数可以应用在普通表和超级表上;
|
||||
- 使用在超级表上的时候,需要搭配 PARTITION by tbname 使用,将结果强制规约到单个时间线。
|
||||
|
||||
|
||||
### TAIL
|
||||
|
@ -1075,7 +1079,6 @@ CSUM(expr)
|
|||
|
||||
- 不支持 +、-、*、/ 运算,如 csum(col1) + csum(col2)。
|
||||
- 只能与聚合(Aggregation)函数一起使用。 该函数可以应用在普通表和超级表上。
|
||||
- 使用在超级表上的时候,需要搭配 PARTITION BY tbname使用,将结果强制规约到单个时间线。
|
||||
|
||||
|
||||
### DERIVATIVE
|
||||
|
@ -1099,7 +1102,6 @@ ignore_negative: {
|
|||
|
||||
**使用说明**:
|
||||
|
||||
- DERIVATIVE 函数可以在由 PARTITION BY 划分出单独时间线的情况下用于超级表(也即 PARTITION BY tbname)。
|
||||
- 可以与选择相关联的列一起使用。 例如: select \_rowts, DERIVATIVE() from。
|
||||
|
||||
### DIFF
|
||||
|
@ -1162,7 +1164,6 @@ MAVG(expr, k)
|
|||
|
||||
- 不支持 +、-、*、/ 运算,如 mavg(col1, k1) + mavg(col2, k1);
|
||||
- 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用;
|
||||
- 使用在超级表上的时候,需要搭配 PARTITION BY tbname使用,将结果强制规约到单个时间线。
|
||||
|
||||
|
||||
### STATECOUNT
|
||||
|
@ -1188,7 +1189,6 @@ STATECOUNT(expr, oper, val)
|
|||
|
||||
**使用说明**:
|
||||
|
||||
- 该函数可以应用在普通表上,在由 PARTITION BY 划分出单独时间线的情况下用于超级表(也即 PARTITION BY tbname)
|
||||
- 不能和窗口操作一起使用,例如 interval/state_window/session_window。
|
||||
|
||||
|
||||
|
@ -1216,7 +1216,6 @@ STATEDURATION(expr, oper, val, unit)
|
|||
|
||||
**使用说明**:
|
||||
|
||||
- 该函数可以应用在普通表上,在由 PARTITION BY 划分出单独时间线的情况下用于超级表(也即 PARTITION BY tbname)
|
||||
- 不能和窗口操作一起使用,例如 interval/state_window/session_window。
|
||||
|
||||
|
||||
|
@ -1234,8 +1233,6 @@ TWA(expr)
|
|||
|
||||
**适用于**:表和超级表。
|
||||
|
||||
**使用说明**: TWA 函数可以在由 PARTITION BY 划分出单独时间线的情况下用于超级表(也即 PARTITION BY tbname)。
|
||||
|
||||
|
||||
## 系统信息函数
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ CREATE [OR REPLACE] AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE
|
|||
```
|
||||
- OR REPLACE: 如果函数已经存在,会修改已有的函数属性。
|
||||
- function_name:聚合函数未来在 SQL 中被调用时的函数名,必须与函数实现中 udfNormalFunc 的实际名称一致;
|
||||
- LANGUAGE 'C|Python':函数编程语言,目前支持C语言和Python语言。
|
||||
- LANGUAGE 'C|Python':函数编程语言,目前支持C语言和Python语言(v3.7+)。
|
||||
- library_path:如果编程语言是C,路径是包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 .so 文件)。如果编程语言是Python,路径是包含 UDF 函数实现的Python文件路径。这个路径需要用英文单引号或英文双引号括起来;;
|
||||
- output_type:此函数计算结果的数据类型名称;
|
||||
- buffer_size:中间计算结果的缓冲区大小,单位是字节。如果不使用可以不设置。
|
||||
|
|
|
@ -177,7 +177,7 @@ Install and configure TDinsight dashboard in Grafana on Ubuntu 18.04/20.04 syste
|
|||
假设您在主机 `tdengine` 上启动 TDengine 数据库,HTTP API 端口为 `6041`,用户为 `root1`,密码为 `pass5ord`。执行脚本:
|
||||
|
||||
```bash
|
||||
sudo ./TDinsight.sh -a http://tdengine:6041 -u root1 -p pass5ord
|
||||
./TDinsight.sh -a http://tdengine:6041 -u root1 -p pass5ord
|
||||
```
|
||||
|
||||
我们提供了一个“-E”选项,用于从命令行配置 TDinsight 使用现有的通知通道(Notification Channel)。假设你的 Grafana 用户和密码是 `admin:admin`,使用以下命令获取已有的通知通道的`uid`:
|
||||
|
@ -189,7 +189,7 @@ curl --no-progress-meter -u admin:admin http://localhost:3000/api/alert-notifica
|
|||
使用上面获取的 `uid` 值作为 `-E` 输入。
|
||||
|
||||
```bash
|
||||
sudo ./TDinsight.sh -a http://tdengine:6041 -u root1 -p pass5ord -E existing-notifier
|
||||
./TDinsight.sh -a http://tdengine:6041 -u root1 -p pass5ord -E existing-notifier
|
||||
```
|
||||
|
||||
如果要监控多个 TDengine 集群,则需要设置多个 TDinsight 仪表盘。设置非默认 TDinsight 需要进行一些更改: `-n` `-i` `-t` 选项需要更改为非默认名称,如果使用 内置短信告警功能,`-N` 和 `-L` 也应该改变。
|
||||
|
|
|
@ -80,11 +80,11 @@ taos --dump-config
|
|||
确保集群中所有主机在端口 6030 上的 TCP 协议能够互通。(详细的端口情况请参见下表)
|
||||
:::
|
||||
| 协议 | 默认端口 | 用途说明 | 修改方法 |
|
||||
| :--- | :-------- | :---------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| :--- | :------- | :----------------------------------------------- | :------------------------------------------------------------------------------------------------- |
|
||||
| TCP | 6030 | 客户端与服务端之间通讯,多节点集群的节点间通讯。 | 由配置文件设置 serverPort 决定。 |
|
||||
| TCP | 6041 | 客户端与服务端之间的 RESTful 通讯。 | 随 serverPort 端口变化。注意 taosAdapter 配置或有不同,请参考相应[文档](/reference/taosadapter/)。 |
|
||||
| TCP | 6043 | taosKeeper 监控服务端口。 | 随 taosKeeper 启动参数设置变化。 |
|
||||
| TCP | 6044 | 支持 StatsD 的数据接入端口。 | 随 taosAdapter 启动参数设置变化|
|
||||
| TCP | 6044 | 支持 StatsD 的数据接入端口。 | 随 taosAdapter 启动参数设置变化 |
|
||||
| UDP | 6045 | 支持 collectd 数据接入端口。 | 随 taosAdapter 启动参数设置变化 |
|
||||
| TCP | 6060 | 企业版内 Monitor 服务的网络端口。 | |
|
||||
|
||||
|
@ -97,6 +97,24 @@ taos --dump-config
|
|||
| 取值范围 | 10-50000000 |
|
||||
| 缺省值 | 5000 |
|
||||
|
||||
### numOfRpcSessions
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | ---------------------------- |
|
||||
| 适用范围 | 客户端和服务端都适用 |
|
||||
| 含义 | 一个客户端能创建的最大连接数 |
|
||||
| 取值范围 | 100-100000 |
|
||||
| 缺省值 | 10000 |
|
||||
|
||||
### timeToGetAvailableConn
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | -------------------------- |
|
||||
| 适用范围 | 客户端和服务端都适用 |
|
||||
| 含义 | 获得可用连接的最长等待时间 |
|
||||
| 取值范围 | 10-50000000(单位为毫秒) |
|
||||
| 缺省值 | 500000 |
|
||||
|
||||
## 监控相关
|
||||
|
||||
:::note
|
||||
|
@ -140,18 +158,18 @@ taos --dump-config
|
|||
### telemetryReporting
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | -------------------------------------------- |
|
||||
| -------- | ------------------------ |
|
||||
| 适用范围 | 仅服务端适用 |
|
||||
| 含义 |是否上传 telemetry |
|
||||
| 含义 | 是否上传 telemetry |
|
||||
| 取值范围 | 0,1 0: 不上传;1:上传 |
|
||||
| 缺省值 | 1 |
|
||||
|
||||
### crashReporting
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | -------------------------------------------- |
|
||||
| -------- | ------------------------ |
|
||||
| 适用范围 | 仅服务端适用 |
|
||||
| 含义 |是否上传 crash 信息 |
|
||||
| 含义 | 是否上传 crash 信息 |
|
||||
| 取值范围 | 0,1 0: 不上传;1:上传 |
|
||||
| 缺省值 | 1 |
|
||||
|
||||
|
@ -160,7 +178,7 @@ taos --dump-config
|
|||
### queryPolicy
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | ----------------------------- |
|
||||
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| 适用范围 | 仅客户端适用 |
|
||||
| 含义 | 查询语句的执行策略 |
|
||||
| 单位 | 无 |
|
||||
|
@ -170,12 +188,12 @@ taos --dump-config
|
|||
### querySmaOptimize
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | -------------------- |
|
||||
| -------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| 适用范围 | 仅客户端适用 |
|
||||
| 含义 | sma index 的优化策略 |
|
||||
| 单位 | 无 |
|
||||
| 缺省值 | 0 |
|
||||
| 补充说明 |0: 表示不使用 sma index,永远从原始数据进行查询; 1: 表示使用 sma index,对符合的语句,直接从预计算的结果进行查询 |
|
||||
| 补充说明 | 0: 表示不使用 sma index,永远从原始数据进行查询; 1: 表示使用 sma index,对符合的语句,直接从预计算的结果进行查询 |
|
||||
|
||||
### maxNumOfDistinctRes
|
||||
|
||||
|
@ -189,7 +207,7 @@ taos --dump-config
|
|||
### keepColumnName
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | -------------------------------- |
|
||||
| -------- | ----------------------------------------------------------- |
|
||||
| 适用范围 | 仅客户端适用 |
|
||||
| 含义 | Last、First、LastRow 函数查询时,返回的列名是否包含函数名。 |
|
||||
| 取值范围 | 0 表示包含函数名,1 表示不包含函数名。 |
|
||||
|
@ -198,7 +216,7 @@ taos --dump-config
|
|||
### countAlwaysReturnValue
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | -------------------------------- |
|
||||
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 适用范围 | 仅服务端适用 |
|
||||
| 含义 | count/hyperloglog函数在输入数据为空或者NULL的情况下是否返回值 |
|
||||
| 取值范围 | 0:返回空行,1:返回 0 |
|
||||
|
@ -315,7 +333,7 @@ charset 的有效值是 UTF-8。
|
|||
### dataDir
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | ------------------------------------------ |
|
||||
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 适用范围 | 仅服务端适用 |
|
||||
| 含义 | 数据文件目录,所有的数据文件都将写入该目录 |
|
||||
| 缺省值 | /var/lib/taos |
|
||||
|
@ -324,7 +342,7 @@ charset 的有效值是 UTF-8。
|
|||
### tempDir
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | ------------------------------------------ |
|
||||
| -------- | ------------------------------------------------ |
|
||||
| 适用范围 | 仅服务端适用 |
|
||||
| 含义 | 该参数指定所有系统运行过程中的临时文件生成的目录 |
|
||||
| 缺省值 | /tmp |
|
||||
|
@ -341,7 +359,7 @@ charset 的有效值是 UTF-8。
|
|||
### minimalDataDirGB
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | ------------------------------------------------ |
|
||||
| -------- | ---------------------------------------------- |
|
||||
| 适用范围 | 仅服务端适用 |
|
||||
| 含义 | dataDir 指定的时序数据存储目录所需要保留的最小 |
|
||||
| 单位 | GB |
|
||||
|
@ -382,7 +400,7 @@ charset 的有效值是 UTF-8。
|
|||
### minimalLogDirGB
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | -------------------------------------------- |
|
||||
| -------- | ------------------------------------------------------ |
|
||||
| 适用范围 | 服务端和客户端均适用 |
|
||||
| 含义 | 当日志文件夹所在磁盘可用空间大小小于该值时,停止写日志 |
|
||||
| 单位 | GB |
|
||||
|
@ -591,7 +609,7 @@ charset 的有效值是 UTF-8。
|
|||
### smlChildTableName
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | ------------------------- |
|
||||
| -------- | ------------------------------- |
|
||||
| 适用范围 | 仅客户端适用 |
|
||||
| 含义 | schemaless 自定义的子表名的 key |
|
||||
| 类型 | 字符串 |
|
||||
|
@ -609,7 +627,7 @@ charset 的有效值是 UTF-8。
|
|||
### smlDataFormat
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | ----------------------------- |
|
||||
| -------- | -------------------------------------------------------- |
|
||||
| 适用范围 | 仅客户端适用 |
|
||||
| 含义 | schemaless 列数据是否顺序一致,从3.0.3.0开始,该配置废弃 |
|
||||
| 值域 | 0:不一致;1: 一致 |
|
||||
|
@ -630,7 +648,7 @@ charset 的有效值是 UTF-8。
|
|||
### enableScience
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| -------- | ---------------------------- |
|
||||
| 适用范围 | 仅客户端 TAOS-CLI 适用 |
|
||||
| 含义 | 是否开启科学计数法显示浮点数 |
|
||||
| 取值范围 | 0:否,1:是 |
|
||||
|
@ -650,7 +668,7 @@ charset 的有效值是 UTF-8。
|
|||
### compressMsgSize
|
||||
|
||||
| 属性 | 说明 |
|
||||
| -------- | ----------------------------- |
|
||||
| -------- | ------------------------------------------------------------------------------- |
|
||||
| 适用于 | 服务端和客户端均适用 |
|
||||
| 含义 | 是否对 RPC 消息进行压缩 |
|
||||
| 取值范围 | -1: 所有消息都不压缩; 0: 所有消息都压缩; N (N>0): 只有大于 N 个字节的消息才压缩 |
|
||||
|
@ -659,7 +677,7 @@ charset 的有效值是 UTF-8。
|
|||
## 3.0 中有效的配置参数列表
|
||||
|
||||
| # | **参数** | **适用于 2.X ** | **适用于 3.0 ** | 3.0 版本的当前行为 |
|
||||
| --- | :---------------------: | --------------- | --------------- | ------------------------------------------------- |
|
||||
| --- | :--------------------: | --------------- | ------------------------------- | ------------------ |
|
||||
| 1 | firstEp | 是 | 是 | |
|
||||
| 2 | secondEp | 是 | 是 | |
|
||||
| 3 | fqdn | 是 | 是 | |
|
||||
|
@ -716,7 +734,7 @@ charset 的有效值是 UTF-8。
|
|||
## 2.x->3.0 的废弃参数
|
||||
|
||||
| # | **参数** | **适用于 2.X ** | **适用于 3.0 ** | 3.0 版本的当前行为 |
|
||||
| --- | :---------------------: | --------------- | --------------- | ------------------------------------------------- |
|
||||
| --- | :---------------------: | --------------- | --------------- | ---------------------------------------------------- |
|
||||
| 1 | arbitrator | 是 | 否 | 通过 RAFT 协议选主 |
|
||||
| 2 | numOfThreadsPerCore | 是 | 否 | 有其它参数设置多种线程池的大小 |
|
||||
| 3 | numOfMnodes | 是 | 否 | 通过 create mnode 命令动态创建 mnode |
|
||||
|
|
|
@ -32,7 +32,7 @@ chmod +x TDinsight.sh
|
|||
- 使用已经存在的 Grafana Notification Channel `uid`,参数 `-E`。该参数可以使用 `curl -u admin:admin localhost:3000/api/alert-notifications |jq` 来获取。
|
||||
|
||||
```bash
|
||||
sudo ./TDinsight.sh -a http://localhost:6041 -u root -p taosdata -E <notifier uid>
|
||||
./TDinsight.sh -a http://localhost:6041 -u root -p taosdata -E <notifier uid>
|
||||
```
|
||||
|
||||
运行程序并重启 Grafana 服务,打开面板:`http://localhost:3000/d/tdinsight`。
|
||||
|
@ -270,7 +270,7 @@ TDinsight dashboard 数据来源于 log 库(存放监控数据的默认db,
|
|||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||监控指标值|
|
||||
|gauge|DOUBLE||监控指标值|
|
||||
|client\_ip|NCHAR|TAG|client ip|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|request\_method|NCHAR|TAG|request method|
|
||||
|
@ -284,7 +284,7 @@ TDinsight dashboard 数据来源于 log 库(存放监控数据的默认db,
|
|||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||监控指标值|
|
||||
|gauge|DOUBLE||监控指标值|
|
||||
|client\_ip|NCHAR|TAG|client ip|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|request\_method|NCHAR|TAG|request method|
|
||||
|
@ -298,7 +298,7 @@ TDinsight dashboard 数据来源于 log 库(存放监控数据的默认db,
|
|||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||监控指标值|
|
||||
|gauge|DOUBLE||监控指标值|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|
||||
### taosadapter\_restful\_http\_request\_summary\_milliseconds 表
|
||||
|
@ -326,7 +326,7 @@ TDinsight dashboard 数据来源于 log 库(存放监控数据的默认db,
|
|||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||监控指标值|
|
||||
|gauge|DOUBLE||监控指标值|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|
||||
### taosadapter\_system\_cpu\_percent 表
|
||||
|
@ -336,5 +336,5 @@ TDinsight dashboard 数据来源于 log 库(存放监控数据的默认db,
|
|||
|field|type|is\_tag|comment|
|
||||
|:----|:---|:-----|:------|
|
||||
|\_ts|TIMESTAMP||timestamp|
|
||||
|guage|DOUBLE||监控指标值|
|
||||
|gauge|DOUBLE||监控指标值|
|
||||
|endpoint|NCHAR|TAG|taosadpater endpoint|
|
||||
|
|
|
@ -247,4 +247,17 @@ launchctl limit maxfiles
|
|||
该提示是创建 db 的 vnode 数量不够了,需要的 vnode 不能超过了 dnode 中 vnode 的上限。因为系统默认是一个 dnode 中有 CPU 核数两倍的 vnode,也可以通过配置文件中的参数 supportVnodes 控制。
|
||||
正常调大 taos.cfg 中 supportVnodes 参数即可。
|
||||
|
||||
### 21 在服务器上的使用 taos-CLI 能查到指定时间段的数据,但在客户端机器上查不到?
|
||||
这种情况是因为客户端与服务器上设置的时区不一致导致的,调整客户端与服务器的时区一致即可解决。
|
||||
|
||||
### 22 表名确认是存在的,但在写入或查询时返回表名不存在,什么原因?
|
||||
TDengine 中的所有名称,包括数据库名、表名等都是区分大小写的,如果这些名称在程序或 taos-CLI 中没有使用反引号(`)括起来使用,即使你输入的是大写的,引擎也会转化成小写来使用,如果名称前后加上了反引号,引擎就不会再转化成小写,会保持原样来使用。
|
||||
|
||||
### 23 在 taos-CLI 中查询,字段内容不能完全显示出来怎么办?
|
||||
可以使用 \G 参数来竖式显示,如 show databases\G; (为了输入方便,在"\"后加 TAB 键,会自动补全后面的内容)
|
||||
|
||||
### 24 使用 taosBenchmark 测试工具写入数据查询很快,为什么我写入的数据查询非常慢?
|
||||
TDengine 在写入数据时如果有很严重的乱序写入问题,会严重影响查询性能,所以需要在写入前解决乱序的问题。如果业务是从 kafka 消费写入,请合理设计消费者,尽可能的一个子表数据由一个消费者去消费并写入,避免由设计产生的乱序。
|
||||
|
||||
### 25 我想统计下前后两条写入记录之间的时间差值是多少?
|
||||
使用 DIFF 函数,可以查看时间列或数值列前后两条记录的差值,非常方便,详细说明见 SQL手册->函数->DIFF
|
||||
|
|
|
@ -10,6 +10,10 @@ TDengine 2.x 各版本安装包请访问[这里](https://www.taosdata.com/all-do
|
|||
|
||||
import Release from "/components/ReleaseV3";
|
||||
|
||||
## 3.0.4.2
|
||||
|
||||
<Release type="tdengine" version="3.0.4.2" />
|
||||
|
||||
## 3.0.4.1
|
||||
|
||||
<Release type="tdengine" version="3.0.4.1" />
|
||||
|
|
|
@ -14,10 +14,6 @@ import Release from "/components/ReleaseV3";
|
|||
|
||||
<Release type="tools" version="2.5.0" />
|
||||
|
||||
## 2.5.0
|
||||
|
||||
<Release type="tools" version="2.5.0" />
|
||||
|
||||
## 2.4.12
|
||||
|
||||
<Release type="tools" version="2.4.12" />
|
||||
|
|
|
@ -73,7 +73,7 @@ static int32_t init_env() {
|
|||
taos_free_result(pRes);
|
||||
|
||||
// create database
|
||||
pRes = taos_query(pConn, "create database tmqdb precision 'ns'");
|
||||
pRes = taos_query(pConn, "create database tmqdb precision 'ns' WAL_RETENTION_PERIOD 3600");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in create tmqdb, reason:%s\n", taos_errstr(pRes));
|
||||
goto END;
|
||||
|
@ -289,7 +289,7 @@ void consume_repeatly(tmq_t* tmq) {
|
|||
}
|
||||
}
|
||||
|
||||
free(pAssign);
|
||||
tmq_free_assignment(pAssign);
|
||||
|
||||
// let's do it again
|
||||
basic_consume_loop(tmq);
|
||||
|
|
|
@ -162,6 +162,7 @@ static int l_query(lua_State *L){
|
|||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
//printf("type:%d, max len:%d, current len:%d\n",fields[i].type, fields[i].bytes, length[i]);
|
||||
lua_pushlstring(L,(char *)row[i], length[i]);
|
||||
break;
|
||||
|
|
|
@ -161,6 +161,7 @@ static int l_query(lua_State *L){
|
|||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
//printf("type:%d, max len:%d, current len:%d\n",fields[i].type, fields[i].bytes, length[i]);
|
||||
lua_pushlstring(L,(char *)row[i], length[i]);
|
||||
break;
|
||||
|
|
|
@ -51,7 +51,8 @@ typedef void TAOS_SUB;
|
|||
#define TSDB_DATA_TYPE_BLOB 18 // binary
|
||||
#define TSDB_DATA_TYPE_MEDIUMBLOB 19
|
||||
#define TSDB_DATA_TYPE_BINARY TSDB_DATA_TYPE_VARCHAR // string
|
||||
#define TSDB_DATA_TYPE_MAX 20
|
||||
#define TSDB_DATA_TYPE_GEOMETRY 20 // geometry
|
||||
#define TSDB_DATA_TYPE_MAX 21
|
||||
|
||||
typedef enum {
|
||||
TSDB_OPTION_LOCALE,
|
||||
|
@ -288,6 +289,7 @@ DLL_EXPORT int32_t tmq_commit_sync(tmq_t *tmq, const TAOS_RES *msg);
|
|||
DLL_EXPORT void tmq_commit_async(tmq_t *tmq, const TAOS_RES *msg, tmq_commit_cb *cb, void *param);
|
||||
DLL_EXPORT int32_t tmq_get_topic_assignment(tmq_t *tmq, const char *pTopicName, tmq_topic_assignment **assignment,
|
||||
int32_t *numOfAssignment);
|
||||
DLL_EXPORT void tmq_free_assignment(tmq_topic_assignment* pAssignment);
|
||||
DLL_EXPORT int32_t tmq_offset_seek(tmq_t *tmq, const char *pTopicName, int32_t vgId, int64_t offset);
|
||||
|
||||
/* ----------------------TMQ CONFIGURATION INTERFACE---------------------- */
|
||||
|
|
|
@ -37,6 +37,13 @@ extern "C" {
|
|||
)
|
||||
// clang-format on
|
||||
|
||||
typedef bool (*state_key_cmpr_fn)(void* pKey1, void* pKey2);
|
||||
|
||||
typedef struct STableKeyInfo {
|
||||
uint64_t uid;
|
||||
uint64_t groupId;
|
||||
} STableKeyInfo;
|
||||
|
||||
typedef struct SWinKey {
|
||||
uint64_t groupId;
|
||||
TSKEY ts;
|
||||
|
|
|
@ -215,7 +215,7 @@ void colInfoDataCleanup(SColumnInfoData* pColumn, uint32_t numOfRows);
|
|||
void blockDataCleanup(SSDataBlock* pDataBlock);
|
||||
void blockDataEmpty(SSDataBlock* pDataBlock);
|
||||
|
||||
size_t blockDataGetCapacityInRow(const SSDataBlock* pBlock, size_t pageSize);
|
||||
size_t blockDataGetCapacityInRow(const SSDataBlock* pBlock, size_t pageSize, int32_t extraSize);
|
||||
|
||||
int32_t blockDataTrimFirstRows(SSDataBlock* pBlock, size_t n);
|
||||
int32_t blockDataKeepFirstNRows(SSDataBlock* pBlock, size_t n);
|
||||
|
|
|
@ -29,7 +29,6 @@ extern "C" {
|
|||
#define SLOW_LOG_TYPE_OTHERS 0x4
|
||||
#define SLOW_LOG_TYPE_ALL 0xFFFFFFFF
|
||||
|
||||
|
||||
// cluster
|
||||
extern char tsFirst[];
|
||||
extern char tsSecond[];
|
||||
|
@ -124,6 +123,7 @@ extern int32_t tsRedirectFactor;
|
|||
extern int32_t tsRedirectMaxPeriod;
|
||||
extern int32_t tsMaxRetryWaitTime;
|
||||
extern bool tsUseAdapter;
|
||||
extern int32_t tsMetaCacheMaxSize;
|
||||
extern int32_t tsSlowLogThreshold;
|
||||
extern int32_t tsSlowLogScope;
|
||||
|
||||
|
@ -179,6 +179,8 @@ extern int32_t tsRpcRetryInterval;
|
|||
extern bool tsDisableStream;
|
||||
extern int64_t tsStreamBufferSize;
|
||||
extern int64_t tsCheckpointInterval;
|
||||
extern bool tsFilterScalarMode;
|
||||
extern int32_t tsMaxStreamBackendCache;
|
||||
|
||||
// #define NEEDTO_COMPRESSS_MSG(size) (tsCompressMsgSize != -1 && (size) > tsCompressMsgSize)
|
||||
|
||||
|
@ -193,7 +195,7 @@ struct SConfig *taosGetCfg();
|
|||
|
||||
void taosSetAllDebugFlag(int32_t flag, bool rewrite);
|
||||
void taosSetDebugFlag(int32_t *pFlagPtr, const char *flagName, int32_t flagVal, bool rewrite);
|
||||
int32_t taosSetCfg(SConfig *pCfg, char *name);
|
||||
int32_t taosApplyLocalCfg(SConfig *pCfg, char *name);
|
||||
void taosLocalCfgForbiddenToChange(char *name, bool *forbidden);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -3191,7 +3191,8 @@ typedef struct {
|
|||
char dbFName[TSDB_DB_FNAME_LEN];
|
||||
uint64_t suid;
|
||||
int32_t version;
|
||||
SArray* pIndex;
|
||||
int32_t indexSize;
|
||||
SArray* pIndex; // STableIndexInfo
|
||||
} STableIndexRsp;
|
||||
|
||||
int32_t tSerializeSTableIndexRsp(void* buf, int32_t bufLen, const STableIndexRsp* pRsp);
|
||||
|
|
|
@ -146,212 +146,212 @@
|
|||
#define TK_MEDIUMBLOB 128
|
||||
#define TK_BLOB 129
|
||||
#define TK_VARBINARY 130
|
||||
#define TK_DECIMAL 131
|
||||
#define TK_COMMENT 132
|
||||
#define TK_MAX_DELAY 133
|
||||
#define TK_WATERMARK 134
|
||||
#define TK_ROLLUP 135
|
||||
#define TK_TTL 136
|
||||
#define TK_SMA 137
|
||||
#define TK_DELETE_MARK 138
|
||||
#define TK_FIRST 139
|
||||
#define TK_LAST 140
|
||||
#define TK_SHOW 141
|
||||
#define TK_PRIVILEGES 142
|
||||
#define TK_DATABASES 143
|
||||
#define TK_TABLES 144
|
||||
#define TK_STABLES 145
|
||||
#define TK_MNODES 146
|
||||
#define TK_QNODES 147
|
||||
#define TK_FUNCTIONS 148
|
||||
#define TK_INDEXES 149
|
||||
#define TK_ACCOUNTS 150
|
||||
#define TK_APPS 151
|
||||
#define TK_CONNECTIONS 152
|
||||
#define TK_LICENCES 153
|
||||
#define TK_GRANTS 154
|
||||
#define TK_QUERIES 155
|
||||
#define TK_SCORES 156
|
||||
#define TK_TOPICS 157
|
||||
#define TK_VARIABLES 158
|
||||
#define TK_CLUSTER 159
|
||||
#define TK_BNODES 160
|
||||
#define TK_SNODES 161
|
||||
#define TK_TRANSACTIONS 162
|
||||
#define TK_DISTRIBUTED 163
|
||||
#define TK_CONSUMERS 164
|
||||
#define TK_SUBSCRIPTIONS 165
|
||||
#define TK_VNODES 166
|
||||
#define TK_ALIVE 167
|
||||
#define TK_LIKE 168
|
||||
#define TK_TBNAME 169
|
||||
#define TK_QTAGS 170
|
||||
#define TK_AS 171
|
||||
#define TK_INDEX 172
|
||||
#define TK_FUNCTION 173
|
||||
#define TK_INTERVAL 174
|
||||
#define TK_COUNT 175
|
||||
#define TK_LAST_ROW 176
|
||||
#define TK_TOPIC 177
|
||||
#define TK_META 178
|
||||
#define TK_CONSUMER 179
|
||||
#define TK_GROUP 180
|
||||
#define TK_DESC 181
|
||||
#define TK_DESCRIBE 182
|
||||
#define TK_RESET 183
|
||||
#define TK_QUERY 184
|
||||
#define TK_CACHE 185
|
||||
#define TK_EXPLAIN 186
|
||||
#define TK_ANALYZE 187
|
||||
#define TK_VERBOSE 188
|
||||
#define TK_NK_BOOL 189
|
||||
#define TK_RATIO 190
|
||||
#define TK_NK_FLOAT 191
|
||||
#define TK_OUTPUTTYPE 192
|
||||
#define TK_AGGREGATE 193
|
||||
#define TK_BUFSIZE 194
|
||||
#define TK_LANGUAGE 195
|
||||
#define TK_REPLACE 196
|
||||
#define TK_STREAM 197
|
||||
#define TK_INTO 198
|
||||
#define TK_PAUSE 199
|
||||
#define TK_RESUME 200
|
||||
#define TK_TRIGGER 201
|
||||
#define TK_AT_ONCE 202
|
||||
#define TK_WINDOW_CLOSE 203
|
||||
#define TK_IGNORE 204
|
||||
#define TK_EXPIRED 205
|
||||
#define TK_FILL_HISTORY 206
|
||||
#define TK_UPDATE 207
|
||||
#define TK_SUBTABLE 208
|
||||
#define TK_UNTREATED 209
|
||||
#define TK_KILL 210
|
||||
#define TK_CONNECTION 211
|
||||
#define TK_TRANSACTION 212
|
||||
#define TK_BALANCE 213
|
||||
#define TK_VGROUP 214
|
||||
#define TK_LEADER 215
|
||||
#define TK_MERGE 216
|
||||
#define TK_REDISTRIBUTE 217
|
||||
#define TK_SPLIT 218
|
||||
#define TK_DELETE 219
|
||||
#define TK_INSERT 220
|
||||
#define TK_NULL 221
|
||||
#define TK_NK_QUESTION 222
|
||||
#define TK_NK_ARROW 223
|
||||
#define TK_ROWTS 224
|
||||
#define TK_QSTART 225
|
||||
#define TK_QEND 226
|
||||
#define TK_QDURATION 227
|
||||
#define TK_WSTART 228
|
||||
#define TK_WEND 229
|
||||
#define TK_WDURATION 230
|
||||
#define TK_IROWTS 231
|
||||
#define TK_ISFILLED 232
|
||||
#define TK_CAST 233
|
||||
#define TK_NOW 234
|
||||
#define TK_TODAY 235
|
||||
#define TK_TIMEZONE 236
|
||||
#define TK_CLIENT_VERSION 237
|
||||
#define TK_SERVER_VERSION 238
|
||||
#define TK_SERVER_STATUS 239
|
||||
#define TK_CURRENT_USER 240
|
||||
#define TK_CASE 241
|
||||
#define TK_WHEN 242
|
||||
#define TK_THEN 243
|
||||
#define TK_ELSE 244
|
||||
#define TK_BETWEEN 245
|
||||
#define TK_IS 246
|
||||
#define TK_NK_LT 247
|
||||
#define TK_NK_GT 248
|
||||
#define TK_NK_LE 249
|
||||
#define TK_NK_GE 250
|
||||
#define TK_NK_NE 251
|
||||
#define TK_MATCH 252
|
||||
#define TK_NMATCH 253
|
||||
#define TK_CONTAINS 254
|
||||
#define TK_IN 255
|
||||
#define TK_JOIN 256
|
||||
#define TK_INNER 257
|
||||
#define TK_SELECT 258
|
||||
#define TK_DISTINCT 259
|
||||
#define TK_WHERE 260
|
||||
#define TK_PARTITION 261
|
||||
#define TK_BY 262
|
||||
#define TK_SESSION 263
|
||||
#define TK_STATE_WINDOW 264
|
||||
#define TK_EVENT_WINDOW 265
|
||||
#define TK_SLIDING 266
|
||||
#define TK_FILL 267
|
||||
#define TK_VALUE 268
|
||||
#define TK_VALUE_F 269
|
||||
#define TK_NONE 270
|
||||
#define TK_PREV 271
|
||||
#define TK_NULL_F 272
|
||||
#define TK_LINEAR 273
|
||||
#define TK_NEXT 274
|
||||
#define TK_HAVING 275
|
||||
#define TK_RANGE 276
|
||||
#define TK_EVERY 277
|
||||
#define TK_ORDER 278
|
||||
#define TK_SLIMIT 279
|
||||
#define TK_SOFFSET 280
|
||||
#define TK_LIMIT 281
|
||||
#define TK_OFFSET 282
|
||||
#define TK_ASC 283
|
||||
#define TK_NULLS 284
|
||||
#define TK_ABORT 285
|
||||
#define TK_AFTER 286
|
||||
#define TK_ATTACH 287
|
||||
#define TK_BEFORE 288
|
||||
#define TK_BEGIN 289
|
||||
#define TK_BITAND 290
|
||||
#define TK_BITNOT 291
|
||||
#define TK_BITOR 292
|
||||
#define TK_BLOCKS 293
|
||||
#define TK_CHANGE 294
|
||||
#define TK_COMMA 295
|
||||
#define TK_CONCAT 296
|
||||
#define TK_CONFLICT 297
|
||||
#define TK_COPY 298
|
||||
#define TK_DEFERRED 299
|
||||
#define TK_DELIMITERS 300
|
||||
#define TK_DETACH 301
|
||||
#define TK_DIVIDE 302
|
||||
#define TK_DOT 303
|
||||
#define TK_EACH 304
|
||||
#define TK_FAIL 305
|
||||
#define TK_FILE 306
|
||||
#define TK_FOR 307
|
||||
#define TK_GLOB 308
|
||||
#define TK_ID 309
|
||||
#define TK_IMMEDIATE 310
|
||||
#define TK_IMPORT 311
|
||||
#define TK_INITIALLY 312
|
||||
#define TK_INSTEAD 313
|
||||
#define TK_ISNULL 314
|
||||
#define TK_KEY 315
|
||||
#define TK_MODULES 316
|
||||
#define TK_NK_BITNOT 317
|
||||
#define TK_NK_SEMI 318
|
||||
#define TK_NOTNULL 319
|
||||
#define TK_OF 320
|
||||
#define TK_PLUS 321
|
||||
#define TK_PRIVILEGE 322
|
||||
#define TK_RAISE 323
|
||||
#define TK_RESTRICT 324
|
||||
#define TK_ROW 325
|
||||
#define TK_SEMI 326
|
||||
#define TK_STAR 327
|
||||
#define TK_STATEMENT 328
|
||||
#define TK_STRICT 329
|
||||
#define TK_STRING 330
|
||||
#define TK_TIMES 331
|
||||
#define TK_VALUES 332
|
||||
#define TK_VARIABLE 333
|
||||
#define TK_VIEW 334
|
||||
#define TK_WAL 335
|
||||
|
||||
#define TK_GEOMETRY 131
|
||||
#define TK_DECIMAL 132
|
||||
#define TK_COMMENT 133
|
||||
#define TK_MAX_DELAY 134
|
||||
#define TK_WATERMARK 135
|
||||
#define TK_ROLLUP 136
|
||||
#define TK_TTL 137
|
||||
#define TK_SMA 138
|
||||
#define TK_DELETE_MARK 139
|
||||
#define TK_FIRST 140
|
||||
#define TK_LAST 141
|
||||
#define TK_SHOW 142
|
||||
#define TK_PRIVILEGES 143
|
||||
#define TK_DATABASES 144
|
||||
#define TK_TABLES 145
|
||||
#define TK_STABLES 146
|
||||
#define TK_MNODES 147
|
||||
#define TK_QNODES 148
|
||||
#define TK_FUNCTIONS 149
|
||||
#define TK_INDEXES 150
|
||||
#define TK_ACCOUNTS 151
|
||||
#define TK_APPS 152
|
||||
#define TK_CONNECTIONS 153
|
||||
#define TK_LICENCES 154
|
||||
#define TK_GRANTS 155
|
||||
#define TK_QUERIES 156
|
||||
#define TK_SCORES 157
|
||||
#define TK_TOPICS 158
|
||||
#define TK_VARIABLES 159
|
||||
#define TK_CLUSTER 160
|
||||
#define TK_BNODES 161
|
||||
#define TK_SNODES 162
|
||||
#define TK_TRANSACTIONS 163
|
||||
#define TK_DISTRIBUTED 164
|
||||
#define TK_CONSUMERS 165
|
||||
#define TK_SUBSCRIPTIONS 166
|
||||
#define TK_VNODES 167
|
||||
#define TK_ALIVE 168
|
||||
#define TK_LIKE 169
|
||||
#define TK_TBNAME 170
|
||||
#define TK_QTAGS 171
|
||||
#define TK_AS 172
|
||||
#define TK_INDEX 173
|
||||
#define TK_FUNCTION 174
|
||||
#define TK_INTERVAL 175
|
||||
#define TK_COUNT 176
|
||||
#define TK_LAST_ROW 177
|
||||
#define TK_TOPIC 178
|
||||
#define TK_META 179
|
||||
#define TK_CONSUMER 180
|
||||
#define TK_GROUP 181
|
||||
#define TK_DESC 182
|
||||
#define TK_DESCRIBE 183
|
||||
#define TK_RESET 184
|
||||
#define TK_QUERY 185
|
||||
#define TK_CACHE 186
|
||||
#define TK_EXPLAIN 187
|
||||
#define TK_ANALYZE 188
|
||||
#define TK_VERBOSE 189
|
||||
#define TK_NK_BOOL 190
|
||||
#define TK_RATIO 191
|
||||
#define TK_NK_FLOAT 192
|
||||
#define TK_OUTPUTTYPE 193
|
||||
#define TK_AGGREGATE 194
|
||||
#define TK_BUFSIZE 195
|
||||
#define TK_LANGUAGE 196
|
||||
#define TK_REPLACE 197
|
||||
#define TK_STREAM 198
|
||||
#define TK_INTO 199
|
||||
#define TK_PAUSE 200
|
||||
#define TK_RESUME 201
|
||||
#define TK_TRIGGER 202
|
||||
#define TK_AT_ONCE 203
|
||||
#define TK_WINDOW_CLOSE 204
|
||||
#define TK_IGNORE 205
|
||||
#define TK_EXPIRED 206
|
||||
#define TK_FILL_HISTORY 207
|
||||
#define TK_UPDATE 208
|
||||
#define TK_SUBTABLE 209
|
||||
#define TK_UNTREATED 210
|
||||
#define TK_KILL 211
|
||||
#define TK_CONNECTION 212
|
||||
#define TK_TRANSACTION 213
|
||||
#define TK_BALANCE 214
|
||||
#define TK_VGROUP 215
|
||||
#define TK_LEADER 216
|
||||
#define TK_MERGE 217
|
||||
#define TK_REDISTRIBUTE 218
|
||||
#define TK_SPLIT 219
|
||||
#define TK_DELETE 220
|
||||
#define TK_INSERT 221
|
||||
#define TK_NULL 222
|
||||
#define TK_NK_QUESTION 223
|
||||
#define TK_NK_ARROW 224
|
||||
#define TK_ROWTS 225
|
||||
#define TK_QSTART 226
|
||||
#define TK_QEND 227
|
||||
#define TK_QDURATION 228
|
||||
#define TK_WSTART 229
|
||||
#define TK_WEND 230
|
||||
#define TK_WDURATION 231
|
||||
#define TK_IROWTS 232
|
||||
#define TK_ISFILLED 233
|
||||
#define TK_CAST 234
|
||||
#define TK_NOW 235
|
||||
#define TK_TODAY 236
|
||||
#define TK_TIMEZONE 237
|
||||
#define TK_CLIENT_VERSION 238
|
||||
#define TK_SERVER_VERSION 239
|
||||
#define TK_SERVER_STATUS 240
|
||||
#define TK_CURRENT_USER 241
|
||||
#define TK_CASE 242
|
||||
#define TK_WHEN 243
|
||||
#define TK_THEN 244
|
||||
#define TK_ELSE 245
|
||||
#define TK_BETWEEN 246
|
||||
#define TK_IS 247
|
||||
#define TK_NK_LT 248
|
||||
#define TK_NK_GT 249
|
||||
#define TK_NK_LE 250
|
||||
#define TK_NK_GE 251
|
||||
#define TK_NK_NE 252
|
||||
#define TK_MATCH 253
|
||||
#define TK_NMATCH 254
|
||||
#define TK_CONTAINS 255
|
||||
#define TK_IN 256
|
||||
#define TK_JOIN 257
|
||||
#define TK_INNER 258
|
||||
#define TK_SELECT 259
|
||||
#define TK_DISTINCT 260
|
||||
#define TK_WHERE 261
|
||||
#define TK_PARTITION 262
|
||||
#define TK_BY 263
|
||||
#define TK_SESSION 264
|
||||
#define TK_STATE_WINDOW 265
|
||||
#define TK_EVENT_WINDOW 266
|
||||
#define TK_SLIDING 267
|
||||
#define TK_FILL 268
|
||||
#define TK_VALUE 269
|
||||
#define TK_VALUE_F 270
|
||||
#define TK_NONE 271
|
||||
#define TK_PREV 272
|
||||
#define TK_NULL_F 273
|
||||
#define TK_LINEAR 274
|
||||
#define TK_NEXT 275
|
||||
#define TK_HAVING 276
|
||||
#define TK_RANGE 277
|
||||
#define TK_EVERY 278
|
||||
#define TK_ORDER 279
|
||||
#define TK_SLIMIT 280
|
||||
#define TK_SOFFSET 281
|
||||
#define TK_LIMIT 282
|
||||
#define TK_OFFSET 283
|
||||
#define TK_ASC 284
|
||||
#define TK_NULLS 285
|
||||
#define TK_ABORT 286
|
||||
#define TK_AFTER 287
|
||||
#define TK_ATTACH 288
|
||||
#define TK_BEFORE 289
|
||||
#define TK_BEGIN 290
|
||||
#define TK_BITAND 291
|
||||
#define TK_BITNOT 292
|
||||
#define TK_BITOR 293
|
||||
#define TK_BLOCKS 294
|
||||
#define TK_CHANGE 295
|
||||
#define TK_COMMA 296
|
||||
#define TK_CONCAT 297
|
||||
#define TK_CONFLICT 298
|
||||
#define TK_COPY 299
|
||||
#define TK_DEFERRED 300
|
||||
#define TK_DELIMITERS 301
|
||||
#define TK_DETACH 302
|
||||
#define TK_DIVIDE 303
|
||||
#define TK_DOT 304
|
||||
#define TK_EACH 305
|
||||
#define TK_FAIL 306
|
||||
#define TK_FILE 307
|
||||
#define TK_FOR 308
|
||||
#define TK_GLOB 309
|
||||
#define TK_ID 310
|
||||
#define TK_IMMEDIATE 311
|
||||
#define TK_IMPORT 312
|
||||
#define TK_INITIALLY 313
|
||||
#define TK_INSTEAD 314
|
||||
#define TK_ISNULL 315
|
||||
#define TK_KEY 316
|
||||
#define TK_MODULES 317
|
||||
#define TK_NK_BITNOT 318
|
||||
#define TK_NK_SEMI 319
|
||||
#define TK_NOTNULL 320
|
||||
#define TK_OF 321
|
||||
#define TK_PLUS 322
|
||||
#define TK_PRIVILEGE 323
|
||||
#define TK_RAISE 324
|
||||
#define TK_RESTRICT 325
|
||||
#define TK_ROW 326
|
||||
#define TK_SEMI 327
|
||||
#define TK_STAR 328
|
||||
#define TK_STATEMENT 329
|
||||
#define TK_STRICT 330
|
||||
#define TK_STRING 331
|
||||
#define TK_TIMES 332
|
||||
#define TK_VALUES 333
|
||||
#define TK_VARIABLE 334
|
||||
#define TK_VIEW 335
|
||||
#define TK_WAL 336
|
||||
|
||||
|
||||
#define TK_NK_SPACE 600
|
||||
|
|
|
@ -269,7 +269,7 @@ typedef struct {
|
|||
(IS_NUMERIC_TYPE(_t) || (_t) == (TSDB_DATA_TYPE_BOOL) || (_t) == (TSDB_DATA_TYPE_TIMESTAMP))
|
||||
|
||||
#define IS_VAR_DATA_TYPE(t) \
|
||||
(((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR) || ((t) == TSDB_DATA_TYPE_JSON))
|
||||
(((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR) || ((t) == TSDB_DATA_TYPE_JSON) || ((t) == TSDB_DATA_TYPE_GEOMETRY))
|
||||
#define IS_STR_DATA_TYPE(t) (((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR))
|
||||
|
||||
#define IS_VALID_TINYINT(_t) ((_t) >= INT8_MIN && (_t) <= INT8_MAX)
|
||||
|
@ -316,6 +316,8 @@ static FORCE_INLINE bool isNull(const void *val, int32_t type) {
|
|||
return *(uint32_t *)val == TSDB_DATA_UINT_NULL;
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
return *(uint64_t *)val == TSDB_DATA_UBIGINT_NULL;
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
return varDataLen(val) == sizeof(int8_t) && *(uint8_t *)varDataVal(val) == TSDB_DATA_GEOMETRY_NULL;
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -214,7 +214,7 @@ int32_t catalogGetSTableMeta(SCatalog* pCatalog, SRequestConnInfo* pConn, const
|
|||
|
||||
int32_t catalogUpdateTableMeta(SCatalog* pCatalog, STableMetaRsp* rspMsg);
|
||||
|
||||
int32_t catalogUpdateTableMeta(SCatalog* pCatalog, STableMetaRsp* rspMsg);
|
||||
int32_t catalogAsyncUpdateTableMeta(SCatalog* pCtg, STableMetaRsp* pMsg);
|
||||
|
||||
int32_t catalogGetCachedTableMeta(SCatalog* pCtg, const SName* pTableName, STableMeta** pTableMeta);
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ typedef struct SDataSinkMgtCfg {
|
|||
uint32_t maxDataBlockNumPerQuery;
|
||||
} SDataSinkMgtCfg;
|
||||
|
||||
int32_t dsDataSinkMgtInit(SDataSinkMgtCfg* cfg);
|
||||
int32_t dsDataSinkMgtInit(SDataSinkMgtCfg* cfg, SStorageAPI* pAPI);
|
||||
|
||||
typedef struct SInputData {
|
||||
const struct SSDataBlock* pData;
|
||||
|
|
|
@ -23,6 +23,7 @@ extern "C" {
|
|||
#include "query.h"
|
||||
#include "tcommon.h"
|
||||
#include "tmsgcb.h"
|
||||
#include "storageapi.h"
|
||||
|
||||
typedef void* qTaskInfo_t;
|
||||
typedef void* DataSinkHandle;
|
||||
|
@ -41,7 +42,6 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
void* tqReader;
|
||||
void* meta;
|
||||
void* config;
|
||||
void* vnode;
|
||||
void* mnd;
|
||||
|
@ -51,10 +51,10 @@ typedef struct {
|
|||
bool initTableReader;
|
||||
bool initTqReader;
|
||||
int32_t numOfVgroups;
|
||||
|
||||
void* sContext; // SSnapContext*
|
||||
|
||||
void* pStateBackend;
|
||||
struct SStorageAPI api;
|
||||
} SReadHandle;
|
||||
|
||||
// in queue mode, data streams are seperated by msg
|
||||
|
|
|
@ -0,0 +1,422 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_STORAGEAPI_H
|
||||
#define TDENGINE_STORAGEAPI_H
|
||||
|
||||
#include "tsimplehash.h"
|
||||
#include "tscalablebf.h"
|
||||
#include "taosdef.h"
|
||||
#include "tmsg.h"
|
||||
#include "tcommon.h"
|
||||
#include "index.h"
|
||||
#include "function.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TIMEWINDOW_RANGE_CONTAINED 1
|
||||
#define TIMEWINDOW_RANGE_EXTERNAL 2
|
||||
|
||||
#define CACHESCAN_RETRIEVE_TYPE_ALL 0x1
|
||||
#define CACHESCAN_RETRIEVE_TYPE_SINGLE 0x2
|
||||
#define CACHESCAN_RETRIEVE_LAST_ROW 0x4
|
||||
#define CACHESCAN_RETRIEVE_LAST 0x8
|
||||
|
||||
#define META_READER_NOLOCK 0x1
|
||||
|
||||
typedef struct SMeta SMeta;
|
||||
typedef TSKEY (*GetTsFun)(void*);
|
||||
|
||||
typedef struct SMetaEntry {
|
||||
int64_t version;
|
||||
int8_t type;
|
||||
int8_t flags; // TODO: need refactor?
|
||||
tb_uid_t uid;
|
||||
char * name;
|
||||
union {
|
||||
struct {
|
||||
SSchemaWrapper schemaRow;
|
||||
SSchemaWrapper schemaTag;
|
||||
SRSmaParam rsmaParam;
|
||||
} stbEntry;
|
||||
struct {
|
||||
int64_t ctime;
|
||||
int32_t ttlDays;
|
||||
int32_t commentLen;
|
||||
char * comment;
|
||||
tb_uid_t suid;
|
||||
uint8_t *pTags;
|
||||
} ctbEntry;
|
||||
struct {
|
||||
int64_t ctime;
|
||||
int32_t ttlDays;
|
||||
int32_t commentLen;
|
||||
char * comment;
|
||||
int32_t ncid; // next column id
|
||||
SSchemaWrapper schemaRow;
|
||||
} ntbEntry;
|
||||
struct {
|
||||
STSma *tsma;
|
||||
} smaEntry;
|
||||
};
|
||||
|
||||
uint8_t *pBuf;
|
||||
} SMetaEntry;
|
||||
|
||||
typedef struct SMetaReader {
|
||||
int32_t flags;
|
||||
void * pMeta;
|
||||
SDecoder coder;
|
||||
SMetaEntry me;
|
||||
void * pBuf;
|
||||
int32_t szBuf;
|
||||
struct SStoreMeta* pAPI;
|
||||
} SMetaReader;
|
||||
|
||||
typedef struct SMTbCursor {
|
||||
void * pDbc;
|
||||
void * pKey;
|
||||
void * pVal;
|
||||
int32_t kLen;
|
||||
int32_t vLen;
|
||||
SMetaReader mr;
|
||||
} SMTbCursor;
|
||||
|
||||
typedef struct SRowBuffPos {
|
||||
void* pRowBuff;
|
||||
void* pKey;
|
||||
bool beFlushed;
|
||||
bool beUsed;
|
||||
} SRowBuffPos;
|
||||
|
||||
// tq
|
||||
typedef struct SMetaTableInfo {
|
||||
int64_t suid;
|
||||
int64_t uid;
|
||||
SSchemaWrapper *schema;
|
||||
char tbName[TSDB_TABLE_NAME_LEN];
|
||||
} SMetaTableInfo;
|
||||
|
||||
typedef struct SSnapContext {
|
||||
SMeta * pMeta; // todo remove it
|
||||
int64_t snapVersion;
|
||||
void * pCur;
|
||||
int64_t suid;
|
||||
int8_t subType;
|
||||
SHashObj * idVersion;
|
||||
SHashObj * suidInfo;
|
||||
SArray * idList;
|
||||
int32_t index;
|
||||
bool withMeta;
|
||||
bool queryMeta; // true-get meta, false-get data
|
||||
} SSnapContext;
|
||||
|
||||
typedef struct {
|
||||
int64_t uid;
|
||||
int64_t ctbNum;
|
||||
} SMetaStbStats;
|
||||
|
||||
// void tqReaderSetColIdList(STqReader *pReader, SArray *pColIdList);
|
||||
// int32_t tqReaderSetTbUidList(STqReader *pReader, const SArray *tbUidList);
|
||||
// int32_t tqReaderAddTbUidList(STqReader *pReader, const SArray *pTableUidList);
|
||||
// int32_t tqReaderRemoveTbUidList(STqReader *pReader, const SArray *tbUidList);
|
||||
// bool tqReaderIsQueriedTable(STqReader* pReader, uint64_t uid);
|
||||
// bool tqCurrentBlockConsumed(const STqReader* pReader);
|
||||
// int32_t tqReaderSeek(STqReader *pReader, int64_t ver, const char *id);
|
||||
// bool tqNextBlockInWal(STqReader* pReader, const char* idstr);
|
||||
// bool tqNextBlockImpl(STqReader *pReader, const char* idstr);
|
||||
// int32_t getTableInfoFromSnapshot(SSnapContext *ctx, void **pBuf, int32_t *contLen, int16_t *type, int64_t *uid);
|
||||
// SMetaTableInfo getMetaTableInfoFromSnapshot(SSnapContext *ctx);
|
||||
// int32_t setForSnapShot(SSnapContext *ctx, int64_t uid);
|
||||
// int32_t destroySnapContext(SSnapContext *ctx);
|
||||
|
||||
// clang-format off
|
||||
/*-------------------------------------------------new api format---------------------------------------------------*/
|
||||
typedef struct TsdReader {
|
||||
int32_t (*tsdReaderOpen)(void* pVnode, SQueryTableDataCond* pCond, void* pTableList, int32_t numOfTables,
|
||||
SSDataBlock* pResBlock, void** ppReader, const char* idstr, bool countOnly,
|
||||
SHashObj** pIgnoreTables);
|
||||
void (*tsdReaderClose)();
|
||||
void (*tsdSetReaderTaskId)(void *pReader, const char *pId);
|
||||
int32_t (*tsdSetQueryTableList)();
|
||||
int32_t (*tsdNextDataBlock)();
|
||||
|
||||
int32_t (*tsdReaderRetrieveBlockSMAInfo)();
|
||||
SSDataBlock *(*tsdReaderRetrieveDataBlock)();
|
||||
|
||||
void (*tsdReaderReleaseDataBlock)();
|
||||
|
||||
int32_t (*tsdReaderResetStatus)();
|
||||
int32_t (*tsdReaderGetDataBlockDistInfo)();
|
||||
int64_t (*tsdReaderGetNumOfInMemRows)();
|
||||
void (*tsdReaderNotifyClosing)();
|
||||
} TsdReader;
|
||||
|
||||
typedef struct SStoreCacheReader {
|
||||
int32_t (*openReader)(void *pVnode, int32_t type, void *pTableIdList, int32_t numOfTables, int32_t numOfCols,
|
||||
SArray *pCidList, int32_t *pSlotIds, uint64_t suid, void **pReader, const char *idstr);
|
||||
void *(*closeReader)(void *pReader);
|
||||
int32_t (*retrieveRows)(void *pReader, SSDataBlock *pResBlock, const int32_t *slotIds, const int32_t *dstSlotIds,
|
||||
SArray *pTableUidList);
|
||||
int32_t (*reuseReader)(void *pReader, void *pTableIdList, int32_t numOfTables);
|
||||
} SStoreCacheReader;
|
||||
|
||||
// clang-format on
|
||||
|
||||
/*------------------------------------------------------------------------------------------------------------------*/
|
||||
/*
|
||||
void tqReaderSetColIdList(STqReader *pReader, SArray *pColIdList);
|
||||
int32_t tqReaderSetTbUidList(STqReader *pReader, const SArray *tbUidList);
|
||||
int32_t tqReaderAddTbUidList(STqReader *pReader, const SArray *pTableUidList);
|
||||
int32_t tqReaderRemoveTbUidList(STqReader *pReader, const SArray *tbUidList);
|
||||
bool tqReaderIsQueriedTable(STqReader* pReader, uint64_t uid);
|
||||
bool tqCurrentBlockConsumed(const STqReader* pReader);
|
||||
|
||||
int32_t tqReaderSeek(STqReader *pReader, int64_t ver, const char *id);
|
||||
bool tqNextBlockInWal(STqReader* pReader, const char* idstr);
|
||||
bool tqNextBlockImpl(STqReader *pReader, const char* idstr);
|
||||
|
||||
int32_t tqRetrieveDataBlock(STqReader *pReader, SSDataBlock **pRes, const char* idstr);
|
||||
STqReader *tqReaderOpen(void *pVnode);
|
||||
void tqReaderClose(STqReader *);
|
||||
|
||||
int32_t tqReaderSetSubmitMsg(STqReader *pReader, void *msgStr, int32_t msgLen, int64_t ver);
|
||||
bool tqNextDataBlockFilterOut(STqReader *pReader, SHashObj *filterOutUids);
|
||||
SWalReader* tqGetWalReader(STqReader* pReader);
|
||||
int32_t tqRetrieveTaosxBlock(STqReader *pReader, SArray *blocks, SArray *schemas, SSubmitTbData **pSubmitTbDataRet);
|
||||
*/
|
||||
// todo rename
|
||||
typedef struct SStoreTqReader {
|
||||
struct STqReader* (*tqReaderOpen)();
|
||||
void (*tqReaderClose)();
|
||||
|
||||
int32_t (*tqReaderSeek)();
|
||||
int32_t (*tqRetrieveBlock)();
|
||||
bool (*tqReaderNextBlockInWal)();
|
||||
bool (*tqNextBlockImpl)(); // todo remove it
|
||||
SSDataBlock* (*tqGetResultBlock)();
|
||||
|
||||
void (*tqReaderSetColIdList)();
|
||||
int32_t (*tqReaderSetQueryTableList)();
|
||||
|
||||
int32_t (*tqReaderAddTables)();
|
||||
int32_t (*tqReaderRemoveTables)();
|
||||
|
||||
bool (*tqReaderIsQueriedTable)();
|
||||
bool (*tqReaderCurrentBlockConsumed)();
|
||||
|
||||
struct SWalReader *(*tqReaderGetWalReader)(); // todo remove it
|
||||
int32_t (*tqReaderRetrieveTaosXBlock)(); // todo remove it
|
||||
|
||||
int32_t (*tqReaderSetSubmitMsg)(); // todo remove it
|
||||
bool (*tqReaderNextBlockFilterOut)();
|
||||
} SStoreTqReader;
|
||||
|
||||
typedef struct SStoreSnapshotFn {
|
||||
int32_t (*createSnapshot)(SSnapContext *ctx, int64_t uid);
|
||||
int32_t (*destroySnapshot)(SSnapContext *ctx);
|
||||
SMetaTableInfo (*getMetaTableInfoFromSnapshot)(SSnapContext* ctx);
|
||||
int32_t (*getTableInfoFromSnapshot)(SSnapContext* ctx, void** pBuf, int32_t* contLen, int16_t* type, int64_t* uid);
|
||||
} SStoreSnapshotFn;
|
||||
|
||||
/**
|
||||
void metaReaderInit(SMetaReader *pReader, SMeta *pMeta, int32_t flags);
|
||||
void metaReaderReleaseLock(SMetaReader *pReader);
|
||||
void metaReaderClear(SMetaReader *pReader);
|
||||
int32_t metaReaderGetTableEntryByUid(SMetaReader *pReader, tb_uid_t uid);
|
||||
int32_t metaReaderGetTableEntryByUidCache(SMetaReader *pReader, tb_uid_t uid);
|
||||
int32_t metaGetTableTags(SMeta *pMeta, uint64_t suid, SArray *uidList);
|
||||
const void *metaGetTableTagVal(void *tag, int16_t type, STagVal *tagVal);
|
||||
int metaGetTableNameByUid(void *meta, uint64_t uid, char *tbName);
|
||||
|
||||
int metaGetTableUidByName(void *meta, char *tbName, uint64_t *uid);
|
||||
int metaGetTableTypeByName(void *meta, char *tbName, ETableType *tbType);
|
||||
bool metaIsTableExist(SMeta *pMeta, tb_uid_t uid);
|
||||
int32_t metaGetCachedTableUidList(SMeta *pMeta, tb_uid_t suid, const uint8_t *key, int32_t keyLen, SArray *pList,
|
||||
bool *acquired);
|
||||
int32_t metaUidFilterCachePut(SMeta *pMeta, uint64_t suid, const void *pKey, int32_t keyLen, void *pPayload,
|
||||
int32_t payloadLen, double selectivityRatio);
|
||||
tb_uid_t metaGetTableEntryUidByName(SMeta *pMeta, const char *name);
|
||||
int32_t metaGetCachedTbGroup(SMeta* pMeta, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray** pList);
|
||||
int32_t metaPutTbGroupToCache(SMeta* pMeta, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload, int32_t payloadLen);
|
||||
*/
|
||||
|
||||
typedef struct SStoreMeta {
|
||||
SMTbCursor *(*openTableMetaCursor)(void *pVnode); // metaOpenTbCursor
|
||||
void (*closeTableMetaCursor)(SMTbCursor *pTbCur); // metaCloseTbCursor
|
||||
int32_t (*cursorNext)(SMTbCursor *pTbCur, ETableType jumpTableType); // metaTbCursorNext
|
||||
int32_t (*cursorPrev)(SMTbCursor *pTbCur, ETableType jumpTableType); // metaTbCursorPrev
|
||||
|
||||
int32_t (*getTableTags)(void *pVnode, uint64_t suid, SArray *uidList);
|
||||
int32_t (*getTableTagsByUid)(void *pVnode, int64_t suid, SArray *uidList);
|
||||
const void *(*extractTagVal)(const void *tag, int16_t type, STagVal *tagVal); // todo remove it
|
||||
|
||||
int32_t (*getTableUidByName)(void *pVnode, char *tbName, uint64_t *uid);
|
||||
int32_t (*getTableTypeByName)(void *pVnode, char *tbName, ETableType *tbType);
|
||||
int32_t (*getTableNameByUid)(void *pVnode, uint64_t uid, char *tbName);
|
||||
bool (*isTableExisted)(void *pVnode, tb_uid_t uid);
|
||||
|
||||
int32_t (*metaGetCachedTbGroup)(void* pVnode, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray** pList);
|
||||
int32_t (*metaPutTbGroupToCache)(void* pVnode, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload, int32_t payloadLen);
|
||||
|
||||
int32_t (*getCachedTableList)(void* pVnode, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray* pList1, bool* acquireRes);
|
||||
int32_t (*putCachedTableList)(void* pVnode, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload, int32_t payloadLen, double selectivityRatio);
|
||||
|
||||
void *(*storeGetIndexInfo)();
|
||||
void *(*getInvertIndex)(void* pVnode);
|
||||
int32_t (*getChildTableList)(void *pVnode, int64_t suid, SArray *list); // support filter and non-filter cases. [vnodeGetCtbIdList & vnodeGetCtbIdListByFilter]
|
||||
int32_t (*storeGetTableList)(void* pVnode, int8_t type, SArray* pList); // vnodeGetStbIdList & vnodeGetAllTableList
|
||||
void *storeGetVersionRange;
|
||||
void *storeGetLastTimestamp;
|
||||
|
||||
int32_t (*getTableSchema)(void *pVnode, int64_t uid, STSchema **pSchema, int64_t *suid); // tsdbGetTableSchema
|
||||
|
||||
// db name, vgId, numOfTables, numOfSTables
|
||||
int32_t (*getNumOfChildTables)(void* pVnode, int64_t uid, int64_t* numOfTables); // int32_t metaGetStbStats(SMeta *pMeta, int64_t uid, SMetaStbStats *pInfo);
|
||||
void (*getBasicInfo)(void *pVnode, const char **dbname, int32_t *vgId, int64_t* numOfTables, int64_t* numOfNormalTables);// vnodeGetInfo(void *pVnode, const char **dbname, int32_t *vgId) & metaGetTbNum(SMeta *pMeta) & metaGetNtbNum(SMeta *pMeta);
|
||||
|
||||
int64_t (*getNumOfRowsInMem)(void* pVnode);
|
||||
/**
|
||||
int32_t vnodeGetCtbIdList(void *pVnode, int64_t suid, SArray *list);
|
||||
int32_t vnodeGetCtbIdListByFilter(void *pVnode, int64_t suid, SArray *list, bool (*filter)(void *arg), void *arg);
|
||||
int32_t vnodeGetStbIdList(void *pVnode, int64_t suid, SArray *list);
|
||||
*/
|
||||
} SStoreMeta;
|
||||
|
||||
typedef struct SStoreMetaReader {
|
||||
void (*initReader)(SMetaReader *pReader, void *pVnode, int32_t flags, SStoreMeta* pAPI);
|
||||
void (*clearReader)(SMetaReader *pReader);
|
||||
void (*readerReleaseLock)(SMetaReader *pReader);
|
||||
int32_t (*getTableEntryByUid)(SMetaReader *pReader, tb_uid_t uid);
|
||||
int32_t (*getTableEntryByName)(SMetaReader *pReader, const char *name);
|
||||
int32_t (*getEntryGetUidCache)(SMetaReader *pReader, tb_uid_t uid);
|
||||
} SStoreMetaReader;
|
||||
|
||||
typedef struct SUpdateInfo {
|
||||
SArray *pTsBuckets;
|
||||
uint64_t numBuckets;
|
||||
SArray *pTsSBFs;
|
||||
uint64_t numSBFs;
|
||||
int64_t interval;
|
||||
int64_t watermark;
|
||||
TSKEY minTS;
|
||||
SScalableBf *pCloseWinSBF;
|
||||
SHashObj *pMap;
|
||||
uint64_t maxDataVersion;
|
||||
} SUpdateInfo;
|
||||
|
||||
typedef struct {
|
||||
void* iter; // rocksdb_iterator_t* iter;
|
||||
void* snapshot; // rocksdb_snapshot_t* snapshot;
|
||||
void* readOpt; // rocksdb_readoptions_t* readOpt;
|
||||
void* db; // rocksdb_t* db;
|
||||
void* pCur;
|
||||
int64_t number;
|
||||
} SStreamStateCur;
|
||||
|
||||
typedef struct SStateStore {
|
||||
int32_t (*streamStatePutParName)(SStreamState* pState, int64_t groupId, const char* tbname);
|
||||
int32_t (*streamStateGetParName)(SStreamState* pState, int64_t groupId, void** pVal);
|
||||
|
||||
int32_t (*streamStateAddIfNotExist)(SStreamState* pState, const SWinKey* key, void** pVal, int32_t* pVLen);
|
||||
int32_t (*streamStateReleaseBuf)(SStreamState* pState, const SWinKey* key, void* pVal);
|
||||
void (*streamStateFreeVal)(void* val);
|
||||
|
||||
int32_t (*streamStatePut)(SStreamState* pState, const SWinKey* key, const void* value, int32_t vLen);
|
||||
int32_t (*streamStateGet)(SStreamState* pState, const SWinKey* key, void** pVal, int32_t* pVLen);
|
||||
bool (*streamStateCheck)(SStreamState* pState, const SWinKey* key);
|
||||
int32_t (*streamStateGetByPos)(SStreamState* pState, void* pos, void** pVal);
|
||||
int32_t (*streamStateDel)(SStreamState* pState, const SWinKey* key);
|
||||
int32_t (*streamStateClear)(SStreamState* pState);
|
||||
void (*streamStateSetNumber)(SStreamState* pState, int32_t number);
|
||||
int32_t (*streamStateSaveInfo)(SStreamState* pState, void* pKey, int32_t keyLen, void* pVal, int32_t vLen);
|
||||
int32_t (*streamStateGetInfo)(SStreamState* pState, void* pKey, int32_t keyLen, void** pVal, int32_t* pLen);
|
||||
|
||||
int32_t (*streamStateFillPut)(SStreamState* pState, const SWinKey* key, const void* value, int32_t vLen);
|
||||
int32_t (*streamStateFillGet)(SStreamState* pState, const SWinKey* key, void** pVal, int32_t* pVLen);
|
||||
int32_t (*streamStateFillDel)(SStreamState* pState, const SWinKey* key);
|
||||
|
||||
int32_t (*streamStateCurNext)(SStreamState* pState, SStreamStateCur* pCur);
|
||||
int32_t (*streamStateCurPrev)(SStreamState* pState, SStreamStateCur* pCur);
|
||||
|
||||
SStreamStateCur* (*streamStateGetAndCheckCur)(SStreamState* pState, SWinKey* key);
|
||||
SStreamStateCur* (*streamStateSeekKeyNext)(SStreamState* pState, const SWinKey* key);
|
||||
SStreamStateCur* (*streamStateFillSeekKeyNext)(SStreamState* pState, const SWinKey* key);
|
||||
SStreamStateCur* (*streamStateFillSeekKeyPrev)(SStreamState* pState, const SWinKey* key);
|
||||
void (*streamStateFreeCur)(SStreamStateCur* pCur);
|
||||
|
||||
int32_t (*streamStateGetGroupKVByCur)(SStreamStateCur* pCur, SWinKey* pKey, const void** pVal, int32_t* pVLen);
|
||||
int32_t (*streamStateGetKVByCur)(SStreamStateCur* pCur, SWinKey* pKey, const void** pVal, int32_t* pVLen);
|
||||
|
||||
int32_t (*streamStateSessionAddIfNotExist)(SStreamState* pState, SSessionKey* key, TSKEY gap, void** pVal, int32_t* pVLen);
|
||||
int32_t (*streamStateSessionPut)(SStreamState* pState, const SSessionKey* key, const void* value, int32_t vLen);
|
||||
int32_t (*streamStateSessionGet)(SStreamState* pState, SSessionKey* key, void** pVal, int32_t* pVLen);
|
||||
int32_t (*streamStateSessionDel)(SStreamState* pState, const SSessionKey* key);
|
||||
int32_t (*streamStateSessionClear)(SStreamState* pState);
|
||||
int32_t (*streamStateSessionGetKVByCur)(SStreamStateCur* pCur, SSessionKey* pKey, void** pVal, int32_t* pVLen);
|
||||
int32_t (*streamStateStateAddIfNotExist)(SStreamState* pState, SSessionKey* key, char* pKeyData, int32_t keyDataLen,
|
||||
state_key_cmpr_fn fn, void** pVal, int32_t* pVLen);
|
||||
int32_t (*streamStateSessionGetKeyByRange)(SStreamState* pState, const SSessionKey* range, SSessionKey* curKey);
|
||||
|
||||
SUpdateInfo* (*updateInfoInit)(int64_t interval, int32_t precision, int64_t watermark);
|
||||
TSKEY (*updateInfoFillBlockData)(SUpdateInfo *pInfo, SSDataBlock *pBlock, int32_t primaryTsCol);
|
||||
bool (*updateInfoIsUpdated)(SUpdateInfo *pInfo, uint64_t tableId, TSKEY ts);
|
||||
bool (*updateInfoIsTableInserted)(SUpdateInfo *pInfo, int64_t tbUid);
|
||||
void (*updateInfoDestroy)(SUpdateInfo *pInfo);
|
||||
|
||||
SUpdateInfo* (*updateInfoInitP)(SInterval *pInterval, int64_t watermark);
|
||||
void (*updateInfoAddCloseWindowSBF)(SUpdateInfo *pInfo);
|
||||
void (*updateInfoDestoryColseWinSBF)(SUpdateInfo *pInfo);
|
||||
int32_t (*updateInfoSerialize)(void *buf, int32_t bufLen, const SUpdateInfo *pInfo);
|
||||
int32_t (*updateInfoDeserialize)(void *buf, int32_t bufLen, SUpdateInfo *pInfo);
|
||||
|
||||
SStreamStateCur* (*streamStateSessionSeekKeyNext)(SStreamState* pState, const SSessionKey* key);
|
||||
SStreamStateCur* (*streamStateSessionSeekKeyCurrentPrev)(SStreamState* pState, const SSessionKey* key);
|
||||
SStreamStateCur* (*streamStateSessionSeekKeyCurrentNext)(SStreamState* pState, const SSessionKey* key);
|
||||
|
||||
struct SStreamFileState* (*streamFileStateInit)(int64_t memSize, uint32_t keySize, uint32_t rowSize,
|
||||
uint32_t selectRowSize, GetTsFun fp, void* pFile, TSKEY delMark);
|
||||
|
||||
void (*streamFileStateDestroy)(struct SStreamFileState* pFileState);
|
||||
void (*streamFileStateClear)(struct SStreamFileState* pFileState);
|
||||
bool (*needClearDiskBuff)(struct SStreamFileState* pFileState);
|
||||
|
||||
SStreamState* (*streamStateOpen)(char* path, void* pTask, bool specPath, int32_t szPage, int32_t pages);
|
||||
void (*streamStateClose)(SStreamState* pState, bool remove);
|
||||
int32_t (*streamStateBegin)(SStreamState* pState);
|
||||
int32_t (*streamStateCommit)(SStreamState* pState);
|
||||
void (*streamStateDestroy)(SStreamState* pState, bool remove);
|
||||
int32_t (*streamStateDeleteCheckPoint)(SStreamState* pState, TSKEY mark);
|
||||
} SStateStore;
|
||||
|
||||
typedef struct SStorageAPI {
|
||||
SStoreMeta metaFn; // todo: refactor
|
||||
TsdReader tsdReader;
|
||||
SStoreMetaReader metaReaderFn;
|
||||
SStoreCacheReader cacheFn;
|
||||
SStoreSnapshotFn snapshotFn;
|
||||
SStoreTqReader tqReaderFn;
|
||||
SStateStore stateStore;
|
||||
SMetaDataFilterAPI metaFilter;
|
||||
SFunctionStateStore functionStore;
|
||||
} SStorageAPI;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TDENGINE_STORAGEAPI_H
|
|
@ -21,6 +21,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#include "tcommon.h"
|
||||
#include "tsimplehash.h"
|
||||
#include "tvariant.h"
|
||||
|
||||
struct SqlFunctionCtx;
|
||||
|
@ -127,13 +128,55 @@ typedef struct SSerializeDataHandle {
|
|||
void *pState;
|
||||
} SSerializeDataHandle;
|
||||
|
||||
// incremental state storage
|
||||
typedef struct STdbState {
|
||||
void *rocksdb;
|
||||
void **pHandle;
|
||||
void *writeOpts;
|
||||
void *readOpts;
|
||||
void **cfOpts;
|
||||
void *dbOpt;
|
||||
struct SStreamTask *pOwner;
|
||||
void *param;
|
||||
void *env;
|
||||
SListNode *pComparNode;
|
||||
void *pBackend;
|
||||
char idstr[64];
|
||||
void *compactFactory;
|
||||
TdThreadRwlock rwLock;
|
||||
|
||||
void *db;
|
||||
void *pStateDb;
|
||||
void *pFuncStateDb;
|
||||
void *pFillStateDb; // todo refactor
|
||||
void *pSessionStateDb;
|
||||
void *pParNameDb;
|
||||
void *pParTagDb;
|
||||
void *txn;
|
||||
} STdbState;
|
||||
|
||||
typedef struct {
|
||||
STdbState *pTdbState;
|
||||
struct SStreamFileState *pFileState;
|
||||
int32_t number;
|
||||
SSHashObj *parNameMap;
|
||||
int64_t checkPointId;
|
||||
int32_t taskId;
|
||||
int64_t streamId;
|
||||
} SStreamState;
|
||||
|
||||
typedef struct SFunctionStateStore {
|
||||
int32_t (*streamStateFuncPut)(SStreamState *pState, const SWinKey *key, const void *value, int32_t vLen);
|
||||
int32_t (*streamStateFuncGet)(SStreamState *pState, const SWinKey *key, void **ppVal, int32_t *pVLen);
|
||||
} SFunctionStateStore;
|
||||
|
||||
// sql function runtime context
|
||||
typedef struct SqlFunctionCtx {
|
||||
SInputColumnInfoData input;
|
||||
SResultDataInfo resDataInfo;
|
||||
uint32_t order; // data block scanner order: asc|desc
|
||||
uint8_t isPseudoFunc;// denote current function is pseudo function or not [added for perf reason]
|
||||
uint8_t isNotNullFunc;// not return null value.
|
||||
uint8_t isPseudoFunc; // denote current function is pseudo function or not [added for perf reason]
|
||||
uint8_t isNotNullFunc; // not return null value.
|
||||
uint8_t scanFlag; // record current running step, default: 0
|
||||
int16_t functionId; // function id
|
||||
char *pOutput; // final result output buffer, point to sdata->data
|
||||
|
@ -155,6 +198,7 @@ typedef struct SqlFunctionCtx {
|
|||
SSerializeDataHandle saveHandle;
|
||||
int32_t exprIdx;
|
||||
char *udfName;
|
||||
SFunctionStateStore *pStore;
|
||||
} SqlFunctionCtx;
|
||||
|
||||
typedef struct tExprNode {
|
||||
|
|
|
@ -158,6 +158,17 @@ typedef enum EFunctionType {
|
|||
FUNCTION_TYPE_STDDEV_PARTIAL,
|
||||
FUNCTION_TYPE_STDDEV_MERGE,
|
||||
|
||||
// geometry functions
|
||||
FUNCTION_TYPE_GEOM_FROM_TEXT = 4250,
|
||||
FUNCTION_TYPE_AS_TEXT,
|
||||
FUNCTION_TYPE_MAKE_POINT,
|
||||
FUNCTION_TYPE_INTERSECTS,
|
||||
FUNCTION_TYPE_EQUALS,
|
||||
FUNCTION_TYPE_TOUCHES,
|
||||
FUNCTION_TYPE_COVERS,
|
||||
FUNCTION_TYPE_CONTAINS,
|
||||
FUNCTION_TYPE_CONTAINS_PROPERLY,
|
||||
|
||||
// user defined funcion
|
||||
FUNCTION_TYPE_UDF = 10000
|
||||
} EFunctionType;
|
||||
|
|
|
@ -109,7 +109,7 @@ typedef uint16_t VarDataLenT; // maxVarDataLen: 65535
|
|||
#define varDataLenByData(v) (*(VarDataLenT *)(((char *)(v)) - VARSTR_HEADER_SIZE))
|
||||
#define varDataSetLen(v, _len) (((VarDataLenT *)(v))[0] = (VarDataLenT)(_len))
|
||||
#define IS_VAR_DATA_TYPE(t) \
|
||||
(((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR) || ((t) == TSDB_DATA_TYPE_JSON))
|
||||
(((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR) || ((t) == TSDB_DATA_TYPE_JSON) || ((t) == TSDB_DATA_TYPE_GEOMETRY))
|
||||
#define IS_STR_DATA_TYPE(t) (((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR))
|
||||
|
||||
static FORCE_INLINE char *udfColDataGetData(const SUdfColumn *pColumn, int32_t row) {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_GEOM_FUNC_H
|
||||
#define TDENGINE_GEOM_FUNC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "function.h"
|
||||
|
||||
int32_t makePointFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
|
||||
int32_t geomFromTextFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t asTextFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
|
||||
int32_t intersectsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t equalsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t touchesFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t coversFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t containsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t containsProperlyFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TDENGINE_GEOM_FUNC_H
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_GEOS_WRAPPER_H
|
||||
#define TDENGINE_GEOS_WRAPPER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "os.h"
|
||||
|
||||
#include "tgeosctx.h"
|
||||
|
||||
void geosFreeBuffer(void *buffer);
|
||||
|
||||
int32_t initCtxMakePoint();
|
||||
int32_t doMakePoint(double x, double y, unsigned char **outputGeom, size_t *size);
|
||||
|
||||
int32_t initCtxGeomFromText();
|
||||
int32_t doGeomFromText(const char *inputWKT, unsigned char **outputGeom, size_t *size);
|
||||
|
||||
int32_t initCtxAsText();
|
||||
int32_t doAsText(const unsigned char *inputGeom, size_t size, char **outputWKT);
|
||||
|
||||
int32_t initCtxRelationFunc();
|
||||
int32_t doIntersects(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
int32_t doEquals(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
int32_t doTouches(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
int32_t doCovers(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
int32_t doContains(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
int32_t doContainsProperly(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
|
||||
int32_t readGeometry(const unsigned char *input, GEOSGeometry **outputGeom, const GEOSPreparedGeometry **outputPreparedGeom);
|
||||
void destroyGeometry(GEOSGeometry **geom, const GEOSPreparedGeometry **preparedGeom);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*TDENGINE_GEOS_WRAPPER_H*/
|
|
@ -212,13 +212,38 @@ typedef struct SIndexMetaArg {
|
|||
void* idx;
|
||||
void* ivtIdx;
|
||||
uint64_t suid;
|
||||
int (*metaFilterFunc)(void* metaEx, void* param, SArray* result);
|
||||
} SIndexMetaArg;
|
||||
|
||||
/**
|
||||
* the underlying storage module must implement this API to employ the index functions.
|
||||
* @param pMeta
|
||||
* @param param
|
||||
* @param results
|
||||
* @return
|
||||
*/
|
||||
typedef struct SMetaFltParam {
|
||||
uint64_t suid;
|
||||
int16_t cid;
|
||||
int16_t type;
|
||||
void *val;
|
||||
bool reverse;
|
||||
bool equal;
|
||||
int (*filterFunc)(void *a, void *b, int16_t type);
|
||||
} SMetaFltParam;
|
||||
|
||||
typedef struct SMetaDataFilterAPI {
|
||||
int32_t (*metaFilterTableIds)(void *pVnode, SMetaFltParam *arg, SArray *pUids);
|
||||
int32_t (*metaFilterCreateTime)(void *pVnode, SMetaFltParam *arg, SArray *pUids);
|
||||
int32_t (*metaFilterTableName)(void *pVnode, SMetaFltParam *arg, SArray *pUids);
|
||||
int32_t (*metaFilterTtl)(void *pVnode, SMetaFltParam *arg, SArray *pUids);
|
||||
} SMetaDataFilterAPI;
|
||||
|
||||
typedef enum { SFLT_NOT_INDEX, SFLT_COARSE_INDEX, SFLT_ACCURATE_INDEX } SIdxFltStatus;
|
||||
|
||||
SIdxFltStatus idxGetFltStatus(SNode* pFilterNode);
|
||||
SIdxFltStatus idxGetFltStatus(SNode* pFilterNode, SMetaDataFilterAPI* pAPI);
|
||||
|
||||
int32_t doFilterTag(SNode* pFilterNode, SIndexMetaArg* metaArg, SArray* result, SIdxFltStatus* status);
|
||||
int32_t doFilterTag(SNode* pFilterNode, SIndexMetaArg* metaArg, SArray* result, SIdxFltStatus* status, SMetaDataFilterAPI* pAPI);
|
||||
|
||||
/*
|
||||
* init index env
|
||||
|
|
|
@ -90,28 +90,23 @@ typedef struct STbVerInfo {
|
|||
int32_t tversion;
|
||||
} STbVerInfo;
|
||||
|
||||
/*
|
||||
* ASSERT(sizeof(SCTableMeta) == 24)
|
||||
* ASSERT(tableType == TSDB_CHILD_TABLE)
|
||||
* The cached child table meta info. For each child table, 24 bytes are required to keep the essential table info.
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct SCTableMeta {
|
||||
int32_t vgId : 24;
|
||||
int8_t tableType;
|
||||
uint64_t uid;
|
||||
uint64_t suid;
|
||||
int32_t vgId;
|
||||
int8_t tableType;
|
||||
} SCTableMeta;
|
||||
#pragma pack(pop)
|
||||
|
||||
/*
|
||||
* Note that the first 24 bytes of STableMeta are identical to SCTableMeta, it is safe to cast a STableMeta to be a
|
||||
* SCTableMeta.
|
||||
*/
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct STableMeta {
|
||||
// BEGIN: KEEP THIS PART SAME WITH SCTableMeta
|
||||
int32_t vgId : 24;
|
||||
int8_t tableType;
|
||||
uint64_t uid;
|
||||
uint64_t suid;
|
||||
int32_t vgId;
|
||||
int8_t tableType;
|
||||
// END: KEEP THIS PART SAME WITH SCTableMeta
|
||||
|
||||
// if the table is TSDB_CHILD_TABLE, the following information is acquired from the corresponding super table meta
|
||||
|
@ -121,6 +116,7 @@ typedef struct STableMeta {
|
|||
STableComInfo tableInfo;
|
||||
SSchema schema[];
|
||||
} STableMeta;
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct SDBVgInfo {
|
||||
int32_t vgVersion;
|
||||
|
@ -130,7 +126,7 @@ typedef struct SDBVgInfo {
|
|||
int32_t numOfTable; // DB's table num, unit is TSDB_TABLE_NUM_UNIT
|
||||
int64_t stateTs;
|
||||
SHashObj* vgHash; // key:vgId, value:SVgroupInfo
|
||||
SArray* vgArray;
|
||||
SArray* vgArray; // SVgroupInfo
|
||||
} SDBVgInfo;
|
||||
|
||||
typedef struct SUseDbOutput {
|
||||
|
|
|
@ -27,65 +27,63 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "storageapi.h"
|
||||
|
||||
// void* streamBackendInit(const char* path);
|
||||
// void streamBackendCleanup(void* arg);
|
||||
// SListNode* streamBackendAddCompare(void* backend, void* arg);
|
||||
// void streamBackendDelCompare(void* backend, void* arg);
|
||||
typedef bool (*state_key_cmpr_fn)(void* pKey1, void* pKey2);
|
||||
|
||||
typedef struct STdbState {
|
||||
rocksdb_t* rocksdb;
|
||||
rocksdb_column_family_handle_t** pHandle;
|
||||
rocksdb_writeoptions_t* writeOpts;
|
||||
rocksdb_readoptions_t* readOpts;
|
||||
rocksdb_options_t** cfOpts;
|
||||
rocksdb_options_t* dbOpt;
|
||||
struct SStreamTask* pOwner;
|
||||
void* param;
|
||||
void* env;
|
||||
SListNode* pComparNode;
|
||||
void* pBackendHandle;
|
||||
char idstr[64];
|
||||
void* compactFactory;
|
||||
// <<<<<<< HEAD
|
||||
// typedef struct STdbState {
|
||||
// rocksdb_t* rocksdb;
|
||||
// rocksdb_column_family_handle_t** pHandle;
|
||||
// rocksdb_writeoptions_t* writeOpts;
|
||||
// rocksdb_readoptions_t* readOpts;
|
||||
// rocksdb_options_t** cfOpts;
|
||||
// rocksdb_options_t* dbOpt;
|
||||
// struct SStreamTask* pOwner;
|
||||
// void* param;
|
||||
// void* env;
|
||||
// SListNode* pComparNode;
|
||||
// void* pBackend;
|
||||
// char idstr[64];
|
||||
// void* compactFactory;
|
||||
// TdThreadRwlock rwLock;
|
||||
// =======
|
||||
// typedef struct STdbState {
|
||||
// rocksdb_t* rocksdb;
|
||||
// rocksdb_column_family_handle_t** pHandle;
|
||||
// rocksdb_writeoptions_t* writeOpts;
|
||||
// rocksdb_readoptions_t* readOpts;
|
||||
// rocksdb_options_t** cfOpts;
|
||||
// rocksdb_options_t* dbOpt;
|
||||
// struct SStreamTask* pOwner;
|
||||
// void* param;
|
||||
// void* env;
|
||||
// SListNode* pComparNode;
|
||||
// void* pBackendHandle;
|
||||
// char idstr[64];
|
||||
// void* compactFactory;
|
||||
//
|
||||
// TDB* db;
|
||||
// TTB* pStateDb;
|
||||
// TTB* pFuncStateDb;
|
||||
// TTB* pFillStateDb; // todo refactor
|
||||
// TTB* pSessionStateDb;
|
||||
// TTB* pParNameDb;
|
||||
// TTB* pParTagDb;
|
||||
// TXN* txn;
|
||||
//} STdbState;
|
||||
//>>>>>>> enh/dev3.0
|
||||
|
||||
TDB* db;
|
||||
TTB* pStateDb;
|
||||
TTB* pFuncStateDb;
|
||||
TTB* pFillStateDb; // todo refactor
|
||||
TTB* pSessionStateDb;
|
||||
TTB* pParNameDb;
|
||||
TTB* pParTagDb;
|
||||
TXN* txn;
|
||||
} STdbState;
|
||||
|
||||
// incremental state storage
|
||||
typedef struct {
|
||||
STdbState* pTdbState;
|
||||
SStreamFileState* pFileState;
|
||||
int32_t number;
|
||||
SSHashObj* parNameMap;
|
||||
int64_t checkPointId;
|
||||
int32_t taskId;
|
||||
int64_t streamId;
|
||||
} SStreamState;
|
||||
|
||||
SStreamState* streamStateOpen(char* path, struct SStreamTask* pTask, bool specPath, int32_t szPage, int32_t pages);
|
||||
SStreamState* streamStateOpen(char* path, void* pTask, bool specPath, int32_t szPage, int32_t pages);
|
||||
void streamStateClose(SStreamState* pState, bool remove);
|
||||
int32_t streamStateBegin(SStreamState* pState);
|
||||
int32_t streamStateCommit(SStreamState* pState);
|
||||
void streamStateDestroy(SStreamState* pState, bool remove);
|
||||
int32_t streamStateDeleteCheckPoint(SStreamState* pState, TSKEY mark);
|
||||
|
||||
typedef struct {
|
||||
rocksdb_iterator_t* iter;
|
||||
rocksdb_snapshot_t* snapshot;
|
||||
rocksdb_readoptions_t* readOpt;
|
||||
rocksdb_t* db;
|
||||
|
||||
TBC* pCur;
|
||||
int64_t number;
|
||||
} SStreamStateCur;
|
||||
|
||||
int32_t streamStateFuncPut(SStreamState* pState, const SWinKey* key, const void* value, int32_t vLen);
|
||||
int32_t streamStateFuncGet(SStreamState* pState, const SWinKey* key, void** ppVal, int32_t* pVLen);
|
||||
|
||||
|
@ -119,7 +117,7 @@ int32_t streamStateFillDel(SStreamState* pState, const SWinKey* key);
|
|||
|
||||
int32_t streamStateAddIfNotExist(SStreamState* pState, const SWinKey* key, void** pVal, int32_t* pVLen);
|
||||
int32_t streamStateReleaseBuf(SStreamState* pState, const SWinKey* key, void* pVal);
|
||||
void streamFreeVal(void* val);
|
||||
void streamStateFreeVal(void* val);
|
||||
|
||||
SStreamStateCur* streamStateGetAndCheckCur(SStreamState* pState, SWinKey* key);
|
||||
SStreamStateCur* streamStateSeekKeyNext(SStreamState* pState, const SWinKey* key);
|
||||
|
|
|
@ -78,11 +78,11 @@ enum {
|
|||
TASK_TRIGGER_STATUS__ACTIVE,
|
||||
};
|
||||
|
||||
enum {
|
||||
typedef enum {
|
||||
TASK_LEVEL__SOURCE = 1,
|
||||
TASK_LEVEL__AGG,
|
||||
TASK_LEVEL__SINK,
|
||||
};
|
||||
} ETASK_LEVEL;
|
||||
|
||||
enum {
|
||||
TASK_OUTPUT__FIXED_DISPATCH = 1,
|
||||
|
@ -284,13 +284,13 @@ struct SStreamTask {
|
|||
int16_t dispatchMsgType;
|
||||
SStreamStatus status;
|
||||
int32_t selfChildId;
|
||||
int32_t nodeId;
|
||||
int32_t nodeId; // vgroup id
|
||||
SEpSet epSet;
|
||||
SCheckpointInfo chkInfo;
|
||||
STaskExec exec;
|
||||
|
||||
// fill history
|
||||
int8_t fillHistory;
|
||||
int8_t fillHistory; // fill history
|
||||
int64_t ekey; // end ts key
|
||||
int64_t endVer; // end version
|
||||
|
||||
// children info
|
||||
SArray* childEpInfo; // SArray<SStreamChildEpInfo*>
|
||||
|
@ -351,7 +351,7 @@ typedef struct SStreamMeta {
|
|||
int32_t tEncodeStreamEpInfo(SEncoder* pEncoder, const SStreamChildEpInfo* pInfo);
|
||||
int32_t tDecodeStreamEpInfo(SDecoder* pDecoder, SStreamChildEpInfo* pInfo);
|
||||
|
||||
SStreamTask* tNewStreamTask(int64_t streamId);
|
||||
SStreamTask* tNewStreamTask(int64_t streamId, int8_t taskLevel, int8_t fillHistory, int64_t triggerParam, SArray* pTaskList);
|
||||
int32_t tEncodeStreamTask(SEncoder* pEncoder, const SStreamTask* pTask);
|
||||
int32_t tDecodeStreamTask(SDecoder* pDecoder, SStreamTask* pTask);
|
||||
void tFreeStreamTask(SStreamTask* pTask);
|
||||
|
@ -372,6 +372,7 @@ typedef struct {
|
|||
int32_t upstreamChildId;
|
||||
int32_t upstreamNodeId;
|
||||
int32_t blockNum;
|
||||
int64_t totalLen;
|
||||
SArray* dataLen; // SArray<int32_t>
|
||||
SArray* data; // SArray<SRetrieveTableRsp*>
|
||||
} SStreamDispatchReq;
|
||||
|
@ -527,7 +528,7 @@ void tDeleteStreamDispatchReq(SStreamDispatchReq* pReq);
|
|||
int32_t streamSetupTrigger(SStreamTask* pTask);
|
||||
|
||||
int32_t streamProcessRunReq(SStreamTask* pTask);
|
||||
int32_t streamProcessDispatchReq(SStreamTask* pTask, SStreamDispatchReq* pReq, SRpcMsg* pMsg, bool exec);
|
||||
int32_t streamProcessDispatchMsg(SStreamTask* pTask, SStreamDispatchReq* pReq, SRpcMsg* pMsg, bool exec);
|
||||
int32_t streamProcessDispatchRsp(SStreamTask* pTask, SStreamDispatchRsp* pRsp, int32_t code);
|
||||
|
||||
int32_t streamProcessRetrieveReq(SStreamTask* pTask, SStreamRetrieveReq* pReq, SRpcMsg* pMsg);
|
||||
|
@ -536,7 +537,7 @@ int32_t streamProcessRetrieveReq(SStreamTask* pTask, SStreamRetrieveReq* pReq, S
|
|||
void streamTaskInputFail(SStreamTask* pTask);
|
||||
int32_t streamTryExec(SStreamTask* pTask);
|
||||
int32_t streamSchedExec(SStreamTask* pTask);
|
||||
int32_t streamTaskOutput(SStreamTask* pTask, SStreamDataBlock* pBlock);
|
||||
int32_t streamTaskOutputResultBlock(SStreamTask* pTask, SStreamDataBlock* pBlock);
|
||||
bool streamTaskShouldStop(const SStreamStatus* pStatus);
|
||||
bool streamTaskShouldPause(const SStreamStatus* pStatus);
|
||||
|
||||
|
|
|
@ -21,23 +21,16 @@
|
|||
#include "tarray.h"
|
||||
#include "tdef.h"
|
||||
#include "tlist.h"
|
||||
#include "storageapi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct SStreamFileState SStreamFileState;
|
||||
typedef struct SRowBuffPos {
|
||||
void* pRowBuff;
|
||||
void* pKey;
|
||||
bool beFlushed;
|
||||
bool beUsed;
|
||||
} SRowBuffPos;
|
||||
|
||||
typedef SList SStreamSnapshot;
|
||||
|
||||
typedef TSKEY (*GetTsFun)(void*);
|
||||
|
||||
SStreamFileState* streamFileStateInit(int64_t memSize, uint32_t keySize, uint32_t rowSize, uint32_t selectRowSize,
|
||||
GetTsFun fp, void* pFile, TSKEY delMark);
|
||||
void streamFileStateDestroy(SStreamFileState* pFileState);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "tarray.h"
|
||||
#include "tcommon.h"
|
||||
#include "tmsg.h"
|
||||
#include "tscalablebf.h"
|
||||
#include "storageapi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -30,18 +30,18 @@ typedef struct SUpdateKey {
|
|||
TSKEY ts;
|
||||
} SUpdateKey;
|
||||
|
||||
typedef struct SUpdateInfo {
|
||||
SArray *pTsBuckets;
|
||||
uint64_t numBuckets;
|
||||
SArray *pTsSBFs;
|
||||
uint64_t numSBFs;
|
||||
int64_t interval;
|
||||
int64_t watermark;
|
||||
TSKEY minTS;
|
||||
SScalableBf *pCloseWinSBF;
|
||||
SHashObj *pMap;
|
||||
uint64_t maxDataVersion;
|
||||
} SUpdateInfo;
|
||||
//typedef struct SUpdateInfo {
|
||||
// SArray *pTsBuckets;
|
||||
// uint64_t numBuckets;
|
||||
// SArray *pTsSBFs;
|
||||
// uint64_t numSBFs;
|
||||
// int64_t interval;
|
||||
// int64_t watermark;
|
||||
// TSKEY minTS;
|
||||
// SScalableBf *pCloseWinSBF;
|
||||
// SHashObj *pMap;
|
||||
// uint64_t maxDataVersion;
|
||||
//} SUpdateInfo;
|
||||
|
||||
SUpdateInfo *updateInfoInitP(SInterval *pInterval, int64_t watermark);
|
||||
SUpdateInfo *updateInfoInit(int64_t interval, int32_t precision, int64_t watermark);
|
||||
|
|
|
@ -149,6 +149,7 @@ struct SWalReader {
|
|||
TdFilePtr pIdxFile;
|
||||
int64_t curFileFirstVer;
|
||||
int64_t curVersion;
|
||||
int64_t skipToVersion; // skip data and jump to destination version, usually used by stream resume ignoring untreated data
|
||||
int64_t capacity;
|
||||
TdThreadMutex mutex;
|
||||
SWalFilterCond cond;
|
||||
|
@ -200,6 +201,8 @@ int32_t walReaderSeekVer(SWalReader *pRead, int64_t ver);
|
|||
int32_t walNextValidMsg(SWalReader *pRead);
|
||||
int64_t walReaderGetCurrentVer(const SWalReader *pReader);
|
||||
int64_t walReaderGetValidFirstVer(const SWalReader *pReader);
|
||||
int64_t walReaderGetSkipToVersion(SWalReader *pReader);
|
||||
void walReaderSetSkipToVersion(SWalReader *pReader, int64_t ver);
|
||||
void walReaderValidVersionRange(SWalReader *pReader, int64_t *sver, int64_t *ever);
|
||||
void walReaderVerifyOffset(SWalReader *pWalReader, STqOffsetVal* pOffset);
|
||||
|
||||
|
|
|
@ -409,6 +409,7 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_MNODE_ALREADY_IS_VOTER TAOS_DEF_ERROR_CODE(0, 0x0413) // internal
|
||||
#define TSDB_CODE_MNODE_ONLY_TWO_MNODE TAOS_DEF_ERROR_CODE(0, 0x0414) // internal
|
||||
#define TSDB_CODE_MNODE_NO_NEED_RESTORE TAOS_DEF_ERROR_CODE(0, 0x0415) // internal
|
||||
#define TSDB_CODE_DNODE_ONLY_USE_WHEN_OFFLINE TAOS_DEF_ERROR_CODE(0, 0x0416)
|
||||
|
||||
// vnode
|
||||
// #define TSDB_CODE_VND_ACTION_IN_PROGRESS TAOS_DEF_ERROR_CODE(0, 0x0500) // 2.x
|
||||
|
|
|
@ -32,7 +32,7 @@ extern "C" {
|
|||
#define TD_VER_MAX UINT64_MAX // TODO: use the real max version from query handle
|
||||
|
||||
// Bytes for each type.
|
||||
extern const int32_t TYPE_BYTES[16];
|
||||
extern const int32_t TYPE_BYTES[17];
|
||||
|
||||
// TODO: replace and remove code below
|
||||
#define CHAR_BYTES sizeof(char)
|
||||
|
@ -57,6 +57,7 @@ extern const int32_t TYPE_BYTES[16];
|
|||
#define TSDB_DATA_DOUBLE_NULL 0x7FFFFF0000000000LL // an NAN
|
||||
#define TSDB_DATA_NCHAR_NULL 0xFFFFFFFF
|
||||
#define TSDB_DATA_BINARY_NULL 0xFF
|
||||
#define TSDB_DATA_GEOMETRY_NULL 0xFF
|
||||
|
||||
#define TSDB_DATA_UTINYINT_NULL 0xFF
|
||||
#define TSDB_DATA_USMALLINT_NULL 0xFFFF
|
||||
|
@ -253,6 +254,7 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_IPv4ADDR_LEN 16
|
||||
#define TSDB_FILENAME_LEN 128
|
||||
#define TSDB_SHOW_SQL_LEN 2048
|
||||
#define TSDB_SHOW_SCHEMA_JSON_LEN TSDB_MAX_COLUMNS * 256
|
||||
#define TSDB_SLOW_QUERY_SQL_LEN 512
|
||||
#define TSDB_SHOW_SUBQUERY_LEN 1000
|
||||
|
||||
|
@ -267,8 +269,8 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_DNODE_CONFIG_LEN 128
|
||||
#define TSDB_DNODE_VALUE_LEN 256
|
||||
|
||||
#define TSDB_ACTIVE_KEY_LEN 109 // history 109:?
|
||||
#define TSDB_CONN_ACTIVE_KEY_LEN 257 // history 257:?
|
||||
#define TSDB_ACTIVE_KEY_LEN 109
|
||||
#define TSDB_CONN_ACTIVE_KEY_LEN 255
|
||||
|
||||
#define TSDB_DEFAULT_PKT_SIZE 65480 // same as RPC_MAX_UDP_SIZE
|
||||
|
||||
|
@ -410,6 +412,8 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_MAX_FIELD_LEN 65519 // 16384:65519
|
||||
#define TSDB_MAX_BINARY_LEN TSDB_MAX_FIELD_LEN // 16384-8:65519
|
||||
#define TSDB_MAX_NCHAR_LEN TSDB_MAX_FIELD_LEN // 16384-8:65519
|
||||
#define TSDB_MAX_GEOMETRY_LEN TSDB_MAX_FIELD_LEN // 16384-8:65519
|
||||
|
||||
#define PRIMARYKEY_TIMESTAMP_COL_ID 1
|
||||
#define COL_REACH_END(colId, maxColId) ((colId) > (maxColId))
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TD_UTIL_GEOS_CTX_H_
|
||||
#define _TD_UTIL_GEOS_CTX_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <geos_c.h>
|
||||
|
||||
typedef struct SGeosContext {
|
||||
GEOSContextHandle_t handle;
|
||||
|
||||
GEOSWKTReader *WKTReader;
|
||||
GEOSWKTWriter *WKTWriter;
|
||||
|
||||
GEOSWKBReader *WKBReader;
|
||||
GEOSWKBWriter *WKBWriter;
|
||||
|
||||
char errMsg[512];
|
||||
} SGeosContext;
|
||||
|
||||
SGeosContext* getThreadLocalGeosCtx();
|
||||
void destroyThreadLocalGeosCtx();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_TD_UTIL_GEOS_CTX_H_*/
|
|
@ -123,6 +123,16 @@ else
|
|||
echo "Unknown cpuType: ${cpuType}"
|
||||
exit 1
|
||||
fi
|
||||
# check the tdengine cloud base image existed or not
|
||||
if [ "$cloudBuild" == "y" ]; then
|
||||
CloudBase=$(docker images | grep tdengine/tdengine-cloud-base ||:)
|
||||
if [[ "$CloudBase" == "" ]]; then
|
||||
echo "Rebuild tdengine cloud base image..."
|
||||
docker build --rm -f "${communityDir}/packaging/docker/DockerfileCloud.base" -t tdengine/tdengine-cloud-base "." --build-arg cpuType=${cpuTypeAlias}
|
||||
else
|
||||
echo "Already found tdengine cloud base image"
|
||||
fi
|
||||
fi
|
||||
|
||||
docker build --rm -f "${Dockerfile}" --network=host -t tdengine/tdengine-${dockername}:${version} "." --build-arg pkgFile=${pkgFile} --build-arg dirName=${dirName} --build-arg cpuType=${cpuTypeAlias}
|
||||
if [ "$cloudBuild" != "y" ]; then
|
||||
|
|
|
@ -175,7 +175,7 @@ if [ "$pagMode" == "lite" ]; then
|
|||
fi
|
||||
chmod a+x ${install_dir}/install_client.sh
|
||||
|
||||
if [[ $productName == "TDengine" ]]; then
|
||||
if [[ $productName == "TDengine" ]] && [ "$verMode" != "cloud" ]; then
|
||||
# Copy example code
|
||||
mkdir -p ${install_dir}/examples
|
||||
examples_dir="${top_dir}/examples"
|
||||
|
@ -191,7 +191,7 @@ if [[ $productName == "TDengine" ]]; then
|
|||
mkdir -p ${install_dir}/examples/taosbenchmark-json && cp ${examples_dir}/../tools/taos-tools/example/* ${install_dir}/examples/taosbenchmark-json
|
||||
fi
|
||||
|
||||
if [ "$verMode" == "cluster" ] || [ "$verMode" == "cloud" ]; then
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
# Copy connector
|
||||
connector_dir="${code_dir}/connector"
|
||||
mkdir -p ${install_dir}/connector
|
||||
|
|
|
@ -69,7 +69,10 @@ if [ "$pagMode" == "lite" ]; then
|
|||
bin_files="${build_dir}/bin/${serverName} ${build_dir}/bin/${clientName} ${script_dir}/remove.sh ${script_dir}/startPre.sh ${build_dir}/bin/taosBenchmark "
|
||||
taostools_bin_files=""
|
||||
else
|
||||
|
||||
if [ "$verMode" == "cloud" ]; then
|
||||
taostools_bin_files=" ${build_dir}/bin/taosdump \
|
||||
${build_dir}/bin/taosBenchmark"
|
||||
else
|
||||
wget https://github.com/taosdata/grafanaplugin/releases/latest/download/TDinsight.sh -O ${build_dir}/bin/TDinsight.sh \
|
||||
&& echo "TDinsight.sh downloaded!" \
|
||||
|| echo "failed to download TDinsight.sh"
|
||||
|
@ -79,7 +82,7 @@ else
|
|||
cd ${build_dir}/bin/ && \
|
||||
chmod +x TDinsight.sh
|
||||
./TDinsight.sh --download-only ||:
|
||||
# tdinsight_caches=$(./TDinsight.sh --download-only | xargs -I printf "${build_dir}/bin/{} ")
|
||||
# tdinsight_caches=$(./TDinsight.sh --download-only | xargs -I printf "${build_dir}/bin/{} ")
|
||||
cd $orig_pwd
|
||||
echo "TDinsight caches: $tdinsight_caches"
|
||||
|
||||
|
@ -88,6 +91,8 @@ else
|
|||
${build_dir}/bin/TDinsight.sh \
|
||||
${build_dir}/bin/tdengine-datasource.zip \
|
||||
${build_dir}/bin/tdengine-datasource.zip.md5sum"
|
||||
fi
|
||||
|
||||
[ -f ${build_dir}/bin/taosx ] && taosx_bin="${build_dir}/bin/taosx"
|
||||
explorer_bin_files=$(find ${build_dir}/bin/ -name '*-explorer')
|
||||
|
||||
|
@ -334,14 +339,14 @@ mkdir -p ${install_dir}/driver && cp ${lib_files} ${install_dir}/driver && echo
|
|||
[ -f ${wslib_files} ] && cp ${wslib_files} ${install_dir}/driver || :
|
||||
|
||||
# Copy connector
|
||||
if [ "$verMode" == "cluster" ] || [ "$verMode" == "cloud" ]; then
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
connector_dir="${code_dir}/connector"
|
||||
mkdir -p ${install_dir}/connector
|
||||
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
||||
tmp_pwd=`pwd`
|
||||
cd ${install_dir}/connector
|
||||
if [ ! -d taos-connector-jdbc ];then
|
||||
git clone -b 3.1.0 --depth=1 https://github.com/taosdata/taos-connector-jdbc.git ||:
|
||||
git clone -b 3.2.1 --depth=1 https://github.com/taosdata/taos-connector-jdbc.git ||:
|
||||
fi
|
||||
cd taos-connector-jdbc
|
||||
mvn clean package -Dmaven.test.skip=true
|
||||
|
@ -424,7 +429,7 @@ if [ "$exitcode" != "0" ]; then
|
|||
exit $exitcode
|
||||
fi
|
||||
|
||||
if [ -n "${taostools_bin_files}" ]; then
|
||||
if [ -n "${taostools_bin_files}" ] && [ "$verMode" != "cloud" ]; then
|
||||
wget https://github.com/taosdata/grafanaplugin/releases/latest/download/TDinsight.sh -O ${taostools_install_dir}/bin/TDinsight.sh && echo "TDinsight.sh downloaded!"|| echo "failed to download TDinsight.sh"
|
||||
if [ "$osType" != "Darwin" ]; then
|
||||
tar -zcv -f "$(basename ${taostools_pkg_name}).tar.gz" "$(basename ${taostools_install_dir})" --remove-files || :
|
||||
|
|
|
@ -232,9 +232,9 @@ int smlJsonParseObjFirst(char **start, SSmlLineInfo *element, int8_t *
|
|||
int smlJsonParseObj(char **start, SSmlLineInfo *element, int8_t *offset);
|
||||
//SArray *smlJsonParseTags(char *start, char *end);
|
||||
bool smlParseNumberOld(SSmlKv *kvVal, SSmlMsgBuf *msg);
|
||||
void* nodeListGet(NodeList* list, const void *key, int32_t len, _equal_fn_sml fn);
|
||||
int nodeListSet(NodeList** list, const void *key, int32_t len, void* value, _equal_fn_sml fn);
|
||||
int nodeListSize(NodeList* list);
|
||||
//void* nodeListGet(NodeList* list, const void *key, int32_t len, _equal_fn_sml fn);
|
||||
//int nodeListSet(NodeList** list, const void *key, int32_t len, void* value, _equal_fn_sml fn);
|
||||
//int nodeListSize(NodeList* list);
|
||||
bool smlDoubleToInt64OverFlow(double num);
|
||||
int32_t smlBuildInvalidDataMsg(SSmlMsgBuf *pBuf, const char *msg1, const char *msg2);
|
||||
bool smlParseNumber(SSmlKv *kvVal, SSmlMsgBuf *msg);
|
||||
|
@ -251,7 +251,7 @@ int32_t smlClearForRerun(SSmlHandle *info);
|
|||
int32_t smlParseValue(SSmlKv *pVal, SSmlMsgBuf *msg);
|
||||
uint8_t smlGetTimestampLen(int64_t num);
|
||||
void clearColValArray(SArray* pCols);
|
||||
void smlDestroyTableInfo(SSmlHandle *info, SSmlTableInfo *tag);
|
||||
void smlDestroyTableInfo(void *para);
|
||||
|
||||
void freeSSmlKv(void* data);
|
||||
int32_t smlParseInfluxString(SSmlHandle *info, char *sql, char *sqlEnd, SSmlLineInfo *elements);
|
||||
|
|
|
@ -158,6 +158,13 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetVgroupId(JN
|
|||
*/
|
||||
JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetTableName(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: com_taosdata_jdbc_tmq_TMQConnector
|
||||
* Method: tmqGetOffset
|
||||
* Signature: (J)Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetOffset(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: com_taosdata_jdbc_tmq_TMQConnector
|
||||
* Method: fetchBlockImp
|
||||
|
@ -166,6 +173,12 @@ JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetTableNam
|
|||
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_fetchRawBlockImp(JNIEnv *, jobject, jlong, jlong,
|
||||
jobject, jobject);
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqSeekImp(JNIEnv *, jobject, jlong, jstring, jint,
|
||||
jlong);
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetTopicAssignmentImp(JNIEnv *, jobject, jlong,
|
||||
jstring, jobject);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -656,7 +656,7 @@ int taos_options_imp(TSDB_OPTION option, const char *str) {
|
|||
} else {
|
||||
tscInfo("set cfg:%s to %s", pItem->name, str);
|
||||
if (TSDB_OPTION_SHELL_ACTIVITY_TIMER == option || TSDB_OPTION_USE_ADAPTER == option) {
|
||||
code = taosSetCfg(pCfg, pItem->name);
|
||||
code = taosApplyLocalCfg(pCfg, pItem->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ static int32_t hbProcessStbInfoRsp(void *value, int32_t valueLen, struct SCatalo
|
|||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
catalogUpdateTableMeta(pCatalog, rsp);
|
||||
catalogAsyncUpdateTableMeta(pCatalog, rsp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -491,7 +491,8 @@ void setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t
|
|||
pResInfo->userFields[i].bytes = pSchema[i].bytes;
|
||||
pResInfo->userFields[i].type = pSchema[i].type;
|
||||
|
||||
if (pSchema[i].type == TSDB_DATA_TYPE_VARCHAR) {
|
||||
if (pSchema[i].type == TSDB_DATA_TYPE_VARCHAR ||
|
||||
pSchema[i].type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
pResInfo->userFields[i].bytes -= VARSTR_HEADER_SIZE;
|
||||
} else if (pSchema[i].type == TSDB_DATA_TYPE_NCHAR || pSchema[i].type == TSDB_DATA_TYPE_JSON) {
|
||||
pResInfo->userFields[i].bytes = (pResInfo->userFields[i].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
|
@ -815,7 +816,7 @@ int32_t handleAlterTbExecRes(void* res, SCatalog* pCatalog) {
|
|||
}
|
||||
|
||||
int32_t handleCreateTbExecRes(void* res, SCatalog* pCatalog) {
|
||||
return catalogUpdateTableMeta(pCatalog, (STableMetaRsp*)res);
|
||||
return catalogAsyncUpdateTableMeta(pCatalog, (STableMetaRsp*)res);
|
||||
}
|
||||
|
||||
int32_t handleQueryExecRsp(SRequestObj* pRequest) {
|
||||
|
@ -1756,6 +1757,7 @@ static int32_t doConvertJson(SReqResultInfo* pResultInfo, int32_t numOfCols, int
|
|||
return TSDB_CODE_TSC_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
taosMemoryFreeClear(pResultInfo->convertJson);
|
||||
pResultInfo->convertJson = taosMemoryCalloc(1, dataLen);
|
||||
if (pResultInfo->convertJson == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
char* p1 = pResultInfo->convertJson;
|
||||
|
|
|
@ -579,7 +579,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
|
|||
dv = GET_DOUBLE_VAL(row[i]);
|
||||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetDoubleFp, i, (jdouble)dv);
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
memcpy(tmp, row[i], length[i]); // handle the case that terminated does not exist
|
||||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetStringFp, i, (*env)->NewStringUTF(env, tmp));
|
||||
|
||||
|
|
|
@ -393,9 +393,10 @@ int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields)
|
|||
} break;
|
||||
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
|
||||
if (fields[i].type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (fields[i].type == TSDB_DATA_TYPE_BINARY || fields[i].type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
if (ASSERT(charLen <= fields[i].bytes && charLen >= 0)) {
|
||||
tscError("taos_print_row error binary. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
|
||||
}
|
||||
|
@ -475,6 +476,8 @@ const char *taos_data_type(int type) {
|
|||
return "TSDB_DATA_TYPE_NCHAR";
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
return "TSDB_DATA_TYPE_JSON";
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
return "TSDB_DATA_TYPE_GEOMETRY";
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
return "TSDB_DATA_TYPE_UTINYINT";
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
|
|
|
@ -56,7 +56,7 @@ static char* buildCreateTableJson(SSchemaWrapper* schemaRow, SSchemaWrapper* sch
|
|||
cJSON_AddItemToObject(column, "name", cname);
|
||||
cJSON* ctype = cJSON_CreateNumber(s->type);
|
||||
cJSON_AddItemToObject(column, "type", ctype);
|
||||
if (s->type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (s->type == TSDB_DATA_TYPE_BINARY || s->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t length = s->bytes - VARSTR_HEADER_SIZE;
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(column, "length", cbytes);
|
||||
|
@ -77,7 +77,7 @@ static char* buildCreateTableJson(SSchemaWrapper* schemaRow, SSchemaWrapper* sch
|
|||
cJSON_AddItemToObject(tag, "name", tname);
|
||||
cJSON* ttype = cJSON_CreateNumber(s->type);
|
||||
cJSON_AddItemToObject(tag, "type", ttype);
|
||||
if (s->type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (s->type == TSDB_DATA_TYPE_BINARY || s->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t length = s->bytes - VARSTR_HEADER_SIZE;
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(tag, "length", cbytes);
|
||||
|
@ -130,7 +130,7 @@ static char* buildAlterSTableJson(void* alterData, int32_t alterDataLen) {
|
|||
cJSON* colType = cJSON_CreateNumber(field->type);
|
||||
cJSON_AddItemToObject(json, "colType", colType);
|
||||
|
||||
if (field->type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (field->type == TSDB_DATA_TYPE_BINARY || field->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t length = field->bytes - VARSTR_HEADER_SIZE;
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(json, "colLength", cbytes);
|
||||
|
@ -155,7 +155,7 @@ static char* buildAlterSTableJson(void* alterData, int32_t alterDataLen) {
|
|||
cJSON_AddItemToObject(json, "colName", colName);
|
||||
cJSON* colType = cJSON_CreateNumber(field->type);
|
||||
cJSON_AddItemToObject(json, "colType", colType);
|
||||
if (field->type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (field->type == TSDB_DATA_TYPE_BINARY || field->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t length = field->bytes - VARSTR_HEADER_SIZE;
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(json, "colLength", cbytes);
|
||||
|
@ -457,7 +457,7 @@ static char* processAlterTable(SMqMetaRsp* metaRsp) {
|
|||
cJSON* colType = cJSON_CreateNumber(vAlterTbReq.type);
|
||||
cJSON_AddItemToObject(json, "colType", colType);
|
||||
|
||||
if (vAlterTbReq.type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (vAlterTbReq.type == TSDB_DATA_TYPE_BINARY || vAlterTbReq.type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t length = vAlterTbReq.bytes - VARSTR_HEADER_SIZE;
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(json, "colLength", cbytes);
|
||||
|
@ -478,7 +478,7 @@ static char* processAlterTable(SMqMetaRsp* metaRsp) {
|
|||
cJSON_AddItemToObject(json, "colName", colName);
|
||||
cJSON* colType = cJSON_CreateNumber(vAlterTbReq.colModType);
|
||||
cJSON_AddItemToObject(json, "colType", colType);
|
||||
if (vAlterTbReq.colModType == TSDB_DATA_TYPE_BINARY) {
|
||||
if (vAlterTbReq.colModType == TSDB_DATA_TYPE_BINARY || vAlterTbReq.colModType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t length = vAlterTbReq.colModBytes - VARSTR_HEADER_SIZE;
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(json, "colLength", cbytes);
|
||||
|
|
|
@ -24,72 +24,91 @@ int64_t smlToMilli[3] = {3600000LL, 60000LL, 1000LL};
|
|||
int64_t smlFactorNS[3] = {NANOSECOND_PER_MSEC, NANOSECOND_PER_USEC, 1};
|
||||
int64_t smlFactorS[3] = {1000LL, 1000000LL, 1000000000LL};
|
||||
|
||||
void *nodeListGet(NodeList *list, const void *key, int32_t len, _equal_fn_sml fn) {
|
||||
NodeList *tmp = list;
|
||||
while (tmp) {
|
||||
if (fn == NULL) {
|
||||
if (tmp->data.used && tmp->data.keyLen == len && memcmp(tmp->data.key, key, len) == 0) {
|
||||
return tmp->data.value;
|
||||
}
|
||||
//void *nodeListGet(NodeList *list, const void *key, int32_t len, _equal_fn_sml fn) {
|
||||
// NodeList *tmp = list;
|
||||
// while (tmp) {
|
||||
// if (fn == NULL) {
|
||||
// if (tmp->data.used && tmp->data.keyLen == len && memcmp(tmp->data.key, key, len) == 0) {
|
||||
// return tmp->data.value;
|
||||
// }
|
||||
// } else {
|
||||
// if (tmp->data.used && fn(tmp->data.key, key) == 0) {
|
||||
// return tmp->data.value;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// tmp = tmp->next;
|
||||
// }
|
||||
// return NULL;
|
||||
//}
|
||||
//
|
||||
//int nodeListSet(NodeList **list, const void *key, int32_t len, void *value, _equal_fn_sml fn) {
|
||||
// NodeList *tmp = *list;
|
||||
// while (tmp) {
|
||||
// if (!tmp->data.used) break;
|
||||
// if (fn == NULL) {
|
||||
// if (tmp->data.keyLen == len && memcmp(tmp->data.key, key, len) == 0) {
|
||||
// return -1;
|
||||
// }
|
||||
// } else {
|
||||
// if (tmp->data.keyLen == len && fn(tmp->data.key, key) == 0) {
|
||||
// return -1;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// tmp = tmp->next;
|
||||
// }
|
||||
// if (tmp) {
|
||||
// tmp->data.key = key;
|
||||
// tmp->data.keyLen = len;
|
||||
// tmp->data.value = value;
|
||||
// tmp->data.used = true;
|
||||
// } else {
|
||||
// NodeList *newNode = (NodeList *)taosMemoryCalloc(1, sizeof(NodeList));
|
||||
// if (newNode == NULL) {
|
||||
// return -1;
|
||||
// }
|
||||
// newNode->data.key = key;
|
||||
// newNode->data.keyLen = len;
|
||||
// newNode->data.value = value;
|
||||
// newNode->data.used = true;
|
||||
// newNode->next = *list;
|
||||
// *list = newNode;
|
||||
// }
|
||||
// return 0;
|
||||
//}
|
||||
//
|
||||
//int nodeListSize(NodeList *list) {
|
||||
// int cnt = 0;
|
||||
// while (list) {
|
||||
// if (list->data.used)
|
||||
// cnt++;
|
||||
// else
|
||||
// break;
|
||||
// list = list->next;
|
||||
// }
|
||||
// return cnt;
|
||||
//}
|
||||
|
||||
static int32_t smlCheckAuth(SSmlHandle *info, SRequestConnInfo* conn, const char* pTabName, AUTH_TYPE type){
|
||||
SUserAuthInfo pAuth = {0};
|
||||
snprintf(pAuth.user, sizeof(pAuth.user), "%s", info->taos->user);
|
||||
if (NULL == pTabName) {
|
||||
tNameSetDbName(&pAuth.tbName, info->taos->acctId, info->pRequest->pDb, strlen(info->pRequest->pDb));
|
||||
} else {
|
||||
if (tmp->data.used && fn(tmp->data.key, key) == 0) {
|
||||
return tmp->data.value;
|
||||
}
|
||||
toName(info->taos->acctId, info->pRequest->pDb, pTabName, &pAuth.tbName);
|
||||
}
|
||||
pAuth.type = type;
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
SUserAuthRes authRes = {0};
|
||||
|
||||
code = catalogChkAuth(info->pCatalog, conn, &pAuth, &authRes);
|
||||
|
||||
|
||||
return (code == TSDB_CODE_SUCCESS) ? (authRes.pass ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED) : code;
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int nodeListSet(NodeList **list, const void *key, int32_t len, void *value, _equal_fn_sml fn) {
|
||||
NodeList *tmp = *list;
|
||||
while (tmp) {
|
||||
if (!tmp->data.used) break;
|
||||
if (fn == NULL) {
|
||||
if (tmp->data.keyLen == len && memcmp(tmp->data.key, key, len) == 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (tmp->data.keyLen == len && fn(tmp->data.key, key) == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
if (tmp) {
|
||||
tmp->data.key = key;
|
||||
tmp->data.keyLen = len;
|
||||
tmp->data.value = value;
|
||||
tmp->data.used = true;
|
||||
} else {
|
||||
NodeList *newNode = (NodeList *)taosMemoryCalloc(1, sizeof(NodeList));
|
||||
if (newNode == NULL) {
|
||||
return -1;
|
||||
}
|
||||
newNode->data.key = key;
|
||||
newNode->data.keyLen = len;
|
||||
newNode->data.value = value;
|
||||
newNode->data.used = true;
|
||||
newNode->next = *list;
|
||||
*list = newNode;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nodeListSize(NodeList *list) {
|
||||
int cnt = 0;
|
||||
while (list) {
|
||||
if (list->data.used)
|
||||
cnt++;
|
||||
else
|
||||
break;
|
||||
list = list->next;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
inline bool smlDoubleToInt64OverFlow(double num) {
|
||||
if (num >= (double)INT64_MAX || num <= (double)INT64_MIN) return true;
|
||||
return false;
|
||||
|
@ -211,6 +230,16 @@ void getTableUid(SSmlHandle *info, SSmlLineInfo *currElement, SSmlTableInfo *tin
|
|||
}
|
||||
}
|
||||
|
||||
static void smlDestroySTableMeta(void *para) {
|
||||
SSmlSTableMeta *meta = *(SSmlSTableMeta**)para;
|
||||
taosHashCleanup(meta->tagHash);
|
||||
taosHashCleanup(meta->colHash);
|
||||
taosArrayDestroy(meta->tags);
|
||||
taosArrayDestroy(meta->cols);
|
||||
taosMemoryFreeClear(meta->tableMeta);
|
||||
taosMemoryFree(meta);
|
||||
}
|
||||
|
||||
SSmlSTableMeta *smlBuildSTableMeta(bool isDataFormat) {
|
||||
SSmlSTableMeta *meta = (SSmlSTableMeta *)taosMemoryCalloc(sizeof(SSmlSTableMeta), 1);
|
||||
if (!meta) {
|
||||
|
@ -245,7 +274,7 @@ SSmlSTableMeta *smlBuildSTableMeta(bool isDataFormat) {
|
|||
return meta;
|
||||
|
||||
cleanup:
|
||||
taosMemoryFree(meta);
|
||||
smlDestroySTableMeta(meta);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -555,7 +584,7 @@ static int32_t smlGenerateSchemaAction(SSchema *colField, SHashObj *colHash, SSm
|
|||
return TSDB_CODE_SML_INVALID_DATA;
|
||||
}
|
||||
|
||||
if ((colField[*index].type == TSDB_DATA_TYPE_VARCHAR &&
|
||||
if (((colField[*index].type == TSDB_DATA_TYPE_VARCHAR || colField[*index].type == TSDB_DATA_TYPE_GEOMETRY) &&
|
||||
(colField[*index].bytes - VARSTR_HEADER_SIZE) < kv->length) ||
|
||||
(colField[*index].type == TSDB_DATA_TYPE_NCHAR &&
|
||||
((colField[*index].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE < kv->length))) {
|
||||
|
@ -586,7 +615,7 @@ static int32_t smlFindNearestPowerOf2(int32_t length, uint8_t type) {
|
|||
}
|
||||
}
|
||||
|
||||
if (type == TSDB_DATA_TYPE_BINARY && result > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) {
|
||||
if ((type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_GEOMETRY) && result > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) {
|
||||
result = TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE;
|
||||
} else if (type == TSDB_DATA_TYPE_NCHAR && result > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
|
||||
result = (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
|
@ -594,7 +623,7 @@ static int32_t smlFindNearestPowerOf2(int32_t length, uint8_t type) {
|
|||
|
||||
if (type == TSDB_DATA_TYPE_NCHAR) {
|
||||
result = result * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE;
|
||||
} else if (type == TSDB_DATA_TYPE_BINARY) {
|
||||
} else if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
result = result + VARSTR_HEADER_SIZE;
|
||||
}
|
||||
return result;
|
||||
|
@ -638,7 +667,7 @@ static int32_t smlCheckMeta(SSchema *schema, int32_t length, SArray *cols, bool
|
|||
}
|
||||
|
||||
static int32_t getBytes(uint8_t type, int32_t length) {
|
||||
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
|
||||
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return smlFindNearestPowerOf2(length, type);
|
||||
} else {
|
||||
return tDataTypes[type].bytes;
|
||||
|
@ -813,6 +842,10 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
|
|||
code = catalogGetSTableMeta(info->pCatalog, &conn, &pName, &pTableMeta);
|
||||
|
||||
if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST || code == TSDB_CODE_MND_STB_NOT_EXIST) {
|
||||
code = smlCheckAuth(info, &conn, NULL, AUTH_TYPE_WRITE);
|
||||
if(code != TSDB_CODE_SUCCESS){
|
||||
goto end;
|
||||
}
|
||||
uDebug("SML:0x%" PRIx64 " smlModifyDBSchemas create table:%s", info->id, pName.tname);
|
||||
SArray *pColumns = taosArrayInit(taosArrayGetSize(sTableData->cols), sizeof(SField));
|
||||
SArray *pTags = taosArrayInit(taosArrayGetSize(sTableData->tags), sizeof(SField));
|
||||
|
@ -857,6 +890,10 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
|
|||
goto end;
|
||||
}
|
||||
if (action != SCHEMA_ACTION_NULL) {
|
||||
code = smlCheckAuth(info, &conn, pName.tname, AUTH_TYPE_WRITE);
|
||||
if(code != TSDB_CODE_SUCCESS){
|
||||
goto end;
|
||||
}
|
||||
uDebug("SML:0x%" PRIx64 " smlModifyDBSchemas change table tag, table:%s, action:%d", info->id, pName.tname,
|
||||
action);
|
||||
SArray *pColumns =
|
||||
|
@ -927,6 +964,10 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
|
|||
goto end;
|
||||
}
|
||||
if (action != SCHEMA_ACTION_NULL) {
|
||||
code = smlCheckAuth(info, &conn, pName.tname, AUTH_TYPE_WRITE);
|
||||
if(code != TSDB_CODE_SUCCESS){
|
||||
goto end;
|
||||
}
|
||||
uDebug("SML:0x%" PRIx64 " smlModifyDBSchemas change table col, table:%s, action:%d", info->id, pName.tname,
|
||||
action);
|
||||
SArray *pColumns =
|
||||
|
@ -1004,6 +1045,7 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
|
|||
}
|
||||
}
|
||||
|
||||
taosMemoryFreeClear(sTableData->tableMeta);
|
||||
sTableData->tableMeta = pTableMeta;
|
||||
uDebug("SML:0x%" PRIx64 "modify schema uid:%" PRIu64 ", sversion:%d, tversion:%d", info->id, pTableMeta->uid,
|
||||
pTableMeta->sversion, pTableMeta->tversion) tmp = (SSmlSTableMeta **)taosHashIterate(info->superTables, tmp);
|
||||
|
@ -1062,15 +1104,6 @@ static void smlInsertMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols) {
|
|||
}
|
||||
}
|
||||
|
||||
static void smlDestroySTableMeta(SSmlSTableMeta *meta) {
|
||||
taosHashCleanup(meta->tagHash);
|
||||
taosHashCleanup(meta->colHash);
|
||||
taosArrayDestroy(meta->tags);
|
||||
taosArrayDestroy(meta->cols);
|
||||
taosMemoryFree(meta->tableMeta);
|
||||
taosMemoryFree(meta);
|
||||
}
|
||||
|
||||
static int32_t smlUpdateMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols, bool isTag, SSmlMsgBuf *msg) {
|
||||
for (int i = 0; i < taosArrayGetSize(cols); ++i) {
|
||||
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i);
|
||||
|
@ -1110,7 +1143,8 @@ static int32_t smlUpdateMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void smlDestroyTableInfo(SSmlHandle *info, SSmlTableInfo *tag) {
|
||||
void smlDestroyTableInfo(void *para) {
|
||||
SSmlTableInfo *tag = *(SSmlTableInfo**)para;
|
||||
for (size_t i = 0; i < taosArrayGetSize(tag->cols); i++) {
|
||||
SHashObj *kvHash = (SHashObj *)taosArrayGetP(tag->cols, i);
|
||||
taosHashCleanup(kvHash);
|
||||
|
@ -1147,18 +1181,18 @@ void smlDestroyInfo(SSmlHandle *info) {
|
|||
qDestroyQuery(info->pQuery);
|
||||
|
||||
// destroy info->childTables
|
||||
SSmlTableInfo **oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, NULL);
|
||||
while (oneTable) {
|
||||
smlDestroyTableInfo(info, *oneTable);
|
||||
oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, oneTable);
|
||||
}
|
||||
// SSmlTableInfo **oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, NULL);
|
||||
// while (oneTable) {
|
||||
// smlDestroyTableInfo(oneTable);
|
||||
// oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, oneTable);
|
||||
// }
|
||||
|
||||
// destroy info->superTables
|
||||
SSmlSTableMeta **oneSTable = (SSmlSTableMeta **)taosHashIterate(info->superTables, NULL);
|
||||
while (oneSTable) {
|
||||
smlDestroySTableMeta(*oneSTable);
|
||||
oneSTable = (SSmlSTableMeta **)taosHashIterate(info->superTables, oneSTable);
|
||||
}
|
||||
// SSmlSTableMeta **oneSTable = (SSmlSTableMeta **)taosHashIterate(info->superTables, NULL);
|
||||
// while (oneSTable) {
|
||||
// smlDestroySTableMeta(*oneSTable);
|
||||
// oneSTable = (SSmlSTableMeta **)taosHashIterate(info->superTables, oneSTable);
|
||||
// }
|
||||
|
||||
// destroy info->pVgHash
|
||||
taosHashCleanup(info->pVgHash);
|
||||
|
@ -1217,6 +1251,8 @@ SSmlHandle *smlBuildSmlInfo(TAOS *taos) {
|
|||
info->childTables = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
|
||||
info->tableUids = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
|
||||
info->superTables = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
|
||||
taosHashSetFreeFp(info->superTables, smlDestroySTableMeta);
|
||||
taosHashSetFreeFp(info->childTables, smlDestroyTableInfo);
|
||||
|
||||
info->id = smlGenId();
|
||||
info->pQuery = smlInitHandle();
|
||||
|
@ -1323,6 +1359,9 @@ static int32_t smlParseLineBottom(SSmlHandle *info) {
|
|||
uDebug("SML:0x%" PRIx64 " smlParseLineBottom add meta, format:%d, linenum:%d", info->id, info->dataFormat,
|
||||
info->lineNum);
|
||||
SSmlSTableMeta *meta = smlBuildSTableMeta(info->dataFormat);
|
||||
if(meta == NULL){
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
taosHashPut(info->superTables, elements->measure, elements->measureLen, &meta, POINTER_BYTES);
|
||||
terrno = 0;
|
||||
smlInsertMeta(meta->tagHash, meta->tags, tinfo->tags);
|
||||
|
@ -1367,6 +1406,11 @@ static int32_t smlInsertData(SSmlHandle *info) {
|
|||
conn.requestObjRefId = info->pRequest->self;
|
||||
conn.mgmtEps = getEpSet_s(&info->taos->pAppInfo->mgmtEp);
|
||||
|
||||
code = smlCheckAuth(info, &conn, pName.tname, AUTH_TYPE_WRITE);
|
||||
if(code != TSDB_CODE_SUCCESS){
|
||||
return code;
|
||||
}
|
||||
|
||||
SVgroupInfo vg;
|
||||
code = catalogGetTableHashVgroup(info->pCatalog, &conn, &pName, &vg);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
|
@ -1437,18 +1481,18 @@ static void smlPrintStatisticInfo(SSmlHandle *info) {
|
|||
int32_t smlClearForRerun(SSmlHandle *info) {
|
||||
info->reRun = false;
|
||||
// clear info->childTables
|
||||
SSmlTableInfo **oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, NULL);
|
||||
while (oneTable) {
|
||||
smlDestroyTableInfo(info, *oneTable);
|
||||
oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, oneTable);
|
||||
}
|
||||
// SSmlTableInfo **oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, NULL);
|
||||
// while (oneTable) {
|
||||
// smlDestroyTableInfo(info, *oneTable);
|
||||
// oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, oneTable);
|
||||
// }
|
||||
|
||||
// clear info->superTables
|
||||
SSmlSTableMeta **oneSTable = (SSmlSTableMeta **)taosHashIterate(info->superTables, NULL);
|
||||
while (oneSTable) {
|
||||
smlDestroySTableMeta(*oneSTable);
|
||||
oneSTable = (SSmlSTableMeta **)taosHashIterate(info->superTables, oneSTable);
|
||||
}
|
||||
// SSmlSTableMeta **oneSTable = (SSmlSTableMeta **)taosHashIterate(info->superTables, NULL);
|
||||
// while (oneSTable) {
|
||||
// smlDestroySTableMeta(*oneSTable);
|
||||
// oneSTable = (SSmlSTableMeta **)taosHashIterate(info->superTables, oneSTable);
|
||||
// }
|
||||
|
||||
taosHashClear(info->childTables);
|
||||
taosHashClear(info->superTables);
|
||||
|
@ -1586,9 +1630,7 @@ static int smlProcess(SSmlHandle *info, char *lines[], char *rawLine, char *rawL
|
|||
|
||||
do {
|
||||
code = smlModifyDBSchemas(info);
|
||||
if (code == 0 || code == TSDB_CODE_SML_INVALID_DATA || code == TSDB_CODE_PAR_TOO_MANY_COLUMNS
|
||||
|| code == TSDB_CODE_PAR_INVALID_TAGS_NUM || code == TSDB_CODE_PAR_INVALID_TAGS_LENGTH
|
||||
|| code == TSDB_CODE_PAR_INVALID_ROW_LENGTH || code == TSDB_CODE_MND_FIELD_VALUE_OVERFLOW) {
|
||||
if (code != TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER && code != TSDB_CODE_SDB_OBJ_CREATING && code != TSDB_CODE_MND_TRANS_CONFLICT) {
|
||||
break;
|
||||
}
|
||||
taosMsleep(100);
|
||||
|
|
|
@ -695,6 +695,10 @@ static int32_t smlParseTagsFromJSON(SSmlHandle *info, cJSON *tags, SSmlLineInfo
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
sMeta = smlBuildSTableMeta(info->dataFormat);
|
||||
if(sMeta == NULL){
|
||||
taosMemoryFreeClear(pTableMeta);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
sMeta->tableMeta = pTableMeta;
|
||||
taosHashPut(info->superTables, elements->measure, elements->measureLen, &sMeta, POINTER_BYTES);
|
||||
for(int i = pTableMeta->tableInfo.numOfColumns; i < pTableMeta->tableInfo.numOfTags + pTableMeta->tableInfo.numOfColumns; i++){
|
||||
|
@ -784,7 +788,7 @@ static int32_t smlParseTagsFromJSON(SSmlHandle *info, cJSON *tags, SSmlLineInfo
|
|||
tinfo->tableDataCtx = smlInitTableDataCtx(info->pQuery, info->currSTableMeta);
|
||||
if (tinfo->tableDataCtx == NULL) {
|
||||
smlBuildInvalidDataMsg(&info->msgBuf, "smlInitTableDataCtx error", NULL);
|
||||
smlDestroyTableInfo(info, tinfo);
|
||||
smlDestroyTableInfo(&tinfo);
|
||||
return TSDB_CODE_SML_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
|
@ -1048,12 +1052,18 @@ static int32_t smlParseJSONExt(SSmlHandle *info, char *payload) {
|
|||
return TSDB_CODE_TSC_INVALID_JSON;
|
||||
}
|
||||
|
||||
info->lineNum = payloadNum;
|
||||
info->dataFormat = true;
|
||||
|
||||
if (unlikely(info->lines != NULL)) {
|
||||
for (int i = 0; i < info->lineNum; i++) {
|
||||
taosArrayDestroyEx(info->lines[i].colArray, freeSSmlKv);
|
||||
if (info->lines[i].measureTagsLen != 0) taosMemoryFree(info->lines[i].measureTag);
|
||||
}
|
||||
taosMemoryFree(info->lines);
|
||||
info->lines = NULL;
|
||||
}
|
||||
info->lineNum = payloadNum;
|
||||
info->dataFormat = true;
|
||||
|
||||
ret = smlClearForRerun(info);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
|
|
|
@ -168,6 +168,10 @@ static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLin
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
sMeta = smlBuildSTableMeta(info->dataFormat);
|
||||
if(sMeta == NULL){
|
||||
taosMemoryFreeClear(pTableMeta);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
sMeta->tableMeta = pTableMeta;
|
||||
taosHashPut(info->superTables, currElement->measure, currElement->measureLen, &sMeta, POINTER_BYTES);
|
||||
for (int i = pTableMeta->tableInfo.numOfColumns;
|
||||
|
@ -326,7 +330,7 @@ static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLin
|
|||
info->currSTableMeta->uid = tinfo->uid;
|
||||
tinfo->tableDataCtx = smlInitTableDataCtx(info->pQuery, info->currSTableMeta);
|
||||
if (tinfo->tableDataCtx == NULL) {
|
||||
smlDestroyTableInfo(info, tinfo);
|
||||
smlDestroyTableInfo(&tinfo);
|
||||
smlBuildInvalidDataMsg(&info->msgBuf, "smlInitTableDataCtx error", NULL);
|
||||
return TSDB_CODE_SML_INVALID_DATA;
|
||||
}
|
||||
|
@ -372,6 +376,10 @@ static int32_t smlParseColKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLin
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
*tmp = smlBuildSTableMeta(info->dataFormat);
|
||||
if(*tmp == NULL){
|
||||
taosMemoryFreeClear(pTableMeta);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
(*tmp)->tableMeta = pTableMeta;
|
||||
taosHashPut(info->superTables, currElement->measure, currElement->measureLen, tmp, POINTER_BYTES);
|
||||
|
||||
|
|
|
@ -91,6 +91,10 @@ static int32_t smlParseTelnetTags(SSmlHandle *info, char *data, char *sqlEnd, SS
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
sMeta = smlBuildSTableMeta(info->dataFormat);
|
||||
if(sMeta == NULL){
|
||||
taosMemoryFreeClear(pTableMeta);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
sMeta->tableMeta = pTableMeta;
|
||||
taosHashPut(info->superTables, elements->measure, elements->measureLen, &sMeta, POINTER_BYTES);
|
||||
for(int i = pTableMeta->tableInfo.numOfColumns; i < pTableMeta->tableInfo.numOfTags + pTableMeta->tableInfo.numOfColumns; i++){
|
||||
|
@ -212,7 +216,7 @@ static int32_t smlParseTelnetTags(SSmlHandle *info, char *data, char *sqlEnd, SS
|
|||
tinfo->tableDataCtx = smlInitTableDataCtx(info->pQuery, info->currSTableMeta);
|
||||
if (tinfo->tableDataCtx == NULL) {
|
||||
smlBuildInvalidDataMsg(&info->msgBuf, "smlInitTableDataCtx error", NULL);
|
||||
smlDestroyTableInfo(info, tinfo);
|
||||
smlDestroyTableInfo(&tinfo);
|
||||
return TSDB_CODE_SML_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#define EMPTY_BLOCK_POLL_IDLE_DURATION 10
|
||||
#define DEFAULT_AUTO_COMMIT_INTERVAL 5000
|
||||
|
||||
#define OFFSET_IS_RESET_OFFSET(_of) ((_of) < 0)
|
||||
|
||||
typedef void (*__tmq_askep_fn_t)(tmq_t* pTmq, int32_t code, SDataBuf* pBuf, void* pParam);
|
||||
|
||||
struct SMqMgmt {
|
||||
|
@ -2584,6 +2586,14 @@ int32_t tmq_get_topic_assignment(tmq_t* tmq, const char* pTopicName, tmq_topic_a
|
|||
}
|
||||
}
|
||||
|
||||
void tmq_free_assignment(tmq_topic_assignment* pAssignment) {
|
||||
if (pAssignment == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
taosMemoryFree(pAssignment);
|
||||
}
|
||||
|
||||
int32_t tmq_offset_seek(tmq_t* tmq, const char* pTopicName, int32_t vgId, int64_t offset) {
|
||||
if (tmq == NULL) {
|
||||
tscError("invalid tmq handle, null");
|
||||
|
@ -2618,12 +2628,12 @@ int32_t tmq_offset_seek(tmq_t* tmq, const char* pTopicName, int32_t vgId, int64_
|
|||
SVgOffsetInfo* pOffsetInfo = &pVg->offsetInfo;
|
||||
|
||||
int32_t type = pOffsetInfo->currentOffset.type;
|
||||
if (type != TMQ_OFFSET__LOG) {
|
||||
if (type != TMQ_OFFSET__LOG && !OFFSET_IS_RESET_OFFSET(type)) {
|
||||
tscError("consumer:0x%" PRIx64 " offset type:%d not wal version, seek not allowed", tmq->consumerId, type);
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
|
||||
if (offset < pOffsetInfo->walVerBegin || offset > pOffsetInfo->walVerEnd) {
|
||||
if (type == TMQ_OFFSET__LOG && (offset < pOffsetInfo->walVerBegin || offset > pOffsetInfo->walVerEnd)) {
|
||||
tscError("consumer:0x%" PRIx64 " invalid seek params, offset:%" PRId64 ", valid range:[%" PRId64 ", %" PRId64 "]",
|
||||
tmq->consumerId, offset, pOffsetInfo->walVerBegin, pOffsetInfo->walVerEnd);
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
|
|
|
@ -20,6 +20,13 @@
|
|||
int __init_tmq = 0;
|
||||
jmethodID g_offsetCallback;
|
||||
|
||||
jclass g_assignmentClass;
|
||||
jmethodID g_assignmentConstructor;
|
||||
jmethodID g_assignmentSetVgId;
|
||||
jmethodID g_assignmentSetCurrentOffset;
|
||||
jmethodID g_assignmentSetBegin;
|
||||
jmethodID g_assignmentSetEnd;
|
||||
|
||||
void tmqGlobalMethod(JNIEnv *env) {
|
||||
// make sure init function executed once
|
||||
switch (atomic_val_compare_exchange_32(&__init_tmq, 0, 1)) {
|
||||
|
@ -46,6 +53,38 @@ void tmqGlobalMethod(JNIEnv *env) {
|
|||
jniDebug("tmq method register finished");
|
||||
}
|
||||
|
||||
int __init_assignment = 0;
|
||||
void tmqAssignmentMethod(JNIEnv *env) {
|
||||
// make sure init function executed once
|
||||
switch (atomic_val_compare_exchange_32(&__init_assignment, 0, 1)) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
do {
|
||||
taosMsleep(0);
|
||||
} while (atomic_load_32(&__init_assignment) == 1);
|
||||
case 2:
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_vm == NULL) {
|
||||
(*env)->GetJavaVM(env, &g_vm);
|
||||
}
|
||||
|
||||
jclass assignment = (*env)->FindClass(env, "com/taosdata/jdbc/tmq/Assignment");
|
||||
g_assignmentClass = (*env)->NewGlobalRef(env, assignment);
|
||||
g_assignmentConstructor = (*env)->GetMethodID(env, g_assignmentClass, "<init>", "()V");
|
||||
g_assignmentSetVgId = (*env)->GetMethodID(env, g_assignmentClass, "setVgId", "(I)V"); // int
|
||||
g_assignmentSetCurrentOffset = (*env)->GetMethodID(env, g_assignmentClass, "setCurrentOffset", "(J)V"); // long
|
||||
g_assignmentSetBegin = (*env)->GetMethodID(env, g_assignmentClass, "setBegin", "(J)V"); // long
|
||||
g_assignmentSetEnd = (*env)->GetMethodID(env, g_assignmentClass, "setEnd", "(J)V"); // long
|
||||
|
||||
(*env)->DeleteLocalRef(env, assignment);
|
||||
|
||||
atomic_store_32(&__init_assignment, 2);
|
||||
jniDebug("tmq method assignment finished");
|
||||
}
|
||||
|
||||
// deprecated
|
||||
void commit_cb(tmq_t *tmq, int32_t code, void *param) {
|
||||
JNIEnv *env = NULL;
|
||||
|
@ -266,8 +305,9 @@ JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqCommitAsync(JN
|
|||
tmq_commit_async(tmq, res, commit_cb, consumer);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_consumerCommitAsync(JNIEnv *env, jobject jobj, jlong jtmq,
|
||||
jlong jres, jobject offset) {
|
||||
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_consumerCommitAsync(JNIEnv *env, jobject jobj,
|
||||
jlong jtmq, jlong jres,
|
||||
jobject offset) {
|
||||
tmqGlobalMethod(env);
|
||||
tmq_t *tmq = (tmq_t *)jtmq;
|
||||
if (tmq == NULL) {
|
||||
|
@ -335,7 +375,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetVgroupId(JN
|
|||
TAOS_RES *res = (TAOS_RES *)jres;
|
||||
if (res == NULL) {
|
||||
jniDebug("jobj:%p, invalid res handle", jobj);
|
||||
return -1;
|
||||
return JNI_RESULT_SET_NULL;
|
||||
}
|
||||
return tmq_get_vgroup_id(res);
|
||||
}
|
||||
|
@ -350,6 +390,15 @@ JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetTableNam
|
|||
return (*env)->NewStringUTF(env, tmq_get_table_name(res));
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetOffset(JNIEnv *env, jobject jobj, jlong jres) {
|
||||
TAOS_RES *res = (TAOS_RES *)jres;
|
||||
if (res == NULL) {
|
||||
jniDebug("jobj:%p, invalid res handle", jobj);
|
||||
return JNI_RESULT_SET_NULL;
|
||||
}
|
||||
return tmq_get_vgroup_offset(res);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_fetchRawBlockImp(JNIEnv *env, jobject jobj, jlong con,
|
||||
jlong res, jobject rowobj,
|
||||
jobject arrayListObj) {
|
||||
|
@ -369,7 +418,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_fetchRawBlockImp(
|
|||
jniDebug("jobj:%p, conn:%p, resultset:%p, no data to retrieve", jobj, tscon, (void *)res);
|
||||
return JNI_FETCH_END;
|
||||
} else {
|
||||
jniError("jobj:%p, conn:%p, query interrupted, tmq fetch block error code:%d, msg:%s", jobj, tscon, error_code, taos_errstr(tres));
|
||||
jniError("jobj:%p, conn:%p, query interrupted, tmq fetch block error code:%d, msg:%s", jobj, tscon, error_code,
|
||||
taos_errstr(tres));
|
||||
return JNI_RESULT_SET_NULL;
|
||||
}
|
||||
}
|
||||
|
@ -399,3 +449,72 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_fetchRawBlockImp(
|
|||
(*env)->CallVoidMethod(env, rowobj, g_blockdataSetByteArrayFp, jniFromNCharToByteArray(env, (char *)data, len));
|
||||
return JNI_SUCCESS;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqSeekImp(JNIEnv *env, jobject jobj, jlong jtmq,
|
||||
jstring jtopic, jint partition,
|
||||
jlong offset) {
|
||||
tmq_t *tmq = (tmq_t *)jtmq;
|
||||
if (tmq == NULL) {
|
||||
jniDebug("jobj:%p, tmq is closed", jobj);
|
||||
return TMQ_CONSUMER_NULL;
|
||||
}
|
||||
|
||||
if (jtopic == NULL) {
|
||||
jniDebug("jobj:%p, topic is null", jobj);
|
||||
return TMQ_TOPIC_NULL;
|
||||
}
|
||||
const char *topicName = (*env)->GetStringUTFChars(env, jtopic, NULL);
|
||||
|
||||
int32_t res = tmq_offset_seek(tmq, topicName, partition, offset);
|
||||
|
||||
if (res != TSDB_CODE_SUCCESS) {
|
||||
jniError("jobj:%p, tmq seek error, code:%d, msg:%s", jobj, res, tmq_err2str(res));
|
||||
}
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, jtopic, topicName);
|
||||
return (jint)res;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqGetTopicAssignmentImp(JNIEnv *env, jobject jobj,
|
||||
jlong jtmq, jstring jtopic,
|
||||
jobject jarrayList) {
|
||||
tmqAssignmentMethod(env);
|
||||
tmq_t *tmq = (tmq_t *)jtmq;
|
||||
if (tmq == NULL) {
|
||||
jniDebug("jobj:%p, tmq is closed", jobj);
|
||||
return TMQ_CONSUMER_NULL;
|
||||
}
|
||||
|
||||
if (jtopic == NULL) {
|
||||
jniDebug("jobj:%p, topic is null", jobj);
|
||||
return TMQ_TOPIC_NULL;
|
||||
}
|
||||
|
||||
const char *topicName = (*env)->GetStringUTFChars(env, jtopic, NULL);
|
||||
|
||||
tmq_topic_assignment *pAssign = NULL;
|
||||
int32_t numOfAssignment = 0;
|
||||
int32_t res = tmq_get_topic_assignment(tmq, topicName, &pAssign, &numOfAssignment);
|
||||
|
||||
if (res != TSDB_CODE_SUCCESS) {
|
||||
(*env)->ReleaseStringUTFChars(env, jtopic, topicName);
|
||||
jniError("jobj:%p, tmq get topic assignment error, topic:%s, code:%d, msg:%s", jobj, topicName, res,
|
||||
tmq_err2str(res));
|
||||
tmq_free_assignment(pAssign);
|
||||
return (jint)res;
|
||||
}
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, jtopic, topicName);
|
||||
|
||||
for (int i = 0; i < numOfAssignment; ++i) {
|
||||
tmq_topic_assignment assignment = pAssign[i];
|
||||
jobject jassignment = (*env)->NewObject(env, g_assignmentClass, g_assignmentConstructor);
|
||||
(*env)->CallVoidMethod(env, jassignment, g_assignmentSetVgId, assignment.vgId);
|
||||
(*env)->CallVoidMethod(env, jassignment, g_assignmentSetCurrentOffset, assignment.currentOffset);
|
||||
(*env)->CallVoidMethod(env, jassignment, g_assignmentSetBegin, assignment.begin);
|
||||
(*env)->CallVoidMethod(env, jassignment, g_assignmentSetEnd, assignment.end);
|
||||
(*env)->CallBooleanMethod(env, jarrayList, g_arrayListAddFp, jassignment);
|
||||
}
|
||||
tmq_free_assignment(pAssign);
|
||||
return JNI_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1100,7 +1100,7 @@ TEST(clientCase, sub_tb_test) {
|
|||
|
||||
// 创建订阅 topics 列表
|
||||
tmq_list_t* topicList = tmq_list_new();
|
||||
tmq_list_append(topicList, "topic_t1");
|
||||
tmq_list_append(topicList, "t1");
|
||||
|
||||
// 启动订阅
|
||||
tmq_subscribe(tmq, topicList);
|
||||
|
@ -1118,7 +1118,7 @@ TEST(clientCase, sub_tb_test) {
|
|||
tmq_topic_assignment* pAssign = NULL;
|
||||
int32_t numOfAssign = 0;
|
||||
|
||||
int32_t code = tmq_get_topic_assignment(tmq, "topic_t1", &pAssign, &numOfAssign);
|
||||
int32_t code = tmq_get_topic_assignment(tmq, "t1", &pAssign, &numOfAssign);
|
||||
if (code != 0) {
|
||||
printf("error occurs:%s\n", tmq_err2str(code));
|
||||
tmq_consumer_close(tmq);
|
||||
|
@ -1127,7 +1127,16 @@ TEST(clientCase, sub_tb_test) {
|
|||
return;
|
||||
}
|
||||
|
||||
tmq_offset_seek(tmq, "topic_t1", pAssign[0].vgId, 0);
|
||||
tmq_offset_seek(tmq, "t1", pAssign[0].vgId, 4);
|
||||
|
||||
code = tmq_get_topic_assignment(tmq, "t1", &pAssign, &numOfAssign);
|
||||
if (code != 0) {
|
||||
printf("error occurs:%s\n", tmq_err2str(code));
|
||||
tmq_consumer_close(tmq);
|
||||
taos_close(pConn);
|
||||
fprintf(stderr, "%d msg consumed, include %d rows\n", msgCnt, totalRows);
|
||||
return;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
TAOS_RES* pRes = tmq_consumer_poll(tmq, timeout);
|
||||
|
|
|
@ -280,7 +280,9 @@ static const SSysDbTableSchema topicSchema[] = {
|
|||
{.name = "db_name", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = false},
|
||||
{.name = "sql", .bytes = TSDB_SHOW_SQL_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
// TODO config
|
||||
{.name = "schema", .bytes = TSDB_SHOW_SCHEMA_JSON_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "meta", .bytes = 4 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "type", .bytes = 8 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -445,12 +445,11 @@ int32_t blockDataSplitRows(SSDataBlock* pBlock, bool hasVarCol, int32_t startInd
|
|||
|
||||
size_t headerSize = sizeof(int32_t);
|
||||
size_t colHeaderSize = sizeof(int32_t) * numOfCols;
|
||||
size_t payloadSize = pageSize - (headerSize + colHeaderSize);
|
||||
|
||||
// TODO speedup by checking if the whole page can fit in firstly.
|
||||
if (!hasVarCol) {
|
||||
size_t rowSize = blockDataGetRowSize(pBlock);
|
||||
int32_t capacity = payloadSize / (rowSize + numOfCols * bitmapChar / 8.0);
|
||||
int32_t capacity = blockDataGetCapacityInRow(pBlock, pageSize, headerSize + colHeaderSize);
|
||||
if (capacity <= 0) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
|
@ -1532,10 +1531,10 @@ SColumnInfoData* bdGetColumnInfoData(const SSDataBlock* pBlock, int32_t index) {
|
|||
return taosArrayGet(pBlock->pDataBlock, index);
|
||||
}
|
||||
|
||||
size_t blockDataGetCapacityInRow(const SSDataBlock* pBlock, size_t pageSize) {
|
||||
size_t blockDataGetCapacityInRow(const SSDataBlock* pBlock, size_t pageSize, int32_t extraSize) {
|
||||
size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
|
||||
|
||||
int32_t payloadSize = pageSize - blockDataGetSerialMetaSize(numOfCols);
|
||||
int32_t payloadSize = pageSize - extraSize;
|
||||
int32_t rowSize = pBlock->info.rowSize;
|
||||
int32_t nRows = payloadSize / rowSize;
|
||||
ASSERT(nRows >= 1);
|
||||
|
@ -1928,7 +1927,8 @@ void blockDebugShowDataBlocks(const SArray* dataBlocks, const char* flag) {
|
|||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
printf(" %15lf |", *(double*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_VARCHAR: {
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
char* pData = colDataGetVarData(pColInfoData, j);
|
||||
int32_t dataSize = TMIN(sizeof(pBuf) - 1, varDataLen(pData));
|
||||
memset(pBuf, 0, dataSize + 1);
|
||||
|
@ -1970,7 +1970,7 @@ char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf)
|
|||
if (len >= size - 1) return dumpBuf;
|
||||
|
||||
for (int32_t j = 0; j < rows; j++) {
|
||||
len += snprintf(dumpBuf + len, size - len, "%s %d|", flag, j);
|
||||
len += snprintf(dumpBuf + len, size - len, "%s|", flag);
|
||||
if (len >= size - 1) return dumpBuf;
|
||||
|
||||
for (int32_t k = 0; k < colNum; k++) {
|
||||
|
@ -2033,7 +2033,8 @@ char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf)
|
|||
len += snprintf(dumpBuf + len, size - len, " %15d |", *(bool*)var);
|
||||
if (len >= size - 1) return dumpBuf;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_VARCHAR: {
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
memset(pBuf, 0, sizeof(pBuf));
|
||||
char* pData = colDataGetVarData(pColInfoData, j);
|
||||
int32_t dataSize = TMIN(sizeof(pBuf), varDataLen(pData));
|
||||
|
@ -2052,7 +2053,7 @@ char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf)
|
|||
} break;
|
||||
}
|
||||
}
|
||||
len += snprintf(dumpBuf + len, size - len, "\n");
|
||||
len += snprintf(dumpBuf + len, size - len, "%d\n", j);
|
||||
if (len >= size - 1) return dumpBuf;
|
||||
}
|
||||
len += snprintf(dumpBuf + len, size - len, "%s |end\n", flag);
|
||||
|
@ -2139,7 +2140,8 @@ int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SSDataBlock* pDataB
|
|||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_VARCHAR: { // TSDB_DATA_TYPE_BINARY
|
||||
case TSDB_DATA_TYPE_VARCHAR: // TSDB_DATA_TYPE_BINARY
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
if (colDataIsNull_s(pColInfoData, j)) {
|
||||
tdAppendColValToRow(&rb, PRIMARYKEY_TIMESTAMP_COL_ID + k, pColInfoData->info.type, TD_VTYPE_NULL, NULL,
|
||||
false, offset, k);
|
||||
|
@ -2514,9 +2516,6 @@ int32_t blockEncode(const SSDataBlock* pBlock, char* data, int32_t numOfCols) {
|
|||
*actualLen = dataLen;
|
||||
*groupId = pBlock->info.id.groupId;
|
||||
ASSERT(dataLen > 0);
|
||||
|
||||
uDebug("build data block, actualLen:%d, rows:%d, cols:%d", dataLen, *rows, *cols);
|
||||
|
||||
return dataLen;
|
||||
}
|
||||
|
||||
|
|
|
@ -1148,7 +1148,8 @@ static void debugPrintTagVal(int8_t type, const void *val, int32_t vlen, const c
|
|||
switch (type) {
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
char tmpVal[32] = {0};
|
||||
strncpy(tmpVal, val, vlen > 31 ? 31 : vlen);
|
||||
printf("%s:%d type:%d vlen:%d, val:\"%s\"\n", tag, ln, (int32_t)type, vlen, tmpVal);
|
||||
|
@ -3542,5 +3543,6 @@ void (*tColDataCalcSMA[])(SColData *pColData, int64_t *sum, int64_t *max, int64_
|
|||
NULL, // TSDB_DATA_TYPE_VARBINARY
|
||||
NULL, // TSDB_DATA_TYPE_DECIMAL
|
||||
NULL, // TSDB_DATA_TYPE_BLOB
|
||||
NULL // TSDB_DATA_TYPE_MEDIUMBLOB
|
||||
NULL, // TSDB_DATA_TYPE_MEDIUMBLOB
|
||||
NULL // TSDB_DATA_TYPE_GEOMETRY
|
||||
};
|
||||
|
|
|
@ -60,6 +60,7 @@ int32_t tsNumOfQnodeQueryThreads = 4;
|
|||
int32_t tsNumOfQnodeFetchThreads = 1;
|
||||
int32_t tsNumOfSnodeStreamThreads = 4;
|
||||
int32_t tsNumOfSnodeWriteThreads = 1;
|
||||
int32_t tsMaxStreamBackendCache = 128; // M
|
||||
|
||||
// sync raft
|
||||
int32_t tsElectInterval = 25 * 1000;
|
||||
|
@ -117,12 +118,10 @@ int32_t tsRedirectFactor = 2;
|
|||
int32_t tsRedirectMaxPeriod = 1000;
|
||||
int32_t tsMaxRetryWaitTime = 10000;
|
||||
bool tsUseAdapter = false;
|
||||
int32_t tsMetaCacheMaxSize = -1; // MB
|
||||
int32_t tsSlowLogThreshold = 3; // seconds
|
||||
int32_t tsSlowLogScope = SLOW_LOG_TYPE_ALL;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* denote if the server needs to compress response message at the application layer to client, including query rsp,
|
||||
* metricmeta rsp, and multi-meter query rsp message body. The client compress the submit message to server.
|
||||
|
@ -210,6 +209,7 @@ char tsUdfdLdLibPath[512] = "";
|
|||
bool tsDisableStream = false;
|
||||
int64_t tsStreamBufferSize = 128 * 1024 * 1024;
|
||||
int64_t tsCheckpointInterval = 3 * 60 * 60 * 1000;
|
||||
bool tsFilterScalarMode = false;
|
||||
|
||||
#ifndef _STORAGE
|
||||
int32_t taosSetTfsCfg(SConfig *pCfg) {
|
||||
|
@ -350,7 +350,9 @@ static int32_t taosAddClientCfg(SConfig *pCfg) {
|
|||
if (cfgAddInt32(pCfg, "maxRetryWaitTime", tsMaxRetryWaitTime, 0, 86400000, 0) != 0) return -1;
|
||||
if (cfgAddBool(pCfg, "useAdapter", tsUseAdapter, true) != 0) return -1;
|
||||
if (cfgAddBool(pCfg, "crashReporting", tsEnableCrashReport, true) != 0) return -1;
|
||||
if (cfgAddInt64(pCfg, "queryMaxConcurrentTables", tsQueryMaxConcurrentTables, INT64_MIN, INT64_MAX, 1) != 0) return -1;
|
||||
if (cfgAddInt64(pCfg, "queryMaxConcurrentTables", tsQueryMaxConcurrentTables, INT64_MIN, INT64_MAX, 1) != 0)
|
||||
return -1;
|
||||
if (cfgAddInt32(pCfg, "metaCacheMaxSize", tsMetaCacheMaxSize, -1, INT32_MAX, 1) != 0) return -1;
|
||||
if (cfgAddInt32(pCfg, "slowLogThreshold", tsSlowLogThreshold, 0, INT32_MAX, true) != 0) return -1;
|
||||
if (cfgAddString(pCfg, "slowLogScope", "", true) != 0) return -1;
|
||||
|
||||
|
@ -523,6 +525,9 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
|
|||
|
||||
if (cfgAddInt32(pCfg, "cacheLazyLoadThreshold", tsCacheLazyLoadThreshold, 0, 100000, 0) != 0) return -1;
|
||||
|
||||
if (cfgAddBool(pCfg, "filterScalarMode", tsFilterScalarMode, 0) != 0) return -1;
|
||||
if (cfgAddInt32(pCfg, "maxStreamBackendCache", tsMaxStreamBackendCache, 16, 1024, 0) != 0) return -1;
|
||||
|
||||
GRANT_CFG_ADD;
|
||||
return 0;
|
||||
}
|
||||
|
@ -788,6 +793,7 @@ static int32_t taosSetClientCfg(SConfig *pCfg) {
|
|||
tsUseAdapter = cfgGetItem(pCfg, "useAdapter")->bval;
|
||||
tsEnableCrashReport = cfgGetItem(pCfg, "crashReporting")->bval;
|
||||
tsQueryMaxConcurrentTables = cfgGetItem(pCfg, "queryMaxConcurrentTables")->i64;
|
||||
tsMetaCacheMaxSize = cfgGetItem(pCfg, "metaCacheMaxSize")->i32;
|
||||
tsSlowLogThreshold = cfgGetItem(pCfg, "slowLogThreshold")->i32;
|
||||
if (taosSetSlowLogScope(cfgGetItem(pCfg, "slowLogScope")->str)) {
|
||||
return -1;
|
||||
|
@ -898,6 +904,9 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
|
|||
tsStreamBufferSize = cfgGetItem(pCfg, "streamBufferSize")->i64;
|
||||
tsCheckpointInterval = cfgGetItem(pCfg, "checkpointInterval")->i64;
|
||||
|
||||
tsFilterScalarMode = cfgGetItem(pCfg, "filterScalarMode")->bval;
|
||||
tsMaxStreamBackendCache = cfgGetItem(pCfg, "maxStreamBackendCache")->i32;
|
||||
|
||||
GRANT_CFG_GET;
|
||||
return 0;
|
||||
}
|
||||
|
@ -916,7 +925,7 @@ void taosLocalCfgForbiddenToChange(char *name, bool *forbidden) {
|
|||
*forbidden = false;
|
||||
}
|
||||
|
||||
int32_t taosSetCfg(SConfig *pCfg, char *name) {
|
||||
int32_t taosApplyLocalCfg(SConfig *pCfg, char *name) {
|
||||
int32_t len = strlen(name);
|
||||
char lowcaseName[CFG_NAME_MAX_LEN + 1] = {0};
|
||||
strntolower(lowcaseName, name, TMIN(CFG_NAME_MAX_LEN, len));
|
||||
|
@ -1051,6 +1060,12 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 'e': {
|
||||
if (strcasecmp("metaCacheMaxSize", name) == 0) {
|
||||
atomic_store_32(&tsMetaCacheMaxSize, cfgGetItem(pCfg, "metaCacheMaxSize")->i32);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'i': {
|
||||
if (strcasecmp("minimalTmpDirGB", name) == 0) {
|
||||
tsTempSpace.reserved = (int64_t)(((double)cfgGetItem(pCfg, "minimalTmpDirGB")->fval) * 1024 * 1024 * 1024);
|
||||
|
|
|
@ -1566,21 +1566,21 @@ int32_t tDeserializeSGetUserAuthRspImpl(SDecoder *pDecoder, SGetUserAuthRsp *pRs
|
|||
char db[TSDB_DB_FNAME_LEN] = {0};
|
||||
if (tDecodeCStrTo(pDecoder, db) < 0) return -1;
|
||||
int32_t len = strlen(db);
|
||||
taosHashPut(pRsp->createdDbs, db, len, db, len);
|
||||
taosHashPut(pRsp->createdDbs, db, len, db, len + 1);
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < numOfReadDbs; ++i) {
|
||||
char db[TSDB_DB_FNAME_LEN] = {0};
|
||||
if (tDecodeCStrTo(pDecoder, db) < 0) return -1;
|
||||
int32_t len = strlen(db);
|
||||
taosHashPut(pRsp->readDbs, db, len, db, len);
|
||||
taosHashPut(pRsp->readDbs, db, len, db, len + 1);
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < numOfWriteDbs; ++i) {
|
||||
char db[TSDB_DB_FNAME_LEN] = {0};
|
||||
if (tDecodeCStrTo(pDecoder, db) < 0) return -1;
|
||||
int32_t len = strlen(db);
|
||||
taosHashPut(pRsp->writeDbs, db, len, db, len);
|
||||
taosHashPut(pRsp->writeDbs, db, len, db, len + 1);
|
||||
}
|
||||
|
||||
if (!tDecodeIsEnd(pDecoder)) {
|
||||
|
@ -3416,6 +3416,7 @@ int32_t tSerializeSTableIndexRsp(void *buf, int32_t bufLen, const STableIndexRsp
|
|||
if (tEncodeCStr(&encoder, pRsp->dbFName) < 0) return -1;
|
||||
if (tEncodeU64(&encoder, pRsp->suid) < 0) return -1;
|
||||
if (tEncodeI32(&encoder, pRsp->version) < 0) return -1;
|
||||
if (tEncodeI32(&encoder, pRsp->indexSize) < 0) return -1;
|
||||
int32_t num = taosArrayGetSize(pRsp->pIndex);
|
||||
if (tEncodeI32(&encoder, num) < 0) return -1;
|
||||
if (num > 0) {
|
||||
|
@ -3461,6 +3462,7 @@ int32_t tDeserializeSTableIndexRsp(void *buf, int32_t bufLen, STableIndexRsp *pR
|
|||
if (tDecodeCStrTo(&decoder, pRsp->dbFName) < 0) return -1;
|
||||
if (tDecodeU64(&decoder, &pRsp->suid) < 0) return -1;
|
||||
if (tDecodeI32(&decoder, &pRsp->version) < 0) return -1;
|
||||
if (tDecodeI32(&decoder, &pRsp->indexSize) < 0) return -1;
|
||||
int32_t num = 0;
|
||||
if (tDecodeI32(&decoder, &num) < 0) return -1;
|
||||
if (num > 0) {
|
||||
|
@ -3735,6 +3737,7 @@ int32_t tSerializeSSTbHbRsp(void *buf, int32_t bufLen, SSTbHbRsp *pRsp) {
|
|||
if (tEncodeCStr(&encoder, pIndexRsp->dbFName) < 0) return -1;
|
||||
if (tEncodeU64(&encoder, pIndexRsp->suid) < 0) return -1;
|
||||
if (tEncodeI32(&encoder, pIndexRsp->version) < 0) return -1;
|
||||
if (tEncodeI32(&encoder, pIndexRsp->indexSize) < 0) return -1;
|
||||
int32_t num = taosArrayGetSize(pIndexRsp->pIndex);
|
||||
if (tEncodeI32(&encoder, num) < 0) return -1;
|
||||
for (int32_t i = 0; i < num; ++i) {
|
||||
|
@ -3797,6 +3800,7 @@ int32_t tDeserializeSSTbHbRsp(void *buf, int32_t bufLen, SSTbHbRsp *pRsp) {
|
|||
if (tDecodeCStrTo(&decoder, tableIndexRsp.dbFName) < 0) return -1;
|
||||
if (tDecodeU64(&decoder, &tableIndexRsp.suid) < 0) return -1;
|
||||
if (tDecodeI32(&decoder, &tableIndexRsp.version) < 0) return -1;
|
||||
if (tDecodeI32(&decoder, &tableIndexRsp.indexSize) < 0) return -1;
|
||||
int32_t num = 0;
|
||||
if (tDecodeI32(&decoder, &num) < 0) return -1;
|
||||
if (num > 0) {
|
||||
|
|
|
@ -126,6 +126,9 @@ void tdSCellValPrint(SCellVal *pVal, int8_t colType) {
|
|||
case TSDB_DATA_TYPE_JSON:
|
||||
printf("JSON ");
|
||||
break;
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
printf("GEOMETRY ");
|
||||
break;
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
printf("VARBIN ");
|
||||
break;
|
||||
|
@ -353,7 +356,7 @@ int32_t tdSTSRowNew(SArray *pArray, STSchema *pTSchema, STSRow **ppRow) {
|
|||
}
|
||||
} else {
|
||||
varDataLen += sizeof(VarDataLenT);
|
||||
if (pTColumn->type == TSDB_DATA_TYPE_VARCHAR) {
|
||||
if (pTColumn->type == TSDB_DATA_TYPE_VARCHAR || pTColumn->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
varDataLen += CHAR_BYTES;
|
||||
if (maxVarDataLen < CHAR_BYTES + sizeof(VarDataLenT)) {
|
||||
maxVarDataLen = CHAR_BYTES + sizeof(VarDataLenT);
|
||||
|
|
|
@ -296,7 +296,7 @@ static void writeDataToDisk(STSBuf* pTSBuf) {
|
|||
metaLen += (int32_t)taosWriteFile(pTSBuf->pFile, &pBlock->tag.nType, sizeof(pBlock->tag.nType));
|
||||
|
||||
int32_t trueLen = pBlock->tag.nLen;
|
||||
if (pBlock->tag.nType == TSDB_DATA_TYPE_BINARY || pBlock->tag.nType == TSDB_DATA_TYPE_NCHAR) {
|
||||
if (pBlock->tag.nType == TSDB_DATA_TYPE_BINARY || pBlock->tag.nType == TSDB_DATA_TYPE_NCHAR || pBlock->tag.nType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
metaLen += (int32_t)taosWriteFile(pTSBuf->pFile, &pBlock->tag.nLen, sizeof(pBlock->tag.nLen));
|
||||
metaLen += (int32_t)taosWriteFile(pTSBuf->pFile, pBlock->tag.pz, (size_t)pBlock->tag.nLen);
|
||||
} else if (pBlock->tag.nType == TSDB_DATA_TYPE_FLOAT) {
|
||||
|
@ -378,7 +378,7 @@ STSBlock* readDataFromDisk(STSBuf* pTSBuf, int32_t order, bool decomp) {
|
|||
|
||||
// NOTE: mix types tags are not supported
|
||||
size_t sz = 0;
|
||||
if (pBlock->tag.nType == TSDB_DATA_TYPE_BINARY || pBlock->tag.nType == TSDB_DATA_TYPE_NCHAR) {
|
||||
if (pBlock->tag.nType == TSDB_DATA_TYPE_BINARY || pBlock->tag.nType == TSDB_DATA_TYPE_NCHAR || pBlock->tag.nType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
char* tp = taosMemoryRealloc(pBlock->tag.pz, pBlock->tag.nLen + 1);
|
||||
ASSERT(tp != NULL);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "ttypes.h"
|
||||
#include "tcompression.h"
|
||||
|
||||
const int32_t TYPE_BYTES[16] = {
|
||||
const int32_t TYPE_BYTES[17] = {
|
||||
-1, // TSDB_DATA_TYPE_NULL
|
||||
CHAR_BYTES, // TSDB_DATA_TYPE_BOOL
|
||||
CHAR_BYTES, // TSDB_DATA_TYPE_TINYINT
|
||||
|
@ -34,6 +34,7 @@ const int32_t TYPE_BYTES[16] = {
|
|||
INT_BYTES, // TSDB_DATA_TYPE_UINT
|
||||
sizeof(uint64_t), // TSDB_DATA_TYPE_UBIGINT
|
||||
TSDB_MAX_JSON_TAG_LEN, // TSDB_DATA_TYPE_JSON
|
||||
sizeof(VarDataOffsetT), // TSDB_DATA_TYPE_GEOMETRY
|
||||
};
|
||||
|
||||
tDataTypeDescriptor tDataTypes[TSDB_DATA_TYPE_MAX] = {
|
||||
|
@ -56,6 +57,7 @@ tDataTypeDescriptor tDataTypes[TSDB_DATA_TYPE_MAX] = {
|
|||
{TSDB_DATA_TYPE_UINT, 12, INT_BYTES, "INT UNSIGNED", 0, UINT32_MAX, tsCompressInt, tsDecompressInt},
|
||||
{TSDB_DATA_TYPE_UBIGINT, 15, LONG_BYTES, "BIGINT UNSIGNED", 0, UINT64_MAX, tsCompressBigint, tsDecompressBigint},
|
||||
{TSDB_DATA_TYPE_JSON, 4, TSDB_MAX_JSON_TAG_LEN, "JSON", 0, 0, tsCompressString, tsDecompressString},
|
||||
{TSDB_DATA_TYPE_GEOMETRY, 8, 1, "GEOMETRY", 0, 0, tsCompressString, tsDecompressString},
|
||||
};
|
||||
|
||||
static float floatMin = -FLT_MAX, floatMax = FLT_MAX;
|
||||
|
@ -125,6 +127,7 @@ void assignVal(char *val, const char *src, int32_t len, int32_t type) {
|
|||
*((int64_t *)val) = GET_INT64_VAL(src);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
varDataCopy(val, src);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue