diff --git a/README-CN.md b/README-CN.md
index afb242d621..d5586c78b7 100644
--- a/README-CN.md
+++ b/README-CN.md
@@ -23,7 +23,7 @@ TDengine是涛思数据专为物联网、车联网、工业互联网、IT运维
TDengine是一个高效的存储、查询、分析时序大数据的平台,专为物联网、车联网、工业互联网、运维监测等优化而设计。您可以像使用关系型数据库MySQL一样来使用它,但建议您在使用前仔细阅读一遍下面的文档,特别是 [数据模型](https://www.taosdata.com/cn/documentation/architecture) 与 [数据建模](https://www.taosdata.com/cn/documentation/model)。除本文档之外,欢迎 [下载产品白皮书](https://www.taosdata.com/downloads/TDengine%20White%20Paper.pdf)。
-# 生成
+# 构建
TDengine目前2.0版服务器仅能在Linux系统上安装和运行,后续会支持Windows、macOS等系统。客户端可以在Windows或Linux上安装和运行。任何OS的应用也可以选择RESTful接口连接服务器taosd。CPU支持X64/ARM64/MIPS64/Alpha64,后续会支持ARM32、RISC-V等CPU架构。用户可根据需求选择通过[源码](https://www.taosdata.com/cn/getting-started/#通过源码安装)或者[安装包](https://www.taosdata.com/cn/getting-started/#通过安装包安装)来安装。本快速指南仅适用于通过源码安装。
@@ -107,7 +107,7 @@ Go 连接器和 Grafana 插件在其他独立仓库,如果安装它们的话
git submodule update --init --recursive
```
-## 生成 TDengine
+## 构建 TDengine
### Linux 系统
@@ -116,6 +116,12 @@ mkdir debug && cd debug
cmake .. && cmake --build .
```
+您可以选择使用 Jemalloc 作为内存分配器,替代默认的 glibc:
+```bash
+apt install autoconf
+cmake .. -DJEMALLOC_ENABLED=true
+```
+
在X86-64、X86、arm64、arm32 和 mips64 平台上,TDengine 生成脚本可以自动检测机器架构。也可以手动配置 CPUTYPE 参数来指定 CPU 类型,如 aarch64 或 aarch32 等。
aarch64:
diff --git a/README.md b/README.md
index 0e1adcd97c..89e35f6e63 100644
--- a/README.md
+++ b/README.md
@@ -110,6 +110,12 @@ mkdir debug && cd debug
cmake .. && cmake --build .
```
+You can use Jemalloc as memory allocator instead of glibc:
+```
+apt install autoconf
+cmake .. -DJEMALLOC_ENABLED=true
+```
+
TDengine build script can detect the host machine's architecture on X86-64, X86, arm64, arm32 and mips64 platform.
You can also specify CPUTYPE option like aarch64 or aarch32 too if the detection result is not correct:
diff --git a/cmake/define.inc b/cmake/define.inc
index a15e0aecbb..d6a3f2b915 100755
--- a/cmake/define.inc
+++ b/cmake/define.inc
@@ -57,7 +57,7 @@ IF (TD_LINUX_64)
ADD_DEFINITIONS(-D_M_X64)
ADD_DEFINITIONS(-D_TD_LINUX_64)
MESSAGE(STATUS "linux64 is defined")
- SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
+ SET(COMMON_FLAGS "-Wall -Werror -fPIC -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ADD_DEFINITIONS(-DUSE_LIBICONV)
IF (JEMALLOC_ENABLED)
@@ -70,7 +70,7 @@ IF (TD_LINUX_32)
ADD_DEFINITIONS(-D_TD_LINUX_32)
ADD_DEFINITIONS(-DUSE_LIBICONV)
MESSAGE(STATUS "linux32 is defined")
- SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -fsigned-char -munaligned-access -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
+ SET(COMMON_FLAGS "-Wall -Werror -fPIC -fsigned-char -munaligned-access -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ENDIF ()
IF (TD_ARM_64)
@@ -78,7 +78,7 @@ IF (TD_ARM_64)
ADD_DEFINITIONS(-D_TD_ARM_)
ADD_DEFINITIONS(-DUSE_LIBICONV)
MESSAGE(STATUS "arm64 is defined")
- SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
+ SET(COMMON_FLAGS "-Wall -Werror -fPIC -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ENDIF ()
IF (TD_ARM_32)
@@ -86,7 +86,7 @@ IF (TD_ARM_32)
ADD_DEFINITIONS(-D_TD_ARM_)
ADD_DEFINITIONS(-DUSE_LIBICONV)
MESSAGE(STATUS "arm32 is defined")
- SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -Wno-incompatible-pointer-types ")
+ SET(COMMON_FLAGS "-Wall -Werror -fPIC -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -Wno-incompatible-pointer-types ")
ENDIF ()
IF (TD_MIPS_64)
@@ -94,7 +94,7 @@ IF (TD_MIPS_64)
ADD_DEFINITIONS(-D_TD_MIPS_64)
ADD_DEFINITIONS(-DUSE_LIBICONV)
MESSAGE(STATUS "mips64 is defined")
- SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
+ SET(COMMON_FLAGS "-Wall -Werror -fPIC -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ENDIF ()
IF (TD_MIPS_32)
@@ -102,7 +102,7 @@ IF (TD_MIPS_32)
ADD_DEFINITIONS(-D_TD_MIPS_32)
ADD_DEFINITIONS(-DUSE_LIBICONV)
MESSAGE(STATUS "mips32 is defined")
- SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
+ SET(COMMON_FLAGS "-Wall -Werror -fPIC -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ENDIF ()
IF (TD_APLHINE)
@@ -147,7 +147,7 @@ IF (TD_DARWIN_64)
ADD_DEFINITIONS(-D_REENTRANT -D__USE_POSIX -D_LIBC_REENTRANT)
ADD_DEFINITIONS(-DUSE_LIBICONV)
MESSAGE(STATUS "darwin64 is defined")
- SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -Wno-missing-braces -fPIC -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
+ SET(COMMON_FLAGS "-Wall -Werror -Wno-missing-braces -fPIC -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
IF (TD_MEMORY_SANITIZER)
SET(DEBUG_FLAGS "-fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -O0 -g3 -DDEBUG")
ELSE ()
diff --git a/cmake/env.inc b/cmake/env.inc
index 6c1ce8fd89..fa15ec6aee 100755
--- a/cmake/env.inc
+++ b/cmake/env.inc
@@ -35,13 +35,13 @@ ENDIF ()
# Set compiler options
SET(COMMON_C_FLAGS "${COMMON_FLAGS} -std=gnu99")
-SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${COMMON_FLAGS} ${DEBUG_FLAGS}")
-SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${COMMON_FLAGS} ${RELEASE_FLAGS}")
+SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${COMMON_C_FLAGS} ${DEBUG_FLAGS}")
+SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${COMMON_C_FLAGS} ${RELEASE_FLAGS}")
# Set c++ compiler options
-# SET(COMMON_CXX_FLAGS "${COMMON_FLAGS} -std=c++11")
-# SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS} ${DEBUG_FLAGS}")
-# SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS} ${RELEASE_FLAGS}")
+SET(COMMON_CXX_FLAGS "${COMMON_FLAGS} -std=c++11 -Wno-unused-function")
+SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS} ${DEBUG_FLAGS}")
+SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS} ${RELEASE_FLAGS}")
IF (${CMAKE_BUILD_TYPE} MATCHES "Debug")
SET(CMAKE_BUILD_TYPE "Debug")
diff --git a/cmake/install.inc b/cmake/install.inc
index 63764348d3..30aa801122 100755
--- a/cmake/install.inc
+++ b/cmake/install.inc
@@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS)
#INSTALL(TARGETS taos RUNTIME DESTINATION driver)
#INSTALL(TARGETS shell RUNTIME DESTINATION .)
IF (TD_MVN_INSTALLED)
- INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.30.jar DESTINATION connector/jdbc)
+ INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.32-dist.jar DESTINATION connector/jdbc)
ENDIF ()
ELSEIF (TD_DARWIN)
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
diff --git a/cmake/version.inc b/cmake/version.inc
index ed8e7a156c..134f09f179 100755
--- a/cmake/version.inc
+++ b/cmake/version.inc
@@ -4,7 +4,7 @@ PROJECT(TDengine)
IF (DEFINED VERNUMBER)
SET(TD_VER_NUMBER ${VERNUMBER})
ELSE ()
- SET(TD_VER_NUMBER "2.1.1.0")
+ SET(TD_VER_NUMBER "2.1.3.0")
ENDIF ()
IF (DEFINED VERCOMPATIBLE)
diff --git a/documentation20/cn/00.index/docs.md b/documentation20/cn/00.index/docs.md
index 49cfa12119..18bdc15d30 100644
--- a/documentation20/cn/00.index/docs.md
+++ b/documentation20/cn/00.index/docs.md
@@ -42,7 +42,7 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专
* [数据写入](/taos-sql#insert):支持单表单条、多条、多表多条写入,支持历史数据写入
* [数据查询](/taos-sql#select):支持时间段、值过滤、排序、查询结果手动分页等
* [SQL函数](/taos-sql#functions):支持各种聚合函数、选择函数、计算函数,如avg, min, diff等
-* [时间维度聚合](/taos-sql#aggregation):将表中数据按照时间段进行切割后聚合,降维处理
+* [窗口切分聚合](/taos-sql#aggregation):将表中数据按照时间段等方式进行切割后聚合,降维处理
* [边界限制](/taos-sql#limitation):库、表、SQL等边界限制条件
* [错误码](/taos-sql/error-code):TDengine 2.0 错误码以及对应的十进制码
@@ -63,7 +63,7 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专
## [高级功能](/advanced-features)
* [连续查询(Continuous Query)](/advanced-features#continuous-query):基于滑动窗口,定时自动的对数据流进行查询计算
-* [数据订阅(Publisher/Subscriber)](/advanced-features#subscribe):象典型的消息队列,应用可订阅接收到的最新数据
+* [数据订阅(Publisher/Subscriber)](/advanced-features#subscribe):类似典型的消息队列,应用可订阅接收到的最新数据
* [缓存(Cache)](/advanced-features#cache):每个设备最新的数据都会缓存在内存中,可快速获取
* [报警监测](/advanced-features#alert):根据配置规则,自动监测超限行为数据,并主动推送
@@ -81,7 +81,7 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专
## [与其他工具的连接](/connections)
* [Grafana](/connections#grafana):获取并可视化保存在TDengine的数据
-* [Matlab](/connections#matlab):通过配置Matlab的JDBC数据源访问保存在TDengine的数据
+* [MATLAB](/connections#matlab):通过配置MATLAB的JDBC数据源访问保存在TDengine的数据
* [R](/connections#r):通过配置R的JDBC数据源访问保存在TDengine的数据
* [IDEA Database](https://www.taosdata.com/blog/2020/08/27/1767.html):通过IDEA 数据库管理工具可视化使用 TDengine
@@ -106,6 +106,7 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专
* [数据导入](/administrator#import):可按脚本文件导入,也可按数据文件导入
* [数据导出](/administrator#export):从shell按表导出,也可用taosdump工具做各种导出
* [系统监控](/administrator#status):检查系统现有的连接、查询、流式计算,日志和事件等
+* [性能优化](/administrator#optimize):对长期运行的系统进行维护优化,保障性能表现
* [文件目录结构](/administrator#directories):TDengine数据文件、配置文件等所在目录
* [参数限制与保留关键字](/administrator#keywords):TDengine的参数限制与保留关键字列表
diff --git a/documentation20/cn/01.evaluation/docs.md b/documentation20/cn/01.evaluation/docs.md
index 0ae2106ff2..7f70ccec56 100644
--- a/documentation20/cn/01.evaluation/docs.md
+++ b/documentation20/cn/01.evaluation/docs.md
@@ -9,8 +9,8 @@ TDengine的模块之一是时序数据库。但除此之外,为减少研发的
* __10倍以上的性能提升__:定义了创新的数据存储结构,单核每秒能处理至少2万次请求,插入数百万个数据点,读出一千万以上数据点,比现有通用数据库快十倍以上。
* __硬件或云服务成本降至1/5__:由于超强性能,计算资源不到通用大数据方案的1/5;通过列式存储和先进的压缩算法,存储空间不到通用数据库的1/10。
* __全栈时序数据处理引擎__:将数据库、消息队列、缓存、流式计算等功能融为一体,应用无需再集成Kafka/Redis/HBase/Spark/HDFS等软件,大幅降低应用开发和维护的复杂度成本。
-* __强大的分析功能__:无论是十年前还是一秒钟前的数据,指定时间范围即可查询。数据可在时间轴上或多个设备上进行聚合。即席查询可通过Shell, Python, R, Matlab随时进行。
-* __与第三方工具无缝连接__:不用一行代码,即可与Telegraf, Grafana, EMQ, HiveMQ, Prometheus, Matlab, R等集成。后续将支持OPC, Hadoop, Spark等, BI工具也将无缝连接。
+* __强大的分析功能__:无论是十年前还是一秒钟前的数据,指定时间范围即可查询。数据可在时间轴上或多个设备上进行聚合。即席查询可通过Shell, Python, R, MATLAB随时进行。
+* __与第三方工具无缝连接__:不用一行代码,即可与Telegraf, Grafana, EMQ, HiveMQ, Prometheus, MATLAB, R等集成。后续将支持OPC, Hadoop, Spark等, BI工具也将无缝连接。
* __零运维成本、零学习成本__:安装集群简单快捷,无需分库分表,实时备份。类似标准SQL,支持RESTful, 支持Python/Java/C/C++/C#/Go/Node.js, 与MySQL相似,零学习成本。
采用TDengine,可将典型的物联网、车联网、工业互联网大数据平台的总拥有成本大幅降低。但需要指出的是,因充分利用了物联网时序数据的特点,它无法用来处理网络爬虫、微博、微信、电商、ERP、CRM等通用型数据。
diff --git a/documentation20/cn/08.connector/01.java/docs.md b/documentation20/cn/08.connector/01.java/docs.md
index e6d214c74d..546e2dbcd3 100644
--- a/documentation20/cn/08.connector/01.java/docs.md
+++ b/documentation20/cn/08.connector/01.java/docs.md
@@ -49,6 +49,7 @@ TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致
+注意:与 JNI 方式不同,RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,RESTful 下所有对表名、超级表名的引用都需要指定数据库名前缀。
## 如何获取 taos-jdbcdriver
@@ -531,8 +532,9 @@ Query OK, 1 row(s) in set (0.000141s)
| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
| -------------------- | ----------------- | -------- |
-| 2.0.22 | 2.0.18.0 及以上 | 1.8.x |
-| 2.0.12 - 2.0.21 | 2.0.8.0 - 2.0.17.0 | 1.8.x |
+| 2.0.31 | 2.1.3.0 及以上 | 1.8.x |
+| 2.0.22 - 20.0.30 | 2.0.18.0 - 2.1.2.x | 1.8.x |
+| 2.0.12 - 2.0.21 | 2.0.8.0 - 2.0.17.x | 1.8.x |
| 2.0.4 - 2.0.11 | 2.0.0.0 - 2.0.7.x | 1.8.x |
| 1.0.3 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
@@ -551,7 +553,7 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对
| BIGINT | java.lang.Long |
| FLOAT | java.lang.Float |
| DOUBLE | java.lang.Double |
-| SMALLINT | java.lang.Short |
+| SMALLINT | java.lang.Short |
| TINYINT | java.lang.Byte |
| BOOL | java.lang.Boolean |
| BINARY | byte array |
diff --git a/documentation20/cn/08.connector/docs.md b/documentation20/cn/08.connector/docs.md
index 991c3ce6ce..c55fcaaafc 100644
--- a/documentation20/cn/08.connector/docs.md
+++ b/documentation20/cn/08.connector/docs.md
@@ -56,7 +56,7 @@ TDengine提供了丰富的应用程序开发接口,其中包括C/C++、Java、
*taos.tar.gz*:应用驱动安装包
*driver*:TDengine应用驱动driver
*connector*: 各种编程语言连接器(go/grafanaplugin/nodejs/python/JDBC)
- *examples*: 各种编程语言的示例程序(c/C#/go/JDBC/matlab/python/R)
+ *examples*: 各种编程语言的示例程序(c/C#/go/JDBC/MATLAB/python/R)
运行install_client.sh进行安装
@@ -427,12 +427,15 @@ TDengine提供时间驱动的实时流式计算API。可以每隔一指定的时
* res:查询结果集,注意结果集中可能没有记录
* param:调用 `taos_subscribe`时客户程序提供的附加参数
* code:错误码
+
**注意**:在这个回调函数里不可以做耗时过长的处理,尤其是对于返回的结果集中数据较多的情况,否则有可能导致客户端阻塞等异常状态。如果必须进行复杂计算,则建议在另外的线程中进行处理。
* `TAOS_RES *taos_consume(TAOS_SUB *tsub)`
同步模式下,该函数用来获取订阅的结果。 用户应用程序将其置于一个循环之中。 如两次调用`taos_consume`的间隔小于订阅的轮询周期,API将会阻塞,直到时间间隔超过此周期。 如果数据库有新记录到达,该API将返回该最新的记录,否则返回一个没有记录的空结果集。 如果返回值为 `NULL`,说明系统出错。 异步模式下,用户程序不应调用此API。
+ **注意**:在调用 `taos_consume()` 之后,用户应用应确保尽快调用 `taos_fetch_row()` 或 `taos_fetch_block()` 来处理订阅结果,否则服务端会持续缓存查询结果数据等待客户端读取,极端情况下会导致服务端内存消耗殆尽,影响服务稳定性。
+
* `void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress)`
取消订阅。 如参数 `keepProgress` 不为0,API会保留订阅的进度信息,后续调用 `taos_subscribe` 时可以基于此进度继续;否则将删除进度信息,后续只能重新开始读取数据。
@@ -554,6 +557,13 @@ c1.close()
conn.close()
```
+#### 关于纳秒 (nanosecond) 在 Python 连接器中的说明
+
+由于目前 Python 对 nanosecond 支持的不完善(参见链接 1. 2. ),目前的实现方式是在 nanosecond 精度时返回整数,而不是 ms 和 us 返回的 datetime 类型,应用开发者需要自行处理,建议使用 pandas 的 to_datetime()。未来如果 Python 正式完整支持了纳秒,涛思数据可能会修改相关接口。
+
+1. https://stackoverflow.com/questions/10611328/parsing-datetime-strings-containing-nanoseconds
+2. https://www.python.org/dev/peps/pep-0564/
+
#### 帮助信息
用户可通过python的帮助信息直接查看模块的使用信息,或者参考tests/examples/python中的示例程序。以下为部分常用类和方法:
@@ -585,7 +595,9 @@ conn.close()
## RESTful Connector
-为支持各种不同类型平台的开发,TDengine提供符合REST设计标准的API,即RESTful API。为最大程度降低学习成本,不同于其他数据库RESTful API的设计方法,TDengine直接通过HTTP POST 请求BODY中包含的SQL语句来操作数据库,仅需要一个URL。RESTful连接器的使用参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1965.html)。
+为支持各种不同类型平台的开发,TDengine 提供符合 REST 设计标准的 API,即 RESTful API。为最大程度降低学习成本,不同于其他数据库 RESTful API 的设计方法,TDengine 直接通过 HTTP POST 请求 BODY 中包含的 SQL 语句来操作数据库,仅需要一个 URL。RESTful 连接器的使用参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1965.html)。
+
+注意:与标准连接器的一个区别是,RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,所有对表名、超级表名的引用都需要指定数据库名前缀。
### HTTP请求格式
@@ -803,7 +815,7 @@ C#连接器支持的系统有:Linux 64/Windows x64/Windows x86
* 应用驱动安装请参考[安装连接器驱动步骤](https://www.taosdata.com/cn/documentation/connector#driver)。
* .NET接口文件TDengineDrivercs.cs和参考程序示例TDengineTest.cs均位于Windows客户端install_directory/examples/C#目录下。
-* 在Windows系统上,C#应用程序可以使用TDengine的原生C接口来执行所有数据库操作,后续版本将提供ORM(dapper)框架驱动。
+* 在Windows系统上,C#应用程序可以使用TDengine的原生C接口来执行所有数据库操作,后续版本将提供ORM(Dapper)框架驱动。
### 安装验证
@@ -895,6 +907,10 @@ go env -w GOPROXY=https://goproxy.io,direct
sql.Open内置的方法,Close closes the statement.
+### 其他代码示例
+
+[Consume Messages from Kafka](https://github.com/taosdata/go-demo-kafka) 是一个通过 Go 语言实现消费 Kafka 队列写入 TDengine 的示例程序,也可以作为通过 Go 连接 TDengine 的写法参考。
+
## Node.js Connector
Node.js连接器支持的系统有:
diff --git a/documentation20/cn/09.connections/docs.md b/documentation20/cn/09.connections/docs.md
index 6a2ead3766..b47f297ae0 100644
--- a/documentation20/cn/09.connections/docs.md
+++ b/documentation20/cn/09.connections/docs.md
@@ -75,50 +75,45 @@ sudo cp -rf /usr/local/taos/connector/grafanaplugin /var/lib/grafana/plugins/tde

-## Matlab
+## MATLAB
-MatLab可以通过安装包内提供的JDBC Driver直接连接到TDengine获取数据到本地工作空间。
+MATLAB 可以通过安装包内提供的 JDBC Driver 直接连接到 TDengine 获取数据到本地工作空间。
-### MatLab的JDBC接口适配
+### MATLAB 的 JDBC 接口适配
-MatLab的适配有下面几个步骤,下面以Windows10上适配MatLab2017a为例:
+MATLAB 的适配有下面几个步骤,下面以 Windows 10 上适配 MATLAB2021a 为例:
-- 将TDengine安装包内的驱动程序JDBCDriver-1.0.0-dist.jar拷贝到${matlab_root}\MATLAB\R2017a\java\jar\toolbox
-- 将TDengine安装包内的taos.lib文件拷贝至${matlab_ root _dir}\MATLAB\R2017a\lib\win64
-- 将新添加的驱动jar包加入MatLab的classpath。在${matlab_ root _dir}\MATLAB\R2017a\toolbox\local\classpath.txt文件中添加下面一行
-
+- 将 TDengine 客户端安装路径下的 `\TDengine\connector\jdbc的驱动程序taos-jdbcdriver-2.0.25-dist.jar` 拷贝到 `${matlab_root}\MATLAB\R2021a\java\jar\toolbox`。
+- 将 TDengine 安装包内的 `taos.lib` 文件拷贝至 `${matlab_root_dir}\MATLAB\R2021\lib\win64`。
+- 将新添加的驱动 jar 包加入 MATLAB 的 classpath。在 `${matlab_root_dir}\MATLAB\R2021a\toolbox\local\classpath.txt` 文件中添加下面一行:
```
-$matlabroot/java/jar/toolbox/JDBCDriver-1.0.0-dist.jar
+$matlabroot/java/jar/toolbox/taos-jdbcdriver-2.0.25-dist.jar
```
-- 在${user_home}\AppData\Roaming\MathWorks\MATLAB\R2017a\下添加一个文件javalibrarypath.txt, 并在该文件中添加taos.dll的路径,比如您的taos.dll是在安装时拷贝到了C:\Windows\System32下,那么就应该在javalibrarypath.txt中添加如下一行:
-
+- 在 `${user_home}\AppData\Roaming\MathWorks\MATLAB\R2021a\` 下添加一个文件 `javalibrarypath.txt`,并在该文件中添加 taos.dll 的路径,比如您的 taos.dll 是在安装时拷贝到了 `C:\Windows\System32` 下,那么就应该在 `javalibrarypath.txt` 中添加如下一行:
```
C:\Windows\System32
```
-### 在MatLab中连接TDengine获取数据
+### 在 MATLAB 中连接 TDengine 获取数据
-在成功进行了上述配置后,打开MatLab。
+在成功进行了上述配置后,打开 MATLAB。
- 创建一个连接:
-
```matlab
-conn = database(‘db’, ‘root’, ‘taosdata’, ‘com.taosdata.jdbc.TSDBDriver’, ‘jdbc:TSDB://127.0.0.1:0/’)
+conn = database(‘test’, ‘root’, ‘taosdata’, ‘com.taosdata.jdbc.TSDBDriver’, ‘jdbc:TSDB://192.168.1.94:6030/’)
```
- 执行一次查询:
-
```matlab
sql0 = [‘select * from tb’]
data = select(conn, sql0);
```
- 插入一条记录:
-
```matlab
sql1 = [‘insert into tb values (now, 1)’]
exec(conn, sql1)
```
-更多例子细节请参考安装包内examples\Matlab\TDengineDemo.m文件。
+更多例子细节请参考安装包内 `examples\Matlab\TDengineDemo.m` 文件。
## R
diff --git a/documentation20/cn/10.cluster/docs.md b/documentation20/cn/10.cluster/docs.md
index 62d709c279..db20ca4edb 100644
--- a/documentation20/cn/10.cluster/docs.md
+++ b/documentation20/cn/10.cluster/docs.md
@@ -85,7 +85,7 @@ taos>
将后续的数据节点添加到现有集群,具体有以下几步:
-1. 按照[《立即开始》](https://www.taosdata.com/cn/documentation/getting-started/)一章的方法在每个物理节点启动taosd;
+1. 按照[《立即开始》](https://www.taosdata.com/cn/documentation/getting-started/)一章的方法在每个物理节点启动taosd;(注意:每个物理节点都需要在 taos.cfg 文件中将 firstEP 参数配置为新集群首个节点的 End Point——在本例中是 h1.taos.com:6030)
2. 在第一个数据节点,使用CLI程序taos, 登录进TDengine系统, 执行命令:
diff --git a/documentation20/cn/11.administrator/docs.md b/documentation20/cn/11.administrator/docs.md
index 9e1f627709..753f91f589 100644
--- a/documentation20/cn/11.administrator/docs.md
+++ b/documentation20/cn/11.administrator/docs.md
@@ -116,20 +116,22 @@ taosd -C
**注意:**对于端口,TDengine会使用从serverPort起13个连续的TCP和UDP端口号,请务必在防火墙打开。因此如果是缺省配置,需要打开从6030到6042共13个端口,而且必须TCP和UDP都打开。(详细的端口情况请参见 [TDengine 2.0 端口说明](https://www.taosdata.com/cn/documentation/faq#port))
-不同应用场景的数据往往具有不同的数据特征,比如保留天数、副本数、采集频次、记录大小、采集点的数量、压缩等都可完全不同。为获得在存储上的最高效率,TDengine提供如下存储相关的系统配置参数:
+不同应用场景的数据往往具有不同的数据特征,比如保留天数、副本数、采集频次、记录大小、采集点的数量、压缩等都可完全不同。为获得在存储上的最高效率,TDengine提供如下存储相关的系统配置参数(既可以作为 create database 指令的参数,也可以写在 taos.cfg 配置文件中用来设定创建新数据库时所采用的默认值):
-- days:一个数据文件存储数据的时间跨度,单位为天,默认值:10。
-- keep:数据库中数据保留的天数,单位为天,默认值:3650。(可通过 alter database 修改)
-- minRows:文件块中记录的最小条数,单位为条,默认值:100。
-- maxRows:文件块中记录的最大条数,单位为条,默认值:4096。
-- comp:文件压缩标志位,0:关闭;1:一阶段压缩;2:两阶段压缩。默认值:2。(可通过 alter database 修改)
-- walLevel:WAL级别。1:写wal,但不执行fsync;2:写wal, 而且执行fsync。默认值:1。
-- fsync:当wal设置为2时,执行fsync的周期。设置为0,表示每次写入,立即执行fsync。单位为毫秒,默认值:3000。
-- cache:内存块的大小,单位为兆字节(MB),默认值:16。
+- days:一个数据文件存储数据的时间跨度。单位为天,默认值:10。
+- keep:数据库中数据保留的天数。单位为天,默认值:3650。(可通过 alter database 修改)
+- minRows:文件块中记录的最小条数。单位为条,默认值:100。
+- maxRows:文件块中记录的最大条数。单位为条,默认值:4096。
+- comp:文件压缩标志位。0:关闭;1:一阶段压缩;2:两阶段压缩。默认值:2。(可通过 alter database 修改)
+- wal:WAL级别。1:写wal,但不执行fsync;2:写wal, 而且执行fsync。默认值:1。(在 taos.cfg 中参数名需要写作 walLevel)(可通过 alter database 修改)
+- fsync:当wal设置为2时,执行fsync的周期。设置为0,表示每次写入,立即执行fsync。单位为毫秒,默认值:3000。(可通过 alter database 修改)
+- cache:内存块的大小。单位为兆字节(MB),默认值:16。
- blocks:每个VNODE(TSDB)中有多少cache大小的内存块。因此一个VNODE的用的内存大小粗略为(cache * blocks)。单位为块,默认值:4。(可通过 alter database 修改)
-- replica:副本个数,取值范围:1-3。单位为个,默认值:1。(可通过 alter database 修改)
-- precision:时间戳精度标识,ms表示毫秒,us表示微秒。默认值:ms。
-- cacheLast:是否在内存中缓存子表的最近数据,0:关闭;1:缓存子表最近一行数据;2:缓存子表每一列的最近的非NULL值,3:同时打开缓存最近行和列功能,默认值:0。(可通过 alter database 修改)(从 2.0.11 版本开始支持此参数)
+- replica:副本个数。取值范围:1-3,单位为个,默认值:1。(可通过 alter database 修改)
+- quorum:多副本环境下指令执行的确认数要求。取值范围:1、2,单位为个,默认值:1。(可通过 alter database 修改)
+- precision:时间戳精度标识。ms表示毫秒,us表示微秒,默认值:ms。(2.1.2.0 版本之前、2.0.20.7 版本之前在 taos.cfg 文件中不支持此参数。)
+- cacheLast:是否在内存中缓存子表的最近数据。0:关闭;1:缓存子表最近一行数据;2:缓存子表每一列的最近的非NULL值;3:同时打开缓存最近行和列功能。默认值:0。(可通过 alter database 修改)(从 2.1.2.0 版本开始此参数支持 0~3 的取值范围,在此之前取值只能是 [0, 1];而 2.0.11.0 之前的版本在 SQL 指令中不支持此参数。)(2.1.2.0 版本之前、2.0.20.7 版本之前在 taos.cfg 文件中不支持此参数。)
+- update:是否允许更新。0:不允许;1:允许。默认值:0。
对于一个应用场景,可能有多种数据特征的数据并存,最佳的设计是将具有相同数据特征的表放在一个库里,这样一个应用有多个库,而每个库可以配置不同的存储参数,从而保证系统有最优的性能。TDengine允许应用在创建库时指定上述存储参数,如果指定,该参数就将覆盖对应的系统配置参数。举例,有下述SQL:
@@ -142,7 +144,6 @@ taosd -C
TDengine集群中加入一个新的dnode时,涉及集群相关的一些参数必须与已有集群的配置相同,否则不能成功加入到集群中。会进行校验的参数如下:
- numOfMnodes:系统中管理节点个数。默认值:3。
-- balance:是否启动负载均衡。0:否,1:是。默认值:1。
- mnodeEqualVnodeNum: 一个mnode等同于vnode消耗的个数。默认值:4。
- offlineThreshold: dnode离线阈值,超过该时间将导致该dnode从集群中删除。单位为秒,默认值:86400*10(即10天)。
- statusInterval: dnode向mnode报告状态时长。单位为秒,默认值:1。
@@ -150,6 +151,10 @@ TDengine集群中加入一个新的dnode时,涉及集群相关的一些参数
- maxVgroupsPerDb: 每个数据库中能够使用的最大vgroup个数。
- arbitrator: 系统中裁决器的end point,缺省为空。
- timezone、locale、charset 的配置见客户端配置。(2.0.20.0 及以上的版本里,集群中加入新节点已不要求 locale 和 charset 参数取值一致)
+- balance:是否启用负载均衡。0:否,1:是。默认值:1。
+- flowctrl:是否启用非阻塞流控。0:否,1:是。默认值:1。
+- slaveQuery:是否启用 slave vnode 参与查询。0:否,1:是。默认值:1。
+- adjustMaster:是否启用 vnode master 负载均衡。0:否,1:是。默认值:1。
为方便调试,可通过SQL语句临时调整每个dnode的日志配置,系统重启后会失效:
@@ -413,6 +418,19 @@ TDengine启动后,会自动创建一个监测数据库log,并自动将服务
这些监测信息的采集缺省是打开的,但可以修改配置文件里的选项enableMonitor将其关闭或打开。
+
+## 性能优化
+
+因数据行 [update](https://www.taosdata.com/cn/documentation/faq#update)、表删除、数据过期等原因,TDengine 的磁盘存储文件有可能出现数据碎片,影响查询操作的性能表现。从 2.1.3.0 版本开始,新增 SQL 指令 COMPACT 来启动碎片重整过程:
+
+```mysql
+COMPACT VNODES IN (vg_id1, vg_id2, ...)
+```
+
+COMPACT 命令对指定的一个或多个 VGroup 启动碎片重整,系统会通过任务队列尽快安排重整操作的具体执行。COMPACT 指令所需的 VGroup id,可以通过 `SHOW VGROUPS;` 指令的输出结果获取;而且在 `SHOW VGROUPS;` 中会有一个 compacting 列,值为 1 时表示对应的 VGroup 正在进行碎片重整,为 0 时则表示并没有处于重整状态。
+
+需要注意的是,碎片重整操作会大幅消耗磁盘 I/O。因此在重整进行期间,有可能会影响节点的写入和查询性能,甚至在极端情况下导致短时间的阻写。
+
## 文件目录结构
安装TDengine后,默认会在操作系统中生成下列目录或文件:
@@ -460,43 +478,44 @@ TDengine的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下
目前 TDengine 有将近 200 个内部保留关键字,这些关键字无论大小写均不可以用作库名、表名、STable 名、数据列名及标签列名等。这些关键字列表如下:
-| 关键字列表 | | | | |
-| ---------- | ----------- | ------------ | ---------- | --------- |
-| ABLOCKS | CONNECTIONS | HAVING | MODULES | SMALLINT |
-| ABORT | COPY | ID | NCHAR | SPREAD |
-| ACCOUNT | COUNT | IF | NE | STABLE |
-| ACCOUNTS | CREATE | IGNORE | NONE | STABLES |
-| ADD | CTIME | IMMEDIATE | NOT | STAR |
-| AFTER | DATABASE | IMPORT | NOTNULL | STATEMENT |
-| ALL | DATABASES | IN | NOW | STDDEV |
-| ALTER | DAYS | INITIALLY | OF | STREAM |
-| AND | DEFERRED | INSERT | OFFSET | STREAMS |
-| AS | DELIMITERS | INSTEAD | OR | STRING |
-| ASC | DESC | INTEGER | ORDER | SUM |
-| ATTACH | DESCRIBE | INTERVAL | PASS | TABLE |
-| AVG | DETACH | INTO | PERCENTILE | TABLES |
-| BEFORE | DIFF | IP | PLUS | TAG |
-| BEGIN | DISTINCT | IS | PRAGMA | TAGS |
-| BETWEEN | DIVIDE | ISNULL | PREV | TBLOCKS |
-| BIGINT | DNODE | JOIN | PRIVILEGE | TBNAME |
-| BINARY | DNODES | KEEP | QUERIES | TIMES |
-| BITAND | DOT | KEY | QUERY | TIMESTAMP |
-| BITNOT | DOUBLE | KILL | RAISE | TINYINT |
-| BITOR | DROP | LAST | REM | TOP |
-| BOOL | EACH | LE | REPLACE | TOPIC |
-| BOTTOM | END | LEASTSQUARES | REPLICA | TRIGGER |
-| BY | EQ | LIKE | RESET | UMINUS |
-| CACHE | EXISTS | LIMIT | RESTRICT | UNION |
-| CASCADE | EXPLAIN | LINEAR | ROW | UPLUS |
-| CHANGE | FAIL | LOCAL | ROWS | USE |
-| CLOG | FILL | LP | RP | USER |
-| CLUSTER | FIRST | LSHIFT | RSHIFT | USERS |
-| COLON | FLOAT | LT | SCORES | USING |
-| COLUMN | FOR | MATCH | SELECT | VALUES |
-| COMMA | FROM | MAX | SEMI | VARIABLE |
-| COMP | GE | METRIC | SET | VGROUPS |
-| CONCAT | GLOB | METRICS | SHOW | VIEW |
-| CONFIGS | GRANTS | MIN | SLASH | WAVG |
-| CONFLICT | GROUP | MINUS | SLIDING | WHERE |
-| CONNECTION | GT | MNODES | SLIMIT | |
+| 关键字列表 | | | | |
+| ------------ | ------------ | ------------ | ------------ | ------------ |
+| ABORT | CREATE | IGNORE | NULL | STAR |
+| ACCOUNT | CTIME | IMMEDIATE | OF | STATE |
+| ACCOUNTS | DATABASE | IMPORT | OFFSET | STATEMENT |
+| ADD | DATABASES | IN | OR | STATE_WINDOW |
+| AFTER | DAYS | INITIALLY | ORDER | STORAGE |
+| ALL | DBS | INSERT | PARTITIONS | STREAM |
+| ALTER | DEFERRED | INSTEAD | PASS | STREAMS |
+| AND | DELIMITERS | INT | PLUS | STRING |
+| AS | DESC | INTEGER | PPS | SYNCDB |
+| ASC | DESCRIBE | INTERVAL | PRECISION | TABLE |
+| ATTACH | DETACH | INTO | PREV | TABLES |
+| BEFORE | DISTINCT | IS | PRIVILEGE | TAG |
+| BEGIN | DIVIDE | ISNULL | QTIME | TAGS |
+| BETWEEN | DNODE | JOIN | QUERIES | TBNAME |
+| BIGINT | DNODES | KEEP | QUERY | TIMES |
+| BINARY | DOT | KEY | QUORUM | TIMESTAMP |
+| BITAND | DOUBLE | KILL | RAISE | TINYINT |
+| BITNOT | DROP | LE | REM | TOPIC |
+| BITOR | EACH | LIKE | REPLACE | TOPICS |
+| BLOCKS | END | LIMIT | REPLICA | TRIGGER |
+| BOOL | EQ | LINEAR | RESET | TSERIES |
+| BY | EXISTS | LOCAL | RESTRICT | UMINUS |
+| CACHE | EXPLAIN | LP | ROW | UNION |
+| CACHELAST | FAIL | LSHIFT | RP | UNSIGNED |
+| CASCADE | FILE | LT | RSHIFT | UPDATE |
+| CHANGE | FILL | MATCH | SCORES | UPLUS |
+| CLUSTER | FLOAT | MAXROWS | SELECT | USE |
+| COLON | FOR | MINROWS | SEMI | USER |
+| COLUMN | FROM | MINUS | SESSION | USERS |
+| COMMA | FSYNC | MNODES | SET | USING |
+| COMP | GE | MODIFY | SHOW | VALUES |
+| COMPACT | GLOB | MODULES | SLASH | VARIABLE |
+| CONCAT | GRANTS | NCHAR | SLIDING | VARIABLES |
+| CONFLICT | GROUP | NE | SLIMIT | VGROUPS |
+| CONNECTION | GT | NONE | SMALLINT | VIEW |
+| CONNECTIONS | HAVING | NOT | SOFFSET | VNODES |
+| CONNS | ID | NOTNULL | STABLE | WAL |
+| COPY | IF | NOW | STABLES | WHERE |
diff --git a/documentation20/cn/12.taos-sql/docs.md b/documentation20/cn/12.taos-sql/docs.md
index 7508bbf86f..764560dbeb 100644
--- a/documentation20/cn/12.taos-sql/docs.md
+++ b/documentation20/cn/12.taos-sql/docs.md
@@ -89,13 +89,13 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
```mysql
USE db_name;
```
- 使用/切换数据库
+ 使用/切换数据库(在 RESTful 连接方式下无效)。
- **删除数据库**
```mysql
DROP DATABASE [IF EXISTS] db_name;
```
- 删除数据库。所包含的全部数据表将被删除,谨慎使用
+ 删除数据库。指定 Database 所包含的全部数据表将被删除,谨慎使用!
- **修改数据库参数**
```mysql
@@ -126,9 +126,20 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
```mysql
ALTER DATABASE db_name CACHELAST 0;
```
- CACHELAST 参数控制是否在内存中缓存数据子表的 last_row。缺省值为 0,取值范围 [0, 1]。其中 0 表示不启用、1 表示启用。(从 2.0.11.0 版本开始支持。从 2.1.1.0 版本开始,修改此参数后无需重启服务器即可生效。)
+ CACHELAST 参数控制是否在内存中缓存子表的最近数据。缺省值为 0,取值范围 [0, 1, 2, 3]。其中 0 表示不缓存,1 表示缓存子表最近一行数据,2 表示缓存子表每一列的最近的非 NULL 值,3 表示同时打开缓存最近行和列功能。(从 2.0.11.0 版本开始支持参数值 [0, 1],从 2.1.2.0 版本开始支持参数值 [0, 1, 2, 3]。)
+ 说明:缓存最近行,将显著改善 LAST_ROW 函数的性能表现;缓存每列的最近非 NULL 值,将显著改善无特殊影响(WHERE、ORDER BY、GROUP BY、INTERVAL)下的 LAST 函数的性能表现。
- **Tips**: 以上所有参数修改后都可以用show databases来确认是否修改成功。
+ ```mysql
+ ALTER DATABASE db_name WAL 1;
+ ```
+ WAL 参数控制 WAL 日志的落盘方式。缺省值为 1,取值范围为 [1, 2]。1 表示写 WAL,但不执行 fsync;2 表示写 WAL,而且执行 fsync。
+
+ ```mysql
+ ALTER DATABASE db_name FSYNC 3000;
+ ```
+ FSYNC 参数控制执行 fsync 操作的周期。缺省值为 3000,单位是毫秒,取值范围为 [0, 180000]。如果设置为 0,表示每次写入,立即执行 fsync。该设置项主要用于调节 WAL 参数设为 2 时的系统行为。
+
+ **Tips**: 以上所有参数修改后都可以用show databases来确认是否修改成功。另外,从 2.1.3.0 版本开始,修改这些参数后无需重启服务器即可生效。
- **显示系统所有数据库**
@@ -247,6 +258,14 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
```
如果表是通过超级表创建,更改表结构的操作只能对超级表进行。同时针对超级表的结构更改对所有通过该结构创建的表生效。对于不是通过超级表创建的表,可以直接修改表结构。
+- **表修改列宽**
+
+ ```mysql
+ ALTER TABLE tb_name MODIFY COLUMN field_name data_type(length);
+ ```
+ 如果数据列的类型是可变长格式(BINARY 或 NCHAR),那么可以使用此指令修改其宽度(只能改大,不能改小)。(2.1.3.0 版本新增)
+ 如果表是通过超级表创建,更改表结构的操作只能对超级表进行。同时针对超级表的结构更改对所有通过该结构创建的表生效。对于不是通过超级表创建的表,可以直接修改表结构。
+
## 超级表STable管理
注意:在 2.0.15.0 及以后的版本中,开始支持 STABLE 保留字。也即,在本节后文的指令说明中,CREATE、DROP、ALTER 三个指令在老版本中保留字需写作 TABLE 而不是 STABLE。
@@ -260,11 +279,11 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
说明:
- 1) TAGS 列的数据类型不能是 timestamp 类型;
+ 1) TAGS 列的数据类型不能是 timestamp 类型;(从 2.1.3.0 版本开始,TAGS 列中支持使用 timestamp 类型,但需注意在 TAGS 中的 timestamp 列写入数据时需要提供给定值,而暂不支持四则运算,例如 `NOW + 10s` 这类表达式)
2) TAGS 列名不能与其他列名相同;
- 3) TAGS 列名不能为预留关键字;
+ 3) TAGS 列名不能为预留关键字(参见:[参数限制与保留关键字](https://www.taosdata.com/cn/documentation/administrator#keywords) 章节);
4) TAGS 最多允许 128 个,至少 1 个,总长度不超过 16 KB。
@@ -307,6 +326,13 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
ALTER STABLE stb_name DROP COLUMN field_name;
```
+- **超级表修改列宽**
+
+ ```mysql
+ ALTER STABLE stb_name MODIFY COLUMN field_name data_type(length);
+ ```
+ 如果数据列的类型是可变长格式(BINARY 或 NCHAR),那么可以使用此指令修改其宽度(只能改大,不能改小)。(2.1.3.0 版本新增)
+
## 超级表 STable 中 TAG 管理
- **添加标签**
@@ -330,6 +356,13 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
```
修改超级表的标签名,从超级表修改某个标签名后,该超级表下的所有子表也会自动更新该标签名。
+- **修改标签列宽度**
+
+ ```mysql
+ ALTER STABLE stb_name MODIFY TAG tag_name data_type(length);
+ ```
+ 如果标签的类型是可变长格式(BINARY 或 NCHAR),那么可以使用此指令修改其宽度(只能改大,不能改小)。(2.1.3.0 版本新增)
+
- **修改子表标签值**
```mysql
@@ -443,9 +476,10 @@ Query OK, 1 row(s) in set (0.001091s)
SELECT select_expr [, select_expr ...]
FROM {tb_name_list}
[WHERE where_condition]
- [INTERVAL (interval_val [, interval_offset])]
- [SLIDING sliding_val]
- [FILL fill_val]
+ [SESSION(ts_col, tol_val)]
+ [STATE_WINDOW(col)]
+ [INTERVAL(interval_val [, interval_offset]) [SLIDING sliding_val]]
+ [FILL(fill_mod_and_val)]
[GROUP BY col_list]
[ORDER BY col_list { DESC | ASC }]
[SLIMIT limit_val [SOFFSET offset_val]]
@@ -669,22 +703,24 @@ Query OK, 1 row(s) in set (0.001091s)
### 支持的条件过滤操作
-| **Operation** | **Note** | **Applicable Data Types** |
-| --------------- | ----------------------------- | ------------------------------------- |
-| > | larger than | **`timestamp`** and all numeric types |
-| < | smaller than | **`timestamp`** and all numeric types |
-| >= | larger than or equal to | **`timestamp`** and all numeric types |
-| <= | smaller than or equal to | **`timestamp`** and all numeric types |
-| = | equal to | all types |
-| <> | not equal to | all types |
-| between and | within a certain range | **`timestamp`** and all numeric types |
-| % | match with any char sequences | **`binary`** **`nchar`** |
-| _ | match with a single char | **`binary`** **`nchar`** |
+| **Operation** | **Note** | **Applicable Data Types** |
+| --------------- | ----------------------------- | ----------------------------------------- |
+| > | larger than | **`timestamp`** and all numeric types |
+| < | smaller than | **`timestamp`** and all numeric types |
+| >= | larger than or equal to | **`timestamp`** and all numeric types |
+| <= | smaller than or equal to | **`timestamp`** and all numeric types |
+| = | equal to | all types |
+| <> | not equal to | all types |
+| between and | within a certain range | **`timestamp`** and all numeric types |
+| in | matches any value in a set | all types except first column `timestamp` |
+| % | match with any char sequences | **`binary`** **`nchar`** |
+| _ | match with a single char | **`binary`** **`nchar`** |
1. <> 算子也可以写为 != ,请注意,这个算子不能用于数据表第一列的 timestamp 字段。
2. 同时进行多个字段的范围过滤,需要使用关键词 AND 来连接不同的查询条件,暂不支持 OR 连接的不同列之间的查询过滤条件。
-3. 针对单一字段的过滤,如果是时间过滤条件,则一条语句中只支持设定一个;但针对其他的(普通)列或标签列,则可以使用 `OR` 关键字进行组合条件的查询过滤。例如:((value > 20 AND value < 30) OR (value < 12)) 。
-4. 从 2.0.17 版本开始,条件过滤开始支持 BETWEEN AND 语法,例如 `WHERE col2 BETWEEN 1.5 AND 3.25` 表示查询条件为“1.5 ≤ col2 ≤ 3.25”。
+3. 针对单一字段的过滤,如果是时间过滤条件,则一条语句中只支持设定一个;但针对其他的(普通)列或标签列,则可以使用 `OR` 关键字进行组合条件的查询过滤。例如: `((value > 20 AND value < 30) OR (value < 12))`。
+4. 从 2.0.17.0 版本开始,条件过滤开始支持 BETWEEN AND 语法,例如 `WHERE col2 BETWEEN 1.5 AND 3.25` 表示查询条件为“1.5 ≤ col2 ≤ 3.25”。
+5. 从 2.1.4.0 版本开始,条件过滤开始支持 IN 算子,例如 `WHERE city IN ('Beijing', 'Shanghai')`。说明:BOOL 类型写作 `{true, false}` 或 `{0, 1}` 均可,但不能写作 0、1 之外的整数;FLOAT 和 DOUBLE 类型会受到浮点数精度影响,集合内的值在精度范围内认为和数据行的值完全相等才能匹配成功。
|
* |<-- Head -->|<--------- flen -------------->| |
* +---------------------+---------------------------------+---------------------------------+
@@ -173,6 +198,18 @@ static FORCE_INLINE int tkeyComparFn(const void *tkey1, const void *tkey2) {
* NOTE: timestamp in this row structure is TKEY instead of TSKEY
*/
typedef void *SDataRow;
+/* A memory data row, the format is like below:
+ *|---------+---------------------+--------------------------- len ---------------------------------->|
+ *|<- type->|<-- Head -->|<--------- flen -------------->| |
+ *|---------+---------------------+---------------------------------+---------------------------------+
+ *| uint8_t | uint16_t | int16_t | | |
+ *|---------+----------+----------+---------------------------------+---------------------------------+
+ *| flag | len | sversion | First part | Second part |
+ *|---------+----------+----------+---------------------------------+---------------------------------+
+ *
+ * NOTE: timestamp in this row structure is TKEY instead of TSKEY
+ */
+typedef void *SMemRow;
#define TD_DATA_ROW_HEAD_SIZE (sizeof(uint16_t) + sizeof(int16_t))
@@ -191,9 +228,10 @@ SDataRow tdNewDataRowFromSchema(STSchema *pSchema);
void tdFreeDataRow(SDataRow row);
void tdInitDataRow(SDataRow row, STSchema *pSchema);
SDataRow tdDataRowDup(SDataRow row);
+SMemRow tdMemRowDup(SMemRow row);
// offset here not include dataRow header length
-static FORCE_INLINE int tdAppendColVal(SDataRow row, void *value, int8_t type, int32_t bytes, int32_t offset) {
+static FORCE_INLINE int tdAppendColVal(SDataRow row, const void *value, int8_t type, int32_t bytes, int32_t offset) {
ASSERT(value != NULL);
int32_t toffset = offset + TD_DATA_ROW_HEAD_SIZE;
char * ptr = (char *)POINTER_SHIFT(row, dataRowLen(row));
@@ -216,12 +254,13 @@ static FORCE_INLINE int tdAppendColVal(SDataRow row, void *value, int8_t type, i
}
// NOTE: offset here including the header size
-static FORCE_INLINE void *tdGetRowDataOfCol(SDataRow row, int8_t type, int32_t offset) {
+static FORCE_INLINE void *tdGetRowDataOfCol(void *row, int8_t type, int32_t offset) {
if (IS_VAR_DATA_TYPE(type)) {
return POINTER_SHIFT(row, *(VarDataOffsetT *)POINTER_SHIFT(row, offset));
} else {
return POINTER_SHIFT(row, offset);
}
+ return NULL;
}
// ----------------- Data column structure
@@ -237,17 +276,56 @@ typedef struct SDataCol {
TSKEY ts; // only used in last NULL column
} SDataCol;
+#define isAllRowOfColNull(pCol) ((pCol)->len == 0)
static FORCE_INLINE void dataColReset(SDataCol *pDataCol) { pDataCol->len = 0; }
void dataColInit(SDataCol *pDataCol, STColumn *pCol, void **pBuf, int maxPoints);
-void dataColAppendVal(SDataCol *pCol, void *value, int numOfRows, int maxPoints);
+void dataColAppendVal(SDataCol *pCol, const void *value, int numOfRows, int maxPoints);
void dataColSetOffset(SDataCol *pCol, int nEle);
bool isNEleNull(SDataCol *pCol, int nEle);
void dataColSetNEleNull(SDataCol *pCol, int nEle, int maxPoints);
+static const void *tdGetNullVal(int8_t type) {
+ switch (type) {
+ case TSDB_DATA_TYPE_BOOL:
+ return &BoolNull;
+ case TSDB_DATA_TYPE_TINYINT:
+ return &TinyintNull;
+ case TSDB_DATA_TYPE_SMALLINT:
+ return &SmallintNull;
+ case TSDB_DATA_TYPE_INT:
+ return &IntNull;
+ case TSDB_DATA_TYPE_BIGINT:
+ return &BigintNull;
+ case TSDB_DATA_TYPE_FLOAT:
+ return &FloatNull;
+ case TSDB_DATA_TYPE_DOUBLE:
+ return &DoubleNull;
+ case TSDB_DATA_TYPE_BINARY:
+ return &BinaryNull;
+ case TSDB_DATA_TYPE_TIMESTAMP:
+ return &TimestampNull;
+ case TSDB_DATA_TYPE_NCHAR:
+ return &NcharNull;
+ case TSDB_DATA_TYPE_UTINYINT:
+ return &UTinyintNull;
+ case TSDB_DATA_TYPE_USMALLINT:
+ return &USmallintNull;
+ case TSDB_DATA_TYPE_UINT:
+ return &UIntNull;
+ case TSDB_DATA_TYPE_UBIGINT:
+ return &UBigintNull;
+ default:
+ ASSERT(0);
+ return NULL;
+ }
+}
// Get the data pointer from a column-wised data
-static FORCE_INLINE void *tdGetColDataOfRow(SDataCol *pCol, int row) {
+static FORCE_INLINE const void *tdGetColDataOfRow(SDataCol *pCol, int row) {
+ if (isAllRowOfColNull(pCol)) {
+ return tdGetNullVal(pCol->type);
+ }
if (IS_VAR_DATA_TYPE(pCol->type)) {
return POINTER_SHIFT(pCol->pData, pCol->dataOff[row]);
} else {
@@ -279,7 +357,7 @@ typedef struct {
} SDataCols;
#define keyCol(pCols) (&((pCols)->cols[0])) // Key column
-#define dataColsTKeyAt(pCols, idx) ((TKEY *)(keyCol(pCols)->pData))[(idx)]
+#define dataColsTKeyAt(pCols, idx) ((TKEY *)(keyCol(pCols)->pData))[(idx)] // the idx row of column-wised data
#define dataColsKeyAt(pCols, idx) tdGetKey(dataColsTKeyAt(pCols, idx))
static FORCE_INLINE TKEY dataColsTKeyFirst(SDataCols *pCols) {
if (pCols->numOfRows) {
@@ -289,6 +367,11 @@ static FORCE_INLINE TKEY dataColsTKeyFirst(SDataCols *pCols) {
}
}
+static FORCE_INLINE TSKEY dataColsKeyAtRow(SDataCols *pCols, int row) {
+ ASSERT(row < pCols->numOfRows);
+ return dataColsKeyAt(pCols, row);
+}
+
static FORCE_INLINE TSKEY dataColsKeyFirst(SDataCols *pCols) {
if (pCols->numOfRows) {
return dataColsKeyAt(pCols, 0);
@@ -318,13 +401,13 @@ void tdResetDataCols(SDataCols *pCols);
int tdInitDataCols(SDataCols *pCols, STSchema *pSchema);
SDataCols *tdDupDataCols(SDataCols *pCols, bool keepData);
SDataCols *tdFreeDataCols(SDataCols *pCols);
-void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols *pCols);
+void tdAppendMemRowToDataCol(SMemRow row, STSchema *pSchema, SDataCols *pCols);
int tdMergeDataCols(SDataCols *target, SDataCols *source, int rowsToMerge, int *pOffset);
// ----------------- K-V data row structure
/*
* +----------+----------+---------------------------------+---------------------------------+
- * | int16_t | int16_t | | |
+ * | uint16_t | int16_t | | |
* +----------+----------+---------------------------------+---------------------------------+
* | len | ncols | cols index | data part |
* +----------+----------+---------------------------------+---------------------------------+
@@ -332,14 +415,14 @@ int tdMergeDataCols(SDataCols *target, SDataCols *source, int rowsToMerge
typedef void *SKVRow;
typedef struct {
- int16_t colId;
- int16_t offset;
+ int16_t colId;
+ uint16_t offset;
} SColIdx;
-#define TD_KV_ROW_HEAD_SIZE (2 * sizeof(int16_t))
+#define TD_KV_ROW_HEAD_SIZE (sizeof(uint16_t) + sizeof(int16_t))
-#define kvRowLen(r) (*(int16_t *)(r))
-#define kvRowNCols(r) (*(int16_t *)POINTER_SHIFT(r, sizeof(int16_t)))
+#define kvRowLen(r) (*(uint16_t *)(r))
+#define kvRowNCols(r) (*(int16_t *)POINTER_SHIFT(r, sizeof(uint16_t)))
#define kvRowSetLen(r, len) kvRowLen(r) = (len)
#define kvRowSetNCols(r, n) kvRowNCols(r) = (n)
#define kvRowColIdx(r) (SColIdx *)POINTER_SHIFT(r, TD_KV_ROW_HEAD_SIZE)
@@ -349,6 +432,11 @@ typedef struct {
#define kvRowColIdxAt(r, i) (kvRowColIdx(r) + (i))
#define kvRowFree(r) tfree(r)
#define kvRowEnd(r) POINTER_SHIFT(r, kvRowLen(r))
+#define kvRowVersion(r) (-1)
+
+#define kvRowTKey(r) (*(TKEY *)(kvRowValues(r)))
+#define kvRowKey(r) tdGetKey(kvRowTKey(r))
+#define kvRowDeleted(r) TKEY_IS_DELETED(kvRowTKey(r))
SKVRow tdKVRowDup(SKVRow row);
int tdSetKVRowDataOfCol(SKVRow *orow, int16_t colId, int8_t type, void *value);
@@ -372,13 +460,40 @@ static FORCE_INLINE void *tdGetKVRowValOfCol(SKVRow row, int16_t colId) {
return kvRowColVal(row, (SColIdx *)ret);
}
+// offset here not include kvRow header length
+static FORCE_INLINE int tdAppendKvColVal(SKVRow row, const void *value, int16_t colId, int8_t type, int32_t offset) {
+ ASSERT(value != NULL);
+ int32_t toffset = offset + TD_KV_ROW_HEAD_SIZE;
+ SColIdx *pColIdx = (SColIdx *)POINTER_SHIFT(row, toffset);
+ char * ptr = (char *)POINTER_SHIFT(row, kvRowLen(row));
+
+ pColIdx->colId = colId;
+ pColIdx->offset = kvRowLen(row);
+
+ if (IS_VAR_DATA_TYPE(type)) {
+ memcpy(ptr, value, varDataTLen(value));
+ kvRowLen(row) += varDataTLen(value);
+ } else {
+ if (offset == 0) {
+ ASSERT(type == TSDB_DATA_TYPE_TIMESTAMP);
+ TKEY tvalue = tdGetTKEY(*(TSKEY *)value);
+ memcpy(ptr, (void *)(&tvalue), TYPE_BYTES[type]);
+ } else {
+ memcpy(ptr, value, TYPE_BYTES[type]);
+ }
+ kvRowLen(row) += TYPE_BYTES[type];
+ }
+
+ return 0;
+}
+
// ----------------- K-V data row builder
typedef struct {
int16_t tCols;
int16_t nCols;
SColIdx *pColIdx;
- int16_t alloc;
- int16_t size;
+ uint16_t alloc;
+ uint16_t size;
void * buf;
} SKVRowBuilder;
@@ -414,6 +529,74 @@ static FORCE_INLINE int tdAddColToKVRow(SKVRowBuilder *pBuilder, int16_t colId,
return 0;
}
+// ----------------- Sequential Data row structure
+/*
+ * |-------------------------------+--------------------------- len ---------------------------------->|
+ * |<-------- Head ------>|<--------- flen -------------->| |
+ * |---------+---------------------+---------------------------------+---------------------------------+
+ * | uint8_t | uint16_t | int16_t | | |
+ * |---------+----------+----------+---------------------------------+---------------------------------+
+ * | flag | len | sversion | First part | Second part |
+ * +---------+----------+----------+---------------------------------+---------------------------------+
+ *
+ * NOTE: timestamp in this row structure is TKEY instead of TSKEY
+ */
+
+// ----------------- K-V data row structure
+/*
+ * |--------------------+----------+---------------------------------+---------------------------------+
+ * | uint8_t | uint16_t | int16_t | | |
+ * |---------+----------+----------+---------------------------------+---------------------------------+
+ * | flag | len | ncols | cols index | data part |
+ * |---------+----------+----------+---------------------------------+---------------------------------+
+ */
+
+#define TD_MEM_ROW_TYPE_SIZE sizeof(uint8_t)
+#define TD_MEM_ROW_HEAD_SIZE (TD_MEM_ROW_TYPE_SIZE + sizeof(uint16_t) + sizeof(int16_t))
+
+#define SMEM_ROW_DATA 0U // SDataRow
+#define SMEM_ROW_KV 1U // SKVRow
+#define TD_DO_NOTHING \
+ do { \
+ } while (0)
+
+#define memRowType(r) (*(uint8_t *)(r))
+#define memRowBody(r) POINTER_SHIFT(r, TD_MEM_ROW_TYPE_SIZE)
+#define memRowLen(r) (*(uint16_t *)POINTER_SHIFT(r, TD_MEM_ROW_TYPE_SIZE))
+#define memRowTLen(r) (*(uint16_t *)POINTER_SHIFT(r, TD_MEM_ROW_TYPE_SIZE) + (uint16_t)TD_MEM_ROW_TYPE_SIZE)
+
+#define isDataRow(r) (SMEM_ROW_DATA == memRowType(r))
+#define isKvRow(r) (SMEM_ROW_KV == memRowType(r))
+#define memRowVersion(r) (isDataRow(r) ? dataRowVersion(memRowBody(r)) : kvRowVersion(r)) // schema version
+
+#define memRowTuple(r) (isDataRow(r) ? dataRowTuple(memRowBody(r)) : kvRowValues(memRowBody(r)))
+
+#define memRowTKey(r) (isDataRow(r) ? dataRowTKey(memRowBody(r)) : kvRowTKey(memRowBody(r)))
+#define memRowKey(r) (isDataRow(r) ? dataRowKey(memRowBody(r)) : kvRowKey(memRowBody(r)))
+
+#define memRowSetType(r, t) (memRowType(r) = (t))
+#define memRowSetLen(r, l) (memRowLen(r) = (l))
+#define memRowSetVersion(r, v) (isDataRow(r) ? dataRowSetVersion(r, v) : TD_DO_NOTHING)
+#define memRowCpy(dst, r) memcpy((dst), (r), memRowTLen(r))
+#define memRowMaxBytesFromSchema(s) (schemaTLen(s) + TD_MEM_ROW_HEAD_SIZE)
+#define memRowDeleted(r) TKEY_IS_DELETED(memRowTKey(r))
+
+// NOTE: offset here including the header size
+static FORCE_INLINE void *tdGetKvRowDataOfCol(void *row, int8_t type, int32_t offset) {
+ return POINTER_SHIFT(row, offset);
+}
+// NOTE: offset here including the header size
+static FORCE_INLINE void *tdGetMemRowDataOfCol(void *row, int8_t type, int32_t offset) {
+ if (isDataRow(row)) {
+ return tdGetRowDataOfCol(row, type, offset);
+ } else if (isKvRow(row)) {
+ return tdGetKvRowDataOfCol(row, type, offset);
+ } else {
+ ASSERT(0);
+ }
+ return NULL;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/src/common/inc/tglobal.h b/src/common/inc/tglobal.h
index 47460a5fab..e35e805efe 100644
--- a/src/common/inc/tglobal.h
+++ b/src/common/inc/tglobal.h
@@ -155,7 +155,7 @@ extern char tsMnodeTmpDir[];
extern char tsDataDir[];
extern char tsLogDir[];
extern char tsScriptDir[];
-extern int64_t tsMsPerDay[3];
+extern int64_t tsTickPerDay[3];
// system info
extern char tsOsName[];
diff --git a/src/common/src/tdataformat.c b/src/common/src/tdataformat.c
index 7ae34d532c..ac7b15ea02 100644
--- a/src/common/src/tdataformat.c
+++ b/src/common/src/tdataformat.c
@@ -18,6 +18,21 @@
#include "tcoding.h"
#include "wchar.h"
+const uint8_t BoolNull = TSDB_DATA_BOOL_NULL;
+const uint8_t TinyintNull = TSDB_DATA_TINYINT_NULL;
+const uint16_t SmallintNull = TSDB_DATA_SMALLINT_NULL;
+const uint32_t IntNull = TSDB_DATA_INT_NULL;
+const uint64_t BigintNull = TSDB_DATA_BIGINT_NULL;
+const uint64_t TimestampNull = TSDB_DATA_BIGINT_NULL;
+const uint8_t UTinyintNull = TSDB_DATA_UTINYINT_NULL;
+const uint16_t USmallintNull = TSDB_DATA_USMALLINT_NULL;
+const uint32_t UIntNull = TSDB_DATA_UINT_NULL;
+const uint64_t UBigintNull = TSDB_DATA_UBIGINT_NULL;
+const uint32_t FloatNull = TSDB_DATA_FLOAT_NULL;
+const uint64_t DoubleNull = TSDB_DATA_DOUBLE_NULL;
+const SBinaryNullT BinaryNull = {1, TSDB_DATA_BINARY_NULL};
+const SNCharNullT NcharNull = {4, TSDB_DATA_NCHAR_NULL};
+
static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limit1, SDataCols *src2, int *iter2,
int limit2, int tRows);
@@ -198,11 +213,19 @@ SDataRow tdDataRowDup(SDataRow row) {
return trow;
}
+SMemRow tdMemRowDup(SMemRow row) {
+ SMemRow trow = malloc(memRowTLen(row));
+ if (trow == NULL) return NULL;
+
+ memRowCpy(trow, row);
+ return trow;
+}
+
void dataColInit(SDataCol *pDataCol, STColumn *pCol, void **pBuf, int maxPoints) {
pDataCol->type = colType(pCol);
pDataCol->colId = colColId(pCol);
pDataCol->bytes = colBytes(pCol);
- pDataCol->offset = colOffset(pCol) + TD_DATA_ROW_HEAD_SIZE;
+ pDataCol->offset = colOffset(pCol) + TD_MEM_ROW_HEAD_SIZE;
pDataCol->len = 0;
if (IS_VAR_DATA_TYPE(pDataCol->type)) {
@@ -219,9 +242,21 @@ void dataColInit(SDataCol *pDataCol, STColumn *pCol, void **pBuf, int maxPoints)
}
// value from timestamp should be TKEY here instead of TSKEY
-void dataColAppendVal(SDataCol *pCol, void *value, int numOfRows, int maxPoints) {
+void dataColAppendVal(SDataCol *pCol, const void *value, int numOfRows, int maxPoints) {
ASSERT(pCol != NULL && value != NULL);
+ if (pCol->len == 0) {
+ if (isNull(value, pCol->type)) {
+ // all null value yet, just return
+ return;
+ }
+
+ if (numOfRows > 0) {
+ // Find the first not null value, fill all previous values as NULL
+ dataColSetNEleNull(pCol, numOfRows, maxPoints);
+ }
+ }
+
if (IS_VAR_DATA_TYPE(pCol->type)) {
// set offset
pCol->dataOff[numOfRows] = pCol->len;
@@ -399,8 +434,7 @@ void tdResetDataCols(SDataCols *pCols) {
}
}
}
-
-void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols *pCols) {
+static void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols *pCols) {
ASSERT(pCols->numOfRows == 0 || dataColsKeyLast(pCols) < dataRowKey(row));
int rcol = 0;
@@ -419,7 +453,7 @@ void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols *pCols)
while (dcol < pCols->numOfCols) {
SDataCol *pDataCol = &(pCols->cols[dcol]);
if (rcol >= schemaNCols(pSchema)) {
- dataColSetNullAt(pDataCol, pCols->numOfRows);
+ dataColAppendVal(pDataCol, tdGetNullVal(pDataCol->type), pCols->numOfRows, pCols->maxPoints);
dcol++;
continue;
}
@@ -433,7 +467,7 @@ void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols *pCols)
} else if (pRowCol->colId < pDataCol->colId) {
rcol++;
} else {
- dataColSetNullAt(pDataCol, pCols->numOfRows);
+ dataColAppendVal(pDataCol, tdGetNullVal(pDataCol->type), pCols->numOfRows, pCols->maxPoints);
dcol++;
}
}
@@ -441,6 +475,98 @@ void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols *pCols)
pCols->numOfRows++;
}
+static void tdGetKVRowColInfo(const STSchema *pSchema, SColIdx *pColIdx, int nRowCols, STColumn *pSTColumn,
+ int *nColMatched) {
+ int nSchema = schemaNCols(pSchema);
+ int iCol = 0;
+ int iSchema = 0;
+ int nColMatch = 0;
+ SColIdx * pIdx = pColIdx;
+ const STColumn *pColumn = NULL;
+
+ while (iCol < nRowCols && iSchema < nSchema) {
+ pColumn = &pSchema->columns[iSchema];
+ if (pIdx->colId == pColumn->colId) {
+ pSTColumn[nColMatch].colId = pIdx->colId;
+ pSTColumn[nColMatch].type = pColumn->type;
+ pSTColumn[nColMatch].bytes = pColumn->bytes;
+ pSTColumn[nColMatch].offset = pIdx->offset;
+
+ pIdx += sizeof(SColIdx);
+
+ ++iCol;
+ ++iSchema;
+ ++nColMatch;
+ } else if (pIdx->colId > pColumn->colId) {
+ ++iSchema;
+ } else {
+ pIdx += sizeof(SColIdx);
+ ++iCol;
+ }
+ }
+ *nColMatched = nColMatch;
+}
+
+static void tdAppendKvRowToDataCol(SKVRow row, STSchema *pSchema, SDataCols *pCols) {
+ ASSERT(pCols->numOfRows == 0 || dataColsKeyLast(pCols) < kvRowKey(row));
+
+ int rcol = 0;
+ int dcol = 0;
+
+ if (kvRowDeleted(row)) {
+ for (; dcol < pCols->numOfCols; dcol++) {
+ SDataCol *pDataCol = &(pCols->cols[dcol]);
+ if (dcol == 0) {
+ dataColAppendVal(pDataCol, kvRowValues(row), pCols->numOfRows, pCols->maxPoints);
+ } else {
+ dataColSetNullAt(pDataCol, pCols->numOfRows);
+ }
+ }
+ } else {
+ int nRowCols = kvRowNCols(row);
+ int nRowColsMatched = 0;
+ STColumn stColumn[nRowCols];
+ tdGetKVRowColInfo(pSchema, kvRowColIdx(row), nRowCols, stColumn, &nRowColsMatched);
+ uDebug("kvRow: nRowCols=%d, nRowColsMatched=%d, nSchemaCols=%d", nRowCols, nRowColsMatched, schemaNCols(pSchema));
+
+ while (dcol < pCols->numOfCols) {
+ SDataCol *pDataCol = &(pCols->cols[dcol]);
+ if (rcol >= nRowColsMatched || rcol >= schemaNCols(pSchema)) {
+ dataColAppendVal(pDataCol, tdGetNullVal(pDataCol->type), pCols->numOfRows, pCols->maxPoints);
+ dcol++;
+ continue;
+ }
+
+ SColIdx *colIdx = kvRowColIdxAt(row, rcol);
+
+ if (colIdx->colId == pDataCol->colId) {
+ ASSERT(pDataCol->type == stColumn[rcol].type);
+
+ void *value = tdGetKvRowDataOfCol(row, pDataCol->type, stColumn[rcol].offset + TD_KV_ROW_HEAD_SIZE);
+ dataColAppendVal(pDataCol, value, pCols->numOfRows, pCols->maxPoints);
+ dcol++;
+ rcol++;
+ } else if (colIdx->colId < pDataCol->colId) {
+ rcol++;
+ } else {
+ dataColAppendVal(pDataCol, tdGetNullVal(pDataCol->type), pCols->numOfRows, pCols->maxPoints);
+ dcol++;
+ }
+ }
+ }
+ pCols->numOfRows++;
+}
+
+void tdAppendMemRowToDataCol(SMemRow row, STSchema *pSchema, SDataCols *pCols) {
+ if (isDataRow(row)) {
+ tdAppendDataRowToDataCol(memRowBody(row), pSchema, pCols);
+ } else if (isKvRow(row)) {
+ tdAppendKvRowToDataCol(memRowBody(row), pSchema, pCols);
+ } else {
+ ASSERT(0);
+ }
+}
+
int tdMergeDataCols(SDataCols *target, SDataCols *source, int rowsToMerge, int *pOffset) {
ASSERT(rowsToMerge > 0 && rowsToMerge <= source->numOfRows);
ASSERT(target->numOfCols == source->numOfCols);
@@ -452,7 +578,7 @@ int tdMergeDataCols(SDataCols *target, SDataCols *source, int rowsToMerge, int *
SDataCols *pTarget = NULL;
- if ((target->numOfRows == 0) || (dataColsKeyLast(target) < dataColsKeyFirst(source))) { // No overlap
+ if ((target->numOfRows == 0) || (dataColsKeyLast(target) < dataColsKeyAtRow(source, *pOffset))) { // No overlap
ASSERT(target->numOfRows + rowsToMerge <= target->maxPoints);
for (int i = 0; i < rowsToMerge; i++) {
for (int j = 0; j < source->numOfCols; j++) {
@@ -559,11 +685,11 @@ int tdSetKVRowDataOfCol(SKVRow *orow, int16_t colId, int8_t type, void *value) {
void * ptr = taosbsearch(&colId, kvRowColIdx(row), kvRowNCols(row), sizeof(SColIdx), comparTagId, TD_GE);
if (ptr == NULL || ((SColIdx *)ptr)->colId > colId) { // need to add a column value to the row
- int diff = IS_VAR_DATA_TYPE(type) ? varDataTLen(value) : TYPE_BYTES[type];
+ uint16_t diff = IS_VAR_DATA_TYPE(type) ? varDataTLen(value) : TYPE_BYTES[type];
nrow = malloc(kvRowLen(row) + sizeof(SColIdx) + diff);
if (nrow == NULL) return -1;
- kvRowSetLen(nrow, kvRowLen(row) + (int16_t)sizeof(SColIdx) + diff);
+ kvRowSetLen(nrow, kvRowLen(row) + (uint16_t)sizeof(SColIdx) + diff);
kvRowSetNCols(nrow, kvRowNCols(row) + 1);
if (ptr == NULL) {
@@ -605,8 +731,8 @@ int tdSetKVRowDataOfCol(SKVRow *orow, int16_t colId, int8_t type, void *value) {
if (varDataTLen(value) == varDataTLen(pOldVal)) { // just update the column value in place
memcpy(pOldVal, value, varDataTLen(value));
} else { // need to reallocate the memory
- int16_t diff = varDataTLen(value) - varDataTLen(pOldVal);
- int16_t nlen = kvRowLen(row) + diff;
+ uint16_t diff = varDataTLen(value) - varDataTLen(pOldVal);
+ uint16_t nlen = kvRowLen(row) + diff;
ASSERT(nlen > 0);
nrow = malloc(nlen);
if (nrow == NULL) return -1;
@@ -693,7 +819,7 @@ void tdResetKVRowBuilder(SKVRowBuilder *pBuilder) {
}
SKVRow tdGetKVRowFromBuilder(SKVRowBuilder *pBuilder) {
- int tlen = sizeof(SColIdx) * pBuilder->nCols + pBuilder->size;
+ uint16_t tlen = sizeof(SColIdx) * pBuilder->nCols + pBuilder->size;
if (tlen == 0) return NULL;
tlen += TD_KV_ROW_HEAD_SIZE;
@@ -709,3 +835,4 @@ SKVRow tdGetKVRowFromBuilder(SKVRowBuilder *pBuilder) {
return row;
}
+
diff --git a/src/common/src/texpr.c b/src/common/src/texpr.c
index 6fa4d68734..973b88fef9 100644
--- a/src/common/src/texpr.c
+++ b/src/common/src/texpr.c
@@ -470,10 +470,20 @@ void buildFilterSetFromBinary(void **q, const char *buf, int32_t len) {
SBufferReader br = tbufInitReader(buf, len, false);
uint32_t type = tbufReadUint32(&br);
SHashObj *pObj = taosHashInit(256, taosGetDefaultHashFunction(type), true, false);
+
+ taosHashSetEqualFp(pObj, taosGetDefaultEqualFunction(type));
+
int dummy = -1;
int32_t sz = tbufReadInt32(&br);
for (int32_t i = 0; i < sz; i++) {
- if (type == TSDB_DATA_TYPE_BOOL || type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_SMALLINT || type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_INT) {
+ if (type == TSDB_DATA_TYPE_BOOL || IS_SIGNED_NUMERIC_TYPE(type)) {
+ int64_t val = tbufReadInt64(&br);
+ taosHashPut(pObj, (char *)&val, sizeof(val), &dummy, sizeof(dummy));
+ } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
+ uint64_t val = tbufReadUint64(&br);
+ taosHashPut(pObj, (char *)&val, sizeof(val), &dummy, sizeof(dummy));
+ }
+ else if (type == TSDB_DATA_TYPE_TIMESTAMP) {
int64_t val = tbufReadInt64(&br);
taosHashPut(pObj, (char *)&val, sizeof(val), &dummy, sizeof(dummy));
} else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_FLOAT) {
diff --git a/src/common/src/tglobal.c b/src/common/src/tglobal.c
index af21ef6d82..ec98915227 100644
--- a/src/common/src/tglobal.c
+++ b/src/common/src/tglobal.c
@@ -84,8 +84,8 @@ int32_t tsMaxNumOfOrderedResults = 100000;
// 10 ms for sliding time, the value will changed in case of time precision changed
int32_t tsMinSlidingTime = 10;
-// 10 ms for interval time range, changed accordingly
-int32_t tsMinIntervalTime = 10;
+// 1 us for interval time range, changed accordingly
+int32_t tsMinIntervalTime = 1;
// 20sec, the maximum value of stream computing delay, changed accordingly
int32_t tsMaxStreamComputDelay = 20000;
@@ -204,7 +204,7 @@ SDiskCfg tsDiskCfg[TSDB_MAX_DISKS];
* TSDB_TIME_PRECISION_MICRO: 86400000000L
* TSDB_TIME_PRECISION_NANO: 86400000000000L
*/
-int64_t tsMsPerDay[] = {86400000L, 86400000000L, 86400000000000L};
+int64_t tsTickPerDay[] = {86400000L, 86400000000L, 86400000000000L};
// system info
char tsOsName[10] = "Linux";
diff --git a/src/common/src/ttypes.c b/src/common/src/ttypes.c
index 6fa27a029b..34dda32401 100644
--- a/src/common/src/ttypes.c
+++ b/src/common/src/ttypes.c
@@ -632,7 +632,15 @@ int32_t tStrToInteger(const char* z, int16_t type, int32_t n, int64_t* value, bo
}
// the string may be overflow according to errno
- *value = issigned? strtoll(z, &endPtr, radix):strtoull(z, &endPtr, radix);
+ if (!issigned) {
+ const char *p = z;
+ while(*p != 0 && *p == ' ') p++;
+ if (*p != 0 && *p == '-') { return -1;}
+
+ *value = strtoull(z, &endPtr, radix);
+ } else {
+ *value = strtoll(z, &endPtr, radix);
+ }
// not a valid integer number, return error
if (endPtr - z != n || errno == ERANGE) {
diff --git a/src/common/src/tvariant.c b/src/common/src/tvariant.c
index 33dab51633..1168eeb231 100644
--- a/src/common/src/tvariant.c
+++ b/src/common/src/tvariant.c
@@ -77,6 +77,10 @@ void tVariantCreate(tVariant *pVar, SStrToken *token) {
pVar->nLen = strRmquote(pVar->pz, token->n);
break;
}
+ case TSDB_DATA_TYPE_TIMESTAMP: {
+ pVar->i64 = taosGetTimestamp(TSDB_TIME_PRECISION_NANO);
+ break;
+ }
default: { // nType == 0 means the null value
type = TSDB_DATA_TYPE_NULL;
diff --git a/src/connector/go b/src/connector/go
index 7a26c432f8..b8f76da4a7 160000
--- a/src/connector/go
+++ b/src/connector/go
@@ -1 +1 @@
-Subproject commit 7a26c432f8b4203e42344ff3290b9b9b01b983d5
+Subproject commit b8f76da4a708d158ec3cc4b844571dc4414e36b4
diff --git a/src/connector/grafanaplugin b/src/connector/grafanaplugin
index 3530c6df09..dbc5f04ebd 160000
--- a/src/connector/grafanaplugin
+++ b/src/connector/grafanaplugin
@@ -1 +1 @@
-Subproject commit 3530c6df097134a410bacec6b3cd013ef38a61aa
+Subproject commit dbc5f04ebd29522d2acd0636f6fc350060d15a6b
diff --git a/src/connector/hivemq-tdengine-extension b/src/connector/hivemq-tdengine-extension
index b62a26ecc1..ce52010141 160000
--- a/src/connector/hivemq-tdengine-extension
+++ b/src/connector/hivemq-tdengine-extension
@@ -1 +1 @@
-Subproject commit b62a26ecc164a310104df57691691b237e091c89
+Subproject commit ce5201014136503d34fecbd56494b67b4961056c
diff --git a/src/connector/jdbc/CMakeLists.txt b/src/connector/jdbc/CMakeLists.txt
index a04902a422..9642b0490f 100644
--- a/src/connector/jdbc/CMakeLists.txt
+++ b/src/connector/jdbc/CMakeLists.txt
@@ -8,9 +8,8 @@ IF (TD_MVN_INSTALLED)
ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME}
POST_BUILD
COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.30.jar ${LIBRARY_OUTPUT_PATH}
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.32-dist.jar ${LIBRARY_OUTPUT_PATH}
COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
COMMENT "build jdbc driver")
ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME})
-ENDIF ()
-
+ENDIF ()
\ No newline at end of file
diff --git a/src/connector/jdbc/deploy-pom.xml b/src/connector/jdbc/deploy-pom.xml
index 657645d46c..06122372f0 100755
--- a/src/connector/jdbc/deploy-pom.xml
+++ b/src/connector/jdbc/deploy-pom.xml
@@ -5,7 +5,7 @@
com.taosdata.jdbc
taos-jdbcdriver
- 2.0.30
+ 2.0.32
jar
JDBCDriver
diff --git a/src/connector/jdbc/pom.xml b/src/connector/jdbc/pom.xml
index 96e17bcd9b..61d7fb85ef 100644
--- a/src/connector/jdbc/pom.xml
+++ b/src/connector/jdbc/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.taosdata.jdbc
taos-jdbcdriver
- 2.0.30
+ 2.0.32
jar
JDBCDriver
https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc
@@ -113,16 +113,16 @@
**/*Test.java
- **/TSDBJNIConnectorTest.java
- **/UnsignedNumberJniTest.java
- **/DatetimeBefore1970Test.java
**/AppMemoryLeakTest.java
**/AuthenticationTest.java
- **/TaosInfoMonitorTest.java
+ **/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java
+ **/DatetimeBefore1970Test.java
**/FailOverTest.java
**/InvalidResultSetPointerTest.java
**/RestfulConnectionTest.java
- **/TD4144Test.java
+ **/TSDBJNIConnectorTest.java
+ **/TaosInfoMonitorTest.java
+ **/UnsignedNumberJniTest.java
true
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractConnection.java
index 2970f6c2d3..b3887d436b 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractConnection.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractConnection.java
@@ -1,5 +1,7 @@
package com.taosdata.jdbc;
+import com.taosdata.jdbc.enums.TimestampFormat;
+
import java.sql.*;
import java.util.Enumeration;
import java.util.Map;
@@ -18,7 +20,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
for (String propName : propNames) {
clientInfoProps.setProperty(propName, properties.getProperty(propName));
}
- String timestampFormat = properties.getProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, "STRING");
+ String timestampFormat = properties.getProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, String.valueOf(TimestampFormat.STRING));
clientInfoProps.setProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, timestampFormat);
}
@@ -304,9 +306,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
- if (isClosed())
- throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
-
switch (resultSetHoldability) {
case ResultSet.HOLD_CURSORS_OVER_COMMIT:
break;
@@ -320,11 +319,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
}
@Override
- public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
- throws SQLException {
- if (isClosed())
- throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
-
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
switch (resultSetHoldability) {
case ResultSet.HOLD_CURSORS_OVER_COMMIT:
break;
@@ -423,7 +418,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
status = resultSet.getInt("server_status()");
resultSet.close();
}
- return status == 1 ? true : false;
+ return status == 1;
});
boolean status = false;
@@ -432,9 +427,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
status = future.get();
else
status = future.get(timeout, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
+ } catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
future.cancel(true);
@@ -450,8 +443,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
if (isClosed)
throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED);
- if (clientInfoProps != null)
- clientInfoProps.setProperty(name, value);
+ clientInfoProps.setProperty(name, value);
}
@Override
@@ -459,8 +451,8 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
if (isClosed)
throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED);
- for (Enumeration