提交 c6e1472a 编写于 作者: H Haojun Liao

Merge branch 'develop' into feature/query

...@@ -147,7 +147,11 @@ IF (TD_DARWIN_64) ...@@ -147,7 +147,11 @@ IF (TD_DARWIN_64)
ADD_DEFINITIONS(-D_REENTRANT -D__USE_POSIX -D_LIBC_REENTRANT) ADD_DEFINITIONS(-D_REENTRANT -D__USE_POSIX -D_LIBC_REENTRANT)
ADD_DEFINITIONS(-DUSE_LIBICONV) ADD_DEFINITIONS(-DUSE_LIBICONV)
MESSAGE(STATUS "darwin64 is defined") MESSAGE(STATUS "darwin64 is defined")
SET(COMMON_FLAGS "-Wall -Werror -Wno-missing-braces -fPIC -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") IF ("${CPUTYPE}" STREQUAL "apple_m1")
SET(COMMON_FLAGS "-Wall -Werror -Wno-missing-braces -fPIC -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ELSE ()
SET(COMMON_FLAGS "-Wall -Werror -Wno-missing-braces -fPIC -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ENDIF ()
IF (TD_MEMORY_SANITIZER) 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") 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 () ELSE ()
......
...@@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS) ...@@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS)
#INSTALL(TARGETS taos RUNTIME DESTINATION driver) #INSTALL(TARGETS taos RUNTIME DESTINATION driver)
#INSTALL(TARGETS shell RUNTIME DESTINATION .) #INSTALL(TARGETS shell RUNTIME DESTINATION .)
IF (TD_MVN_INSTALLED) IF (TD_MVN_INSTALLED)
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.31.jar DESTINATION connector/jdbc) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.32-dist.jar DESTINATION connector/jdbc)
ENDIF () ENDIF ()
ELSEIF (TD_DARWIN) ELSEIF (TD_DARWIN)
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh") SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
......
...@@ -108,6 +108,10 @@ IF ("${CPUTYPE}" STREQUAL "") ...@@ -108,6 +108,10 @@ IF ("${CPUTYPE}" STREQUAL "")
SET(TD_LINUX TRUE) SET(TD_LINUX TRUE)
SET(TD_LINUX_64 FALSE) SET(TD_LINUX_64 FALSE)
SET(TD_MIPS_64 TRUE) SET(TD_MIPS_64 TRUE)
ELSEIF (CMAKE_SYSTEM_PROCESSOR MATCHES "arm64")
SET(CPUTYPE "apple_m1")
MESSAGE(STATUS "Set CPUTYPE to apple silicon m1")
SET(TD_ARM_64 TRUE)
ENDIF () ENDIF ()
ELSE () ELSE ()
......
...@@ -63,7 +63,7 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专 ...@@ -63,7 +63,7 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专
## [高级功能](/advanced-features) ## [高级功能](/advanced-features)
* [连续查询(Continuous Query)](/advanced-features#continuous-query):基于滑动窗口,定时自动的对数据流进行查询计算 * [连续查询(Continuous Query)](/advanced-features#continuous-query):基于滑动窗口,定时自动的对数据流进行查询计算
* [数据订阅(Publisher/Subscriber)](/advanced-features#subscribe)典型的消息队列,应用可订阅接收到的最新数据 * [数据订阅(Publisher/Subscriber)](/advanced-features#subscribe)类似典型的消息队列,应用可订阅接收到的最新数据
* [缓存(Cache)](/advanced-features#cache):每个设备最新的数据都会缓存在内存中,可快速获取 * [缓存(Cache)](/advanced-features#cache):每个设备最新的数据都会缓存在内存中,可快速获取
* [报警监测](/advanced-features#alert):根据配置规则,自动监测超限行为数据,并主动推送 * [报警监测](/advanced-features#alert):根据配置规则,自动监测超限行为数据,并主动推送
...@@ -106,6 +106,7 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专 ...@@ -106,6 +106,7 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专
* [数据导入](/administrator#import):可按脚本文件导入,也可按数据文件导入 * [数据导入](/administrator#import):可按脚本文件导入,也可按数据文件导入
* [数据导出](/administrator#export):从shell按表导出,也可用taosdump工具做各种导出 * [数据导出](/administrator#export):从shell按表导出,也可用taosdump工具做各种导出
* [系统监控](/administrator#status):检查系统现有的连接、查询、流式计算,日志和事件等 * [系统监控](/administrator#status):检查系统现有的连接、查询、流式计算,日志和事件等
* [性能优化](/administrator#optimize):对长期运行的系统进行维护优化,保障性能表现
* [文件目录结构](/administrator#directories):TDengine数据文件、配置文件等所在目录 * [文件目录结构](/administrator#directories):TDengine数据文件、配置文件等所在目录
* [参数限制与保留关键字](/administrator#keywords):TDengine的参数限制与保留关键字列表 * [参数限制与保留关键字](/administrator#keywords):TDengine的参数限制与保留关键字列表
......
...@@ -532,8 +532,9 @@ Query OK, 1 row(s) in set (0.000141s) ...@@ -532,8 +532,9 @@ Query OK, 1 row(s) in set (0.000141s)
| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 | | taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
| -------------------- | ----------------- | -------- | | -------------------- | ----------------- | -------- |
| 2.0.22 | 2.0.18.0 及以上 | 1.8.x | | 2.0.31 | 2.1.3.0 及以上 | 1.8.x |
| 2.0.12 - 2.0.21 | 2.0.8.0 - 2.0.17.0 | 1.8.x | | 2.0.22 - 2.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 | | 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.3 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.2 | 1.6.1.x 及以上 | 1.8.x | | 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
......
...@@ -259,7 +259,7 @@ typedef struct taosField { ...@@ -259,7 +259,7 @@ typedef struct taosField {
获取最近一次API调用失败的原因,返回值为字符串。 获取最近一次API调用失败的原因,返回值为字符串。
- `char *taos_errno(TAOS_RES *res)` - `int taos_errno(TAOS_RES *res)`
获取最近一次API调用失败的原因,返回值为错误代码。 获取最近一次API调用失败的原因,返回值为错误代码。
...@@ -427,12 +427,15 @@ TDengine提供时间驱动的实时流式计算API。可以每隔一指定的时 ...@@ -427,12 +427,15 @@ TDengine提供时间驱动的实时流式计算API。可以每隔一指定的时
* res:查询结果集,注意结果集中可能没有记录 * res:查询结果集,注意结果集中可能没有记录
* param:调用 `taos_subscribe`时客户程序提供的附加参数 * param:调用 `taos_subscribe`时客户程序提供的附加参数
* code:错误码 * code:错误码
**注意**:在这个回调函数里不可以做耗时过长的处理,尤其是对于返回的结果集中数据较多的情况,否则有可能导致客户端阻塞等异常状态。如果必须进行复杂计算,则建议在另外的线程中进行处理。 **注意**:在这个回调函数里不可以做耗时过长的处理,尤其是对于返回的结果集中数据较多的情况,否则有可能导致客户端阻塞等异常状态。如果必须进行复杂计算,则建议在另外的线程中进行处理。
* `TAOS_RES *taos_consume(TAOS_SUB *tsub)` * `TAOS_RES *taos_consume(TAOS_SUB *tsub)`
同步模式下,该函数用来获取订阅的结果。 用户应用程序将其置于一个循环之中。 如两次调用`taos_consume`的间隔小于订阅的轮询周期,API将会阻塞,直到时间间隔超过此周期。 如果数据库有新记录到达,该API将返回该最新的记录,否则返回一个没有记录的空结果集。 如果返回值为 `NULL`,说明系统出错。 异步模式下,用户程序不应调用此API。 同步模式下,该函数用来获取订阅的结果。 用户应用程序将其置于一个循环之中。 如两次调用`taos_consume`的间隔小于订阅的轮询周期,API将会阻塞,直到时间间隔超过此周期。 如果数据库有新记录到达,该API将返回该最新的记录,否则返回一个没有记录的空结果集。 如果返回值为 `NULL`,说明系统出错。 异步模式下,用户程序不应调用此API。
**注意**:在调用 `taos_consume()` 之后,用户应用应确保尽快调用 `taos_fetch_row()``taos_fetch_block()` 来处理订阅结果,否则服务端会持续缓存查询结果数据等待客户端读取,极端情况下会导致服务端内存消耗殆尽,影响服务稳定性。
* `void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress)` * `void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress)`
取消订阅。 如参数 `keepProgress` 不为0,API会保留订阅的进度信息,后续调用 `taos_subscribe` 时可以基于此进度继续;否则将删除进度信息,后续只能重新开始读取数据。 取消订阅。 如参数 `keepProgress` 不为0,API会保留订阅的进度信息,后续调用 `taos_subscribe` 时可以基于此进度继续;否则将删除进度信息,后续只能重新开始读取数据。
...@@ -554,6 +557,13 @@ c1.close() ...@@ -554,6 +557,13 @@ c1.close()
conn.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中的示例程序。以下为部分常用类和方法: 用户可通过python的帮助信息直接查看模块的使用信息,或者参考tests/examples/python中的示例程序。以下为部分常用类和方法:
...@@ -897,6 +907,10 @@ go env -w GOPROXY=https://goproxy.io,direct ...@@ -897,6 +907,10 @@ go env -w GOPROXY=https://goproxy.io,direct
sql.Open内置的方法,Close closes the statement. sql.Open内置的方法,Close closes the statement.
### 其他代码示例
[Consume Messages from Kafka](https://github.com/taosdata/go-demo-kafka) 是一个通过 Go 语言实现消费 Kafka 队列写入 TDengine 的示例程序,也可以作为通过 Go 连接 TDengine 的写法参考。
## <a class="anchor" id="nodejs"></a>Node.js Connector ## <a class="anchor" id="nodejs"></a>Node.js Connector
Node.js连接器支持的系统有: Node.js连接器支持的系统有:
......
...@@ -418,6 +418,19 @@ TDengine启动后,会自动创建一个监测数据库log,并自动将服务 ...@@ -418,6 +418,19 @@ TDengine启动后,会自动创建一个监测数据库log,并自动将服务
这些监测信息的采集缺省是打开的,但可以修改配置文件里的选项enableMonitor将其关闭或打开。 这些监测信息的采集缺省是打开的,但可以修改配置文件里的选项enableMonitor将其关闭或打开。
<a class="anchor" id="optimize"></a>
## 性能优化
因数据行 [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。因此在重整进行期间,有可能会影响节点的写入和查询性能,甚至在极端情况下导致短时间的阻写。
## <a class="anchor" id="directories"></a>文件目录结构 ## <a class="anchor" id="directories"></a>文件目录结构
安装TDengine后,默认会在操作系统中生成下列目录或文件: 安装TDengine后,默认会在操作系统中生成下列目录或文件:
...@@ -465,43 +478,44 @@ TDengine的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下 ...@@ -465,43 +478,44 @@ TDengine的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下
目前 TDengine 有将近 200 个内部保留关键字,这些关键字无论大小写均不可以用作库名、表名、STable 名、数据列名及标签列名等。这些关键字列表如下: 目前 TDengine 有将近 200 个内部保留关键字,这些关键字无论大小写均不可以用作库名、表名、STable 名、数据列名及标签列名等。这些关键字列表如下:
| 关键字列表 | | | | | | 关键字列表 | | | | |
| ---------- | ----------- | ------------ | ---------- | --------- | | ------------ | ------------ | ------------ | ------------ | ------------ |
| ABLOCKS | CONNECTIONS | HAVING | MODULES | SMALLINT | | ABORT | CREATE | IGNORE | NULL | STAR |
| ABORT | COPY | ID | NCHAR | SPREAD | | ACCOUNT | CTIME | IMMEDIATE | OF | STATE |
| ACCOUNT | COUNT | IF | NE | STABLE | | ACCOUNTS | DATABASE | IMPORT | OFFSET | STATEMENT |
| ACCOUNTS | CREATE | IGNORE | NONE | STABLES | | ADD | DATABASES | IN | OR | STATE_WINDOW |
| ADD | CTIME | IMMEDIATE | NOT | STAR | | AFTER | DAYS | INITIALLY | ORDER | STORAGE |
| AFTER | DATABASE | IMPORT | NOTNULL | STATEMENT | | ALL | DBS | INSERT | PARTITIONS | STREAM |
| ALL | DATABASES | IN | NOW | STDDEV | | ALTER | DEFERRED | INSTEAD | PASS | STREAMS |
| ALTER | DAYS | INITIALLY | OF | STREAM | | AND | DELIMITERS | INT | PLUS | STRING |
| AND | DEFERRED | INSERT | OFFSET | STREAMS | | AS | DESC | INTEGER | PPS | SYNCDB |
| AS | DELIMITERS | INSTEAD | OR | STRING | | ASC | DESCRIBE | INTERVAL | PRECISION | TABLE |
| ASC | DESC | INTEGER | ORDER | SUM | | ATTACH | DETACH | INTO | PREV | TABLES |
| ATTACH | DESCRIBE | INTERVAL | PASS | TABLE | | BEFORE | DISTINCT | IS | PRIVILEGE | TAG |
| AVG | DETACH | INTO | PERCENTILE | TABLES | | BEGIN | DIVIDE | ISNULL | QTIME | TAGS |
| BEFORE | DIFF | IP | PLUS | TAG | | BETWEEN | DNODE | JOIN | QUERIES | TBNAME |
| BEGIN | DISTINCT | IS | PRAGMA | TAGS | | BIGINT | DNODES | KEEP | QUERY | TIMES |
| BETWEEN | DIVIDE | ISNULL | PREV | TBLOCKS | | BINARY | DOT | KEY | QUORUM | TIMESTAMP |
| BIGINT | DNODE | JOIN | PRIVILEGE | TBNAME | | BITAND | DOUBLE | KILL | RAISE | TINYINT |
| BINARY | DNODES | KEEP | QUERIES | TIMES | | BITNOT | DROP | LE | REM | TOPIC |
| BITAND | DOT | KEY | QUERY | TIMESTAMP | | BITOR | EACH | LIKE | REPLACE | TOPICS |
| BITNOT | DOUBLE | KILL | RAISE | TINYINT | | BLOCKS | END | LIMIT | REPLICA | TRIGGER |
| BITOR | DROP | LAST | REM | TOP | | BOOL | EQ | LINEAR | RESET | TSERIES |
| BOOL | EACH | LE | REPLACE | TOPIC | | BY | EXISTS | LOCAL | RESTRICT | UMINUS |
| BOTTOM | END | LEASTSQUARES | REPLICA | TRIGGER | | CACHE | EXPLAIN | LP | ROW | UNION |
| BY | EQ | LIKE | RESET | UMINUS | | CACHELAST | FAIL | LSHIFT | RP | UNSIGNED |
| CACHE | EXISTS | LIMIT | RESTRICT | UNION | | CASCADE | FILE | LT | RSHIFT | UPDATE |
| CASCADE | EXPLAIN | LINEAR | ROW | UPLUS | | CHANGE | FILL | MATCH | SCORES | UPLUS |
| CHANGE | FAIL | LOCAL | ROWS | USE | | CLUSTER | FLOAT | MAXROWS | SELECT | USE |
| CLOG | FILL | LP | RP | USER | | COLON | FOR | MINROWS | SEMI | USER |
| CLUSTER | FIRST | LSHIFT | RSHIFT | USERS | | COLUMN | FROM | MINUS | SESSION | USERS |
| COLON | FLOAT | LT | SCORES | USING | | COMMA | FSYNC | MNODES | SET | USING |
| COLUMN | FOR | MATCH | SELECT | VALUES | | COMP | GE | MODIFY | SHOW | VALUES |
| COMMA | FROM | MAX | SEMI | VARIABLE | | COMPACT | GLOB | MODULES | SLASH | VARIABLE |
| COMP | GE | METRIC | SET | VGROUPS | | CONCAT | GRANTS | NCHAR | SLIDING | VARIABLES |
| CONCAT | GLOB | METRICS | SHOW | VIEW | | CONFLICT | GROUP | NE | SLIMIT | VGROUPS |
| CONFIGS | GRANTS | MIN | SLASH | WAVG | | CONNECTION | GT | NONE | SMALLINT | VIEW |
| CONFLICT | GROUP | MINUS | SLIDING | WHERE | | CONNECTIONS | HAVING | NOT | SOFFSET | VNODES |
| CONNECTION | GT | MNODES | SLIMIT | | | CONNS | ID | NOTNULL | STABLE | WAL |
| COPY | IF | NOW | STABLES | WHERE |
...@@ -89,13 +89,13 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传 ...@@ -89,13 +89,13 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
```mysql ```mysql
USE db_name; USE db_name;
``` ```
使用/切换数据库 使用/切换数据库(在 RESTful 连接方式下无效)。
- **删除数据库** - **删除数据库**
```mysql ```mysql
DROP DATABASE [IF EXISTS] db_name; DROP DATABASE [IF EXISTS] db_name;
``` ```
删除数据库。所包含的全部数据表将被删除,谨慎使用 删除数据库。指定 Database 所包含的全部数据表将被删除,谨慎使用!
- **修改数据库参数** - **修改数据库参数**
```mysql ```mysql
...@@ -279,11 +279,11 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传 ...@@ -279,11 +279,11 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
说明: 说明:
1) TAGS 列的数据类型不能是 timestamp 类型; 1) TAGS 列的数据类型不能是 timestamp 类型;(从 2.1.3.0 版本开始,TAGS 列中支持使用 timestamp 类型,但需注意在 TAGS 中的 timestamp 列写入数据时需要提供给定值,而暂不支持四则运算,例如 `NOW + 10s` 这类表达式)
2) TAGS 列名不能与其他列名相同; 2) TAGS 列名不能与其他列名相同;
3) TAGS 列名不能为预留关键字; 3) TAGS 列名不能为预留关键字(参见:[参数限制与保留关键字](https://www.taosdata.com/cn/documentation/administrator#keywords) 章节)
4) TAGS 最多允许 128 个,至少 1 个,总长度不超过 16 KB。 4) TAGS 最多允许 128 个,至少 1 个,总长度不超过 16 KB。
...@@ -703,22 +703,24 @@ Query OK, 1 row(s) in set (0.001091s) ...@@ -703,22 +703,24 @@ Query OK, 1 row(s) in set (0.001091s)
### 支持的条件过滤操作 ### 支持的条件过滤操作
| **Operation** | **Note** | **Applicable Data Types** | | **Operation** | **Note** | **Applicable Data Types** |
| --------------- | ----------------------------- | ------------------------------------- | | --------------- | ----------------------------- | ----------------------------------------- |
| > | larger than | **`timestamp`** and all numeric types | | > | larger than | **`timestamp`** and all numeric types |
| < | smaller than | **`timestamp`** and all numeric types | | < | smaller than | **`timestamp`** and all numeric types |
| >= | larger than or equal to | **`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 | | <= | smaller than or equal to | **`timestamp`** and all numeric types |
| = | equal to | all types | | = | equal to | all types |
| <> | not equal to | all types | | <> | not equal to | all types |
| between and | within a certain range | **`timestamp`** and all numeric types | | between and | within a certain range | **`timestamp`** and all numeric types |
| % | match with any char sequences | **`binary`** **`nchar`** | | in | matches any value in a set | all types except first column `timestamp` |
| _ | match with a single char | **`binary`** **`nchar`** | | % | match with any char sequences | **`binary`** **`nchar`** |
| _ | match with a single char | **`binary`** **`nchar`** |
1. <> 算子也可以写为 != ,请注意,这个算子不能用于数据表第一列的 timestamp 字段。 1. <> 算子也可以写为 != ,请注意,这个算子不能用于数据表第一列的 timestamp 字段。
2. 同时进行多个字段的范围过滤,需要使用关键词 AND 来连接不同的查询条件,暂不支持 OR 连接的不同列之间的查询过滤条件。 2. 同时进行多个字段的范围过滤,需要使用关键词 AND 来连接不同的查询条件,暂不支持 OR 连接的不同列之间的查询过滤条件。
3. 针对单一字段的过滤,如果是时间过滤条件,则一条语句中只支持设定一个;但针对其他的(普通)列或标签列,则可以使用 `OR` 关键字进行组合条件的查询过滤。例如:((value > 20 AND value < 30) OR (value < 12)) 。 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”。 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 类型会受到浮点数精度影响,集合内的值在精度范围内认为和数据行的值完全相等才能匹配成功。<!-- REPLACE_OPEN_TO_ENTERPRISE__IN_OPERATOR_AND_UNSIGNED_INTEGER -->
<!-- <!--
<a class="anchor" id="having"></a> <a class="anchor" id="having"></a>
...@@ -854,7 +856,23 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ...@@ -854,7 +856,23 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。
适用于:**表**。 适用于:**表、(超级表)**。
说明:从 2.1.3.0 版本开始,TWA 函数可以在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname)。
- **IRATE**
```mysql
SELECT IRATE(field_name) FROM tb_name WHERE clause;
```
功能说明:计算瞬时增长率。使用时间区间中最后两个样本数据来计算瞬时增长速率;如果这两个值呈递减关系,那么只取最后一个数用于计算,而不是使用二者差值。
返回结果数据类型:双精度浮点数Double。
应用字段:不能应用在timestamp、binary、nchar、bool类型字段。
适用于:**表、(超级表)**。
说明:(从 2.1.3.0 版本开始新增此函数)IRATE 可以在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname)。
- **SUM** - **SUM**
```mysql ```mysql
...@@ -1203,13 +1221,14 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ...@@ -1203,13 +1221,14 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
``` ```
### 计算函数 ### 计算函数
- **DIFF** - **DIFF**
```mysql ```mysql
SELECT DIFF(field_name) FROM tb_name [WHERE clause]; SELECT DIFF(field_name) FROM tb_name [WHERE clause];
``` ```
功能说明:统计表中某列的值与前一行对应值的差。 功能说明:统计表中某列的值与前一行对应值的差。
返回结果数据类型: 同应用字段。 返回结果数据类型:同应用字段。
应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。
...@@ -1227,13 +1246,27 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ...@@ -1227,13 +1246,27 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
Query OK, 2 row(s) in set (0.001162s) Query OK, 2 row(s) in set (0.001162s)
``` ```
- **DERIVATIVE**
```mysql
SELECT DERIVATIVE(field_name, time_interval, ignore_negative) FROM tb_name [WHERE clause];
```
功能说明:统计表中某列数值的单位变化率。其中单位时间区间的长度可以通过 time_interval 参数指定,最小可以是 1 秒(1s);ignore_negative 参数的值可以是 0 或 1,为 1 时表示忽略负值。
返回结果数据类型:双精度浮点数。
应用字段:不能应用在 timestamp、binary、nchar、bool 类型字段。
适用于:**表、(超级表)**。
说明:(从 2.1.3.0 版本开始新增此函数)输出结果行数是范围内总行数减一,第一行没有结果输出。DERIVATIVE 函数可以在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname)。
- **SPREAD** - **SPREAD**
```mysql ```mysql
SELECT SPREAD(field_name) FROM { tb_name | stb_name } [WHERE clause]; SELECT SPREAD(field_name) FROM { tb_name | stb_name } [WHERE clause];
``` ```
功能说明:统计表/超级表中某列的最大值和最小值之差。 功能说明:统计表/超级表中某列的最大值和最小值之差。
返回结果数据类型: 双精度浮点数。 返回结果数据类型:双精度浮点数。
应用字段:不能应用在binary、nchar、bool类型字段。 应用字段:不能应用在binary、nchar、bool类型字段。
......
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
TDengine还没有一组专用的validation queries。然而建议你使用系统监测的数据库”log"来做。 TDengine还没有一组专用的validation queries。然而建议你使用系统监测的数据库”log"来做。
<a class="anchor" id="update"></a>
## 9. 我可以删除或更新一条记录吗? ## 9. 我可以删除或更新一条记录吗?
TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。 TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。
......
...@@ -515,6 +515,13 @@ c1.close() ...@@ -515,6 +515,13 @@ c1.close()
conn.close() conn.close()
``` ```
#### Using nanosecond in Python connector
So far Python still does not completely support nanosecond type. Please refer to the link 1 and 2. The implementation of the python connector is to return an integer number for nanosecond value rather than datatime type as what ms and us do. The developer needs to handle it themselves. We recommend using pandas to_datetime() function. If Python officially support nanosecond in the future, TAOS Data might be possible to change the interface accordingly, which mean the application need change too.
1. https://stackoverflow.com/questions/10611328/parsing-datetime-strings-containing-nanoseconds
2. https://www.python.org/dev/peps/pep-0564/
#### Helper #### Helper
Users can directly view the usage information of the module through Python's helper, or refer to the sample program in tests/examples/Python. The following are some common classes and methods: Users can directly view the usage information of the module through Python's helper, or refer to the sample program in tests/examples/Python. The following are some common classes and methods:
......
...@@ -637,6 +637,19 @@ int32_t bnDropDnode(SDnodeObj *pDnode) { ...@@ -637,6 +637,19 @@ int32_t bnDropDnode(SDnodeObj *pDnode) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
int32_t bnDnodeCanCreateMnode(struct SDnodeObj *pDnode) {
if (pDnode == NULL)
return 0;
if (pDnode->isMgmt || pDnode->alternativeRole == TAOS_DN_ALTERNATIVE_ROLE_VNODE
|| pDnode->status == TAOS_DN_STATUS_DROPPING
|| pDnode->status == TAOS_DN_STATUS_OFFLINE) {
return 0;
} else {
return 1;
}
}
static void bnMonitorDnodeModule() { static void bnMonitorDnodeModule() {
int32_t numOfMnodes = mnodeGetMnodesNum(); int32_t numOfMnodes = mnodeGetMnodesNum();
if (numOfMnodes >= tsNumOfMnodes) return; if (numOfMnodes >= tsNumOfMnodes) return;
...@@ -645,13 +658,7 @@ static void bnMonitorDnodeModule() { ...@@ -645,13 +658,7 @@ static void bnMonitorDnodeModule() {
SDnodeObj *pDnode = tsBnDnodes.list[i]; SDnodeObj *pDnode = tsBnDnodes.list[i];
if (pDnode == NULL) break; if (pDnode == NULL) break;
if (pDnode->isMgmt || pDnode->status == TAOS_DN_STATUS_DROPPING || pDnode->status == TAOS_DN_STATUS_OFFLINE) { if (!bnDnodeCanCreateMnode(pDnode)) continue;
continue;
}
if (pDnode->alternativeRole == TAOS_DN_ALTERNATIVE_ROLE_VNODE) {
continue;
}
mLInfo("dnode:%d, numOfMnodes:%d expect:%d, create mnode in this dnode", pDnode->dnodeId, numOfMnodes, tsNumOfMnodes); mLInfo("dnode:%d, numOfMnodes:%d expect:%d, create mnode in this dnode", pDnode->dnodeId, numOfMnodes, tsNumOfMnodes);
mnodeCreateMnode(pDnode->dnodeId, pDnode->dnodeEp, true); mnodeCreateMnode(pDnode->dnodeId, pDnode->dnodeEp, true);
......
...@@ -898,7 +898,9 @@ SSDataBlock* doGlobalAggregate(void* param, bool* newgroup) { ...@@ -898,7 +898,9 @@ SSDataBlock* doGlobalAggregate(void* param, bool* newgroup) {
SSDataBlock* pBlock = NULL; SSDataBlock* pBlock = NULL;
while(1) { while(1) {
bool prev = *newgroup; bool prev = *newgroup;
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
pBlock = upstream->exec(upstream, newgroup); pBlock = upstream->exec(upstream, newgroup);
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
*newgroup = prev; *newgroup = prev;
break; break;
...@@ -966,7 +968,9 @@ static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) { ...@@ -966,7 +968,9 @@ static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) {
SSDataBlock* pBlock = NULL; SSDataBlock* pBlock = NULL;
if (pInfo->currentGroupOffset == 0) { if (pInfo->currentGroupOffset == 0) {
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
pOperator->status = OP_EXEC_DONE; pOperator->status = OP_EXEC_DONE;
...@@ -974,7 +978,9 @@ static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) { ...@@ -974,7 +978,9 @@ static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) {
if (*newgroup == false && pInfo->limit.limit > 0 && pInfo->rowsTotal >= pInfo->limit.limit) { if (*newgroup == false && pInfo->limit.limit > 0 && pInfo->rowsTotal >= pInfo->limit.limit) {
while ((*newgroup) == false) { // ignore the remain blocks while ((*newgroup) == false) { // ignore the remain blocks
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
pOperator->status = OP_EXEC_DONE; pOperator->status = OP_EXEC_DONE;
...@@ -986,7 +992,10 @@ static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) { ...@@ -986,7 +992,10 @@ static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) {
return pBlock; return pBlock;
} }
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
pOperator->status = OP_EXEC_DONE; pOperator->status = OP_EXEC_DONE;
...@@ -1000,7 +1009,10 @@ static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) { ...@@ -1000,7 +1009,10 @@ static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) {
} }
while ((*newgroup) == false) { while ((*newgroup) == false) {
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
pOperator->status = OP_EXEC_DONE; pOperator->status = OP_EXEC_DONE;
......
...@@ -485,6 +485,7 @@ static int32_t tscGetDBInfo(SCreateBuilder *builder, char *result) { ...@@ -485,6 +485,7 @@ static int32_t tscGetDBInfo(SCreateBuilder *builder, char *result) {
char buf[TSDB_DB_NAME_LEN + 64] = {0}; char buf[TSDB_DB_NAME_LEN + 64] = {0};
do { do {
memset(buf, 0, sizeof(buf));
int32_t* lengths = taos_fetch_lengths(pSql); int32_t* lengths = taos_fetch_lengths(pSql);
int32_t ret = tscGetNthFieldResult(row, fields, lengths, 0, buf); int32_t ret = tscGetNthFieldResult(row, fields, lengths, 0, buf);
if (0 == ret && STR_NOCASE_EQUAL(buf, strlen(buf), builder->buf, strlen(builder->buf))) { if (0 == ret && STR_NOCASE_EQUAL(buf, strlen(buf), builder->buf, strlen(builder->buf))) {
......
...@@ -165,6 +165,7 @@ bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType, ...@@ -165,6 +165,7 @@ bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType,
} else { } else {
tbufWriteUint32(&bw, colType); tbufWriteUint32(&bw, colType);
} }
tbufWriteInt32(&bw, (int32_t)(pList->size)); tbufWriteInt32(&bw, (int32_t)(pList->size));
for (int32_t i = 0; i < (int32_t)pList->size; i++) { for (int32_t i = 0; i < (int32_t)pList->size; i++) {
...@@ -181,10 +182,11 @@ bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType, ...@@ -181,10 +182,11 @@ bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType,
} }
tbufWriteInt64(&bw, var->i64); tbufWriteInt64(&bw, var->i64);
} else if (IS_UNSIGNED_NUMERIC_TYPE(colType)) { } else if (IS_UNSIGNED_NUMERIC_TYPE(colType)) {
if (IS_SIGNED_NUMERIC_TYPE(var->nType) && IS_UNSIGNED_NUMERIC_TYPE(var->nType)) { if (IS_SIGNED_NUMERIC_TYPE(var->nType) || IS_UNSIGNED_NUMERIC_TYPE(var->nType)) {
tbufWriteUint64(&bw, var->u64);
} else {
break; break;
} }
tbufWriteUint64(&bw, var->u64);
} else if (colType == TSDB_DATA_TYPE_DOUBLE || colType == TSDB_DATA_TYPE_FLOAT) { } else if (colType == TSDB_DATA_TYPE_DOUBLE || colType == TSDB_DATA_TYPE_FLOAT) {
if (IS_SIGNED_NUMERIC_TYPE(var->nType) || IS_UNSIGNED_NUMERIC_TYPE(var->nType)) { if (IS_SIGNED_NUMERIC_TYPE(var->nType) || IS_UNSIGNED_NUMERIC_TYPE(var->nType)) {
tbufWriteDouble(&bw, (double)(var->i64)); tbufWriteDouble(&bw, (double)(var->i64));
...@@ -3342,6 +3344,7 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, ...@@ -3342,6 +3344,7 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
if (pRight->flags & (1 << EXPR_FLAG_NS_TIMESTAMP)) { if (pRight->flags & (1 << EXPR_FLAG_NS_TIMESTAMP)) {
pRight->value.i64 = pRight->value.i64 =
convertTimePrecision(pRight->value.i64, TSDB_TIME_PRECISION_NANO, timePrecision); convertTimePrecision(pRight->value.i64, TSDB_TIME_PRECISION_NANO, timePrecision);
pRight->flags &= ~(1 << EXPR_FLAG_NS_TIMESTAMP);
} }
} }
...@@ -4906,6 +4909,7 @@ int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t t ...@@ -4906,6 +4909,7 @@ int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t t
*/ */
if (pRight->flags & (1 << EXPR_FLAG_NS_TIMESTAMP)) { if (pRight->flags & (1 << EXPR_FLAG_NS_TIMESTAMP)) {
pRight->value.i64 = convertTimePrecision(pRight->value.i64, TSDB_TIME_PRECISION_NANO, timePrecision); pRight->value.i64 = convertTimePrecision(pRight->value.i64, TSDB_TIME_PRECISION_NANO, timePrecision);
pRight->flags &= ~(1 << EXPR_FLAG_NS_TIMESTAMP);
} }
tVariantDump(&pRight->value, (char*)&val, TSDB_DATA_TYPE_BIGINT, true); tVariantDump(&pRight->value, (char*)&val, TSDB_DATA_TYPE_BIGINT, true);
...@@ -5103,7 +5107,7 @@ static void setDefaultOrderInfo(SQueryInfo* pQueryInfo) { ...@@ -5103,7 +5107,7 @@ static void setDefaultOrderInfo(SQueryInfo* pQueryInfo) {
int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode, SSchema* pSchema) { int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode, SSchema* pSchema) {
const char* msg0 = "only support order by primary timestamp"; const char* msg0 = "only support order by primary timestamp";
const char* msg1 = "invalid column name"; const char* msg1 = "invalid column name";
const char* msg2 = "order by primary timestamp or first tag in groupby clause allowed"; const char* msg2 = "order by primary timestamp, first tag or groupby column in groupby clause allowed";
const char* msg3 = "invalid column in order by clause, only primary timestamp or first tag in groupby clause allowed"; const char* msg3 = "invalid column in order by clause, only primary timestamp or first tag in groupby clause allowed";
setDefaultOrderInfo(pQueryInfo); setDefaultOrderInfo(pQueryInfo);
...@@ -5156,6 +5160,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq ...@@ -5156,6 +5160,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
bool orderByTags = false; bool orderByTags = false;
bool orderByTS = false; bool orderByTS = false;
bool orderByGroupbyCol = false;
if (index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) { if (index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) {
int32_t relTagIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta); int32_t relTagIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
...@@ -5175,11 +5180,18 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq ...@@ -5175,11 +5180,18 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
if (PRIMARYKEY_TIMESTAMP_COL_INDEX == index.columnIndex) { if (PRIMARYKEY_TIMESTAMP_COL_INDEX == index.columnIndex) {
orderByTS = true; orderByTS = true;
} }
if (!(orderByTags || orderByTS) && !isTopBottomQuery(pQueryInfo)) { SArray *columnInfo = pQueryInfo->groupbyExpr.columnInfo;
if (columnInfo != NULL && taosArrayGetSize(columnInfo) > 0) {
SColIndex* pColIndex = taosArrayGet(columnInfo, 0);
if (PRIMARYKEY_TIMESTAMP_COL_INDEX != index.columnIndex && pColIndex->colIndex == index.columnIndex) {
orderByGroupbyCol = true;
}
}
if (!(orderByTags || orderByTS || orderByGroupbyCol) && !isTopBottomQuery(pQueryInfo)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
} else { // order by top/bottom result value column is not supported in case of interval query. } else { // order by top/bottom result value column is not supported in case of interval query.
assert(!(orderByTags && orderByTS)); assert(!(orderByTags && orderByTS && orderByGroupbyCol));
} }
size_t s = taosArrayGetSize(pSortorder); size_t s = taosArrayGetSize(pSortorder);
...@@ -5189,6 +5201,11 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq ...@@ -5189,6 +5201,11 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0); tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
pQueryInfo->groupbyExpr.orderType = p1->sortOrder; pQueryInfo->groupbyExpr.orderType = p1->sortOrder;
} else if (orderByGroupbyCol) {
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
pQueryInfo->groupbyExpr.orderType = p1->sortOrder;
pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId;
} else if (isTopBottomQuery(pQueryInfo)) { } else if (isTopBottomQuery(pQueryInfo)) {
/* order of top/bottom query in interval is not valid */ /* order of top/bottom query in interval is not valid */
SExprInfo* pExpr = tscExprGet(pQueryInfo, 0); SExprInfo* pExpr = tscExprGet(pQueryInfo, 0);
...@@ -5221,6 +5238,9 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq ...@@ -5221,6 +5238,9 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
if (orderByTags) { if (orderByTags) {
pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta); pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
pQueryInfo->groupbyExpr.orderType = pItem->sortOrder; pQueryInfo->groupbyExpr.orderType = pItem->sortOrder;
} else if (orderByGroupbyCol){
pQueryInfo->order.order = pItem->sortOrder;
pQueryInfo->order.orderColId = index.columnIndex;
} else { } else {
pQueryInfo->order.order = pItem->sortOrder; pQueryInfo->order.order = pItem->sortOrder;
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX; pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
...@@ -5246,9 +5266,20 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq ...@@ -5246,9 +5266,20 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
if (getColumnIndexByName(pCmd, &columnName, pQueryInfo, &index) != TSDB_CODE_SUCCESS) { if (getColumnIndexByName(pCmd, &columnName, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
} }
if (index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX && !isTopBottomQuery(pQueryInfo)) { if (index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX && !isTopBottomQuery(pQueryInfo)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); bool validOrder = false;
SArray *columnInfo = pQueryInfo->groupbyExpr.columnInfo;
if (columnInfo != NULL && taosArrayGetSize(columnInfo) > 0) {
SColIndex* pColIndex = taosArrayGet(columnInfo, 0);
validOrder = (pColIndex->colIndex == index.columnIndex);
}
if (!validOrder) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
pQueryInfo->groupbyExpr.orderIndex = pSchema[index.columnIndex].colId;
pQueryInfo->groupbyExpr.orderType = p1->sortOrder;
} }
if (isTopBottomQuery(pQueryInfo)) { if (isTopBottomQuery(pQueryInfo)) {
...@@ -5269,6 +5300,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq ...@@ -5269,6 +5300,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
tVariantListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0); tVariantListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
pQueryInfo->order.order = pItem->sortOrder; pQueryInfo->order.order = pItem->sortOrder;
pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId;
} }
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
...@@ -7785,6 +7817,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf ...@@ -7785,6 +7817,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
const char* msg5 = "only tag query not compatible with normal column filter"; const char* msg5 = "only tag query not compatible with normal column filter";
const char* msg6 = "not support stddev/percentile/interp in the outer query yet"; const char* msg6 = "not support stddev/percentile/interp in the outer query yet";
const char* msg7 = "derivative/twa/irate requires timestamp column exists in subquery"; const char* msg7 = "derivative/twa/irate requires timestamp column exists in subquery";
const char* msg8 = "condition missing for join query";
int32_t code = TSDB_CODE_SUCCESS; int32_t code = TSDB_CODE_SUCCESS;
...@@ -7870,6 +7903,10 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf ...@@ -7870,6 +7903,10 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
if (validateWhereNode(pQueryInfo, &pSqlNode->pWhere, pSql) != TSDB_CODE_SUCCESS) { if (validateWhereNode(pQueryInfo, &pSqlNode->pWhere, pSql) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_OPERATION; return TSDB_CODE_TSC_INVALID_OPERATION;
} }
} else {
if (pQueryInfo->numOfTables > 1) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg8);
}
} }
// validate the interval info // validate the interval info
......
...@@ -484,8 +484,8 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) { ...@@ -484,8 +484,8 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
} }
if (shouldFree) { // in case of table-meta/vgrouplist query, automatically free it if (shouldFree) { // in case of table-meta/vgrouplist query, automatically free it
taosRemoveRef(tscObjRef, handle);
tscDebug("0x%"PRIx64" sqlObj is automatically freed", pSql->self); tscDebug("0x%"PRIx64" sqlObj is automatically freed", pSql->self);
taosRemoveRef(tscObjRef, handle);
} }
taosReleaseRef(tscObjRef, handle); taosReleaseRef(tscObjRef, handle);
......
...@@ -3604,10 +3604,10 @@ void* createQInfoFromQueryNode(SQueryInfo* pQueryInfo, STableGroupInfo* pTableGr ...@@ -3604,10 +3604,10 @@ void* createQInfoFromQueryNode(SQueryInfo* pQueryInfo, STableGroupInfo* pTableGr
// todo refactor: filter should not be applied here. // todo refactor: filter should not be applied here.
createFilterInfo(pQueryAttr, 0); createFilterInfo(pQueryAttr, 0);
pQueryAttr->numOfFilterCols = 0;
SArray* pa = NULL; SArray* pa = NULL;
if (stage == MASTER_SCAN) { if (stage == MASTER_SCAN) {
pQueryAttr->createFilterOperator = false; // no need for parent query
pa = createExecOperatorPlan(pQueryAttr); pa = createExecOperatorPlan(pQueryAttr);
} else { } else {
pa = createGlobalMergePlan(pQueryAttr); pa = createGlobalMergePlan(pQueryAttr);
......
...@@ -825,7 +825,10 @@ static void fetchNextBlockIfCompleted(SOperatorInfo* pOperator, bool* newgroup) ...@@ -825,7 +825,10 @@ static void fetchNextBlockIfCompleted(SOperatorInfo* pOperator, bool* newgroup)
SJoinStatus* pStatus = &pJoinInfo->status[i]; SJoinStatus* pStatus = &pJoinInfo->status[i];
if (pStatus->pBlock == NULL || pStatus->index >= pStatus->pBlock->info.rows) { if (pStatus->pBlock == NULL || pStatus->index >= pStatus->pBlock->info.rows) {
tscDebug("Retrieve nest query result, index:%d, total:%d", i, pOperator->numOfUpstream); tscDebug("Retrieve nest query result, index:%d, total:%d", i, pOperator->numOfUpstream);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
pStatus->pBlock = pOperator->upstream[i]->exec(pOperator->upstream[i], newgroup); pStatus->pBlock = pOperator->upstream[i]->exec(pOperator->upstream[i], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
pStatus->index = 0; pStatus->index = 0;
if (pStatus->pBlock == NULL) { if (pStatus->pBlock == NULL) {
...@@ -1304,7 +1307,7 @@ void tscResetSqlCmd(SSqlCmd* pCmd, bool clearCachedMeta) { ...@@ -1304,7 +1307,7 @@ void tscResetSqlCmd(SSqlCmd* pCmd, bool clearCachedMeta) {
if (pCmd->pTableMetaMap != NULL) { if (pCmd->pTableMetaMap != NULL) {
STableMetaVgroupInfo* p = taosHashIterate(pCmd->pTableMetaMap, NULL); STableMetaVgroupInfo* p = taosHashIterate(pCmd->pTableMetaMap, NULL);
while (p) { while (p) {
tfree(p->pVgroupInfo); tscVgroupInfoClear(p->pVgroupInfo);
tfree(p->pTableMeta); tfree(p->pTableMeta);
p = taosHashIterate(pCmd->pTableMetaMap, p); p = taosHashIterate(pCmd->pTableMetaMap, p);
} }
...@@ -3524,6 +3527,7 @@ void executeQuery(SSqlObj* pSql, SQueryInfo* pQueryInfo) { ...@@ -3524,6 +3527,7 @@ void executeQuery(SSqlObj* pSql, SQueryInfo* pQueryInfo) {
pSql->pSubs = calloc(pSql->subState.numOfSub, POINTER_BYTES); pSql->pSubs = calloc(pSql->subState.numOfSub, POINTER_BYTES);
pSql->subState.states = calloc(pSql->subState.numOfSub, sizeof(int8_t)); pSql->subState.states = calloc(pSql->subState.numOfSub, sizeof(int8_t));
pthread_mutex_init(&pSql->subState.mutex, NULL);
for(int32_t i = 0; i < pSql->subState.numOfSub; ++i) { for(int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
SQueryInfo* pSub = taosArrayGetP(pQueryInfo->pUpstream, i); SQueryInfo* pSub = taosArrayGetP(pQueryInfo->pUpstream, i);
...@@ -4080,7 +4084,10 @@ SVgroupsInfo* tscVgroupsInfoDup(SVgroupsInfo* pVgroupsInfo) { ...@@ -4080,7 +4084,10 @@ SVgroupsInfo* tscVgroupsInfoDup(SVgroupsInfo* pVgroupsInfo) {
size_t size = sizeof(SVgroupInfo) * pVgroupsInfo->numOfVgroups + sizeof(SVgroupsInfo); size_t size = sizeof(SVgroupInfo) * pVgroupsInfo->numOfVgroups + sizeof(SVgroupsInfo);
SVgroupsInfo* pInfo = calloc(1, size); SVgroupsInfo* pInfo = calloc(1, size);
memcpy(pInfo, pVgroupsInfo, size); pInfo->numOfVgroups = pVgroupsInfo->numOfVgroups;
for (int32_t m = 0; m < pVgroupsInfo->numOfVgroups; ++m) {
tscSVgroupInfoCopy(&pInfo->vgroups[m], &pVgroupsInfo->vgroups[m]);
}
return pInfo; return pInfo;
} }
......
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <iostream> #include <iostream>
#include <inttypes.h>
#include "taos.h" #include "taos.h"
#include "tglobal.h" #include "tglobal.h"
...@@ -132,7 +133,7 @@ void validateResultFields() { ...@@ -132,7 +133,7 @@ void validateResultFields() {
taos_free_result(res); taos_free_result(res);
char sql[512] = {0}; char sql[512] = {0};
sprintf(sql, "insert into t1 values(%ld, 99, 'abc', 'test')", start_ts); sprintf(sql, "insert into t1 values(%" PRId64 ", 99, 'abc', 'test')", start_ts);
res = taos_query(conn, sql); res = taos_query(conn, sql);
ASSERT_EQ(taos_errno(res), 0); ASSERT_EQ(taos_errno(res), 0);
......
#include "os.h"
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
#include <inttypes.h>
#include "os.h"
#include "taos.h" #include "taos.h"
#include "ttoken.h" #include "ttoken.h"
#include "tutil.h" #include "tutil.h"
...@@ -15,10 +17,10 @@ int main(int argc, char** argv) { ...@@ -15,10 +17,10 @@ int main(int argc, char** argv) {
extern void deltaToUtcInitOnce(); extern void deltaToUtcInitOnce();
/* test parse time function */ /* test parse time function */
TEST(testCase, parse_time) { TEST(testCase, parse_time) {
taos_options(TSDB_OPTION_TIMEZONE, "GMT-8"); taos_options(TSDB_OPTION_TIMEZONE, "GMT-8");
deltaToUtcInitOnce(); deltaToUtcInitOnce();
char t1[] = "2018-1-1 1:1:1.952798"; char t1[] = "2018-1-1 1:1:1.952798";
char t13[] = "1970-1-1 0:0:0"; char t13[] = "1970-1-1 0:0:0";
...@@ -77,15 +79,15 @@ TEST(testCase, parse_time) { ...@@ -77,15 +79,15 @@ TEST(testCase, parse_time) {
taosParseTime(t12, &time1, strlen(t12), TSDB_TIME_PRECISION_MILLI, 0); taosParseTime(t12, &time1, strlen(t12), TSDB_TIME_PRECISION_MILLI, 0);
EXPECT_EQ(time, time1); EXPECT_EQ(time, time1);
taos_options(TSDB_OPTION_TIMEZONE, "UTC"); taos_options(TSDB_OPTION_TIMEZONE, "UTC");
deltaToUtcInitOnce(); deltaToUtcInitOnce();
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0); taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
EXPECT_EQ(time, 0); EXPECT_EQ(time, 0);
taos_options(TSDB_OPTION_TIMEZONE, "Asia/Shanghai"); taos_options(TSDB_OPTION_TIMEZONE, "Asia/Shanghai");
deltaToUtcInitOnce(); deltaToUtcInitOnce();
char t14[] = "1970-1-1T0:0:0Z"; char t14[] = "1970-1-1T0:0:0Z";
taosParseTime(t14, &time, strlen(t14), TSDB_TIME_PRECISION_MILLI, 0); taosParseTime(t14, &time, strlen(t14), TSDB_TIME_PRECISION_MILLI, 0);
EXPECT_EQ(time, 0); EXPECT_EQ(time, 0);
...@@ -135,7 +137,7 @@ TEST(testCase, parse_time) { ...@@ -135,7 +137,7 @@ TEST(testCase, parse_time) {
//======================== add some case ============================// //======================== add some case ============================//
char b1[] = "9999-12-31 23:59:59.999"; char b1[] = "9999-12-31 23:59:59.999";
taosParseTime(b1, &time, strlen(b1), TSDB_TIME_PRECISION_MILLI,0); taosParseTime(b1, &time, strlen(b1), TSDB_TIME_PRECISION_MILLI,0);
EXPECT_EQ(time, 253402271999999); EXPECT_EQ(time, 253402271999999);
...@@ -145,27 +147,27 @@ TEST(testCase, parse_time) { ...@@ -145,27 +147,27 @@ TEST(testCase, parse_time) {
taosParseTime(b2, &time, strlen(b2), TSDB_TIME_PRECISION_MILLI, 0); taosParseTime(b2, &time, strlen(b2), TSDB_TIME_PRECISION_MILLI, 0);
EXPECT_EQ(time, 1577811661321); EXPECT_EQ(time, 1577811661321);
taos_options(TSDB_OPTION_TIMEZONE, "America/New_York"); taos_options(TSDB_OPTION_TIMEZONE, "America/New_York");
deltaToUtcInitOnce(); deltaToUtcInitOnce();
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0); taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
EXPECT_EQ(time, 18000 * MILLISECOND_PER_SECOND); EXPECT_EQ(time, 18000 * MILLISECOND_PER_SECOND);
taos_options(TSDB_OPTION_TIMEZONE, "Asia/Tokyo"); taos_options(TSDB_OPTION_TIMEZONE, "Asia/Tokyo");
deltaToUtcInitOnce(); deltaToUtcInitOnce();
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0); taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
EXPECT_EQ(time, -32400 * MILLISECOND_PER_SECOND); EXPECT_EQ(time, -32400 * MILLISECOND_PER_SECOND);
taos_options(TSDB_OPTION_TIMEZONE, "Asia/Shanghai"); taos_options(TSDB_OPTION_TIMEZONE, "Asia/Shanghai");
deltaToUtcInitOnce(); deltaToUtcInitOnce();
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0); taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
EXPECT_EQ(time, -28800 * MILLISECOND_PER_SECOND); EXPECT_EQ(time, -28800 * MILLISECOND_PER_SECOND);
char t[] = "2021-01-08T02:11:40.000+00:00"; char t[] = "2021-01-08T02:11:40.000+00:00";
taosParseTime(t, &time, strlen(t), TSDB_TIME_PRECISION_MILLI, 0); taosParseTime(t, &time, strlen(t), TSDB_TIME_PRECISION_MILLI, 0);
printf("%ld\n", time); printf("%" PRId64 "\n", time);
} }
...@@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED) ...@@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED)
ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME} ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME}
POST_BUILD POST_BUILD
COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml 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.31.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 COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
COMMENT "build jdbc driver") COMMENT "build jdbc driver")
ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME}) ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME})
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<groupId>com.taosdata.jdbc</groupId> <groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId> <artifactId>taos-jdbcdriver</artifactId>
<version>2.0.31</version> <version>2.0.32</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>JDBCDriver</name> <name>JDBCDriver</name>
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.taosdata.jdbc</groupId> <groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId> <artifactId>taos-jdbcdriver</artifactId>
<version>2.0.31</version> <version>2.0.32</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>JDBCDriver</name> <name>JDBCDriver</name>
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url> <url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
...@@ -113,16 +113,16 @@ ...@@ -113,16 +113,16 @@
<include>**/*Test.java</include> <include>**/*Test.java</include>
</includes> </includes>
<excludes> <excludes>
<exclude>**/TSDBJNIConnectorTest.java</exclude>
<exclude>**/UnsignedNumberJniTest.java</exclude>
<exclude>**/DatetimeBefore1970Test.java</exclude>
<exclude>**/AppMemoryLeakTest.java</exclude> <exclude>**/AppMemoryLeakTest.java</exclude>
<exclude>**/AuthenticationTest.java</exclude> <exclude>**/AuthenticationTest.java</exclude>
<exclude>**/TaosInfoMonitorTest.java</exclude> <exclude>**/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java</exclude>
<exclude>**/DatetimeBefore1970Test.java</exclude>
<exclude>**/FailOverTest.java</exclude> <exclude>**/FailOverTest.java</exclude>
<exclude>**/InvalidResultSetPointerTest.java</exclude> <exclude>**/InvalidResultSetPointerTest.java</exclude>
<exclude>**/RestfulConnectionTest.java</exclude> <exclude>**/RestfulConnectionTest.java</exclude>
<exclude>**/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java</exclude> <exclude>**/TSDBJNIConnectorTest.java</exclude>
<exclude>**/TaosInfoMonitorTest.java</exclude>
<exclude>**/UnsignedNumberJniTest.java</exclude>
</excludes> </excludes>
<testFailureIgnore>true</testFailureIgnore> <testFailureIgnore>true</testFailureIgnore>
</configuration> </configuration>
......
package com.taosdata.jdbc; package com.taosdata.jdbc;
import com.taosdata.jdbc.rs.enums.TimestampFormat; import com.taosdata.jdbc.enums.TimestampFormat;
import java.sql.*; import java.sql.*;
import java.util.Enumeration; import java.util.Enumeration;
...@@ -306,9 +306,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti ...@@ -306,9 +306,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
@Override @Override
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
switch (resultSetHoldability) { switch (resultSetHoldability) {
case ResultSet.HOLD_CURSORS_OVER_COMMIT: case ResultSet.HOLD_CURSORS_OVER_COMMIT:
break; break;
...@@ -322,11 +319,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti ...@@ -322,11 +319,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
} }
@Override @Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
switch (resultSetHoldability) { switch (resultSetHoldability) {
case ResultSet.HOLD_CURSORS_OVER_COMMIT: case ResultSet.HOLD_CURSORS_OVER_COMMIT:
break; break;
...@@ -425,7 +418,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti ...@@ -425,7 +418,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
status = resultSet.getInt("server_status()"); status = resultSet.getInt("server_status()");
resultSet.close(); resultSet.close();
} }
return status == 1 ? true : false; return status == 1;
}); });
boolean status = false; boolean status = false;
...@@ -434,9 +427,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti ...@@ -434,9 +427,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
status = future.get(); status = future.get();
else else
status = future.get(timeout, TimeUnit.SECONDS); status = future.get(timeout, TimeUnit.SECONDS);
} catch (InterruptedException e) { } catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace(); e.printStackTrace();
} catch (TimeoutException e) { } catch (TimeoutException e) {
future.cancel(true); future.cancel(true);
...@@ -452,8 +443,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti ...@@ -452,8 +443,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
if (isClosed) if (isClosed)
throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED); throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED);
if (clientInfoProps != null) clientInfoProps.setProperty(name, value);
clientInfoProps.setProperty(name, value);
} }
@Override @Override
...@@ -461,8 +451,8 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti ...@@ -461,8 +451,8 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
if (isClosed) if (isClosed)
throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED); throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED);
for (Enumeration<Object> enumer = properties.keys(); enumer.hasMoreElements(); ) { for (Enumeration<Object> enumeration = properties.keys(); enumeration.hasMoreElements(); ) {
String name = (String) enumer.nextElement(); String name = (String) enumeration.nextElement();
clientInfoProps.put(name, properties.getProperty(name)); clientInfoProps.put(name, properties.getProperty(name));
} }
} }
...@@ -528,14 +518,13 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti ...@@ -528,14 +518,13 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
if (milliseconds < 0) if (milliseconds < 0)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); // do nothing
} }
@Override @Override
public int getNetworkTimeout() throws SQLException { public int getNetworkTimeout() throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
return 0;
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
} }
...@@ -12,8 +12,7 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da ...@@ -12,8 +12,7 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da
private final static int DRIVER_MAJAR_VERSION = 2; private final static int DRIVER_MAJAR_VERSION = 2;
private final static int DRIVER_MINOR_VERSION = 0; private final static int DRIVER_MINOR_VERSION = 0;
private String precision = "ms"; private String precision = TSDBConstants.DEFAULT_PRECISION;
private String database;
public boolean allProceduresAreCallable() throws SQLException { public boolean allProceduresAreCallable() throws SQLException {
return false; return false;
...@@ -1223,7 +1222,6 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da ...@@ -1223,7 +1222,6 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da
ResultSet databases = stmt.executeQuery("show databases"); ResultSet databases = stmt.executeQuery("show databases");
while (databases.next()) { while (databases.next()) {
String dbname = databases.getString("name"); String dbname = databases.getString("name");
this.database = dbname;
this.precision = databases.getString("precision"); this.precision = databases.getString("precision");
if (dbname.equalsIgnoreCase(catalog)) if (dbname.equalsIgnoreCase(catalog))
return true; return true;
......
...@@ -58,7 +58,7 @@ public abstract class AbstractDriver implements Driver { ...@@ -58,7 +58,7 @@ public abstract class AbstractDriver implements Driver {
value = parameterValuePair.substring(indexOfEqual + 1); value = parameterValuePair.substring(indexOfEqual + 1);
} }
} }
if ((value != null && value.length() > 0) && (parameter != null && parameter.length() > 0)) { if (value != null && value.length() > 0 && parameter.length() > 0) {
urlProps.setProperty(parameter, value); urlProps.setProperty(parameter, value);
} }
} }
...@@ -87,7 +87,7 @@ public abstract class AbstractDriver implements Driver { ...@@ -87,7 +87,7 @@ public abstract class AbstractDriver implements Driver {
url = url.substring(0, indexOfColon); url = url.substring(0, indexOfColon);
} }
// parse host // parse host
if (url != null && url.length() > 0 && url.trim().length() > 0) { if (url.length() > 0 && url.trim().length() > 0) {
urlProps.setProperty(TSDBDriver.PROPERTY_KEY_HOST, url); urlProps.setProperty(TSDBDriver.PROPERTY_KEY_HOST, url);
} }
return urlProps; return urlProps;
......
package com.taosdata.jdbc; package com.taosdata.jdbc;
import com.sun.org.apache.xpath.internal.operations.Bool;
import java.sql.ParameterMetaData; import java.sql.ParameterMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
......
...@@ -15,10 +15,12 @@ ...@@ -15,10 +15,12 @@
package com.taosdata.jdbc; package com.taosdata.jdbc;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.*; import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Iterator;
import java.util.List; import java.util.List;
/* /*
...@@ -130,7 +132,7 @@ public class DatabaseMetaDataResultSet extends AbstractResultSet { ...@@ -130,7 +132,7 @@ public class DatabaseMetaDataResultSet extends AbstractResultSet {
public Timestamp getTimestamp(int columnIndex) throws SQLException { public Timestamp getTimestamp(int columnIndex) throws SQLException {
int colType = columnMetaDataList.get(columnIndex - 1).getColType(); int colType = columnMetaDataList.get(columnIndex - 1).getColType();
int nativeType = TSDBConstants.jdbcType2TaosType(colType); int nativeType = TSDBConstants.jdbcType2TaosType(colType);
return rowCursor.getTimestamp(columnIndex,nativeType); return rowCursor.getTimestamp(columnIndex, nativeType);
} }
@Override @Override
...@@ -145,9 +147,7 @@ public class DatabaseMetaDataResultSet extends AbstractResultSet { ...@@ -145,9 +147,7 @@ public class DatabaseMetaDataResultSet extends AbstractResultSet {
@Override @Override
public int findColumn(String columnLabel) throws SQLException { public int findColumn(String columnLabel) throws SQLException {
Iterator<ColumnMetaData> colMetaDataIt = this.columnMetaDataList.iterator(); for (ColumnMetaData colMetaData : this.columnMetaDataList) {
while (colMetaDataIt.hasNext()) {
ColumnMetaData colMetaData = colMetaDataIt.next();
if (colMetaData.getColName() != null && colMetaData.getColName().equals(columnLabel)) { if (colMetaData.getColName() != null && colMetaData.getColName().equals(columnLabel)) {
return colMetaData.getColIndex(); return colMetaData.getColIndex();
} }
......
...@@ -23,7 +23,7 @@ import java.util.Calendar; ...@@ -23,7 +23,7 @@ import java.util.Calendar;
import java.util.Map; import java.util.Map;
/* /*
* TDengine only supports a subset of the standard SQL, thus this implemetation of the * TDengine only supports a subset of the standard SQL, thus this implementation of the
* standard JDBC API contains more or less some adjustments customized for certain * standard JDBC API contains more or less some adjustments customized for certain
* compatibility needs. * compatibility needs.
*/ */
......
...@@ -20,7 +20,7 @@ import java.util.Properties; ...@@ -20,7 +20,7 @@ import java.util.Properties;
public class TSDBConnection extends AbstractConnection { public class TSDBConnection extends AbstractConnection {
private TSDBJNIConnector connector; private TSDBJNIConnector connector;
private TSDBDatabaseMetaData databaseMetaData; private final TSDBDatabaseMetaData databaseMetaData;
private boolean batchFetch; private boolean batchFetch;
public Boolean getBatchFetch() { public Boolean getBatchFetch() {
......
...@@ -54,10 +54,11 @@ public abstract class TSDBConstants { ...@@ -54,10 +54,11 @@ public abstract class TSDBConstants {
public static final int TSDB_DATA_TYPE_USMALLINT = 12; //unsigned smallint public static final int TSDB_DATA_TYPE_USMALLINT = 12; //unsigned smallint
public static final int TSDB_DATA_TYPE_UINT = 13; //unsigned int public static final int TSDB_DATA_TYPE_UINT = 13; //unsigned int
public static final int TSDB_DATA_TYPE_UBIGINT = 14; //unsigned bigint public static final int TSDB_DATA_TYPE_UBIGINT = 14; //unsigned bigint
// nchar column max length // nchar column max length
public static final int maxFieldSize = 16 * 1024; public static final int maxFieldSize = 16 * 1024;
// precision for data types // precision for data types, this is used for metadata
public static final int BOOLEAN_PRECISION = 1; public static final int BOOLEAN_PRECISION = 1;
public static final int TINYINT_PRECISION = 4; public static final int TINYINT_PRECISION = 4;
public static final int SMALLINT_PRECISION = 6; public static final int SMALLINT_PRECISION = 6;
...@@ -67,10 +68,12 @@ public abstract class TSDBConstants { ...@@ -67,10 +68,12 @@ public abstract class TSDBConstants {
public static final int DOUBLE_PRECISION = 22; public static final int DOUBLE_PRECISION = 22;
public static final int TIMESTAMP_MS_PRECISION = 23; public static final int TIMESTAMP_MS_PRECISION = 23;
public static final int TIMESTAMP_US_PRECISION = 26; public static final int TIMESTAMP_US_PRECISION = 26;
// scale for data types // scale for data types, this is used for metadata
public static final int FLOAT_SCALE = 31; public static final int FLOAT_SCALE = 31;
public static final int DOUBLE_SCALE = 31; public static final int DOUBLE_SCALE = 31;
public static final String DEFAULT_PRECISION = "ms";
public static int typeName2JdbcType(String type) { public static int typeName2JdbcType(String type) {
switch (type.toUpperCase()) { switch (type.toUpperCase()) {
case "TIMESTAMP": case "TIMESTAMP":
......
...@@ -20,8 +20,8 @@ import java.sql.SQLException; ...@@ -20,8 +20,8 @@ import java.sql.SQLException;
public class TSDBDatabaseMetaData extends AbstractDatabaseMetaData { public class TSDBDatabaseMetaData extends AbstractDatabaseMetaData {
private String url; private final String url;
private String userName; private final String userName;
private Connection conn; private Connection conn;
public TSDBDatabaseMetaData(String url, String userName) { public TSDBDatabaseMetaData(String url, String userName) {
......
...@@ -176,7 +176,7 @@ public class TSDBDriver extends AbstractDriver { ...@@ -176,7 +176,7 @@ public class TSDBDriver extends AbstractDriver {
int beginningOfSlashes = url.indexOf("//"); int beginningOfSlashes = url.indexOf("//");
int index = url.indexOf("?"); int index = url.indexOf("?");
if (index != -1) { if (index != -1) {
String paramString = url.substring(index + 1, url.length()); String paramString = url.substring(index + 1);
url = url.substring(0, index); url = url.substring(0, index);
StringTokenizer queryParams = new StringTokenizer(paramString, "&"); StringTokenizer queryParams = new StringTokenizer(paramString, "&");
while (queryParams.hasMoreElements()) { while (queryParams.hasMoreElements()) {
...@@ -213,7 +213,7 @@ public class TSDBDriver extends AbstractDriver { ...@@ -213,7 +213,7 @@ public class TSDBDriver extends AbstractDriver {
url = url.substring(0, indexOfColon); url = url.substring(0, indexOfColon);
} }
if (url != null && url.length() > 0 && url.trim().length() > 0) { if (url.length() > 0 && url.trim().length() > 0) {
urlProps.setProperty(TSDBDriver.PROPERTY_KEY_HOST, url); urlProps.setProperty(TSDBDriver.PROPERTY_KEY_HOST, url);
} }
...@@ -233,7 +233,7 @@ public class TSDBDriver extends AbstractDriver { ...@@ -233,7 +233,7 @@ public class TSDBDriver extends AbstractDriver {
return false; return false;
} }
public Logger getParentLogger() throws SQLFeatureNotSupportedException { public Logger getParentLogger() {
return null; return null;
} }
......
...@@ -8,7 +8,7 @@ import java.util.HashMap; ...@@ -8,7 +8,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class TSDBError { public class TSDBError {
private static Map<Integer, String> TSDBErrorMap = new HashMap<>(); private static final Map<Integer, String> TSDBErrorMap = new HashMap<>();
static { static {
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED, "connection already closed"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED, "connection already closed");
...@@ -34,9 +34,8 @@ public class TSDBError { ...@@ -34,9 +34,8 @@ public class TSDBError {
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE, "unknown taos type in tdengine"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE, "unknown taos type in tdengine");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PERCISION, "unknown timestamp precision"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PERCISION, "unknown timestamp precision");
/**************************************************/
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error");
/**************************************************/
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_SUBSCRIBE_FAILED, "failed to create subscription"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_SUBSCRIBE_FAILED, "failed to create subscription");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNSUPPORTED_ENCODING, "Unsupported encoding"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNSUPPORTED_ENCODING, "Unsupported encoding");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_TDENGINE_ERROR, "internal error of database"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_TDENGINE_ERROR, "internal error of database");
......
package com.taosdata.jdbc; package com.taosdata.jdbc;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set;
public class TSDBErrorNumbers { public class TSDBErrorNumbers {
...@@ -39,10 +40,9 @@ public class TSDBErrorNumbers { ...@@ -39,10 +40,9 @@ public class TSDBErrorNumbers {
public static final int ERROR_JNI_FETCH_END = 0x2358; // fetch to the end of resultSet public static final int ERROR_JNI_FETCH_END = 0x2358; // fetch to the end of resultSet
public static final int ERROR_JNI_OUT_OF_MEMORY = 0x2359; // JNI alloc memory failed public static final int ERROR_JNI_OUT_OF_MEMORY = 0x2359; // JNI alloc memory failed
private static final HashSet<Integer> errorNumbers; private static final Set<Integer> errorNumbers = new HashSet();
static { static {
errorNumbers = new HashSet();
errorNumbers.add(ERROR_CONNECTION_CLOSED); errorNumbers.add(ERROR_CONNECTION_CLOSED);
errorNumbers.add(ERROR_UNSUPPORTED_METHOD); errorNumbers.add(ERROR_UNSUPPORTED_METHOD);
errorNumbers.add(ERROR_INVALID_VARIABLE); errorNumbers.add(ERROR_INVALID_VARIABLE);
...@@ -65,7 +65,6 @@ public class TSDBErrorNumbers { ...@@ -65,7 +65,6 @@ public class TSDBErrorNumbers {
errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE); errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE);
errorNumbers.add(ERROR_UNKNOWN_TIMESTAMP_PERCISION); errorNumbers.add(ERROR_UNKNOWN_TIMESTAMP_PERCISION);
/*****************************************************/
errorNumbers.add(ERROR_SUBSCRIBE_FAILED); errorNumbers.add(ERROR_SUBSCRIBE_FAILED);
errorNumbers.add(ERROR_UNSUPPORTED_ENCODING); errorNumbers.add(ERROR_UNSUPPORTED_ENCODING);
errorNumbers.add(ERROR_JNI_TDENGINE_ERROR); errorNumbers.add(ERROR_JNI_TDENGINE_ERROR);
......
...@@ -29,14 +29,9 @@ import java.util.List; ...@@ -29,14 +29,9 @@ import java.util.List;
public class TSDBJNIConnector { public class TSDBJNIConnector {
private static volatile Boolean isInitialized = false; private static volatile Boolean isInitialized = false;
private TaosInfo taosInfo = TaosInfo.getInstance(); private final TaosInfo taosInfo = TaosInfo.getInstance();
private long taos = TSDBConstants.JNI_NULL_POINTER; // Connection pointer used in C
// Connection pointer used in C private boolean isResultsetClosed; // result set status in current connection
private long taos = TSDBConstants.JNI_NULL_POINTER;
// result set status in current connection
private boolean isResultsetClosed;
private int affectedRows = -1; private int affectedRows = -1;
static { static {
...@@ -96,11 +91,9 @@ public class TSDBJNIConnector { ...@@ -96,11 +91,9 @@ public class TSDBJNIConnector {
/** /**
* Execute DML/DDL operation * Execute DML/DDL operation
*
* @throws SQLException
*/ */
public long executeQuery(String sql) throws SQLException { public long executeQuery(String sql) throws SQLException {
Long pSql = 0l; long pSql = 0L;
try { try {
pSql = this.executeQueryImp(sql.getBytes(TaosGlobalConfig.getCharset()), this.taos); pSql = this.executeQueryImp(sql.getBytes(TaosGlobalConfig.getCharset()), this.taos);
taosInfo.stmt_count_increment(); taosInfo.stmt_count_increment();
...@@ -161,7 +154,7 @@ public class TSDBJNIConnector { ...@@ -161,7 +154,7 @@ public class TSDBJNIConnector {
private native long getResultSetImp(long connection, long pSql); private native long getResultSetImp(long connection, long pSql);
public boolean isUpdateQuery(long pSql) { public boolean isUpdateQuery(long pSql) {
return isUpdateQueryImp(this.taos, pSql) == 1 ? true : false; return isUpdateQueryImp(this.taos, pSql) == 1;
} }
private native long isUpdateQueryImp(long connection, long pSql); private native long isUpdateQueryImp(long connection, long pSql);
...@@ -195,7 +188,7 @@ public class TSDBJNIConnector { ...@@ -195,7 +188,7 @@ public class TSDBJNIConnector {
*/ */
public int getSchemaMetaData(long resultSet, List<ColumnMetaData> columnMetaData) { public int getSchemaMetaData(long resultSet, List<ColumnMetaData> columnMetaData) {
int ret = this.getSchemaMetaDataImp(this.taos, resultSet, columnMetaData); int ret = this.getSchemaMetaDataImp(this.taos, resultSet, columnMetaData);
columnMetaData.stream().forEach(column -> column.setColIndex(column.getColIndex() + 1)); columnMetaData.forEach(column -> column.setColIndex(column.getColIndex() + 1));
return ret; return ret;
} }
...@@ -218,8 +211,9 @@ public class TSDBJNIConnector { ...@@ -218,8 +211,9 @@ public class TSDBJNIConnector {
/** /**
* Get Result Time Precision. * Get Result Time Precision.
*
* @return 0: ms, 1: us, 2: ns * @return 0: ms, 1: us, 2: ns
*/ */
public int getResultTimePrecision(long sqlObj) { public int getResultTimePrecision(long sqlObj) {
return this.getResultTimePrecisionImp(this.taos, sqlObj); return this.getResultTimePrecisionImp(this.taos, sqlObj);
} }
...@@ -228,8 +222,6 @@ public class TSDBJNIConnector { ...@@ -228,8 +222,6 @@ public class TSDBJNIConnector {
/** /**
* Execute close operation from C to release connection pointer by JNI * Execute close operation from C to release connection pointer by JNI
*
* @throws SQLException
*/ */
public void closeConnection() throws SQLException { public void closeConnection() throws SQLException {
int code = this.closeConnectionImp(this.taos); int code = this.closeConnectionImp(this.taos);
...@@ -268,8 +260,6 @@ public class TSDBJNIConnector { ...@@ -268,8 +260,6 @@ public class TSDBJNIConnector {
/** /**
* Unsubscribe, close a subscription * Unsubscribe, close a subscription
*
* @param subscription
*/ */
void unsubscribe(long subscription, boolean isKeep) { void unsubscribe(long subscription, boolean isKeep) {
unsubscribeImp(subscription, isKeep); unsubscribeImp(subscription, isKeep);
...@@ -282,13 +272,13 @@ public class TSDBJNIConnector { ...@@ -282,13 +272,13 @@ public class TSDBJNIConnector {
*/ */
public boolean validateCreateTableSql(String sql) { public boolean validateCreateTableSql(String sql) {
int res = validateCreateTableSqlImp(taos, sql.getBytes()); int res = validateCreateTableSqlImp(taos, sql.getBytes());
return res != 0 ? false : true; return res == 0;
} }
private native int validateCreateTableSqlImp(long connection, byte[] sqlBytes); private native int validateCreateTableSqlImp(long connection, byte[] sqlBytes);
public long prepareStmt(String sql) throws SQLException { public long prepareStmt(String sql) throws SQLException {
Long stmt; long stmt;
try { try {
stmt = prepareStmtImp(sql.getBytes(), this.taos); stmt = prepareStmtImp(sql.getBytes(), this.taos);
} catch (Exception e) { } catch (Exception e) {
......
...@@ -62,8 +62,8 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -62,8 +62,8 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
if (parameterCnt > 1) { if (parameterCnt > 1) {
// the table name is also a parameter, so ignore it. // the table name is also a parameter, so ignore it.
this.colData = new ArrayList<ColumnInfo>(); this.colData = new ArrayList<>();
this.tableTags = new ArrayList<TableTagInfo>(); this.tableTags = new ArrayList<>();
} }
} }
...@@ -73,12 +73,16 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -73,12 +73,16 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
} }
/* /*
*
*/
/**
* Some of the SQLs sent by other popular frameworks or tools like Spark, contains syntax that cannot be parsed by * Some of the SQLs sent by other popular frameworks or tools like Spark, contains syntax that cannot be parsed by
* the TDengine client. Thus, some simple parsers/filters are intentionally added in this JDBC implementation in * the TDengine client. Thus, some simple parsers/filters are intentionally added in this JDBC implementation in
* order to process those supported SQLs. * order to process those supported SQLs.
*/ */
private void preprocessSql() { private void preprocessSql() {
/***** For processing some of Spark SQLs*****/ /***For processing some of Spark SQLs*/
// should replace it first // should replace it first
this.rawSql = this.rawSql.replaceAll("or (.*) is null", ""); this.rawSql = this.rawSql.replaceAll("or (.*) is null", "");
this.rawSql = this.rawSql.replaceAll(" where ", " WHERE "); this.rawSql = this.rawSql.replaceAll(" where ", " WHERE ");
...@@ -125,7 +129,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -125,7 +129,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
} }
rawSql = rawSql.replace(matcher.group(1), tableFullName); rawSql = rawSql.replace(matcher.group(1), tableFullName);
} }
/***** for inner queries *****/
} }
@Override @Override
...@@ -519,12 +522,10 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -519,12 +522,10 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
} }
} }
;
private static class TableTagInfo { private static class TableTagInfo {
private boolean isNull; private boolean isNull;
private Object value; private final Object value;
private int type; private final int type;
public TableTagInfo(Object value, int type) { public TableTagInfo(Object value, int type) {
this.value = value; this.value = value;
...@@ -538,8 +539,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -538,8 +539,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
} }
} }
;
public void setTableName(String name) { public void setTableName(String name) {
this.tableName = name; this.tableName = name;
} }
...@@ -627,7 +626,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -627,7 +626,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
this.colData.addAll(Collections.nCopies(this.parameters.length - 1 - this.tableTags.size(), null)); this.colData.addAll(Collections.nCopies(this.parameters.length - 1 - this.tableTags.size(), null));
} }
ColumnInfo col = (ColumnInfo) this.colData.get(columnIndex); ColumnInfo col = this.colData.get(columnIndex);
if (col == null) { if (col == null) {
ColumnInfo p = new ColumnInfo(); ColumnInfo p = new ColumnInfo();
p.setType(type); p.setType(type);
...@@ -718,8 +717,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -718,8 +717,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
ByteBuffer isNullList = ByteBuffer.allocate(num * Integer.BYTES); ByteBuffer isNullList = ByteBuffer.allocate(num * Integer.BYTES);
isNullList.order(ByteOrder.LITTLE_ENDIAN); isNullList.order(ByteOrder.LITTLE_ENDIAN);
for (int i = 0; i < num; ++i) { for (TableTagInfo tag : this.tableTags) {
TableTagInfo tag = this.tableTags.get(i);
if (tag.isNull) { if (tag.isNull) {
typeList.put((byte) tag.type); typeList.put((byte) tag.type);
isNullList.putInt(1); isNullList.putInt(1);
...@@ -818,7 +816,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -818,7 +816,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
typeList, lengthList, isNullList); typeList, lengthList, isNullList);
} }
ColumnInfo colInfo = (ColumnInfo) this.colData.get(0); ColumnInfo colInfo = this.colData.get(0);
if (colInfo == null) { if (colInfo == null) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "column data not bind"); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "column data not bind");
} }
...@@ -954,7 +952,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat ...@@ -954,7 +952,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "not support data types"); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "not support data types");
} }
} }
;
connector.bindColumnDataArray(this.nativeStmtHandle, colDataList, lengthList, isNullList, col1.type, col1.bytes, rows, i); connector.bindColumnDataArray(this.nativeStmtHandle, colDataList, lengthList, isNullList, col1.type, col1.bytes, rows, i);
} }
......
...@@ -339,11 +339,11 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { ...@@ -339,11 +339,11 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:
case TSDBConstants.TSDB_DATA_TYPE_INT: case TSDBConstants.TSDB_DATA_TYPE_INT:
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: case TSDBConstants.TSDB_DATA_TYPE_BIGINT:
res = new BigDecimal(Long.valueOf(this.rowData.getObject(columnIndex).toString())); res = new BigDecimal(Long.parseLong(this.rowData.getObject(columnIndex).toString()));
break; break;
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
res = new BigDecimal(Double.valueOf(this.rowData.getObject(columnIndex).toString())); res = BigDecimal.valueOf(Double.parseDouble(this.rowData.getObject(columnIndex).toString()));
break; break;
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
return new BigDecimal(((Timestamp) this.rowData.getObject(columnIndex)).getTime()); return new BigDecimal(((Timestamp) this.rowData.getObject(columnIndex)).getTime());
......
...@@ -36,23 +36,20 @@ public class TSDBResultSetBlockData { ...@@ -36,23 +36,20 @@ public class TSDBResultSetBlockData {
private int rowIndex = 0; private int rowIndex = 0;
private List<ColumnMetaData> columnMetaDataList; private List<ColumnMetaData> columnMetaDataList;
private ArrayList<Object> colData = null; private ArrayList<Object> colData;
public TSDBResultSetBlockData(List<ColumnMetaData> colMeta, int numOfCols) { public TSDBResultSetBlockData(List<ColumnMetaData> colMeta, int numOfCols) {
this.columnMetaDataList = colMeta; this.columnMetaDataList = colMeta;
this.colData = new ArrayList<Object>(numOfCols); this.colData = new ArrayList<>(numOfCols);
} }
public TSDBResultSetBlockData() { public TSDBResultSetBlockData() {
this.colData = new ArrayList<Object>(); this.colData = new ArrayList<>();
} }
public void clear() { public void clear() {
int size = this.colData.size(); int size = this.colData.size();
if (this.colData != null) { this.colData.clear();
this.colData.clear();
}
setNumOfCols(size); setNumOfCols(size);
} }
...@@ -69,7 +66,7 @@ public class TSDBResultSetBlockData { ...@@ -69,7 +66,7 @@ public class TSDBResultSetBlockData {
} }
public void setNumOfCols(int numOfCols) { public void setNumOfCols(int numOfCols) {
this.colData = new ArrayList<Object>(numOfCols); this.colData = new ArrayList<>(numOfCols);
this.colData.addAll(Collections.nCopies(numOfCols, null)); this.colData.addAll(Collections.nCopies(numOfCols, null));
} }
...@@ -166,15 +163,10 @@ public class TSDBResultSetBlockData { ...@@ -166,15 +163,10 @@ public class TSDBResultSetBlockData {
} }
} }
/** /**
* The original type may not be a string type, but will be converted to by * The original type may not be a string type, but will be converted to by
* calling this method * calling this method
*
* @param col column index
* @return
* @throws SQLException
*/ */
public String getString(int col) throws SQLException { public String getString(int col) throws SQLException {
Object obj = get(col); Object obj = get(col);
...@@ -387,7 +379,7 @@ public class TSDBResultSetBlockData { ...@@ -387,7 +379,7 @@ public class TSDBResultSetBlockData {
return null; return null;
} }
return (long) val; return val;
} }
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { case TSDBConstants.TSDB_DATA_TYPE_FLOAT: {
......
...@@ -41,10 +41,7 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD ...@@ -41,10 +41,7 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD
} }
public boolean isSearchable(int column) throws SQLException { public boolean isSearchable(int column) throws SQLException {
if (column == 1) { return column == 1;
return true;
}
return false;
} }
public boolean isCurrency(int column) throws SQLException { public boolean isCurrency(int column) throws SQLException {
......
...@@ -19,14 +19,13 @@ import com.taosdata.jdbc.utils.NullType; ...@@ -19,14 +19,13 @@ import com.taosdata.jdbc.utils.NullType;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
public class TSDBResultSetRowData { public class TSDBResultSetRowData {
private ArrayList<Object> data; private ArrayList<Object> data;
private int colSize; private final int colSize;
public TSDBResultSetRowData(int colSize) { public TSDBResultSetRowData(int colSize) {
this.colSize = colSize; this.colSize = colSize;
...@@ -390,27 +389,27 @@ public class TSDBResultSetRowData { ...@@ -390,27 +389,27 @@ public class TSDBResultSetRowData {
switch (nativeType) { switch (nativeType) {
case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: { case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: {
Byte value = new Byte(String.valueOf(obj)); byte value = new Byte(String.valueOf(obj));
if (value >= 0) if (value >= 0)
return value.toString(); return Byte.toString(value);
return Integer.toString(value & 0xff); return Integer.toString(value & 0xff);
} }
case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: { case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: {
Short value = new Short(String.valueOf(obj)); short value = new Short(String.valueOf(obj));
if (value >= 0) if (value >= 0)
return value.toString(); return Short.toString(value);
return Integer.toString(value & 0xffff); return Integer.toString(value & 0xffff);
} }
case TSDBConstants.TSDB_DATA_TYPE_UINT: { case TSDBConstants.TSDB_DATA_TYPE_UINT: {
Integer value = new Integer(String.valueOf(obj)); int value = new Integer(String.valueOf(obj));
if (value >= 0) if (value >= 0)
return value.toString(); return Integer.toString(value);
return Long.toString(value & 0xffffffffl); return Long.toString(value & 0xffffffffL);
} }
case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: { case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: {
Long value = new Long(String.valueOf(obj)); long value = new Long(String.valueOf(obj));
if (value >= 0) if (value >= 0)
return value.toString(); return Long.toString(value);
long lowValue = value & 0x7fffffffffffffffL; long lowValue = value & 0x7fffffffffffffffL;
return BigDecimal.valueOf(lowValue).add(BigDecimal.valueOf(Long.MAX_VALUE)).add(BigDecimal.valueOf(1)).toString(); return BigDecimal.valueOf(lowValue).add(BigDecimal.valueOf(Long.MAX_VALUE)).add(BigDecimal.valueOf(1)).toString();
} }
...@@ -432,25 +431,26 @@ public class TSDBResultSetRowData { ...@@ -432,25 +431,26 @@ public class TSDBResultSetRowData {
/** /**
* !!! this method is invoked by JNI method and the index start from 0 in C implementations * !!! this method is invoked by JNI method and the index start from 0 in C implementations
*
* @param precision 0 : ms, 1 : us, 2 : ns * @param precision 0 : ms, 1 : us, 2 : ns
*/ */
public void setTimestamp(int col, long ts, int precision) { public void setTimestamp(int col, long ts, int precision) {
long milliseconds = 0; long milliseconds;
int fracNanoseconds = 0; int fracNanoseconds;
switch (precision) { switch (precision) {
case 0: { case 0: {
milliseconds = ts; milliseconds = ts;
fracNanoseconds = (int)(ts*1_000_000%1_000_000_000); fracNanoseconds = (int) (ts * 1_000_000 % 1_000_000_000);
break; break;
} }
case 1: { case 1: {
milliseconds = ts/1_000; milliseconds = ts / 1_000;
fracNanoseconds = (int)(ts*1_000%1_000_000_000); fracNanoseconds = (int) (ts * 1_000 % 1_000_000_000);
break; break;
} }
case 2: { case 2: {
milliseconds = ts/1_000_000; milliseconds = ts / 1_000_000;
fracNanoseconds = (int)(ts%1_000_000_000); fracNanoseconds = (int) (ts % 1_000_000_000);
break; break;
} }
default: { default: {
...@@ -467,12 +467,10 @@ public class TSDBResultSetRowData { ...@@ -467,12 +467,10 @@ public class TSDBResultSetRowData {
Object obj = data.get(col - 1); Object obj = data.get(col - 1);
if (obj == null) if (obj == null)
return null; return null;
switch (nativeType) { if (nativeType == TSDBConstants.TSDB_DATA_TYPE_BIGINT) {
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return new Timestamp((Long) obj);
return new Timestamp((Long) obj);
default:
return (Timestamp) obj;
} }
return (Timestamp) obj;
} }
public Object getObject(int col) { public Object getObject(int col) {
......
...@@ -47,9 +47,6 @@ public class TSDBSubscribe { ...@@ -47,9 +47,6 @@ public class TSDBSubscribe {
/** /**
* close subscription * close subscription
*
* @param keepProgress
* @throws SQLException
*/ */
public void close(boolean keepProgress) throws SQLException { public void close(boolean keepProgress) throws SQLException {
if (this.connecter.isClosed()) if (this.connecter.isClosed())
......
package com.taosdata.jdbc.rs.enums; package com.taosdata.jdbc.enums;
public enum TimestampFormat { public enum TimestampFormat {
STRING, STRING,
......
...@@ -16,7 +16,7 @@ public class RestfulConnection extends AbstractConnection { ...@@ -16,7 +16,7 @@ public class RestfulConnection extends AbstractConnection {
private final String host; private final String host;
private final int port; private final int port;
private final String url; private final String url;
private volatile String database; private final String database;
private final String token; private final String token;
/******************************************************/ /******************************************************/
private boolean isClosed; private boolean isClosed;
......
...@@ -13,7 +13,7 @@ import java.util.Calendar; ...@@ -13,7 +13,7 @@ import java.util.Calendar;
public class RestfulPreparedStatement extends RestfulStatement implements PreparedStatement { public class RestfulPreparedStatement extends RestfulStatement implements PreparedStatement {
private ParameterMetaData parameterMetaData; private final ParameterMetaData parameterMetaData;
private final String rawSql; private final String rawSql;
private Object[] parameters; private Object[] parameters;
private boolean isPrepared; private boolean isPrepared;
......
...@@ -7,7 +7,7 @@ import com.google.common.primitives.Longs; ...@@ -7,7 +7,7 @@ import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts; import com.google.common.primitives.Shorts;
import com.taosdata.jdbc.*; import com.taosdata.jdbc.*;
import com.taosdata.jdbc.enums.TimestampPrecision; import com.taosdata.jdbc.enums.TimestampPrecision;
import com.taosdata.jdbc.rs.enums.TimestampFormat; import com.taosdata.jdbc.enums.TimestampFormat;
import com.taosdata.jdbc.utils.Utils; import com.taosdata.jdbc.utils.Utils;
import java.math.BigDecimal; import java.math.BigDecimal;
...@@ -17,19 +17,20 @@ import java.time.ZoneOffset; ...@@ -17,19 +17,20 @@ import java.time.ZoneOffset;
import java.time.format.DateTimeParseException; import java.time.format.DateTimeParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List;
public class RestfulResultSet extends AbstractResultSet implements ResultSet { public class RestfulResultSet extends AbstractResultSet implements ResultSet {
private volatile boolean isClosed;
private int pos = -1;
private final String database;
private final Statement statement; private final Statement statement;
// data // data
private final ArrayList<ArrayList<Object>> resultSet = new ArrayList<>(); private final List<List<Object>> resultSet = new ArrayList<>();
// meta // meta
private ArrayList<String> columnNames = new ArrayList<>(); private final List<String> columnNames = new ArrayList<>();
private ArrayList<Field> columns = new ArrayList<>(); private final List<Field> columns = new ArrayList<>();
private RestfulResultSetMetaData metaData; private final RestfulResultSetMetaData metaData;
private volatile boolean isClosed;
private int pos = -1;
/** /**
* 由一个result的Json构造结果集,对应执行show databases, show tables等这些语句,返回结果集,但无法获取结果集对应的meta,统一当成String处理 * 由一个result的Json构造结果集,对应执行show databases, show tables等这些语句,返回结果集,但无法获取结果集对应的meta,统一当成String处理
...@@ -37,35 +38,30 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -37,35 +38,30 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
* @param resultJson: 包含data信息的结果集,有sql返回的结果集 * @param resultJson: 包含data信息的结果集,有sql返回的结果集
***/ ***/
public RestfulResultSet(String database, Statement statement, JSONObject resultJson) throws SQLException { public RestfulResultSet(String database, Statement statement, JSONObject resultJson) throws SQLException {
this.database = database;
this.statement = statement; this.statement = statement;
// get head
JSONArray head = resultJson.getJSONArray("head");
// get column metadata // get column metadata
JSONArray columnMeta = resultJson.getJSONArray("column_meta"); JSONArray columnMeta = resultJson.getJSONArray("column_meta");
// get row data // get row data
JSONArray data = resultJson.getJSONArray("data"); JSONArray data = resultJson.getJSONArray("data");
if (data == null || data.isEmpty()) {
columnNames.clear();
columns.clear();
this.resultSet.clear();
this.metaData = new RestfulResultSetMetaData(this.database, null, this);
return;
}
// get head
JSONArray head = resultJson.getJSONArray("head");
// get rows // get rows
Integer rows = resultJson.getInteger("rows"); Integer rows = resultJson.getInteger("rows");
// parse column_meta // parse column_meta
if (columnMeta != null) { if (columnMeta != null) {
parseColumnMeta_new(columnMeta); parseColumnMeta_new(columnMeta);
} else { } else {
parseColumnMeta_old(head, data, rows); parseColumnMeta_old(head, data, rows);
} }
this.metaData = new RestfulResultSetMetaData(this.database, columns, this); this.metaData = new RestfulResultSetMetaData(database, columns, this);
if (data == null || data.isEmpty())
return;
// parse row data // parse row data
resultSet.clear();
for (int rowIndex = 0; rowIndex < data.size(); rowIndex++) { for (int rowIndex = 0; rowIndex < data.size(); rowIndex++) {
ArrayList row = new ArrayList(); List<Object> row = new ArrayList();
JSONArray jsonRow = data.getJSONArray(rowIndex); JSONArray jsonRow = data.getJSONArray(rowIndex);
for (int colIndex = 0; colIndex < this.metaData.getColumnCount(); colIndex++) { for (int colIndex = 0; colIndex < this.metaData.getColumnCount(); colIndex++) {
row.add(parseColumnData(jsonRow, colIndex, columns.get(colIndex).taos_type)); row.add(parseColumnData(jsonRow, colIndex, columns.get(colIndex).taos_type));
...@@ -174,8 +170,8 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -174,8 +170,8 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
//TODO: this implementation has bug if the timestamp bigger than 9999_9999_9999_9 //TODO: this implementation has bug if the timestamp bigger than 9999_9999_9999_9
if (value < 1_0000_0000_0000_0L) if (value < 1_0000_0000_0000_0L)
return new Timestamp(value); return new Timestamp(value);
long epochSec = value / 1000_000l; long epochSec = value / 1000_000L;
long nanoAdjustment = value % 1000_000l * 1000l; long nanoAdjustment = value % 1000_000L * 1000L;
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment)); return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
} }
case UTC: { case UTC: {
...@@ -244,10 +240,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -244,10 +240,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
pos++; pos++;
if (pos <= resultSet.size() - 1) { return pos <= resultSet.size() - 1;
return true;
}
return false;
} }
@Override @Override
...@@ -257,13 +250,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -257,13 +250,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
} }
} }
// @Override
// public boolean wasNull() throws SQLException {
// if (isClosed())
// throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
// return resultSet.isEmpty();
// }
@Override @Override
public String getString(int columnIndex) throws SQLException { public String getString(int columnIndex) throws SQLException {
checkAvailability(columnIndex, resultSet.get(pos).size()); checkAvailability(columnIndex, resultSet.get(pos).size());
...@@ -288,7 +274,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -288,7 +274,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
wasNull = false; wasNull = false;
if (value instanceof Boolean) if (value instanceof Boolean)
return (boolean) value; return (boolean) value;
return Boolean.valueOf(value.toString()); return Boolean.parseBoolean(value.toString());
} }
@Override @Override
...@@ -443,9 +429,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -443,9 +429,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
return null; return null;
if (value instanceof Timestamp) if (value instanceof Timestamp)
return new Date(((Timestamp) value).getTime()); return new Date(((Timestamp) value).getTime());
Date date = null; return Utils.parseDate(value.toString());
date = Utils.parseDate(value.toString());
return date;
} }
@Override @Override
...@@ -460,8 +444,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -460,8 +444,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
Time time = null; Time time = null;
try { try {
time = Utils.parseTime(value.toString()); time = Utils.parseTime(value.toString());
} catch (DateTimeParseException e) { } catch (DateTimeParseException ignored) {
time = null;
} }
return time; return time;
} }
...@@ -525,9 +508,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -525,9 +508,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
return null; return null;
if (value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Byte) if (value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Byte)
return new BigDecimal(Long.valueOf(value.toString())); return new BigDecimal(Long.parseLong(value.toString()));
if (value instanceof Double || value instanceof Float) if (value instanceof Double || value instanceof Float)
return new BigDecimal(Double.valueOf(value.toString())); return BigDecimal.valueOf(Double.parseDouble(value.toString()));
if (value instanceof Timestamp) if (value instanceof Timestamp)
return new BigDecimal(((Timestamp) value).getTime()); return new BigDecimal(((Timestamp) value).getTime());
BigDecimal ret; BigDecimal ret;
...@@ -637,36 +620,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -637,36 +620,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
// if (this.resultSet.size() == 0)
// return false;
//
// if (row == 0) {
// beforeFirst();
// return false;
// } else if (row == 1) {
// return first();
// } else if (row == -1) {
// return last();
// } else if (row > this.resultSet.size()) {
// afterLast();
// return false;
// } else {
// if (row < 0) {
// // adjust to reflect after end of result set
// int newRowPosition = this.resultSet.size() + row + 1;
// if (newRowPosition <= 0) {
// beforeFirst();
// return false;
// } else {
// return absolute(newRowPosition);
// }
// } else {
// row--; // adjust for index difference
// this.pos = row;
// return true;
// }
// }
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
...@@ -710,5 +663,4 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ...@@ -710,5 +663,4 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
return isClosed; return isClosed;
} }
}
} \ No newline at end of file
...@@ -7,20 +7,17 @@ import java.sql.ResultSetMetaData; ...@@ -7,20 +7,17 @@ import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.sql.Types; import java.sql.Types;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
public class RestfulResultSetMetaData extends WrapperImpl implements ResultSetMetaData { public class RestfulResultSetMetaData extends WrapperImpl implements ResultSetMetaData {
private final String database; private final String database;
private List<RestfulResultSet.Field> fields; private final List<RestfulResultSet.Field> fields;
private final RestfulResultSet resultSet;
public RestfulResultSetMetaData(String database, ArrayList<RestfulResultSet.Field> fields, RestfulResultSet resultSet) { public RestfulResultSetMetaData(String database, List<RestfulResultSet.Field> fields, RestfulResultSet resultSet) {
this.database = database; this.database = database;
this.fields = fields == null ? Collections.emptyList() : fields; this.fields = fields == null ? Collections.emptyList() : fields;
this.resultSet = resultSet;
} }
public List<RestfulResultSet.Field> getFields() { public List<RestfulResultSet.Field> getFields() {
...@@ -141,8 +138,8 @@ public class RestfulResultSetMetaData extends WrapperImpl implements ResultSetMe ...@@ -141,8 +138,8 @@ public class RestfulResultSetMetaData extends WrapperImpl implements ResultSetMe
@Override @Override
public String getColumnTypeName(int column) throws SQLException { public String getColumnTypeName(int column) throws SQLException {
int taos_type = fields.get(column - 1).taos_type; int taosType = fields.get(column - 1).taos_type;
return TSDBConstants.taosType2JdbcTypeName(taos_type); return TSDBConstants.taosType2JdbcTypeName(taosType);
} }
@Override @Override
......
...@@ -35,10 +35,6 @@ public class RestfulStatement extends AbstractStatement { ...@@ -35,10 +35,6 @@ public class RestfulStatement extends AbstractStatement {
if (!SqlSyntaxValidator.isValidForExecuteQuery(sql)) if (!SqlSyntaxValidator.isValidForExecuteQuery(sql))
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: " + sql); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: " + sql);
if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) {
return executeOneQuery(sql);
}
return executeOneQuery(sql); return executeOneQuery(sql);
} }
...@@ -50,9 +46,6 @@ public class RestfulStatement extends AbstractStatement { ...@@ -50,9 +46,6 @@ public class RestfulStatement extends AbstractStatement {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_UPDATE, "not a valid sql for executeUpdate: " + sql); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_UPDATE, "not a valid sql for executeUpdate: " + sql);
final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
if (SqlSyntaxValidator.isDatabaseUnspecifiedUpdate(sql)) {
return executeOneUpdate(url, sql);
}
return executeOneUpdate(url, sql); return executeOneUpdate(url, sql);
} }
......
...@@ -27,19 +27,18 @@ public class HttpClientPoolUtil { ...@@ -27,19 +27,18 @@ public class HttpClientPoolUtil {
private static final int DEFAULT_MAX_TOTAL = 1000; private static final int DEFAULT_MAX_TOTAL = 1000;
private static final int DEFAULT_HTTP_KEEP_TIME = 15000; private static final int DEFAULT_HTTP_KEEP_TIME = 15000;
private static PoolingHttpClientConnectionManager connectionManager;
private static CloseableHttpClient httpClient; private static CloseableHttpClient httpClient;
private static synchronized void initPools() { private static synchronized void initPools() {
if (httpClient == null) { if (httpClient == null) {
connectionManager = new PoolingHttpClientConnectionManager(); PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE); connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL); connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL);
httpClient = HttpClients.custom().setKeepAliveStrategy(DEFAULT_KEEP_ALIVE_STRATEGY).setConnectionManager(connectionManager).build(); httpClient = HttpClients.custom().setKeepAliveStrategy(DEFAULT_KEEP_ALIVE_STRATEGY).setConnectionManager(connectionManager).build();
} }
} }
private static ConnectionKeepAliveStrategy DEFAULT_KEEP_ALIVE_STRATEGY = (response, context) -> { private static final ConnectionKeepAliveStrategy DEFAULT_KEEP_ALIVE_STRATEGY = (response, context) -> {
HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE)); HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
int keepTime = DEFAULT_HTTP_KEEP_TIME * 1000; int keepTime = DEFAULT_HTTP_KEEP_TIME * 1000;
while (it.hasNext()) { while (it.hasNext()) {
......
...@@ -14,10 +14,6 @@ ...@@ -14,10 +14,6 @@
*****************************************************************************/ *****************************************************************************/
package com.taosdata.jdbc.utils; package com.taosdata.jdbc.utils;
import com.taosdata.jdbc.TSDBConnection;
import java.sql.Connection;
public class SqlSyntaxValidator { public class SqlSyntaxValidator {
private static final String[] SQL = {"select", "insert", "import", "create", "use", "alter", "drop", "set", "show", "describe"}; private static final String[] SQL = {"select", "insert", "import", "create", "use", "alter", "drop", "set", "show", "describe"};
...@@ -26,12 +22,6 @@ public class SqlSyntaxValidator { ...@@ -26,12 +22,6 @@ public class SqlSyntaxValidator {
private static final String[] databaseUnspecifiedShow = {"databases", "dnodes", "mnodes", "variables"}; private static final String[] databaseUnspecifiedShow = {"databases", "dnodes", "mnodes", "variables"};
private TSDBConnection tsdbConnection;
public SqlSyntaxValidator(Connection connection) {
this.tsdbConnection = (TSDBConnection) connection;
}
public static boolean isValidForExecuteUpdate(String sql) { public static boolean isValidForExecuteUpdate(String sql) {
for (String prefix : updateSQL) { for (String prefix : updateSQL) {
if (sql.trim().toLowerCase().startsWith(prefix)) if (sql.trim().toLowerCase().startsWith(prefix))
......
...@@ -6,6 +6,7 @@ import com.google.common.collect.TreeRangeSet; ...@@ -6,6 +6,7 @@ import com.google.common.collect.TreeRangeSet;
import com.taosdata.jdbc.enums.TimestampPrecision; import com.taosdata.jdbc.enums.TimestampPrecision;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.sql.Date; import java.sql.Date;
import java.sql.Time; import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
...@@ -160,7 +161,7 @@ public class Utils { ...@@ -160,7 +161,7 @@ public class Utils {
String paraStr; String paraStr;
if (para != null) { if (para != null) {
if (para instanceof byte[]) { if (para instanceof byte[]) {
paraStr = new String((byte[]) para, Charset.forName("UTF-8")); paraStr = new String((byte[]) para, StandardCharsets.UTF_8);
} else { } else {
paraStr = para.toString(); paraStr = para.toString();
} }
......
package com.taosdata.jdbc;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import java.sql.*;
import java.util.Properties;
public class StatementTest {
static Connection connection = null;
static Statement statement = null;
static String dbName = "test";
static String tName = "t0";
static String host = "localhost";
@BeforeClass
public static void createConnection() throws SQLException {
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", properties);
statement = connection.createStatement();
statement.executeUpdate("drop database if exists " + dbName);
} catch (ClassNotFoundException e) {
return;
}
}
@Test
public void testCase() {
try {
ResultSet rs = statement.executeQuery("show databases");
ResultSetMetaData metaData = rs.getMetaData();
while (rs.next()) {
for (int i = 1; i <= metaData.getColumnCount(); i++) {
System.out.print(metaData.getColumnLabel(i) + ":" + rs.getString(i) + "\t");
}
System.out.println();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void createTableAndQuery() throws SQLException {
long ts = System.currentTimeMillis();
statement.executeUpdate("create database if not exists " + dbName);
statement.executeUpdate("create table if not exists " + dbName + "." + tName + "(ts timestamp, k1 int)");
statement.executeUpdate("insert into " + dbName + "." + tName + " values (" + ts + ", 1)");
statement.execute("select * from " + dbName + "." + tName);
ResultSet resultSet = statement.getResultSet();
Assert.assertNotNull(resultSet);
boolean isClosed = statement.isClosed();
Assert.assertEquals(false, isClosed);
}
@Test(expected = SQLException.class)
public void testUnsupport() throws SQLException {
Assert.assertNotNull(statement.unwrap(TSDBStatement.class));
Assert.assertTrue(statement.isWrapperFor(TSDBStatement.class));
statement.getMaxFieldSize();
statement.setMaxFieldSize(0);
statement.setEscapeProcessing(true);
statement.cancel();
statement.getWarnings();
statement.clearWarnings();
statement.setCursorName(null);
statement.getMoreResults();
statement.setFetchDirection(0);
statement.getFetchDirection();
statement.getResultSetConcurrency();
statement.getResultSetType();
statement.getConnection();
statement.getMoreResults();
statement.getGeneratedKeys();
statement.executeUpdate(null, 0);
statement.executeUpdate(null, new int[]{0});
statement.executeUpdate(null, new String[]{"str1", "str2"});
statement.getResultSetHoldability();
statement.setPoolable(true);
statement.isPoolable();
statement.closeOnCompletion();
statement.isCloseOnCompletion();
}
@AfterClass
public static void close() {
try {
statement.execute("drop database if exists " + dbName);
if (statement != null)
statement.close();
if (connection != null)
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
...@@ -380,14 +380,15 @@ public class TSDBConnectionTest { ...@@ -380,14 +380,15 @@ public class TSDBConnectionTest {
conn.abort(null); conn.abort(null);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test
public void setNetworkTimeout() throws SQLException { public void setNetworkTimeout() throws SQLException {
conn.setNetworkTimeout(null, 1000); conn.setNetworkTimeout(null, 1000);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test
public void getNetworkTimeout() throws SQLException { public void getNetworkTimeout() throws SQLException {
conn.getNetworkTimeout(); int networkTimeout = conn.getNetworkTimeout();
Assert.assertEquals(0, networkTimeout);
} }
@Test @Test
......
...@@ -14,24 +14,6 @@ public class TSDBStatementTest { ...@@ -14,24 +14,6 @@ public class TSDBStatementTest {
private static Connection conn; private static Connection conn;
private static Statement stmt; private static Statement stmt;
@Test
public void executeQuery() {
try {
ResultSet rs = stmt.executeQuery("show databases");
Assert.assertNotNull(rs);
ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) {
System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t");
}
System.out.println();
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test @Test
public void executeUpdate() { public void executeUpdate() {
final String dbName = ("test_" + UUID.randomUUID()).replace("-", "_").substring(0, 32); final String dbName = ("test_" + UUID.randomUUID()).replace("-", "_").substring(0, 32);
...@@ -173,10 +155,6 @@ public class TSDBStatementTest { ...@@ -173,10 +155,6 @@ public class TSDBStatementTest {
Assert.assertEquals(3, meta.getColumnCount()); Assert.assertEquals(3, meta.getColumnCount());
int count = 0; int count = 0;
while (rs.next()) { while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) {
System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t");
}
System.out.println();
count++; count++;
} }
Assert.assertEquals(1, count); Assert.assertEquals(1, count);
......
package com.taosdata.jdbc.cases; package com.taosdata.jdbc.cases;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import java.sql.Connection; import java.sql.Connection;
...@@ -12,21 +13,19 @@ public class AppMemoryLeakTest { ...@@ -12,21 +13,19 @@ public class AppMemoryLeakTest {
@Test(expected = SQLException.class) @Test(expected = SQLException.class)
public void testCreateTooManyConnection() throws ClassNotFoundException, SQLException { public void testCreateTooManyConnection() throws ClassNotFoundException, SQLException {
Class.forName("com.taosdata.jdbc.TSDBDriver"); Class.forName("com.taosdata.jdbc.TSDBDriver");
int conCnt = 0;
while (true) { while (true) {
Connection conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata"); Connection conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata");
System.out.println(conCnt++ + " : " + conn); Assert.assertNotNull(conn);
} }
} }
@Test(expected = Exception.class) @Test(expected = Exception.class)
public void testCreateTooManyStatement() throws ClassNotFoundException, SQLException { public void testCreateTooManyStatement() throws ClassNotFoundException, SQLException {
Class.forName("com.taosdata.jdbc.TSDBDriver"); Class.forName("com.taosdata.jdbc.TSDBDriver");
int stmtCnt = 0;
Connection conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata"); Connection conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata");
while (true) { while (true) {
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
System.out.println(++stmtCnt + " : " + stmt); Assert.assertNotNull(stmt);
} }
} }
......
package com.taosdata.jdbc.rs; package com.taosdata.jdbc.cases;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
......
...@@ -60,7 +60,6 @@ public class BatchInsertTest { ...@@ -60,7 +60,6 @@ public class BatchInsertTest {
final int index = i; final int index = i;
executorService.execute(() -> { executorService.execute(() -> {
try { try {
long startTime = System.currentTimeMillis();
Statement statement = connection.createStatement(); // get statement Statement statement = connection.createStatement(); // get statement
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("INSERT INTO " + tablePrefix + index + " VALUES"); sb.append("INSERT INTO " + tablePrefix + index + " VALUES");
...@@ -73,8 +72,6 @@ public class BatchInsertTest { ...@@ -73,8 +72,6 @@ public class BatchInsertTest {
} }
statement.addBatch(sb.toString()); statement.addBatch(sb.toString());
statement.executeBatch(); statement.executeBatch();
long endTime = System.currentTimeMillis();
System.out.println("Thread " + index + " takes " + (endTime - startTime) + " microseconds");
connection.commit(); connection.commit();
statement.close(); statement.close();
} catch (Exception e) { } catch (Exception e) {
......
...@@ -31,9 +31,6 @@ public class ConnectMultiTaosdByRestfulWithDifferentTokenTest { ...@@ -31,9 +31,6 @@ public class ConnectMultiTaosdByRestfulWithDifferentTokenTest {
ResultSet rs = stmt.executeQuery("select server_status()"); ResultSet rs = stmt.executeQuery("select server_status()");
ResultSetMetaData meta = rs.getMetaData(); ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) { while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) {
System.out.println(meta.getColumnLabel(i) + ": " + rs.getString(i));
}
} }
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
......
package com.taosdata.jdbc.cases; package com.taosdata.jdbc.cases;
import com.taosdata.jdbc.utils.TimestampUtil; import com.taosdata.jdbc.utils.TimestampUtil;
import org.junit.AfterClass; import org.junit.*;
import org.junit.BeforeClass;
import org.junit.Test;
import java.sql.*; import java.sql.*;
public class DatetimeBefore1970Test { public class DatetimeBefore1970Test {
private static Connection conn; private static final String host = "127.0.0.1";
private Connection conn;
@Test @Test
public void test() { public void test() {
try (Statement stmt = conn.createStatement()) { try (Statement stmt = conn.createStatement()) {
// given
stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999')"); stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999')");
stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000')"); stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000')");
stmt.executeUpdate("insert into weather(ts) values('1970-01-01 08:00:00.000')"); stmt.executeUpdate("insert into weather(ts) values('1970-01-01 08:00:00.000')");
stmt.executeUpdate("insert into weather(ts) values('1970-01-01 07:59:59.999')"); stmt.executeUpdate("insert into weather(ts) values('1970-01-01 07:59:59.999')");
ResultSet rs = stmt.executeQuery("select * from weather order by ts asc");
ResultSetMetaData metaData = rs.getMetaData();
Assert.assertEquals(2, metaData.getColumnCount());
// when
rs.next();
// then
Timestamp ts = rs.getTimestamp("ts");
Assert.assertEquals("1969-12-31 23:59:59.999", TimestampUtil.longToDatetime(ts.getTime()));
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals("1970-01-01 00:00:00.000", TimestampUtil.longToDatetime(ts.getTime()));
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals("1970-01-01 08:00:00.000", TimestampUtil.longToDatetime(ts.getTime()));
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals("1970-01-01 07:59:59.999", TimestampUtil.longToDatetime(ts.getTime()));
ResultSet rs = stmt.executeQuery("select * from weather");
while (rs.next()) {
Timestamp ts = rs.getTimestamp("ts");
System.out.println("long: " + ts.getTime() + ", string: " + TimestampUtil.longToDatetime(ts.getTime()));
}
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
public static void main(String[] args) { @Before
System.out.println("timestamp: " + Long.MAX_VALUE + ", string: " + TimestampUtil.longToDatetime(Long.MAX_VALUE)); public void before() {
System.out.println("timestamp: " + Long.MIN_VALUE + ", string: " + TimestampUtil.longToDatetime(Long.MIN_VALUE));
System.out.println("timestamp: " + 0 + ", string: " + TimestampUtil.longToDatetime(0));
System.out.println("timestamp: " + -1 + ", string: " + TimestampUtil.longToDatetime(-1));
String datetime = "1970-01-01 00:00:00.000";
System.out.println("timestamp: " + TimestampUtil.datetimeToLong(datetime) + ", string: " + datetime);
datetime = "1969-12-31 23:59:59.999";
System.out.println("timestamp: " + TimestampUtil.datetimeToLong(datetime) + ", string: " + datetime);
}
@BeforeClass
public static void beforeClass() {
try { try {
Class.forName("com.taosdata.jdbc.TSDBDriver"); conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata");
conn = DriverManager.getConnection("jdbc:TAOS://127.0.0.1:6030/?user=root&password=taosdata");
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
stmt.execute("drop database if exists test_timestamp"); stmt.execute("drop database if exists test_timestamp");
stmt.execute("create database if not exists test_timestamp keep 36500"); stmt.execute("create database if not exists test_timestamp keep 36500");
stmt.execute("use test_timestamp"); stmt.execute("use test_timestamp");
stmt.execute("create table weather(ts timestamp,f1 float)"); stmt.execute("create table weather(ts timestamp,f1 float)");
stmt.close(); stmt.close();
} catch (ClassNotFoundException | SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
@AfterClass @After
public static void afterClass() { public void after() {
try { try {
Statement stmt = conn.createStatement();
stmt.execute("drop database if exists test_timestamp");
if (conn != null) if (conn != null)
conn.close(); conn.close();
} catch (SQLException e) { } catch (SQLException e) {
......
...@@ -20,7 +20,6 @@ public class ImportTest { ...@@ -20,7 +20,6 @@ public class ImportTest {
@BeforeClass @BeforeClass
public static void before() { public static void before() {
try { try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties(); Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
...@@ -33,8 +32,6 @@ public class ImportTest { ...@@ -33,8 +32,6 @@ public class ImportTest {
stmt.close(); stmt.close();
ts = System.currentTimeMillis(); ts = System.currentTimeMillis();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
...@@ -47,7 +44,6 @@ public class ImportTest { ...@@ -47,7 +44,6 @@ public class ImportTest {
for (int i = 0; i < 50; i++) { for (int i = 0; i < 50; i++) {
ts++; ts++;
int row = stmt.executeUpdate("import into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")"); int row = stmt.executeUpdate("import into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")");
System.out.println("import into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")\t" + row);
assertEquals(1, row); assertEquals(1, row);
} }
} }
...@@ -84,7 +80,6 @@ public class ImportTest { ...@@ -84,7 +80,6 @@ public class ImportTest {
long t = (++ts) + a; long t = (++ts) + a;
sqlBuilder.append("(").append(t).append(",").append((100 + i)).append(",").append(i).append(") "); sqlBuilder.append("(").append(t).append(",").append((100 + i)).append(",").append(i).append(") ");
} }
System.out.println(sqlBuilder.toString());
int rows = stmt.executeUpdate(sqlBuilder.toString()); int rows = stmt.executeUpdate(sqlBuilder.toString());
assertEquals(50, rows); assertEquals(50, rows);
} catch (SQLException e) { } catch (SQLException e) {
......
...@@ -41,7 +41,6 @@ public class MicroSecondPrecisionJNITest { ...@@ -41,7 +41,6 @@ public class MicroSecondPrecisionJNITest {
rs.next(); rs.next();
Timestamp timestamp = rs.getTimestamp(1); Timestamp timestamp = rs.getTimestamp(1);
System.out.println(timestamp);
long ts = timestamp.getTime(); long ts = timestamp.getTime();
Assert.assertEquals(timestamp1, ts); Assert.assertEquals(timestamp1, ts);
int nanos = timestamp.getNanos(); int nanos = timestamp.getNanos();
......
...@@ -7,7 +7,7 @@ import org.junit.Test; ...@@ -7,7 +7,7 @@ import org.junit.Test;
import java.sql.*; import java.sql.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class MultiThreadsWithSameStatmentTest { public class MultiThreadsWithSameStatementTest {
private class Service { private class Service {
...@@ -16,12 +16,11 @@ public class MultiThreadsWithSameStatmentTest { ...@@ -16,12 +16,11 @@ public class MultiThreadsWithSameStatmentTest {
public Service() { public Service() {
try { try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata"); conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata");
stmt = conn.createStatement(); stmt = conn.createStatement();
stmt.execute("create database if not exists jdbctest"); stmt.execute("create database if not exists jdbctest");
stmt.executeUpdate("create table if not exists jdbctest.weather (ts timestamp, f1 int)"); stmt.executeUpdate("create table if not exists jdbctest.weather (ts timestamp, f1 int)");
} catch (ClassNotFoundException | SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
...@@ -48,10 +47,6 @@ public class MultiThreadsWithSameStatmentTest { ...@@ -48,10 +47,6 @@ public class MultiThreadsWithSameStatmentTest {
ResultSet resultSet = service.stmt.executeQuery("select * from jdbctest.weather"); ResultSet resultSet = service.stmt.executeQuery("select * from jdbctest.weather");
while (resultSet.next()) { while (resultSet.next()) {
ResultSetMetaData metaData = resultSet.getMetaData(); ResultSetMetaData metaData = resultSet.getMetaData();
for (int i = 1; i <= metaData.getColumnCount(); i++) {
System.out.print(metaData.getColumnLabel(i) + ": " + resultSet.getString(i));
}
System.out.println();
} }
resultSet.close(); resultSet.close();
service.release(); service.release();
......
...@@ -17,11 +17,6 @@ public class NullValueInResultSetJNITest { ...@@ -17,11 +17,6 @@ public class NullValueInResultSetJNITest {
ResultSet rs = stmt.executeQuery("select * from weather"); ResultSet rs = stmt.executeQuery("select * from weather");
ResultSetMetaData meta = rs.getMetaData(); ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) { while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) {
Object value = rs.getObject(i);
System.out.print(meta.getColumnLabel(i) + ": " + value + "\t");
}
System.out.println();
} }
} catch (SQLException e) { } catch (SQLException e) {
......
...@@ -19,9 +19,7 @@ public class NullValueInResultSetRestfulTest { ...@@ -19,9 +19,7 @@ public class NullValueInResultSetRestfulTest {
while (rs.next()) { while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) { for (int i = 1; i <= meta.getColumnCount(); i++) {
Object value = rs.getObject(i); Object value = rs.getObject(i);
System.out.print(meta.getColumnLabel(i) + ": " + value + "\t");
} }
System.out.println();
} }
} catch (SQLException e) { } catch (SQLException e) {
......
...@@ -21,7 +21,6 @@ public class QueryDataTest { ...@@ -21,7 +21,6 @@ public class QueryDataTest {
@Before @Before
public void createDatabase() { public void createDatabase() {
try { try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties(); Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
...@@ -36,7 +35,7 @@ public class QueryDataTest { ...@@ -36,7 +35,7 @@ public class QueryDataTest {
String createTableSql = "create table " + stbName + "(ts timestamp, name binary(64))"; String createTableSql = "create table " + stbName + "(ts timestamp, name binary(64))";
statement.executeUpdate(createTableSql); statement.executeUpdate(createTableSql);
} catch (ClassNotFoundException | SQLException e) { } catch (SQLException e) {
return; return;
} }
} }
...@@ -44,7 +43,6 @@ public class QueryDataTest { ...@@ -44,7 +43,6 @@ public class QueryDataTest {
@Test @Test
public void testQueryBinaryData() throws SQLException { public void testQueryBinaryData() throws SQLException {
String insertSql = "insert into " + stbName + " values(now, 'taosdata')"; String insertSql = "insert into " + stbName + " values(now, 'taosdata')";
System.out.println(insertSql);
statement.executeUpdate(insertSql); statement.executeUpdate(insertSql);
String querySql = "select * from " + stbName; String querySql = "select * from " + stbName;
...@@ -52,7 +50,6 @@ public class QueryDataTest { ...@@ -52,7 +50,6 @@ public class QueryDataTest {
while (rs.next()) { while (rs.next()) {
String name = rs.getString(2); String name = rs.getString(2);
System.out.println("name = " + name);
assertEquals("taosdata", name); assertEquals("taosdata", name);
} }
rs.close(); rs.close();
......
...@@ -31,7 +31,7 @@ public class ResultSetMetaShouldNotBeNullRestfulTest { ...@@ -31,7 +31,7 @@ public class ResultSetMetaShouldNotBeNullRestfulTest {
// then // then
Assert.assertNotNull(metaData); Assert.assertNotNull(metaData);
Assert.assertEquals(0, columnCount); Assert.assertEquals(2, columnCount);
} }
@Test @Test
...@@ -53,7 +53,7 @@ public class ResultSetMetaShouldNotBeNullRestfulTest { ...@@ -53,7 +53,7 @@ public class ResultSetMetaShouldNotBeNullRestfulTest {
// then // then
Assert.assertEquals(true, execute); Assert.assertEquals(true, execute);
Assert.assertNotNull(metaData); Assert.assertNotNull(metaData);
Assert.assertEquals(0, columnCount); Assert.assertEquals(2, columnCount);
} }
@Before @Before
......
...@@ -19,7 +19,6 @@ public class SelectTest { ...@@ -19,7 +19,6 @@ public class SelectTest {
@Before @Before
public void createDatabaseAndTable() { public void createDatabaseAndTable() {
try { try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties(); Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
...@@ -31,8 +30,6 @@ public class SelectTest { ...@@ -31,8 +30,6 @@ public class SelectTest {
stmt.execute("create database if not exists " + dbName); stmt.execute("create database if not exists " + dbName);
stmt.execute("create table if not exists " + dbName + "." + tName + " (ts timestamp, k int, v int)"); stmt.execute("create table if not exists " + dbName + "." + tName + " (ts timestamp, k int, v int)");
stmt.close(); stmt.close();
} catch (ClassNotFoundException e) {
return;
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
...@@ -47,7 +44,6 @@ public class SelectTest { ...@@ -47,7 +44,6 @@ public class SelectTest {
for (int i = 0; i < 50; i++) { for (int i = 0; i < 50; i++) {
ts++; ts++;
int row = stmt.executeUpdate("insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")"); int row = stmt.executeUpdate("insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")");
System.out.println("insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")\t" + row);
assertEquals(1, row); assertEquals(1, row);
} }
......
...@@ -23,7 +23,6 @@ public class StableTest { ...@@ -23,7 +23,6 @@ public class StableTest {
@BeforeClass @BeforeClass
public static void createDatabase() { public static void createDatabase() {
try { try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties(); Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
...@@ -34,8 +33,6 @@ public class StableTest { ...@@ -34,8 +33,6 @@ public class StableTest {
statement.execute("create database if not exists " + dbName); statement.execute("create database if not exists " + dbName);
statement.execute("use " + dbName); statement.execute("use " + dbName);
statement.close(); statement.close();
} catch (ClassNotFoundException e) {
return;
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
...@@ -68,9 +65,6 @@ public class StableTest { ...@@ -68,9 +65,6 @@ public class StableTest {
String sql = "describe " + stbName; String sql = "describe " + stbName;
ResultSet rs = stmt.executeQuery(sql); ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) { while (rs.next()) {
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
System.out.println(i + ":" + rs.getString(i));
}
num++; num++;
} }
rs.close(); rs.close();
...@@ -86,9 +80,6 @@ public class StableTest { ...@@ -86,9 +80,6 @@ public class StableTest {
try (Statement stmt = connection.createStatement()) { try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("describe t1"); ResultSet rs = stmt.executeQuery("describe t1");
while (rs.next()) { while (rs.next()) {
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
System.out.printf("%d: %s\n", i, rs.getString(i));
}
num++; num++;
} }
rs.close(); rs.close();
......
...@@ -8,11 +8,6 @@ import java.sql.*; ...@@ -8,11 +8,6 @@ import java.sql.*;
public class RestfulDriverTest { public class RestfulDriverTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
@Test
public void connect() {
}
@Test @Test
public void acceptsURL() throws SQLException { public void acceptsURL() throws SQLException {
Driver driver = new RestfulDriver(); Driver driver = new RestfulDriver();
...@@ -27,9 +22,7 @@ public class RestfulDriverTest { ...@@ -27,9 +22,7 @@ public class RestfulDriverTest {
Driver driver = new RestfulDriver(); Driver driver = new RestfulDriver();
final String url = ""; final String url = "";
DriverPropertyInfo[] propertyInfo = driver.getPropertyInfo(url, null); DriverPropertyInfo[] propertyInfo = driver.getPropertyInfo(url, null);
for (DriverPropertyInfo prop : propertyInfo) { Assert.assertNotNull(propertyInfo);
System.out.println(prop);
}
} }
@Test @Test
......
...@@ -10,132 +10,151 @@ import java.util.Random; ...@@ -10,132 +10,151 @@ import java.util.Random;
public class RestfulJDBCTest { public class RestfulJDBCTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
private static Connection connection; private final Random random = new Random(System.currentTimeMillis());
private Random random = new Random(System.currentTimeMillis()); private Connection connection;
/**
* select * from log.log
**/
@Test @Test
public void testCase001() { public void testCase001() {
try { // given
Statement statement = connection.createStatement(); String sql = "drop database if exists restful_test";
ResultSet resultSet = statement.executeQuery("select * from log.log"); // when
ResultSetMetaData metaData = resultSet.getMetaData(); boolean execute = execute(connection, sql);
while (resultSet.next()) { // then
for (int i = 1; i <= metaData.getColumnCount(); i++) { Assert.assertFalse(execute);
String column = metaData.getColumnLabel(i);
String value = resultSet.getString(i); // given
System.out.print(column + ":" + value + "\t"); sql = "create database if not exists restful_test";
} // when
System.out.println(); execute = execute(connection, sql);
} // then
statement.close(); Assert.assertFalse(execute);
} catch (SQLException e) {
e.printStackTrace(); // given
} sql = "use restful_test";
// when
execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
/**
* create database
*/
@Test @Test
public void testCase002() { public void testCase002() {
try (Statement stmt = connection.createStatement()) { // given
stmt.execute("drop database if exists restful_test"); String sql = "create table weather(ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)";
stmt.execute("create database if not exists restful_test"); // when
stmt.execute("use restful_test"); boolean execute = execute(connection, sql);
} catch (SQLException e) { // then
e.printStackTrace(); Assert.assertFalse(execute);
}
} }
/**
* create super table
***/
@Test @Test
public void testCase003() { public void testCase004() {
try (Statement stmt = connection.createStatement()) { for (int i = 1; i <= 100; i++) {
stmt.execute("create table weather(ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)"); // given
} catch (SQLException e) { String sql = "create table t" + i + " using weather tags('beijing', '" + i + "')";
e.printStackTrace(); // when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
} }
@Test @Test
public void testCase004() { public void testCase005() {
try (Statement stmt = connection.createStatement()) { int rows = 0;
for (int i = 1; i <= 100; i++) { for (int i = 0; i < 10; i++) {
stmt.execute("create table t" + i + " using weather tags('beijing', '" + i + "')"); for (int j = 1; j <= 100; j++) {
// given
long currentTimeMillis = System.currentTimeMillis();
String sql = "insert into t" + j + " values(" + currentTimeMillis + "," + (random.nextFloat() * 50) + "," + random.nextInt(100) + ")";
// when
int affectRows = executeUpdate(connection, sql);
// then
Assert.assertEquals(1, affectRows);
rows += affectRows;
} }
} catch (SQLException e) {
e.printStackTrace();
} }
Assert.assertEquals(1000, rows);
} }
@Test
public void testCase006() throws SQLException {
// given
String sql = "select * from weather";
// when
ResultSet rs = executeQuery(connection, sql);
ResultSetMetaData meta = rs.getMetaData();
// then
Assert.assertEquals(5, meta.getColumnCount());
while (rs.next()) {
Assert.assertNotNull(rs.getTimestamp("ts"));
Assert.assertNotNull(rs.getFloat("temperature"));
Assert.assertNotNull(rs.getInt("humidity"));
Assert.assertNotNull(rs.getString("location"));
}
}
@Test @Test
public void testCase005() { public void testCase007() {
// given
String sql = "drop database restful_test";
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
}
private int executeUpdate(Connection connection, String sql) {
try (Statement stmt = connection.createStatement()) { try (Statement stmt = connection.createStatement()) {
int rows = 0; return stmt.executeUpdate(sql);
for (int i = 0; i < 10; i++) {
for (int j = 1; j <= 100; j++) {
long currentTimeMillis = System.currentTimeMillis();
int affectRows = stmt.executeUpdate("insert into t" + j + " values(" + currentTimeMillis + "," + (random.nextFloat() * 50) + "," + random.nextInt(100) + ")");
Assert.assertEquals(1, affectRows);
rows += affectRows;
}
}
Assert.assertEquals(1000, rows);
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
return 0;
} }
@Test private boolean execute(Connection connection, String sql) {
public void testCase006() {
try (Statement stmt = connection.createStatement()) { try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("select * from weather"); return stmt.execute(sql);
while (rs.next()) {
System.out.print("ts: " + rs.getTimestamp("ts"));
System.out.print(", temperature: " + rs.getString("temperature"));
System.out.print(", humidity: " + rs.getString("humidity"));
System.out.println(", location: " + rs.getString("location"));
}
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
return false;
} }
@Test
public void testCase007() { private ResultSet executeQuery(Connection connection, String sql) {
try (Statement stmt = connection.createStatement()) { try (Statement statement = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("select * from weather"); return statement.executeQuery(sql);
ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) {
int columnCount = meta.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
String columnLabel = meta.getColumnLabel(i);
String value = rs.getString(i);
System.out.print(columnLabel + ": " + value + "\t");
}
System.out.println();
}
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
return null;
} }
@BeforeClass @Before
public static void before() throws ClassNotFoundException, SQLException { public void before() {
Class.forName("com.taosdata.jdbc.rs.RestfulDriver"); try {
connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=root&password=taosdata"); connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=root&password=taosdata");
} catch (SQLException e) {
e.printStackTrace();
}
} }
@AfterClass @After
public static void after() throws SQLException { public void after() {
if (connection != null) try {
connection.close(); if (connection != null)
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
} }
} }
...@@ -27,12 +27,9 @@ public class RestfulPreparedStatementTest { ...@@ -27,12 +27,9 @@ public class RestfulPreparedStatementTest {
ResultSet rs = pstmt_select.executeQuery(); ResultSet rs = pstmt_select.executeQuery();
Assert.assertNotNull(rs); Assert.assertNotNull(rs);
ResultSetMetaData meta = rs.getMetaData(); ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) { int columnCount = meta.getColumnCount();
for (int i = 1; i <= meta.getColumnCount(); i++) { Assert.assertEquals(10, columnCount);
System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); Assert.assertNotNull(rs);
}
System.out.println();
}
} }
@Test @Test
...@@ -373,18 +370,19 @@ public class RestfulPreparedStatementTest { ...@@ -373,18 +370,19 @@ public class RestfulPreparedStatementTest {
@BeforeClass @BeforeClass
public static void beforeClass() { public static void beforeClass() {
try { try {
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata"); conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata");
try (Statement stmt = conn.createStatement()) {
stmt.execute("drop database if exists test_pstmt"); Statement stmt = conn.createStatement();
stmt.execute("create database if not exists test_pstmt"); stmt.execute("drop database if exists test_pstmt");
stmt.execute("use test_pstmt"); stmt.execute("create database if not exists test_pstmt");
stmt.execute("create table weather(ts timestamp, f1 int, f2 bigint, f3 float, f4 double, f5 smallint, f6 tinyint, f7 bool, f8 binary(64), f9 nchar(64)) tags(loc nchar(64))"); stmt.execute("use test_pstmt");
stmt.execute("create table t1 using weather tags('beijing')"); stmt.execute("create table weather(ts timestamp, f1 int, f2 bigint, f3 float, f4 double, f5 smallint, f6 tinyint, f7 bool, f8 binary(64), f9 nchar(64)) tags(loc nchar(64))");
} stmt.execute("create table t1 using weather tags('beijing')");
stmt.close();
pstmt_insert = conn.prepareStatement(sql_insert); pstmt_insert = conn.prepareStatement(sql_insert);
pstmt_select = conn.prepareStatement(sql_select); pstmt_select = conn.prepareStatement(sql_select);
} catch (ClassNotFoundException | SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
......
...@@ -12,6 +12,7 @@ import java.util.UUID; ...@@ -12,6 +12,7 @@ import java.util.UUID;
public class RestfulStatementTest { public class RestfulStatementTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
private static Connection conn; private static Connection conn;
private static Statement stmt; private static Statement stmt;
...@@ -21,11 +22,11 @@ public class RestfulStatementTest { ...@@ -21,11 +22,11 @@ public class RestfulStatementTest {
ResultSet rs = stmt.executeQuery("show databases"); ResultSet rs = stmt.executeQuery("show databases");
Assert.assertNotNull(rs); Assert.assertNotNull(rs);
ResultSetMetaData meta = rs.getMetaData(); ResultSetMetaData meta = rs.getMetaData();
int columnCount = meta.getColumnCount();
Assert.assertTrue(columnCount > 1);
while (rs.next()) { while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) { Assert.assertEquals("name", meta.getColumnLabel(1));
System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); Assert.assertNotNull(rs.getString("name"));
}
System.out.println();
} }
rs.close(); rs.close();
} catch (SQLException e) { } catch (SQLException e) {
...@@ -174,10 +175,10 @@ public class RestfulStatementTest { ...@@ -174,10 +175,10 @@ public class RestfulStatementTest {
Assert.assertEquals(3, meta.getColumnCount()); Assert.assertEquals(3, meta.getColumnCount());
int count = 0; int count = 0;
while (rs.next()) { while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) { Assert.assertEquals("ts", meta.getColumnLabel(1));
System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); Assert.assertNotNull(rs.getTimestamp(1));
} Assert.assertEquals("temperature", meta.getColumnLabel(2));
System.out.println(); Assert.assertEquals(22.33, rs.getFloat(2), 0.001f);
count++; count++;
} }
Assert.assertEquals(1, count); Assert.assertEquals(1, count);
...@@ -388,15 +389,12 @@ public class RestfulStatementTest { ...@@ -388,15 +389,12 @@ public class RestfulStatementTest {
@BeforeClass @BeforeClass
public static void beforeClass() { public static void beforeClass() {
try { try {
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
Properties properties = new Properties(); Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata", properties); conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata", properties);
stmt = conn.createStatement(); stmt = conn.createStatement();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
......
package com.taosdata.jdbc.rs; package com.taosdata.jdbc.rs;
import com.taosdata.jdbc.utils.SQLExecutor; import org.junit.*;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters; import org.junit.runners.MethodSorters;
import java.sql.*; import java.sql.*;
@FixMethodOrder(MethodSorters.NAME_ASCENDING) @FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SQLTest { public class SQLTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
private static Connection connection; private static Connection connection;
@Test @Test
public void testCase001() { public void testCase001() {
// given
String sql = "create database if not exists restful_test"; String sql = "create database if not exists restful_test";
SQLExecutor.execute(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
@Test @Test
public void testCase002() { public void testCase002() {
// given
String sql = "use restful_test"; String sql = "use restful_test";
SQLExecutor.execute(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
@Test @Test
public void testCase003() { public void testCase003() {
// given
String sql = "show databases"; String sql = "show databases";
SQLExecutor.executeWithResult(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertTrue(execute);
} }
@Test @Test
public void testCase004() { public void testCase004() {
// given
String sql = "show tables"; String sql = "show tables";
SQLExecutor.executeWithResult(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertTrue(execute);
} }
@Test @Test
public void testCase005() { public void testCase005() {
// given
String sql = "show stables"; String sql = "show stables";
SQLExecutor.executeWithResult(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertTrue(execute);
} }
@Test @Test
public void testCase006() { public void testCase006() {
// given
String sql = "show dnodes"; String sql = "show dnodes";
SQLExecutor.executeWithResult(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertTrue(execute);
} }
@Test @Test
public void testCase007() { public void testCase007() {
// given
String sql = "show vgroups"; String sql = "show vgroups";
SQLExecutor.executeWithResult(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertTrue(execute);
} }
@Test @Test
public void testCase008() { public void testCase008() {
// given
String sql = "drop table if exists restful_test.weather"; String sql = "drop table if exists restful_test.weather";
SQLExecutor.execute(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
@Test @Test
public void testCase009() { public void testCase009() {
// given
String sql = "create table if not exists restful_test.weather(ts timestamp, temperature float) tags(location nchar(64))"; String sql = "create table if not exists restful_test.weather(ts timestamp, temperature float) tags(location nchar(64))";
SQLExecutor.execute(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
@Test @Test
public void testCase010() { public void testCase010() {
// given
String sql = "create table t1 using restful_test.weather tags('北京')"; String sql = "create table t1 using restful_test.weather tags('北京')";
SQLExecutor.execute(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
@Test @Test
public void testCase011() { public void testCase011() {
// given
String sql = "insert into restful_test.t1 values(now, 22.22)"; String sql = "insert into restful_test.t1 values(now, 22.22)";
SQLExecutor.executeUpdate(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
@Test @Test
public void testCase012() { public void testCase012() {
// given
String sql = "insert into restful_test.t1 values('2020-01-01 00:00:00.000', 22.22)"; String sql = "insert into restful_test.t1 values('2020-01-01 00:00:00.000', 22.22)";
SQLExecutor.executeUpdate(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
@Test @Test
public void testCase013() { public void testCase013() {
// given
String sql = "insert into restful_test.t1 values('2020-01-01 00:01:00.000', 22.22),('2020-01-01 00:02:00.000', 22.22)"; String sql = "insert into restful_test.t1 values('2020-01-01 00:01:00.000', 22.22),('2020-01-01 00:02:00.000', 22.22)";
SQLExecutor.executeUpdate(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
@Test @Test
public void testCase014() { public void testCase014() {
// given
String sql = "insert into restful_test.t2 using weather tags('上海') values('2020-01-01 00:03:00.000', 22.22)"; String sql = "insert into restful_test.t2 using weather tags('上海') values('2020-01-01 00:03:00.000', 22.22)";
SQLExecutor.executeUpdate(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
@Test @Test
public void testCase015() { public void testCase015() {
// given
String sql = "insert into restful_test.t2 using weather tags('上海') values('2020-01-01 00:01:00.000', 22.22),('2020-01-01 00:02:00.000', 22.22)"; String sql = "insert into restful_test.t2 using weather tags('上海') values('2020-01-01 00:01:00.000', 22.22),('2020-01-01 00:02:00.000', 22.22)";
SQLExecutor.executeUpdate(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
@Test @Test
public void testCase016() { public void testCase016() {
// given
String sql = "insert into t1 values('2020-01-01 01:0:00.000', 22.22),('2020-01-01 02:00:00.000', 22.22) t2 values('2020-01-01 01:0:00.000', 33.33),('2020-01-01 02:00:00.000', 33.33)"; String sql = "insert into t1 values('2020-01-01 01:0:00.000', 22.22),('2020-01-01 02:00:00.000', 22.22) t2 values('2020-01-01 01:0:00.000', 33.33),('2020-01-01 02:00:00.000', 33.33)";
SQLExecutor.executeUpdate(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
@Test @Test
public void testCase017() { public void testCase017() {
// given
String sql = "Insert into t3 using weather tags('广东') values('2020-01-01 01:0:00.000', 22.22),('2020-01-01 02:00:00.000', 22.22) t4 using weather tags('天津') values('2020-01-01 01:0:00.000', 33.33),('2020-01-01 02:00:00.000', 33.33)"; String sql = "Insert into t3 using weather tags('广东') values('2020-01-01 01:0:00.000', 22.22),('2020-01-01 02:00:00.000', 22.22) t4 using weather tags('天津') values('2020-01-01 01:0:00.000', 33.33),('2020-01-01 02:00:00.000', 33.33)";
SQLExecutor.executeUpdate(connection, sql);
// when
boolean execute = execute(connection, sql);
// then
Assert.assertFalse(execute);
} }
@Test @Test
public void testCase018() { public void testCase018() {
// given
String sql = "select * from restful_test.t1"; String sql = "select * from restful_test.t1";
SQLExecutor.executeQuery(connection, sql); // when
boolean execute = execute(connection, sql);
// then
Assert.assertTrue(execute);
} }
@Test @Test
public void testCase019() { public void testCase019() {
// given
String sql = "select * from restful_test.weather"; String sql = "select * from restful_test.weather";
SQLExecutor.executeQuery(connection, sql); // when
boolean execute = execute(connection, sql);
// then
Assert.assertTrue(execute);
} }
@Test @Test
public void testCase020() { public void testCase020() {
// given
String sql = "select ts, temperature from restful_test.t1"; String sql = "select ts, temperature from restful_test.t1";
SQLExecutor.executeQuery(connection, sql); // when
boolean execute = execute(connection, sql);
// then
Assert.assertTrue(execute);
} }
@Test @Test
public void testCase021() { public void testCase021() {
// given
String sql = "select ts, temperature from restful_test.weather"; String sql = "select ts, temperature from restful_test.weather";
SQLExecutor.executeQuery(connection, sql); // when
boolean execute = execute(connection, sql);
// then
Assert.assertTrue(execute);
} }
@Test @Test
public void testCase022() { public void testCase022() {
// given
String sql = "select temperature, ts from restful_test.t1"; String sql = "select temperature, ts from restful_test.t1";
SQLExecutor.executeQuery(connection, sql); // when
boolean execute = execute(connection, sql);
// then
Assert.assertTrue(execute);
} }
@Test @Test
public void testCase023() { public void testCase023() {
// given
String sql = "select temperature, ts from restful_test.weather"; String sql = "select temperature, ts from restful_test.weather";
SQLExecutor.executeQuery(connection, sql); // when
boolean execute = execute(connection, sql);
// then
Assert.assertTrue(execute);
} }
@Test @Test
public void testCase024() { public void testCase024() {
// given
String sql = "import into restful_test.t5 using weather tags('石家庄') values('2020-01-01 00:01:00.000', 22.22)"; String sql = "import into restful_test.t5 using weather tags('石家庄') values('2020-01-01 00:01:00.000', 22.22)";
SQLExecutor.executeUpdate(connection, sql); // when
int affectedRows = executeUpdate(connection, sql);
// then
Assert.assertEquals(1, affectedRows);
} }
@Test @Test
public void testCase025() { public void testCase025() {
// given
String sql = "import into restful_test.t6 using weather tags('沈阳') values('2020-01-01 00:01:00.000', 22.22),('2020-01-01 00:02:00.000', 22.22)"; String sql = "import into restful_test.t6 using weather tags('沈阳') values('2020-01-01 00:01:00.000', 22.22),('2020-01-01 00:02:00.000', 22.22)";
SQLExecutor.executeUpdate(connection, sql); // when
int affectedRows = executeUpdate(connection, sql);
// then
Assert.assertEquals(2, affectedRows);
} }
@Test @Test
public void testCase026() { public void testCase026() {
// given
String sql = "import into restful_test.t7 using weather tags('长沙') values('2020-01-01 00:01:00.000', 22.22) restful_test.t8 using weather tags('吉林') values('2020-01-01 00:01:00.000', 22.22)"; String sql = "import into restful_test.t7 using weather tags('长沙') values('2020-01-01 00:01:00.000', 22.22) restful_test.t8 using weather tags('吉林') values('2020-01-01 00:01:00.000', 22.22)";
SQLExecutor.executeUpdate(connection, sql);
// when
int affectedRows = executeUpdate(connection, sql);
// then
Assert.assertEquals(2, affectedRows);
} }
@Test @Test
public void testCase027() { public void testCase027() {
// given
String sql = "import into restful_test.t9 using weather tags('武汉') values('2020-01-01 00:01:00.000', 22.22) ,('2020-01-02 00:01:00.000', 22.22) restful_test.t10 using weather tags('哈尔滨') values('2020-01-01 00:01:00.000', 22.22),('2020-01-02 00:01:00.000', 22.22)"; String sql = "import into restful_test.t9 using weather tags('武汉') values('2020-01-01 00:01:00.000', 22.22) ,('2020-01-02 00:01:00.000', 22.22) restful_test.t10 using weather tags('哈尔滨') values('2020-01-01 00:01:00.000', 22.22),('2020-01-02 00:01:00.000', 22.22)";
SQLExecutor.executeUpdate(connection, sql); // when
int affectedRows = executeUpdate(connection, sql);
// then
Assert.assertEquals(4, affectedRows);
} }
@Test @Test
public void testCase028() { public void testCase028() {
// given
String sql = "select location, temperature, ts from restful_test.weather where temperature > 1"; String sql = "select location, temperature, ts from restful_test.weather where temperature > 1";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase029() { public void testCase029() {
String sql = "select location, temperature, ts from restful_test.weather where temperature < 1"; String sql = "select location, temperature, ts from restful_test.weather where temperature < 1";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase030() { public void testCase030() {
String sql = "select location, temperature, ts from restful_test.weather where ts > now"; String sql = "select location, temperature, ts from restful_test.weather where ts > now";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase031() { public void testCase031() {
String sql = "select location, temperature, ts from restful_test.weather where ts < now"; String sql = "select location, temperature, ts from restful_test.weather where ts < now";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase032() { public void testCase032() {
String sql = "select count(*) from restful_test.weather"; String sql = "select count(*) from restful_test.weather";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase033() { public void testCase033() {
String sql = "select first(*) from restful_test.weather"; String sql = "select first(*) from restful_test.weather";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase034() { public void testCase034() {
String sql = "select last(*) from restful_test.weather"; String sql = "select last(*) from restful_test.weather";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase035() { public void testCase035() {
String sql = "select last_row(*) from restful_test.weather"; String sql = "select last_row(*) from restful_test.weather";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase036() { public void testCase036() {
String sql = "select ts, ts as primary_key from restful_test.weather"; String sql = "select ts, ts as primary_key from restful_test.weather";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase037() { public void testCase037() {
String sql = "select database()"; String sql = "select database()";
SQLExecutor.execute(connection, "use restful_test"); // when
SQLExecutor.executeQuery(connection, sql); ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase038() { public void testCase038() {
String sql = "select client_version()"; String sql = "select client_version()";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase039() { public void testCase039() {
String sql = "select server_status()"; String sql = "select server_status()";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase040() { public void testCase040() {
String sql = "select server_status() as status"; String sql = "select server_status() as status";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase041() { public void testCase041() {
String sql = "select tbname, location from restful_test.weather"; String sql = "select tbname, location from restful_test.weather";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase042() { public void testCase042() {
String sql = "select count(tbname) from restful_test.weather"; String sql = "select count(tbname) from restful_test.weather";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase043() { public void testCase043() {
String sql = "select * from restful_test.weather where ts < now - 1h"; String sql = "select * from restful_test.weather where ts < now - 1h";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase044() { public void testCase044() {
String sql = "select * from restful_test.weather where ts < now - 1h and location like '%'"; String sql = "select * from restful_test.weather where ts < now - 1h and location like '%'";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase045() { public void testCase045() {
String sql = "select * from restful_test.weather where ts < now - 1h order by ts"; String sql = "select * from restful_test.weather where ts < now - 1h order by ts";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase046() { public void testCase046() {
String sql = "select last(*) from restful_test.weather where ts < now - 1h group by tbname order by tbname"; String sql = "select last(*) from restful_test.weather where ts < now - 1h group by tbname order by tbname";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase047() { public void testCase047() {
String sql = "select * from restful_test.weather limit 2"; String sql = "select * from restful_test.weather limit 2";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase048() { public void testCase048() {
String sql = "select * from restful_test.weather limit 2 offset 5"; String sql = "select * from restful_test.weather limit 2 offset 5";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase049() { public void testCase049() {
String sql = "select * from restful_test.t1, restful_test.t3 where t1.ts = t3.ts "; String sql = "select * from restful_test.t1, restful_test.t3 where t1.ts = t3.ts ";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase050() { public void testCase050() {
String sql = "select * from restful_test.t1, restful_test.t3 where t1.ts = t3.ts and t1.location = t3.location"; String sql = "select * from restful_test.t1, restful_test.t3 where t1.ts = t3.ts and t1.location = t3.location";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase051() { public void testCase051() {
String sql = "select * from restful_test.t1 tt, restful_test.t3 yy where tt.ts = yy.ts"; String sql = "select * from restful_test.t1 tt, restful_test.t3 yy where tt.ts = yy.ts";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase052() { public void testCase052() {
String sql = "select server_status()"; String sql = "select server_status()";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
} }
@Test @Test
public void testCase053() { public void testCase053() {
String sql = "select avg(cpu_taosd), avg(cpu_system), max(cpu_cores), avg(mem_taosd), avg(mem_system), max(mem_total), avg(disk_used), max(disk_total), avg(band_speed), avg(io_read), avg(io_write), sum(req_http), sum(req_select), sum(req_insert) from log.dn1 where ts> now - 60m and ts<= now interval(1m) fill(value, 0)"; String sql = "select avg(cpu_taosd), avg(cpu_system), max(cpu_cores), avg(mem_taosd), avg(mem_system), max(mem_total), avg(disk_used), max(disk_total), avg(band_speed), avg(io_read), avg(io_write), sum(req_http), sum(req_select), sum(req_insert) from log.dn1 where ts> now - 60m and ts<= now interval(1m) fill(value, 0)";
SQLExecutor.executeQuery(connection, sql); // when
ResultSet rs = executeQuery(connection, sql);
// then
Assert.assertNotNull(rs);
}
private boolean execute(Connection connection, String sql) {
try (Statement statement = connection.createStatement()) {
return statement.execute(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
private ResultSet executeQuery(Connection connection, String sql) {
try (Statement statement = connection.createStatement()) {
return statement.executeQuery(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
private int executeUpdate(Connection connection, String sql) {
try (Statement statement = connection.createStatement()) {
return statement.executeUpdate(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
} }
@BeforeClass @BeforeClass
public static void before() throws ClassNotFoundException, SQLException { public static void before() throws SQLException {
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=root&password=taosdata"); connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=root&password=taosdata");
} }
......
package com.taosdata.jdbc.utils;
import java.sql.*;
public class SQLExecutor {
// insert, import
public static void executeUpdate(Connection connection, String sql) {
try (Statement statement = connection.createStatement()) {
long start = System.currentTimeMillis();
int affectedRows = statement.executeUpdate(sql);
long end = System.currentTimeMillis();
System.out.println("[ affected rows : " + affectedRows + " ] time cost: " + (end - start) + " ms, execute statement ====> " + sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
// show databases, show tables, show stables
public static void executeWithResult(Connection connection, String sql) {
try (Statement statement = connection.createStatement()) {
statement.execute(sql);
ResultSet resultSet = statement.getResultSet();
printResult(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
}
// use database, create database, create table, drop table...
public static void execute(Connection connection, String sql) {
try (Statement statement = connection.createStatement()) {
long start = System.currentTimeMillis();
boolean execute = statement.execute(sql);
long end = System.currentTimeMillis();
printSql(sql, execute, (end - start));
} catch (SQLException e) {
System.out.println("ERROR execute SQL ===> " + sql);
e.printStackTrace();
}
}
// select
public static void executeQuery(Connection connection, String sql) {
try (Statement statement = connection.createStatement()) {
long start = System.currentTimeMillis();
ResultSet resultSet = statement.executeQuery(sql);
long end = System.currentTimeMillis();
printSql(sql, true, (end - start));
printResult(resultSet);
} catch (SQLException e) {
System.out.println("ERROR execute SQL ===> " + sql);
e.printStackTrace();
}
}
private static void printSql(String sql, boolean succeed, long cost) {
System.out.println("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql);
}
private static void printResult(ResultSet resultSet) throws SQLException {
ResultSetMetaData metaData = resultSet.getMetaData();
while (resultSet.next()) {
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= metaData.getColumnCount(); i++) {
String columnLabel = metaData.getColumnLabel(i);
String value = resultSet.getString(i);
sb.append(columnLabel + ": " + value + "\t");
}
System.out.println(sb.toString());
}
}
}
...@@ -126,30 +126,20 @@ function convertDouble(data, num_of_rows, nbytes = 0, offset = 0, micro = false) ...@@ -126,30 +126,20 @@ function convertDouble(data, num_of_rows, nbytes = 0, offset = 0, micro = false)
} }
return res; return res;
} }
function convertBinary(data, num_of_rows, nbytes = 0, offset = 0, micro = false) {
function convertNchar(data, num_of_rows, nbytes = 0, offset = 0, micro = false) {
data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset);
let res = []; let res = [];
let currOffset = 0; let currOffset = 0;
while (currOffset < data.length) { while (currOffset < data.length) {
let dataEntry = data.slice(currOffset, currOffset + nbytes); let len = data.readIntLE(currOffset, 2);
if (dataEntry[0] == FieldTypes.C_BINARY_NULL) { let dataEntry = data.slice(currOffset + 2, currOffset + len + 2); //one entry in a row under a column;
res.push(null); res.push(dataEntry.toString("utf-8"));
}
else {
res.push(ref.readCString(dataEntry));
}
currOffset += nbytes; currOffset += nbytes;
} }
return res; return res;
} }
function convertNchar(data, num_of_rows, nbytes = 0, offset = 0, micro = false) {
data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset);
let res = [];
let dataEntry = data.slice(0, nbytes); //one entry in a row under a column;
//TODO: should use the correct character encoding
res.push(dataEntry.toString("utf-8"));
return res;
}
// Object with all the relevant converters from pblock data to javascript readable data // Object with all the relevant converters from pblock data to javascript readable data
let convertFunctions = { let convertFunctions = {
...@@ -160,7 +150,7 @@ let convertFunctions = { ...@@ -160,7 +150,7 @@ let convertFunctions = {
[FieldTypes.C_BIGINT]: convertBigint, [FieldTypes.C_BIGINT]: convertBigint,
[FieldTypes.C_FLOAT]: convertFloat, [FieldTypes.C_FLOAT]: convertFloat,
[FieldTypes.C_DOUBLE]: convertDouble, [FieldTypes.C_DOUBLE]: convertDouble,
[FieldTypes.C_BINARY]: convertBinary, [FieldTypes.C_BINARY]: convertNchar,
[FieldTypes.C_TIMESTAMP]: convertTimestamp, [FieldTypes.C_TIMESTAMP]: convertTimestamp,
[FieldTypes.C_NCHAR]: convertNchar [FieldTypes.C_NCHAR]: convertNchar
} }
......
{ {
"name": "td2.0-connector", "name": "td2.0-connector",
"version": "2.0.7", "version": "2.0.8",
"description": "A Node.js connector for TDengine.", "description": "A Node.js connector for TDengine.",
"main": "tdengine.js", "main": "tdengine.js",
"directories": { "directories": {
......
...@@ -31,6 +31,7 @@ void bnReset(); ...@@ -31,6 +31,7 @@ void bnReset();
int32_t bnAllocVnodes(struct SVgObj *pVgroup); int32_t bnAllocVnodes(struct SVgObj *pVgroup);
int32_t bnAlterDnode(struct SDnodeObj *pDnode, int32_t vnodeId, int32_t dnodeId); int32_t bnAlterDnode(struct SDnodeObj *pDnode, int32_t vnodeId, int32_t dnodeId);
int32_t bnDropDnode(struct SDnodeObj *pDnode); int32_t bnDropDnode(struct SDnodeObj *pDnode);
int32_t bnDnodeCanCreateMnode(struct SDnodeObj *pDnode);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -636,6 +636,9 @@ static FILE * g_fpOfInsertResult = NULL; ...@@ -636,6 +636,9 @@ static FILE * g_fpOfInsertResult = NULL;
#define errorPrint(fmt, ...) \ #define errorPrint(fmt, ...) \
do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0) do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)
// for strncpy buffer overflow
#define min(a, b) (((a) < (b)) ? (a) : (b))
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
...@@ -1204,23 +1207,24 @@ static void fetchResult(TAOS_RES *res, threadInfo* pThreadInfo) { ...@@ -1204,23 +1207,24 @@ static void fetchResult(TAOS_RES *res, threadInfo* pThreadInfo) {
return ; return ;
} }
int totalLen = 0; int64_t totalLen = 0;
// fetch the records row by row // fetch the records row by row
while((row = taos_fetch_row(res))) { while((row = taos_fetch_row(res))) {
if ((strlen(pThreadInfo->filePath) > 0) if (totalLen >= 100*1024*1024 - 32000) {
&& (totalLen >= 100*1024*1024 - 32000)) { if (strlen(pThreadInfo->filePath) > 0)
appendResultBufToFile(databuf, pThreadInfo); appendResultBufToFile(databuf, pThreadInfo);
totalLen = 0; totalLen = 0;
memset(databuf, 0, 100*1024*1024); memset(databuf, 0, 100*1024*1024);
} }
num_rows++; num_rows++;
char temp[16000] = {0}; char temp[16000] = {0};
int len = taos_print_row(temp, row, fields, num_fields); int len = taos_print_row(temp, row, fields, num_fields);
len += sprintf(temp + len, "\n"); len += sprintf(temp + len, "\n");
//printf("query result:%s\n", temp); //printf("query result:%s\n", temp);
memcpy(databuf + totalLen, temp, len); memcpy(databuf + totalLen, temp, len);
totalLen += len; totalLen += len;
verbosePrint("%s() LN%d, totalLen: %"PRId64"\n", __func__, __LINE__, totalLen);
} }
verbosePrint("%s() LN%d, databuf=%s resultFile=%s\n", verbosePrint("%s() LN%d, databuf=%s resultFile=%s\n",
...@@ -2573,7 +2577,7 @@ static int getSuperTableFromServer(TAOS * taos, char* dbName, ...@@ -2573,7 +2577,7 @@ static int getSuperTableFromServer(TAOS * taos, char* dbName,
fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes); fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
tstrncpy(superTbls->tags[tagIndex].dataType, tstrncpy(superTbls->tags[tagIndex].dataType,
(char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX], (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes); min(15, fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes));
superTbls->tags[tagIndex].dataLen = superTbls->tags[tagIndex].dataLen =
*((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]); *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
tstrncpy(superTbls->tags[tagIndex].note, tstrncpy(superTbls->tags[tagIndex].note,
...@@ -2586,7 +2590,7 @@ static int getSuperTableFromServer(TAOS * taos, char* dbName, ...@@ -2586,7 +2590,7 @@ static int getSuperTableFromServer(TAOS * taos, char* dbName,
fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes); fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
tstrncpy(superTbls->columns[columnIndex].dataType, tstrncpy(superTbls->columns[columnIndex].dataType,
(char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX], (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes); min(15, fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes));
superTbls->columns[columnIndex].dataLen = superTbls->columns[columnIndex].dataLen =
*((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]); *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
tstrncpy(superTbls->columns[columnIndex].note, tstrncpy(superTbls->columns[columnIndex].note,
...@@ -4407,14 +4411,12 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { ...@@ -4407,14 +4411,12 @@ static bool getMetaFromQueryJsonFile(cJSON* root) {
cJSON* resubAfterConsume = cJSON* resubAfterConsume =
cJSON_GetObjectItem(specifiedQuery, "resubAfterConsume"); cJSON_GetObjectItem(specifiedQuery, "resubAfterConsume");
g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = -1;
if ((resubAfterConsume) if ((resubAfterConsume)
&& (resubAfterConsume->type == cJSON_Number) && (resubAfterConsume->type == cJSON_Number)
&& (resubAfterConsume->valueint >= 0)) { && (resubAfterConsume->valueint >= 0)) {
g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] g_queryInfo.specifiedQueryInfo.resubAfterConsume[j]
= resubAfterConsume->valueint; = resubAfterConsume->valueint;
} else if (!resubAfterConsume) {
// default value is -1, which mean do not resub
g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = -1;
} }
cJSON *result = cJSON_GetObjectItem(sql, "result"); cJSON *result = cJSON_GetObjectItem(sql, "result");
...@@ -4571,14 +4573,12 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { ...@@ -4571,14 +4573,12 @@ static bool getMetaFromQueryJsonFile(cJSON* root) {
cJSON* superResubAfterConsume = cJSON* superResubAfterConsume =
cJSON_GetObjectItem(superQuery, "resubAfterConsume"); cJSON_GetObjectItem(superQuery, "resubAfterConsume");
g_queryInfo.superQueryInfo.resubAfterConsume = -1;
if ((superResubAfterConsume) if ((superResubAfterConsume)
&& (superResubAfterConsume->type == cJSON_Number) && (superResubAfterConsume->type == cJSON_Number)
&& (superResubAfterConsume->valueint >= 0)) { && (superResubAfterConsume->valueint >= 0)) {
g_queryInfo.superQueryInfo.resubAfterConsume = g_queryInfo.superQueryInfo.resubAfterConsume =
superResubAfterConsume->valueint; superResubAfterConsume->valueint;
} else if (!superResubAfterConsume) {
// default value is -1, which mean do not resub
g_queryInfo.superQueryInfo.resubAfterConsume = -1;
} }
// supert table sqls // supert table sqls
...@@ -7221,151 +7221,159 @@ static TAOS_SUB* subscribeImpl( ...@@ -7221,151 +7221,159 @@ static TAOS_SUB* subscribeImpl(
} }
if (tsub == NULL) { if (tsub == NULL) {
printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql); errorPrint("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
return NULL; return NULL;
} }
return tsub; return tsub;
} }
static void *superSubscribe(void *sarg) { static void *superSubscribe(void *sarg) {
threadInfo *pThreadInfo = (threadInfo *)sarg; threadInfo *pThreadInfo = (threadInfo *)sarg;
char subSqlstr[MAX_QUERY_SQL_LENGTH]; char subSqlstr[MAX_QUERY_SQL_LENGTH];
TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT] = {0}; TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT] = {0};
uint64_t tsubSeq; uint64_t tsubSeq;
if (pThreadInfo->ntables > MAX_QUERY_SQL_COUNT) { if (pThreadInfo->ntables > MAX_QUERY_SQL_COUNT) {
errorPrint("The table number(%"PRId64") of the thread is more than max query sql count: %d\n", errorPrint("The table number(%"PRId64") of the thread is more than max query sql count: %d\n",
pThreadInfo->ntables, pThreadInfo->ntables, MAX_QUERY_SQL_COUNT);
MAX_QUERY_SQL_COUNT); exit(-1);
exit(-1); }
}
if (pThreadInfo->taos == NULL) {
pThreadInfo->taos = taos_connect(g_queryInfo.host,
g_queryInfo.user,
g_queryInfo.password,
g_queryInfo.dbName,
g_queryInfo.port);
if (pThreadInfo->taos == NULL) { if (pThreadInfo->taos == NULL) {
errorPrint("[%d] Failed to connect to TDengine, reason:%s\n", pThreadInfo->taos = taos_connect(g_queryInfo.host,
pThreadInfo->threadID, taos_errstr(NULL)); g_queryInfo.user,
return NULL; g_queryInfo.password,
g_queryInfo.dbName,
g_queryInfo.port);
if (pThreadInfo->taos == NULL) {
errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
pThreadInfo->threadID, taos_errstr(NULL));
return NULL;
}
} }
}
char sqlStr[MAX_TB_NAME_SIZE*2]; char sqlStr[MAX_TB_NAME_SIZE*2];
sprintf(sqlStr, "use %s", g_queryInfo.dbName); sprintf(sqlStr, "use %s", g_queryInfo.dbName);
if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) { if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
taos_close(pThreadInfo->taos); taos_close(pThreadInfo->taos);
errorPrint( "use database %s failed!\n\n", errorPrint( "use database %s failed!\n\n",
g_queryInfo.dbName); g_queryInfo.dbName);
return NULL; return NULL;
} }
char topic[32] = {0}; char topic[32] = {0};
for (uint64_t i = pThreadInfo->start_table_from; for (uint64_t i = pThreadInfo->start_table_from;
i <= pThreadInfo->end_table_to; i++) { i <= pThreadInfo->end_table_to; i++) {
tsubSeq = i - pThreadInfo->start_table_from;
verbosePrint("%s() LN%d, [%d], start=%"PRId64" end=%"PRId64" i=%"PRIu64"\n",
__func__, __LINE__,
pThreadInfo->threadID,
pThreadInfo->start_table_from,
pThreadInfo->end_table_to, i);
sprintf(topic, "taosdemo-subscribe-%"PRIu64"-%"PRIu64"",
i, pThreadInfo->querySeq);
memset(subSqlstr, 0, sizeof(subSqlstr));
replaceChildTblName(
g_queryInfo.superQueryInfo.sql[pThreadInfo->querySeq],
subSqlstr, i);
if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
sprintf(pThreadInfo->filePath, "%s-%d",
g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
pThreadInfo->threadID);
}
tsubSeq = i - pThreadInfo->start_table_from; verbosePrint("%s() LN%d, [%d] subSqlstr: %s\n",
verbosePrint("%s() LN%d, [%d], start=%"PRId64" end=%"PRId64" i=%"PRIu64"\n", __func__, __LINE__, pThreadInfo->threadID, subSqlstr);
__func__, __LINE__, tsub[tsubSeq] = subscribeImpl(
pThreadInfo->threadID, STABLE_CLASS,
pThreadInfo->start_table_from, pThreadInfo, subSqlstr, topic,
pThreadInfo->end_table_to, i); g_queryInfo.superQueryInfo.subscribeRestart,
sprintf(topic, "taosdemo-subscribe-%"PRIu64"-%"PRIu64"", g_queryInfo.superQueryInfo.subscribeInterval);
i, pThreadInfo->querySeq); if (NULL == tsub[tsubSeq]) {
memset(subSqlstr, 0, sizeof(subSqlstr)); taos_close(pThreadInfo->taos);
replaceChildTblName( return NULL;
g_queryInfo.superQueryInfo.sql[pThreadInfo->querySeq], }
subSqlstr, i); }
if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
sprintf(pThreadInfo->filePath, "%s-%d",
g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
pThreadInfo->threadID);
}
debugPrint("%s() LN%d, [%d] subSqlstr: %s\n", // start loop to consume result
__func__, __LINE__, pThreadInfo->threadID, subSqlstr); int consumed[MAX_QUERY_SQL_COUNT];
tsub[tsubSeq] = subscribeImpl( for (int i = 0; i < MAX_QUERY_SQL_COUNT; i++) {
STABLE_CLASS, consumed[i] = 0;
pThreadInfo, subSqlstr, topic, }
g_queryInfo.superQueryInfo.subscribeRestart, TAOS_RES* res = NULL;
g_queryInfo.superQueryInfo.subscribeInterval);
if (NULL == tsub[tsubSeq]) {
taos_close(pThreadInfo->taos);
return NULL;
}
}
// start loop to consume result uint64_t st = 0, et = 0;
int consumed[MAX_QUERY_SQL_COUNT];
for (int i = 0; i < MAX_QUERY_SQL_COUNT; i++) {
consumed[i] = 0;
}
TAOS_RES* res = NULL;
uint64_t st = 0, et = 0; while ((g_queryInfo.superQueryInfo.endAfterConsume == -1)
|| (g_queryInfo.superQueryInfo.endAfterConsume >
consumed[pThreadInfo->end_table_to
- pThreadInfo->start_table_from])) {
while ((g_queryInfo.superQueryInfo.endAfterConsume == -1) verbosePrint("super endAfterConsume: %d, consumed: %d\n",
|| (g_queryInfo.superQueryInfo.endAfterConsume < g_queryInfo.superQueryInfo.endAfterConsume,
consumed[pThreadInfo->end_table_to - pThreadInfo->start_table_from])) { consumed[pThreadInfo->end_table_to
- pThreadInfo->start_table_from]);
for (uint64_t i = pThreadInfo->start_table_from;
i <= pThreadInfo->end_table_to; i++) {
tsubSeq = i - pThreadInfo->start_table_from;
if (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode) {
continue;
}
st = taosGetTimestampMs();
performancePrint("st: %"PRIu64" et: %"PRIu64" st-et: %"PRIu64"\n", st, et, (st - et));
res = taos_consume(tsub[tsubSeq]);
et = taosGetTimestampMs();
performancePrint("st: %"PRIu64" et: %"PRIu64" delta: %"PRIu64"\n", st, et, (et - st));
if (res) {
if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
sprintf(pThreadInfo->filePath, "%s-%d",
g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
pThreadInfo->threadID);
fetchResult(res, pThreadInfo);
}
consumed[tsubSeq] ++;
if ((g_queryInfo.superQueryInfo.resubAfterConsume != -1)
&& (consumed[tsubSeq] >=
g_queryInfo.superQueryInfo.resubAfterConsume)) {
verbosePrint("%s() LN%d, keepProgress:%d, resub super table query: %"PRIu64"\n",
__func__, __LINE__,
g_queryInfo.superQueryInfo.subscribeKeepProgress,
pThreadInfo->querySeq);
taos_unsubscribe(tsub[tsubSeq],
g_queryInfo.superQueryInfo.subscribeKeepProgress);
consumed[tsubSeq]= 0;
tsub[tsubSeq] = subscribeImpl(
STABLE_CLASS,
pThreadInfo, subSqlstr, topic,
g_queryInfo.superQueryInfo.subscribeRestart,
g_queryInfo.superQueryInfo.subscribeInterval
);
if (NULL == tsub[tsubSeq]) {
taos_close(pThreadInfo->taos);
return NULL;
}
}
}
}
}
verbosePrint("%s() LN%d, super endAfterConsume: %d, consumed: %d\n",
__func__, __LINE__,
g_queryInfo.superQueryInfo.endAfterConsume,
consumed[pThreadInfo->end_table_to - pThreadInfo->start_table_from]);
taos_free_result(res);
for (uint64_t i = pThreadInfo->start_table_from; for (uint64_t i = pThreadInfo->start_table_from;
i <= pThreadInfo->end_table_to; i++) { i <= pThreadInfo->end_table_to; i++) {
tsubSeq = i - pThreadInfo->start_table_from; tsubSeq = i - pThreadInfo->start_table_from;
if (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode) { taos_unsubscribe(tsub[tsubSeq], 0);
continue;
}
st = taosGetTimestampMs();
performancePrint("st: %"PRIu64" et: %"PRIu64" st-et: %"PRIu64"\n", st, et, (st - et));
res = taos_consume(tsub[tsubSeq]);
et = taosGetTimestampMs();
performancePrint("st: %"PRIu64" et: %"PRIu64" delta: %"PRIu64"\n", st, et, (et - st));
if (res) {
if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
sprintf(pThreadInfo->filePath, "%s-%d",
g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
pThreadInfo->threadID);
fetchResult(res, pThreadInfo);
}
consumed[tsubSeq] ++;
if ((g_queryInfo.superQueryInfo.resubAfterConsume != -1)
&& (consumed[tsubSeq] >=
g_queryInfo.superQueryInfo.resubAfterConsume)) {
printf("keepProgress:%d, resub super table query: %"PRIu64"\n",
g_queryInfo.superQueryInfo.subscribeKeepProgress,
pThreadInfo->querySeq);
taos_unsubscribe(tsub[tsubSeq],
g_queryInfo.superQueryInfo.subscribeKeepProgress);
consumed[tsubSeq]= 0;
tsub[tsubSeq] = subscribeImpl(
STABLE_CLASS,
pThreadInfo, subSqlstr, topic,
g_queryInfo.superQueryInfo.subscribeRestart,
g_queryInfo.superQueryInfo.subscribeInterval
);
if (NULL == tsub[tsubSeq]) {
taos_close(pThreadInfo->taos);
return NULL;
}
}
}
} }
}
taos_free_result(res);
for (uint64_t i = pThreadInfo->start_table_from; taos_close(pThreadInfo->taos);
i <= pThreadInfo->end_table_to; i++) { return NULL;
tsubSeq = i - pThreadInfo->start_table_from;
taos_unsubscribe(tsub[tsubSeq], 0);
}
taos_close(pThreadInfo->taos);
return NULL;
} }
static void *specifiedSubscribe(void *sarg) { static void *specifiedSubscribe(void *sarg) {
...@@ -7419,8 +7427,13 @@ static void *specifiedSubscribe(void *sarg) { ...@@ -7419,8 +7427,13 @@ static void *specifiedSubscribe(void *sarg) {
|| (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] < || (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] <
g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq])) { g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq])) {
printf("consumed[%d]: %d, endAfterConsum[%"PRId64"]: %d\n",
pThreadInfo->threadID,
g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID],
pThreadInfo->querySeq,
g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq]);
if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) { if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
continue; continue;
} }
g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID] = taos_consume( g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID] = taos_consume(
...@@ -7462,7 +7475,6 @@ static void *specifiedSubscribe(void *sarg) { ...@@ -7462,7 +7475,6 @@ static void *specifiedSubscribe(void *sarg) {
} }
} }
taos_free_result(g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]); taos_free_result(g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]);
taos_unsubscribe(g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->querySeq], 0);
taos_close(pThreadInfo->taos); taos_close(pThreadInfo->taos);
return NULL; return NULL;
......
...@@ -1126,7 +1126,7 @@ int taosGetTableDes( ...@@ -1126,7 +1126,7 @@ int taosGetTableDes(
strncpy(tableDes->cols[count].field, (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX], strncpy(tableDes->cols[count].field, (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes); fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
strncpy(tableDes->cols[count].type, (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX], strncpy(tableDes->cols[count].type, (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
min(16, fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes)); min(15, fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes));
tableDes->cols[count].length = *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]); tableDes->cols[count].length = *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
strncpy(tableDes->cols[count].note, (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], strncpy(tableDes->cols[count].note, (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes); fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#define _DEFAULT_SOURCE #define _DEFAULT_SOURCE
#include "os.h" #include "os.h"
#include "tgrant.h" #include "tgrant.h"
#include "tbn.h"
#include "tglobal.h" #include "tglobal.h"
#include "tconfig.h" #include "tconfig.h"
#include "tutil.h" #include "tutil.h"
...@@ -632,7 +631,8 @@ static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) { ...@@ -632,7 +631,8 @@ static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) {
} }
int32_t numOfMnodes = mnodeGetMnodesNum(); int32_t numOfMnodes = mnodeGetMnodesNum();
if (numOfMnodes < tsNumOfMnodes && numOfMnodes < mnodeGetOnlineDnodesNum() && !pDnode->isMgmt) { if (numOfMnodes < tsNumOfMnodes && numOfMnodes < mnodeGetOnlineDnodesNum()
&& bnDnodeCanCreateMnode(pDnode)) {
bnNotify(); bnNotify();
} }
......
...@@ -1068,7 +1068,7 @@ static int32_t mnodeProcessCreateSuperTableMsg(SMnodeMsg *pMsg) { ...@@ -1068,7 +1068,7 @@ static int32_t mnodeProcessCreateSuperTableMsg(SMnodeMsg *pMsg) {
pStable->info.tableId = strdup(pCreate->tableName); pStable->info.tableId = strdup(pCreate->tableName);
pStable->info.type = TSDB_SUPER_TABLE; pStable->info.type = TSDB_SUPER_TABLE;
pStable->createdTime = taosGetTimestampMs(); pStable->createdTime = taosGetTimestampMs();
int64_t x = (us&0x000000FFFFFFFFFF); uint64_t x = (us&0x000000FFFFFFFFFF);
x = x<<24; x = x<<24;
pStable->uid = x + ((sdbGetVersion() & ((1ul << 16) - 1ul)) << 8) + (taosRand() & ((1ul << 8) - 1ul)); pStable->uid = x + ((sdbGetVersion() & ((1ul << 16) - 1ul)) << 8) + (taosRand() & ((1ul << 8) - 1ul));
pStable->sversion = 0; pStable->sversion = 0;
...@@ -2075,7 +2075,9 @@ static int32_t mnodeDoCreateChildTable(SMnodeMsg *pMsg, int32_t tid) { ...@@ -2075,7 +2075,9 @@ static int32_t mnodeDoCreateChildTable(SMnodeMsg *pMsg, int32_t tid) {
} else { } else {
if (pTable->info.type == TSDB_SUPER_TABLE) { if (pTable->info.type == TSDB_SUPER_TABLE) {
int64_t us = taosGetTimestampUs(); int64_t us = taosGetTimestampUs();
pTable->uid = (us << 24) + ((sdbGetVersion() & ((1ul << 16) - 1ul)) << 8) + (taosRand() & ((1ul << 8) - 1ul)); uint64_t x = (us&0x000000FFFFFFFFFF);
x = x<<24;
pTable->uid = x + ((sdbGetVersion() & ((1ul << 16) - 1ul)) << 8) + (taosRand() & ((1ul << 8) - 1ul));
} else { } else {
pTable->uid = (((uint64_t)pTable->vgId) << 48) + ((((uint64_t)pTable->tid) & ((1ul << 24) - 1ul)) << 24) + pTable->uid = (((uint64_t)pTable->vgId) << 48) + ((((uint64_t)pTable->tid) & ((1ul << 24) - 1ul)) << 24) +
((sdbGetVersion() & ((1ul << 16) - 1ul)) << 8) + (taosRand() & ((1ul << 8) - 1ul)); ((sdbGetVersion() & ((1ul << 16) - 1ul)) << 8) + (taosRand() & ((1ul << 8) - 1ul));
......
...@@ -29,7 +29,7 @@ extern "C" { ...@@ -29,7 +29,7 @@ extern "C" {
#include "osMath.h" #include "osMath.h"
#include "osMemory.h" #include "osMemory.h"
#include "osRand.h" #include "osRand.h"
#include "osSemphone.h" #include "osSemaphore.h"
#include "osSignal.h" #include "osSignal.h"
#include "osSleep.h" #include "osSleep.h"
#include "osSocket.h" #include "osSocket.h"
......
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef TDENGINE_OS_SEMPHONE_H #ifndef TDENGINE_OS_SEMAPHORE_H
#define TDENGINE_OS_SEMPHONE_H #define TDENGINE_OS_SEMAPHORE_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
......
...@@ -228,13 +228,11 @@ bool gcBuildQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, ...@@ -228,13 +228,11 @@ bool gcBuildQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result,
case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_NCHAR:
httpJsonStringForTransMean(jsonBuf, (char *)row[i], fields[i].bytes); httpJsonStringForTransMean(jsonBuf, (char *)row[i], fields[i].bytes);
break; break;
case TSDB_DATA_TYPE_TIMESTAMP: case TSDB_DATA_TYPE_TIMESTAMP: {
if (precision == TSDB_TIME_PRECISION_MILLI) { // ms int64_t ts = convertTimePrecision(*((int64_t *)row[i]), precision, TSDB_TIME_PRECISION_MILLI);
httpJsonInt64(jsonBuf, *((int64_t *)row[i])); httpJsonInt64(jsonBuf, ts);
} else {
httpJsonInt64(jsonBuf, *((int64_t *)row[i]) / 1000);
}
break; break;
}
default: default:
httpJsonString(jsonBuf, "-", 1); httpJsonString(jsonBuf, "-", 1);
break; break;
......
...@@ -133,6 +133,28 @@ typedef struct STableQueryInfo { ...@@ -133,6 +133,28 @@ typedef struct STableQueryInfo {
SResultRowInfo resInfo; SResultRowInfo resInfo;
} STableQueryInfo; } STableQueryInfo;
typedef enum {
QUERY_PROF_BEFORE_OPERATOR_EXEC = 0,
QUERY_PROF_AFTER_OPERATOR_EXEC,
QUERY_PROF_QUERY_ABORT
} EQueryProfEventType;
typedef struct {
EQueryProfEventType eventType;
int64_t eventTime;
union {
uint8_t operatorType; //for operator event
int32_t abortCode; //for query abort event
};
} SQueryProfEvent;
typedef struct {
uint8_t operatorType;
int64_t sumSelfTime;
int64_t sumRunTimes;
} SOperatorProfResult;
typedef struct SQueryCostInfo { typedef struct SQueryCostInfo {
uint64_t loadStatisTime; uint64_t loadStatisTime;
uint64_t loadFileBlockTime; uint64_t loadFileBlockTime;
...@@ -154,6 +176,9 @@ typedef struct SQueryCostInfo { ...@@ -154,6 +176,9 @@ typedef struct SQueryCostInfo {
uint64_t tableInfoSize; uint64_t tableInfoSize;
uint64_t hashSize; uint64_t hashSize;
uint64_t numOfTimeWindows; uint64_t numOfTimeWindows;
SArray* queryProfEvents; //SArray<SQueryProfEvent>
SHashObj* operatorProfResults; //map<operator_type, SQueryProfEvent>
} SQueryCostInfo; } SQueryCostInfo;
typedef struct { typedef struct {
...@@ -192,6 +217,7 @@ typedef struct SQueryAttr { ...@@ -192,6 +217,7 @@ typedef struct SQueryAttr {
bool needReverseScan; // need reverse scan bool needReverseScan; // need reverse scan
bool distinctTag; // distinct tag query bool distinctTag; // distinct tag query
bool stateWindow; // window State on sub/normal table bool stateWindow; // window State on sub/normal table
bool createFilterOperator; // if filter operator is needed
int32_t interBufSize; // intermediate buffer sizse int32_t interBufSize; // intermediate buffer sizse
int32_t havingNum; // having expr number int32_t havingNum; // having expr number
...@@ -586,7 +612,12 @@ int32_t doDumpQueryResult(SQInfo *pQInfo, char *data); ...@@ -586,7 +612,12 @@ int32_t doDumpQueryResult(SQInfo *pQInfo, char *data);
size_t getResultSize(SQInfo *pQInfo, int64_t *numOfRows); size_t getResultSize(SQInfo *pQInfo, int64_t *numOfRows);
void setQueryKilled(SQInfo *pQInfo); void setQueryKilled(SQInfo *pQInfo);
void publishOperatorProfEvent(SOperatorInfo* operatorInfo, EQueryProfEventType eventType);
void publishQueryAbortEvent(SQInfo* pQInfo, int32_t code);
void calculateOperatorProfResults(SQInfo* pQInfo);
void queryCostStatis(SQInfo *pQInfo); void queryCostStatis(SQInfo *pQInfo);
void freeQInfo(SQInfo *pQInfo); void freeQInfo(SQInfo *pQInfo);
void freeQueryAttr(SQueryAttr *pQuery); void freeQueryAttr(SQueryAttr *pQuery);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "qFill.h" #include "qFill.h"
#include "taosmsg.h" #include "taosmsg.h"
#include "tglobal.h" #include "tglobal.h"
#include "talgo.h"
#include "exception.h" #include "exception.h"
#include "hash.h" #include "hash.h"
...@@ -26,6 +27,7 @@ ...@@ -26,6 +27,7 @@
#include "queryLog.h" #include "queryLog.h"
#include "tlosertree.h" #include "tlosertree.h"
#include "ttype.h" #include "ttype.h"
#include "tcompare.h"
#include "tscompression.h" #include "tscompression.h"
#define IS_MASTER_SCAN(runtime) ((runtime)->scanFlag == MASTER_SCAN) #define IS_MASTER_SCAN(runtime) ((runtime)->scanFlag == MASTER_SCAN)
...@@ -207,7 +209,66 @@ static void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowIn ...@@ -207,7 +209,66 @@ static void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowIn
SQLFunctionCtx* pCtx, int32_t* rowCellInfoOffset, int32_t numOfOutput, SQLFunctionCtx* pCtx, int32_t* rowCellInfoOffset, int32_t numOfOutput,
int32_t groupIndex); int32_t groupIndex);
// setup the output buffer for each operator SArray* getOrderCheckColumns(SQueryAttr* pQuery);
typedef struct SRowCompSupporter {
SQueryRuntimeEnv *pRuntimeEnv;
int16_t dataOffset;
__compar_fn_t comFunc;
} SRowCompSupporter;
static int compareRowData(const void *a, const void *b, const void *userData) {
const SResultRow *pRow1 = (const SResultRow *)a;
const SResultRow *pRow2 = (const SResultRow *)b;
SRowCompSupporter *supporter = (SRowCompSupporter *)userData;
SQueryRuntimeEnv* pRuntimeEnv = supporter->pRuntimeEnv;
tFilePage *page1 = getResBufPage(pRuntimeEnv->pResultBuf, pRow1->pageId);
tFilePage *page2 = getResBufPage(pRuntimeEnv->pResultBuf, pRow2->pageId);
int16_t offset = supporter->dataOffset;
char *in1 = getPosInResultPage(pRuntimeEnv->pQueryAttr, page1, pRow1->offset, offset);
char *in2 = getPosInResultPage(pRuntimeEnv->pQueryAttr, page2, pRow2->offset, offset);
return (in1 != NULL && in2 != NULL) ? supporter->comFunc(in1, in2) : 0;
}
static void sortGroupResByOrderList(SGroupResInfo *pGroupResInfo, SQueryRuntimeEnv *pRuntimeEnv, SSDataBlock* pDataBlock) {
SArray *columnOrderList = getOrderCheckColumns(pRuntimeEnv->pQueryAttr);
if (taosArrayGetSize(columnOrderList) <= 0) {
return;
}
int32_t orderId = pRuntimeEnv->pQueryAttr->order.orderColId;
if (orderId <= 0) {
return;
}
bool found = false;
int16_t dataOffset = 0;
//SColIndex *index = taosArrayGet(columnOrderList, 0);
for (int32_t j = 0; j < pDataBlock->info.numOfCols; ++j) {
SColumnInfoData* pColInfoData = (SColumnInfoData *)taosArrayGet(pDataBlock->pDataBlock, j);
if (orderId == j) {
found = true;
break;
}
dataOffset += pColInfoData->info.bytes;
}
if (found == false) {
return;
}
int16_t type = pRuntimeEnv->pQueryAttr->pExpr1[orderId].base.resType;
SRowCompSupporter support = {.pRuntimeEnv = pRuntimeEnv, .dataOffset = dataOffset, .comFunc = getComparFunc(type, 0)};
taosArraySortPWithExt(pGroupResInfo->pRows, compareRowData, &support);
return;
}
//setup the output buffer for each operator
SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numOfRows) { SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numOfRows) {
const static int32_t minSize = 8; const static int32_t minSize = 8;
...@@ -3785,6 +3846,103 @@ int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutp ...@@ -3785,6 +3846,103 @@ int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutp
return pOutput->info.rows; return pOutput->info.rows;
} }
void publishOperatorProfEvent(SOperatorInfo* operatorInfo, EQueryProfEventType eventType) {
SQueryProfEvent event;
event.eventType = eventType;
event.eventTime = taosGetTimestampUs();
event.operatorType = operatorInfo->operatorType;
SQInfo* qInfo = operatorInfo->pRuntimeEnv->qinfo;
if (qInfo->summary.queryProfEvents) {
taosArrayPush(qInfo->summary.queryProfEvents, &event);
}
}
void publishQueryAbortEvent(SQInfo* pQInfo, int32_t code) {
SQueryProfEvent event;
event.eventType = QUERY_PROF_QUERY_ABORT;
event.eventTime = taosGetTimestampUs();
event.abortCode = code;
if (pQInfo->summary.queryProfEvents) {
taosArrayPush(pQInfo->summary.queryProfEvents, &event);
}
}
typedef struct {
uint8_t operatorType;
int64_t beginTime;
int64_t endTime;
int64_t selfTime;
int64_t descendantsTime;
} SOperatorStackItem;
static void doOperatorExecProfOnce(SOperatorStackItem* item, SQueryProfEvent* event, SArray* opStack, SHashObj* profResults) {
item->endTime = event->eventTime;
item->selfTime = (item->endTime - item->beginTime) - (item->descendantsTime);
for (int32_t j = 0; j < taosArrayGetSize(opStack); ++j) {
SOperatorStackItem* ancestor = taosArrayGet(opStack, j);
ancestor->descendantsTime += item->selfTime;
}
uint8_t operatorType = item->operatorType;
SOperatorProfResult* result = taosHashGet(profResults, &operatorType, sizeof(operatorType));
if (result != NULL) {
result->sumRunTimes++;
result->sumSelfTime += item->selfTime;
} else {
SOperatorProfResult opResult;
opResult.operatorType = operatorType;
opResult.sumSelfTime = item->selfTime;
opResult.sumRunTimes = 1;
taosHashPut(profResults, &(operatorType), sizeof(operatorType),
&opResult, sizeof(opResult));
}
}
void calculateOperatorProfResults(SQInfo* pQInfo) {
if (pQInfo->summary.queryProfEvents == NULL) {
qDebug("QInfo:0x%"PRIx64" query prof events array is null", pQInfo->qId);
return;
}
if (pQInfo->summary.operatorProfResults == NULL) {
qDebug("QInfo:0x%"PRIx64" operator prof results hash is null", pQInfo->qId);
return;
}
SArray* opStack = taosArrayInit(32, sizeof(SOperatorStackItem));
if (opStack == NULL) {
return;
}
size_t size = taosArrayGetSize(pQInfo->summary.queryProfEvents);
SHashObj* profResults = pQInfo->summary.operatorProfResults;
for (int i = 0; i < size; ++i) {
SQueryProfEvent* event = taosArrayGet(pQInfo->summary.queryProfEvents, i);
if (event->eventType == QUERY_PROF_BEFORE_OPERATOR_EXEC) {
SOperatorStackItem opItem;
opItem.operatorType = event->operatorType;
opItem.beginTime = event->eventTime;
opItem.descendantsTime = 0;
taosArrayPush(opStack, &opItem);
} else if (event->eventType == QUERY_PROF_AFTER_OPERATOR_EXEC) {
SOperatorStackItem* item = taosArrayPop(opStack);
assert(item->operatorType == event->operatorType);
doOperatorExecProfOnce(item, event, opStack, profResults);
} else if (event->eventType == QUERY_PROF_QUERY_ABORT) {
SOperatorStackItem* item;
while ((item = taosArrayPop(opStack)) != NULL) {
doOperatorExecProfOnce(item, event, opStack, profResults);
}
}
}
taosArrayDestroy(opStack);
}
void queryCostStatis(SQInfo *pQInfo) { void queryCostStatis(SQInfo *pQInfo) {
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
SQueryCostInfo *pSummary = &pQInfo->summary; SQueryCostInfo *pSummary = &pQInfo->summary;
...@@ -3805,6 +3963,8 @@ void queryCostStatis(SQInfo *pQInfo) { ...@@ -3805,6 +3963,8 @@ void queryCostStatis(SQInfo *pQInfo) {
pSummary->numOfTimeWindows = 0; pSummary->numOfTimeWindows = 0;
} }
calculateOperatorProfResults(pQInfo);
qDebug("QInfo:0x%"PRIx64" :cost summary: elapsed time:%"PRId64" us, first merge:%"PRId64" us, total blocks:%d, " qDebug("QInfo:0x%"PRIx64" :cost summary: elapsed time:%"PRId64" us, first merge:%"PRId64" us, total blocks:%d, "
"load block statis:%d, load data block:%d, total rows:%"PRId64 ", check rows:%"PRId64, "load block statis:%d, load data block:%d, total rows:%"PRId64 ", check rows:%"PRId64,
pQInfo->qId, pSummary->elapsedTime, pSummary->firstStageMergeTime, pSummary->totalBlocks, pSummary->loadBlockStatis, pQInfo->qId, pSummary->elapsedTime, pSummary->firstStageMergeTime, pSummary->totalBlocks, pSummary->loadBlockStatis,
...@@ -3812,6 +3972,15 @@ void queryCostStatis(SQInfo *pQInfo) { ...@@ -3812,6 +3972,15 @@ void queryCostStatis(SQInfo *pQInfo) {
qDebug("QInfo:0x%"PRIx64" :cost summary: winResPool size:%.2f Kb, numOfWin:%"PRId64", tableInfoSize:%.2f Kb, hashTable:%.2f Kb", pQInfo->qId, pSummary->winInfoSize/1024.0, qDebug("QInfo:0x%"PRIx64" :cost summary: winResPool size:%.2f Kb, numOfWin:%"PRId64", tableInfoSize:%.2f Kb, hashTable:%.2f Kb", pQInfo->qId, pSummary->winInfoSize/1024.0,
pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0); pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0);
if (pSummary->operatorProfResults) {
SOperatorProfResult* opRes = taosHashIterate(pSummary->operatorProfResults, NULL);
while (opRes != NULL) {
qDebug("QInfo:0x%" PRIx64 " :cost summary: operator : %d, exec times: %" PRId64 ", self time: %" PRId64,
pQInfo->qId, opRes->operatorType, opRes->sumRunTimes, opRes->sumSelfTime);
opRes = taosHashIterate(pSummary->operatorProfResults, opRes);
}
}
} }
//static void updateOffsetVal(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBlockInfo) { //static void updateOffsetVal(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBlockInfo) {
...@@ -4213,6 +4382,15 @@ int32_t doInitQInfo(SQInfo* pQInfo, STSBuf* pTsBuf, void* tsdb, void* sourceOptr ...@@ -4213,6 +4382,15 @@ int32_t doInitQInfo(SQInfo* pQInfo, STSBuf* pTsBuf, void* tsdb, void* sourceOptr
// create runtime environment // create runtime environment
int32_t numOfTables = (int32_t)pQueryAttr->tableGroupInfo.numOfTables; int32_t numOfTables = (int32_t)pQueryAttr->tableGroupInfo.numOfTables;
pQInfo->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo)); pQInfo->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo));
pQInfo->summary.queryProfEvents = taosArrayInit(512, sizeof(SQueryProfEvent));
if (pQInfo->summary.queryProfEvents == NULL) {
qDebug("QInfo:0x%"PRIx64" failed to allocate query prof events array", pQInfo->qId);
}
pQInfo->summary.operatorProfResults =
taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_TINYINT), true, HASH_NO_LOCK);
if (pQInfo->summary.operatorProfResults == NULL) {
qDebug("QInfo:0x%"PRIx64" failed to allocate operator prof results hash", pQInfo->qId);
}
code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQueryAttr->tableGroupInfo.numOfTables, pOperator, param); code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQueryAttr->tableGroupInfo.numOfTables, pOperator, param);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
...@@ -4837,7 +5015,10 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) { ...@@ -4837,7 +5015,10 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) {
SOperatorInfo* upstream = pOperator->upstream[0]; SOperatorInfo* upstream = pOperator->upstream[0];
while(1) { while(1) {
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
SSDataBlock* pBlock = upstream->exec(upstream, newgroup); SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
break; break;
} }
...@@ -4892,7 +5073,10 @@ static SSDataBlock* doSTableAggregate(void* param, bool* newgroup) { ...@@ -4892,7 +5073,10 @@ static SSDataBlock* doSTableAggregate(void* param, bool* newgroup) {
SOperatorInfo* upstream = pOperator->upstream[0]; SOperatorInfo* upstream = pOperator->upstream[0];
while(1) { while(1) {
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
SSDataBlock* pBlock = upstream->exec(upstream, newgroup); SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
break; break;
} }
...@@ -4972,7 +5156,10 @@ static SSDataBlock* doProjectOperation(void* param, bool* newgroup) { ...@@ -4972,7 +5156,10 @@ static SSDataBlock* doProjectOperation(void* param, bool* newgroup) {
bool prevVal = *newgroup; bool prevVal = *newgroup;
// The upstream exec may change the value of the newgroup, so use a local variable instead. // The upstream exec may change the value of the newgroup, so use a local variable instead.
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
SSDataBlock* pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); SSDataBlock* pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
assert(*newgroup == false); assert(*newgroup == false);
...@@ -5032,7 +5219,10 @@ static SSDataBlock* doLimit(void* param, bool* newgroup) { ...@@ -5032,7 +5219,10 @@ static SSDataBlock* doLimit(void* param, bool* newgroup) {
SSDataBlock* pBlock = NULL; SSDataBlock* pBlock = NULL;
while (1) { while (1) {
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
pOperator->status = OP_EXEC_DONE; pOperator->status = OP_EXEC_DONE;
...@@ -5082,7 +5272,10 @@ static SSDataBlock* doFilter(void* param, bool* newgroup) { ...@@ -5082,7 +5272,10 @@ static SSDataBlock* doFilter(void* param, bool* newgroup) {
SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
while (1) { while (1) {
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
SSDataBlock *pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); SSDataBlock *pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
break; break;
} }
...@@ -5127,7 +5320,10 @@ static SSDataBlock* doIntervalAgg(void* param, bool* newgroup) { ...@@ -5127,7 +5320,10 @@ static SSDataBlock* doIntervalAgg(void* param, bool* newgroup) {
SOperatorInfo* upstream = pOperator->upstream[0]; SOperatorInfo* upstream = pOperator->upstream[0];
while(1) { while(1) {
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
SSDataBlock* pBlock = upstream->exec(upstream, newgroup); SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
break; break;
} }
...@@ -5180,7 +5376,10 @@ static SSDataBlock* doSTableIntervalAgg(void* param, bool* newgroup) { ...@@ -5180,7 +5376,10 @@ static SSDataBlock* doSTableIntervalAgg(void* param, bool* newgroup) {
SOperatorInfo* upstream = pOperator->upstream[0]; SOperatorInfo* upstream = pOperator->upstream[0];
while(1) { while(1) {
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
SSDataBlock* pBlock = upstream->exec(upstream, newgroup); SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
break; break;
} }
...@@ -5308,7 +5507,10 @@ static SSDataBlock* doStateWindowAgg(void *param, bool* newgroup) { ...@@ -5308,7 +5507,10 @@ static SSDataBlock* doStateWindowAgg(void *param, bool* newgroup) {
STimeWindow win = pQueryAttr->window; STimeWindow win = pQueryAttr->window;
SOperatorInfo* upstream = pOperator->upstream[0]; SOperatorInfo* upstream = pOperator->upstream[0];
while (1) { while (1) {
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
SSDataBlock* pBlock = upstream->exec(upstream, newgroup); SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
break; break;
} }
...@@ -5366,7 +5568,9 @@ static SSDataBlock* doSessionWindowAgg(void* param, bool* newgroup) { ...@@ -5366,7 +5568,9 @@ static SSDataBlock* doSessionWindowAgg(void* param, bool* newgroup) {
SOperatorInfo* upstream = pOperator->upstream[0]; SOperatorInfo* upstream = pOperator->upstream[0];
while(1) { while(1) {
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
SSDataBlock* pBlock = upstream->exec(upstream, newgroup); SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
break; break;
} }
...@@ -5417,7 +5621,9 @@ static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) { ...@@ -5417,7 +5621,9 @@ static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) {
SOperatorInfo* upstream = pOperator->upstream[0]; SOperatorInfo* upstream = pOperator->upstream[0];
while(1) { while(1) {
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
SSDataBlock* pBlock = upstream->exec(upstream, newgroup); SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
break; break;
} }
...@@ -5443,8 +5649,11 @@ static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) { ...@@ -5443,8 +5649,11 @@ static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) {
} }
initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo); initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo);
if (!pRuntimeEnv->pQueryAttr->stableQuery) {
sortGroupResByOrderList(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
}
toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes); toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
if (pInfo->binfo.pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { if (pInfo->binfo.pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
pOperator->status = OP_EXEC_DONE; pOperator->status = OP_EXEC_DONE;
} }
...@@ -5483,7 +5692,10 @@ static SSDataBlock* doFill(void* param, bool* newgroup) { ...@@ -5483,7 +5692,10 @@ static SSDataBlock* doFill(void* param, bool* newgroup) {
} }
while(1) { while(1) {
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
SSDataBlock* pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); SSDataBlock* pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (*newgroup) { if (*newgroup) {
assert(pBlock != NULL); assert(pBlock != NULL);
} }
...@@ -6153,7 +6365,10 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) { ...@@ -6153,7 +6365,10 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
pRes->info.rows = 0; pRes->info.rows = 0;
SSDataBlock* pBlock = NULL; SSDataBlock* pBlock = NULL;
while(1) { while(1) {
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
pOperator->status = OP_EXEC_DONE; pOperator->status = OP_EXEC_DONE;
...@@ -7039,6 +7254,8 @@ int32_t createFilterInfo(SQueryAttr* pQueryAttr, uint64_t qId) { ...@@ -7039,6 +7254,8 @@ int32_t createFilterInfo(SQueryAttr* pQueryAttr, uint64_t qId) {
doCreateFilterInfo(pQueryAttr->tableCols, pQueryAttr->numOfCols, pQueryAttr->numOfFilterCols, doCreateFilterInfo(pQueryAttr->tableCols, pQueryAttr->numOfCols, pQueryAttr->numOfFilterCols,
&pQueryAttr->pFilterInfo, qId); &pQueryAttr->pFilterInfo, qId);
pQueryAttr->createFilterOperator = true;
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
...@@ -7477,6 +7694,9 @@ void freeQInfo(SQInfo *pQInfo) { ...@@ -7477,6 +7694,9 @@ void freeQInfo(SQInfo *pQInfo) {
tfree(pQInfo->pBuf); tfree(pQInfo->pBuf);
tfree(pQInfo->sql); tfree(pQInfo->sql);
taosArrayDestroy(pQInfo->summary.queryProfEvents);
taosHashCleanup(pQInfo->summary.operatorProfResults);
taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows); taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows);
pQInfo->signature = 0; pQInfo->signature = 0;
......
...@@ -623,7 +623,7 @@ SArray* createExecOperatorPlan(SQueryAttr* pQueryAttr) { ...@@ -623,7 +623,7 @@ SArray* createExecOperatorPlan(SQueryAttr* pQueryAttr) {
taosArrayPush(plan, &op); taosArrayPush(plan, &op);
} }
} else { // diff/add/multiply/subtract/division } else { // diff/add/multiply/subtract/division
if (pQueryAttr->numOfFilterCols > 0 && pQueryAttr->vgId == 0) { // todo refactor if (pQueryAttr->numOfFilterCols > 0 && pQueryAttr->createFilterOperator && pQueryAttr->vgId == 0) { // todo refactor
op = OP_Filter; op = OP_Filter;
taosArrayPush(plan, &op); taosArrayPush(plan, &op);
} else { } else {
......
...@@ -232,6 +232,7 @@ bool qTableQuery(qinfo_t qinfo, uint64_t *qId) { ...@@ -232,6 +232,7 @@ bool qTableQuery(qinfo_t qinfo, uint64_t *qId) {
// error occurs, record the error code and return to client // error occurs, record the error code and return to client
int32_t ret = setjmp(pQInfo->runtimeEnv.env); int32_t ret = setjmp(pQInfo->runtimeEnv.env);
if (ret != TSDB_CODE_SUCCESS) { if (ret != TSDB_CODE_SUCCESS) {
publishQueryAbortEvent(pQInfo, ret);
pQInfo->code = ret; pQInfo->code = ret;
qDebug("QInfo:0x%"PRIx64" query abort due to error/cancel occurs, code:%s", pQInfo->qId, tstrerror(pQInfo->code)); qDebug("QInfo:0x%"PRIx64" query abort due to error/cancel occurs, code:%s", pQInfo->qId, tstrerror(pQInfo->code));
return doBuildResCheck(pQInfo); return doBuildResCheck(pQInfo);
...@@ -240,7 +241,9 @@ bool qTableQuery(qinfo_t qinfo, uint64_t *qId) { ...@@ -240,7 +241,9 @@ bool qTableQuery(qinfo_t qinfo, uint64_t *qId) {
qDebug("QInfo:0x%"PRIx64" query task is launched", pQInfo->qId); qDebug("QInfo:0x%"PRIx64" query task is launched", pQInfo->qId);
bool newgroup = false; bool newgroup = false;
publishOperatorProfEvent(pRuntimeEnv->proot, QUERY_PROF_BEFORE_OPERATOR_EXEC);
pRuntimeEnv->outputBuf = pRuntimeEnv->proot->exec(pRuntimeEnv->proot, &newgroup); pRuntimeEnv->outputBuf = pRuntimeEnv->proot->exec(pRuntimeEnv->proot, &newgroup);
publishOperatorProfEvent(pRuntimeEnv->proot, QUERY_PROF_AFTER_OPERATOR_EXEC);
pRuntimeEnv->resultInfo.total += GET_NUM_OF_RESULTS(pRuntimeEnv); pRuntimeEnv->resultInfo.total += GET_NUM_OF_RESULTS(pRuntimeEnv);
if (isQueryKilled(pQInfo)) { if (isQueryKilled(pQInfo)) {
......
...@@ -197,8 +197,21 @@ void* taosArraySearch(const SArray* pArray, const void* key, __compar_fn_t compa ...@@ -197,8 +197,21 @@ void* taosArraySearch(const SArray* pArray, const void* key, __compar_fn_t compa
*/ */
char* taosArraySearchString(const SArray* pArray, const char* key, __compar_fn_t comparFn, int flags); char* taosArraySearchString(const SArray* pArray, const char* key, __compar_fn_t comparFn, int flags);
/**
* sort the pointer data in the array
* @param pArray
* @param compar
* @param param
* @return
*/
void taosArraySortPWithExt(SArray* pArray, __ext_compar_fn_t fn, const void *param);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif // TDENGINE_TAOSARRAY_H #endif // TDENGINE_TAOSARRAY_H
...@@ -28,10 +28,41 @@ typedef struct SSchedMsg { ...@@ -28,10 +28,41 @@ typedef struct SSchedMsg {
void *thandle; void *thandle;
} SSchedMsg; } SSchedMsg;
void *taosInitScheduler(int queueSize, int numOfThreads, const char *label); /**
void *taosInitSchedulerWithInfo(int queueSize, int numOfThreads, const char *label, void *tmrCtrl); * Create a thread-safe ring-buffer based task queue and return the instance. A thread
int taosScheduleTask(void *qhandle, SSchedMsg *pMsg); * pool will be created to consume the messages in the queue.
void taosCleanUpScheduler(void *param); * @param capacity the queue capacity
* @param numOfThreads the number of threads for the thread pool
* @param label the label of the queue
* @return the created queue scheduler
*/
void *taosInitScheduler(int capacity, int numOfThreads, const char *label);
/**
* Create a thread-safe ring-buffer based task queue and return the instance.
* Same as taosInitScheduler, and it also print the queue status every 1 minite.
* @param capacity the queue capacity
* @param numOfThreads the number of threads for the thread pool
* @param label the label of the queue
* @param tmrCtrl the timer controller, tmr_ctrl_t*
* @return the created queue scheduler
*/
void *taosInitSchedulerWithInfo(int capacity, int numOfThreads, const char *label, void *tmrCtrl);
/**
* Clean up the queue scheduler instance and free the memory.
* @param queueScheduler the queue scheduler to free
*/
void taosCleanUpScheduler(void *queueScheduler);
/**
* Schedule a new task to run, the task is described by pMsg.
* The function may be blocked if no thread is available to execute the task.
* That may happen when all threads are busy.
* @param queueScheduler the queue scheduler instance
* @param pMsg the message for the task
*/
void taosScheduleTask(void *queueScheduler, SSchedMsg *pMsg);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "os.h" #include "os.h"
#include "tarray.h" #include "tarray.h"
#include "talgo.h"
void* taosArrayInit(size_t size, size_t elemSize) { void* taosArrayInit(size_t size, size_t elemSize) {
assert(elemSize > 0); assert(elemSize > 0);
...@@ -249,4 +250,62 @@ char* taosArraySearchString(const SArray* pArray, const char* key, __compar_fn_t ...@@ -249,4 +250,62 @@ char* taosArraySearchString(const SArray* pArray, const char* key, __compar_fn_t
return NULL; return NULL;
} }
return *(char**)p; return *(char**)p;
} }
\ No newline at end of file
static int taosArrayPartition(SArray *pArray, int i, int j, __ext_compar_fn_t fn, const void *userData) {
void* key = taosArrayGetP(pArray, i);
while (i < j) {
while (i < j && fn(taosArrayGetP(pArray, j), key, userData) >= 0) { j--; }
if (i < j) {
void *a = taosArrayGetP(pArray, j);
taosArraySet(pArray, i, &a);
}
while (i < j && fn(taosArrayGetP(pArray, i), key, userData) <= 0) { i++;}
if (i < j) {
void *a = taosArrayGetP(pArray, i);
taosArraySet(pArray, j, &a);
}
}
taosArraySet(pArray, i, &key);
return i;
}
static void taosArrayQuicksortHelper(SArray *pArray, int low, int high, __ext_compar_fn_t fn, const void *param) {
if (low < high) {
int idx = taosArrayPartition(pArray, low, high, fn, param);
taosArrayQuicksortHelper(pArray, low, idx - 1, fn, param);
taosArrayQuicksortHelper(pArray, idx + 1, high, fn, param);
}
}
static void taosArrayQuickSort(SArray* pArray, __ext_compar_fn_t fn, const void *param) {
if (pArray->size <= 1) {
return;
}
taosArrayQuicksortHelper(pArray, 0, (int)(taosArrayGetSize(pArray) - 1), fn, param);
}
static void taosArrayInsertSort(SArray* pArray, __ext_compar_fn_t fn, const void *param) {
if (pArray->size <= 1) {
return;
}
for (int i = 1; i <= pArray->size - 1; ++i) {
for (int j = i; j > 0; --j) {
if (fn(taosArrayGetP(pArray, j), taosArrayGetP(pArray, j - 1), param) == -1) {
void *a = taosArrayGetP(pArray, j);
void *b = taosArrayGetP(pArray, j - 1);
taosArraySet(pArray, j - 1, &a);
taosArraySet(pArray, j, &b);
} else {
break;
}
}
}
return;
}
// order array<type *>
void taosArraySortPWithExt(SArray* pArray, __ext_compar_fn_t fn, const void *param) {
taosArrayGetSize(pArray) > 8 ?
taosArrayQuickSort(pArray, fn, param) : taosArrayInsertSort(pArray, fn, param);
}
//TODO(yihaoDeng) add order array<type>
...@@ -108,39 +108,47 @@ void *taosInitScheduler(int queueSize, int numOfThreads, const char *label) { ...@@ -108,39 +108,47 @@ void *taosInitScheduler(int queueSize, int numOfThreads, const char *label) {
void *taosInitSchedulerWithInfo(int queueSize, int numOfThreads, const char *label, void *tmrCtrl) { void *taosInitSchedulerWithInfo(int queueSize, int numOfThreads, const char *label, void *tmrCtrl) {
SSchedQueue* pSched = taosInitScheduler(queueSize, numOfThreads, label); SSchedQueue* pSched = taosInitScheduler(queueSize, numOfThreads, label);
if (tmrCtrl != NULL && pSched != NULL) { if (tmrCtrl != NULL && pSched != NULL) {
pSched->pTmrCtrl = tmrCtrl; pSched->pTmrCtrl = tmrCtrl;
taosTmrReset(taosDumpSchedulerStatus, DUMP_SCHEDULER_TIME_WINDOW, pSched, pSched->pTmrCtrl, &pSched->pTimer); taosTmrReset(taosDumpSchedulerStatus, DUMP_SCHEDULER_TIME_WINDOW, pSched, pSched->pTmrCtrl, &pSched->pTimer);
} }
return pSched; return pSched;
} }
void *taosProcessSchedQueue(void *param) { void *taosProcessSchedQueue(void *scheduler) {
SSchedMsg msg; SSchedMsg msg;
SSchedQueue *pSched = (SSchedQueue *)param; SSchedQueue *pSched = (SSchedQueue *)scheduler;
int ret = 0;
while (1) { while (1) {
if (tsem_wait(&pSched->fullSem) != 0) { if ((ret = tsem_wait(&pSched->fullSem)) != 0) {
uError("wait %s fullSem failed(%s)", pSched->label, strerror(errno)); uFatal("wait %s fullSem failed(%s)", pSched->label, strerror(errno));
exit(ret);
} }
if (pSched->stop) { if (pSched->stop) {
break; break;
} }
if (pthread_mutex_lock(&pSched->queueMutex) != 0) if ((ret = pthread_mutex_lock(&pSched->queueMutex)) != 0) {
uError("lock %s queueMutex failed(%s)", pSched->label, strerror(errno)); uFatal("lock %s queueMutex failed(%s)", pSched->label, strerror(errno));
exit(ret);
}
msg = pSched->queue[pSched->fullSlot]; msg = pSched->queue[pSched->fullSlot];
memset(pSched->queue + pSched->fullSlot, 0, sizeof(SSchedMsg)); memset(pSched->queue + pSched->fullSlot, 0, sizeof(SSchedMsg));
pSched->fullSlot = (pSched->fullSlot + 1) % pSched->queueSize; pSched->fullSlot = (pSched->fullSlot + 1) % pSched->queueSize;
if (pthread_mutex_unlock(&pSched->queueMutex) != 0) if ((ret = pthread_mutex_unlock(&pSched->queueMutex)) != 0) {
uError("unlock %s queueMutex failed(%s)", pSched->label, strerror(errno)); uFatal("unlock %s queueMutex failed(%s)", pSched->label, strerror(errno));
exit(ret);
}
if (tsem_post(&pSched->emptySem) != 0) if ((ret = tsem_post(&pSched->emptySem)) != 0) {
uError("post %s emptySem failed(%s)", pSched->label, strerror(errno)); uFatal("post %s emptySem failed(%s)", pSched->label, strerror(errno));
exit(ret);
}
if (msg.fp) if (msg.fp)
(*(msg.fp))(&msg); (*(msg.fp))(&msg);
...@@ -151,30 +159,37 @@ void *taosProcessSchedQueue(void *param) { ...@@ -151,30 +159,37 @@ void *taosProcessSchedQueue(void *param) {
return NULL; return NULL;
} }
int taosScheduleTask(void *qhandle, SSchedMsg *pMsg) { void taosScheduleTask(void *queueScheduler, SSchedMsg *pMsg) {
SSchedQueue *pSched = (SSchedQueue *)qhandle; SSchedQueue *pSched = (SSchedQueue *)queueScheduler;
int ret = 0;
if (pSched == NULL) { if (pSched == NULL) {
uError("sched is not ready, msg:%p is dropped", pMsg); uError("sched is not ready, msg:%p is dropped", pMsg);
return 0; return;
} }
if (tsem_wait(&pSched->emptySem) != 0) { if ((ret = tsem_wait(&pSched->emptySem)) != 0) {
uError("wait %s emptySem failed(%s)", pSched->label, strerror(errno)); uFatal("wait %s emptySem failed(%s)", pSched->label, strerror(errno));
exit(ret);
} }
if (pthread_mutex_lock(&pSched->queueMutex) != 0) if ((ret = pthread_mutex_lock(&pSched->queueMutex)) != 0) {
uError("lock %s queueMutex failed(%s)", pSched->label, strerror(errno)); uFatal("lock %s queueMutex failed(%s)", pSched->label, strerror(errno));
exit(ret);
}
pSched->queue[pSched->emptySlot] = *pMsg; pSched->queue[pSched->emptySlot] = *pMsg;
pSched->emptySlot = (pSched->emptySlot + 1) % pSched->queueSize; pSched->emptySlot = (pSched->emptySlot + 1) % pSched->queueSize;
if (pthread_mutex_unlock(&pSched->queueMutex) != 0) if ((ret = pthread_mutex_unlock(&pSched->queueMutex)) != 0) {
uError("unlock %s queueMutex failed(%s)", pSched->label, strerror(errno)); uFatal("unlock %s queueMutex failed(%s)", pSched->label, strerror(errno));
exit(ret);
if (tsem_post(&pSched->fullSem) != 0) }
uError("post %s fullSem failed(%s)", pSched->label, strerror(errno));
return 0; if ((ret = tsem_post(&pSched->fullSem)) != 0) {
uFatal("post %s fullSem failed(%s)", pSched->label, strerror(errno));
exit(ret);
}
} }
void taosCleanUpScheduler(void *param) { void taosCleanUpScheduler(void *param) {
...@@ -219,4 +234,4 @@ void taosDumpSchedulerStatus(void *qhandle, void *tmrId) { ...@@ -219,4 +234,4 @@ void taosDumpSchedulerStatus(void *qhandle, void *tmrId) {
} }
taosTmrReset(taosDumpSchedulerStatus, DUMP_SCHEDULER_TIME_WINDOW, pSched, pSched->pTmrCtrl, &pSched->pTimer); taosTmrReset(taosDumpSchedulerStatus, DUMP_SCHEDULER_TIME_WINDOW, pSched, pSched->pTmrCtrl, &pSched->pTimer);
} }
\ No newline at end of file
...@@ -12,9 +12,6 @@ ...@@ -12,9 +12,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from basic import * from basic import *
from util.sql import tdSql
class TDTestCase: class TDTestCase:
...@@ -36,4 +33,6 @@ td = TDTestCase() ...@@ -36,4 +33,6 @@ td = TDTestCase()
td.init() td.init()
## usage: python3 OneMnodeMultipleVnodesTest.py
...@@ -44,7 +44,16 @@ class BuildDockerCluser: ...@@ -44,7 +44,16 @@ class BuildDockerCluser:
"jnidebugFlag":"135", "jnidebugFlag":"135",
"qdebugFlag":"135", "qdebugFlag":"135",
"maxSQLLength":"1048576" "maxSQLLength":"1048576"
} }
cmd = "mkdir -p %s" % self.dockerDir
self.execCmd(cmd)
cmd = "cp *.yml %s" % self.dockerDir
self.execCmd(cmd)
cmd = "cp Dockerfile %s" % self.dockerDir
self.execCmd(cmd)
# execute command, and return the output # execute command, and return the output
# ref: https://blog.csdn.net/wowocpp/article/details/80775650 # ref: https://blog.csdn.net/wowocpp/article/details/80775650
...@@ -81,7 +90,7 @@ class BuildDockerCluser: ...@@ -81,7 +90,7 @@ class BuildDockerCluser:
def removeFile(self, rootDir, index, dir): def removeFile(self, rootDir, index, dir):
cmd = "rm -rf %s/node%d/%s/*" % (rootDir, index, dir) cmd = "rm -rf %s/node%d/%s/*" % (rootDir, index, dir)
self.execCmd(cmd) self.execCmd(cmd)
def clearEnv(self): def clearEnv(self):
cmd = "cd %s && docker-compose down --remove-orphans" % self.dockerDir cmd = "cd %s && docker-compose down --remove-orphans" % self.dockerDir
self.execCmd(cmd) self.execCmd(cmd)
...@@ -108,10 +117,14 @@ class BuildDockerCluser: ...@@ -108,10 +117,14 @@ class BuildDockerCluser:
self.execCmd(cmd) self.execCmd(cmd)
def updateLocalhosts(self): def updateLocalhosts(self):
cmd = "grep '172.27.0.7 *tdnode1' /etc/hosts" cmd = "grep '172.27.0.7 *tdnode1' /etc/hosts | sed 's: ::g'"
result = self.execCmdAndGetOutput(cmd) result = self.execCmdAndGetOutput(cmd)
if result and not result.isspace(): print(result)
if result is None or result.isspace():
print("==========")
cmd = "echo '172.27.0.7 tdnode1' >> /etc/hosts" cmd = "echo '172.27.0.7 tdnode1' >> /etc/hosts"
display = "echo %s" % cmd
self.execCmd(display)
self.execCmd(cmd) self.execCmd(cmd)
def deploy(self): def deploy(self):
...@@ -138,13 +151,13 @@ class BuildDockerCluser: ...@@ -138,13 +151,13 @@ class BuildDockerCluser:
if self.numOfNodes < 2 or self.numOfNodes > 10: if self.numOfNodes < 2 or self.numOfNodes > 10:
print("the number of nodes must be between 2 and 10") print("the number of nodes must be between 2 and 10")
exit(0) exit(0)
self.clearEnv()
self.createDirs()
self.updateLocalhosts() self.updateLocalhosts()
self.deploy() self.deploy()
def run(self): def run(self):
cmd = "./buildClusterEnv.sh -n %d -v %s -d %s" % (self.numOfNodes, self.getTaosdVersion(), self.dockerDir) cmd = "./buildClusterEnv.sh -n %d -v %s -d %s" % (self.numOfNodes, self.getTaosdVersion(), self.dockerDir)
display = "echo %s" % cmd
self.execCmd(display)
self.execCmd(cmd) self.execCmd(cmd)
self.getConnection() self.getConnection()
self.createDondes() self.createDondes()
......
...@@ -150,6 +150,7 @@ python3 ./test.py -f import_merge/importCSV.py ...@@ -150,6 +150,7 @@ python3 ./test.py -f import_merge/importCSV.py
#======================p2-start=============== #======================p2-start===============
# tools # tools
python3 test.py -f tools/taosdumpTest.py python3 test.py -f tools/taosdumpTest.py
python3 test.py -f tools/taosdumpTest2.py
python3 test.py -f tools/taosdemoTest.py python3 test.py -f tools/taosdemoTest.py
python3 test.py -f tools/taosdemoTestWithoutMetric.py python3 test.py -f tools/taosdemoTestWithoutMetric.py
...@@ -333,6 +334,7 @@ python3 ./test.py -f insert/unsignedInt.py ...@@ -333,6 +334,7 @@ python3 ./test.py -f insert/unsignedInt.py
python3 ./test.py -f insert/unsignedBigint.py python3 ./test.py -f insert/unsignedBigint.py
python3 ./test.py -f insert/unsignedSmallint.py python3 ./test.py -f insert/unsignedSmallint.py
python3 ./test.py -f insert/unsignedTinyint.py python3 ./test.py -f insert/unsignedTinyint.py
python3 ./test.py -f insert/insertFromCSV.py
python3 ./test.py -f query/filterAllUnsignedIntTypes.py python3 ./test.py -f query/filterAllUnsignedIntTypes.py
python3 ./test.py -f tag_lite/unsignedInt.py python3 ./test.py -f tag_lite/unsignedInt.py
......
...@@ -28,16 +28,15 @@ class TDTestCase: ...@@ -28,16 +28,15 @@ class TDTestCase:
tdLog.debug("start to execute %s" % __file__) tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor(), logSql) tdSql.init(conn.cursor(), logSql)
self.ts = 1500074556514 self.ts = 1500074556514
self.csvfile = "/tmp/csvfile.csv"
self.rows = 100000
def writeCSV(self): def writeCSV(self):
with open('test3.csv','w', encoding='utf-8', newline='') as csvFile: with open(self.csvfile, 'w', encoding='utf-8', newline='') as csvFile:
writer = csv.writer(csvFile, dialect='excel') writer = csv.writer(csvFile, dialect='excel')
for i in range(1000000): for i in range(self.rows):
newTimestamp = self.ts + random.randint(10000000, 10000000000) + random.randint(1000, 10000000) + random.randint(1, 1000) writer.writerow([self.ts + i, random.randint(1, 100), random.uniform(1, 100), random.randint(1, 100), random.randint(1, 100)])
d = datetime.datetime.fromtimestamp(newTimestamp / 1000)
dt = str(d.strftime("%Y-%m-%d %H:%M:%S.%f"))
writer.writerow(["'%s'" % dt, random.randint(1, 100), random.uniform(1, 100), random.randint(1, 100), random.randint(1, 100)])
def removCSVHeader(self): def removCSVHeader(self):
data = pd.read_csv("ordered.csv") data = pd.read_csv("ordered.csv")
...@@ -45,23 +44,25 @@ class TDTestCase: ...@@ -45,23 +44,25 @@ class TDTestCase:
data.to_csv("ordered.csv", header = False, index = False) data.to_csv("ordered.csv", header = False, index = False)
def run(self): def run(self):
self.writeCSV()
tdSql.prepare() tdSql.prepare()
tdSql.execute("create table t1(ts timestamp, c1 int, c2 float, c3 int, c4 int)") tdSql.execute("create table t1(ts timestamp, c1 int, c2 float, c3 int, c4 int)")
startTime = time.time() startTime = time.time()
tdSql.execute("insert into t1 file 'outoforder.csv'") tdSql.execute("insert into t1 file '%s'" % self.csvfile)
duration = time.time() - startTime duration = time.time() - startTime
print("Out of Order - Insert time: %d" % duration) print("Insert time: %d" % duration)
tdSql.query("select count(*) from t1") tdSql.query("select * from t1")
rows = tdSql.getData(0, 0) tdSql.checkRows(self.rows)
tdSql.execute("create table t2(ts timestamp, c1 int, c2 float, c3 int, c4 int)") tdSql.execute("create table stb(ts timestamp, c1 int, c2 float, c3 int, c4 int) tags(t1 int, t2 binary(20))")
startTime = time.time() tdSql.execute("insert into t2 using stb(t1) tags(1) file '%s'" % self.csvfile)
tdSql.execute("insert into t2 file 'ordered.csv'") tdSql.query("select * from stb")
duration = time.time() - startTime tdSql.checkRows(self.rows)
print("Ordered - Insert time: %d" % duration)
tdSql.query("select count(*) from t2") tdSql.execute("insert into t3 using stb tags(1, 'test') file '%s'" % self.csvfile)
tdSql.checkData(0,0, rows) tdSql.query("select * from stb")
tdSql.checkRows(self.rows * 2)
def stop(self): def stop(self):
tdSql.close() tdSql.close()
......
...@@ -115,7 +115,7 @@ class TDTestRetetion: ...@@ -115,7 +115,7 @@ class TDTestRetetion:
cmd = 'select * from test' cmd = 'select * from test'
self.queryRows=tdSql.query(cmd) self.queryRows=tdSql.query(cmd)
self.checkRows(4,cmd) self.checkRows(4,cmd)
while datetime.datetime.now() < (ttime + datetime.timedelta(hours=72)): while datetime.datetime.now() <= (ttime + datetime.timedelta(hours=72)):
time.sleep(0.001) time.sleep(0.001)
cmd = 'select * from test' cmd = 'select * from test'
self.queryRows=tdSql.query(cmd) self.queryRows=tdSql.query(cmd)
......
...@@ -127,6 +127,7 @@ class TDDnode: ...@@ -127,6 +127,7 @@ class TDDnode:
"anyIp":"0", "anyIp":"0",
"tsEnableTelemetryReporting":"0", "tsEnableTelemetryReporting":"0",
"dDebugFlag":"135", "dDebugFlag":"135",
"tsdbDebugFlag":"135",
"mDebugFlag":"135", "mDebugFlag":"135",
"sdbDebugFlag":"135", "sdbDebugFlag":"135",
"rpcDebugFlag":"135", "rpcDebugFlag":"135",
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册