[td-225]merge develop.
This commit is contained in:
commit
03d4cf770f
|
@ -147,7 +147,11 @@ IF (TD_DARWIN_64)
|
|||
ADD_DEFINITIONS(-D_REENTRANT -D__USE_POSIX -D_LIBC_REENTRANT)
|
||||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
MESSAGE(STATUS "darwin64 is defined")
|
||||
SET(COMMON_FLAGS "-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)
|
||||
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 ()
|
||||
|
|
|
@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS)
|
|||
#INSTALL(TARGETS taos RUNTIME DESTINATION driver)
|
||||
#INSTALL(TARGETS shell RUNTIME DESTINATION .)
|
||||
IF (TD_MVN_INSTALLED)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.31.jar DESTINATION connector/jdbc)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.32-dist.jar DESTINATION connector/jdbc)
|
||||
ENDIF ()
|
||||
ELSEIF (TD_DARWIN)
|
||||
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
|
||||
|
|
|
@ -108,6 +108,10 @@ IF ("${CPUTYPE}" STREQUAL "")
|
|||
SET(TD_LINUX TRUE)
|
||||
SET(TD_LINUX_64 FALSE)
|
||||
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 ()
|
||||
|
||||
ELSE ()
|
||||
|
|
|
@ -63,7 +63,7 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专
|
|||
## [高级功能](/advanced-features)
|
||||
|
||||
* [连续查询(Continuous Query)](/advanced-features#continuous-query):基于滑动窗口,定时自动的对数据流进行查询计算
|
||||
* [数据订阅(Publisher/Subscriber)](/advanced-features#subscribe):象典型的消息队列,应用可订阅接收到的最新数据
|
||||
* [数据订阅(Publisher/Subscriber)](/advanced-features#subscribe):类似典型的消息队列,应用可订阅接收到的最新数据
|
||||
* [缓存(Cache)](/advanced-features#cache):每个设备最新的数据都会缓存在内存中,可快速获取
|
||||
* [报警监测](/advanced-features#alert):根据配置规则,自动监测超限行为数据,并主动推送
|
||||
|
||||
|
@ -106,6 +106,7 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专
|
|||
* [数据导入](/administrator#import):可按脚本文件导入,也可按数据文件导入
|
||||
* [数据导出](/administrator#export):从shell按表导出,也可用taosdump工具做各种导出
|
||||
* [系统监控](/administrator#status):检查系统现有的连接、查询、流式计算,日志和事件等
|
||||
* [性能优化](/administrator#optimize):对长期运行的系统进行维护优化,保障性能表现
|
||||
* [文件目录结构](/administrator#directories):TDengine数据文件、配置文件等所在目录
|
||||
* [参数限制与保留关键字](/administrator#keywords):TDengine的参数限制与保留关键字列表
|
||||
|
||||
|
|
|
@ -532,8 +532,9 @@ Query OK, 1 row(s) in set (0.000141s)
|
|||
|
||||
| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
|
||||
| -------------------- | ----------------- | -------- |
|
||||
| 2.0.22 | 2.0.18.0 及以上 | 1.8.x |
|
||||
| 2.0.12 - 2.0.21 | 2.0.8.0 - 2.0.17.0 | 1.8.x |
|
||||
| 2.0.31 | 2.1.3.0 及以上 | 1.8.x |
|
||||
| 2.0.22 - 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 |
|
||||
| 1.0.3 | 1.6.1.x 及以上 | 1.8.x |
|
||||
| 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
|
||||
|
|
|
@ -259,7 +259,7 @@ typedef struct taosField {
|
|||
|
||||
获取最近一次API调用失败的原因,返回值为字符串。
|
||||
|
||||
- `char *taos_errno(TAOS_RES *res)`
|
||||
- `int taos_errno(TAOS_RES *res)`
|
||||
|
||||
获取最近一次API调用失败的原因,返回值为错误代码。
|
||||
|
||||
|
@ -427,12 +427,15 @@ TDengine提供时间驱动的实时流式计算API。可以每隔一指定的时
|
|||
* res:查询结果集,注意结果集中可能没有记录
|
||||
* param:调用 `taos_subscribe`时客户程序提供的附加参数
|
||||
* code:错误码
|
||||
|
||||
**注意**:在这个回调函数里不可以做耗时过长的处理,尤其是对于返回的结果集中数据较多的情况,否则有可能导致客户端阻塞等异常状态。如果必须进行复杂计算,则建议在另外的线程中进行处理。
|
||||
|
||||
* `TAOS_RES *taos_consume(TAOS_SUB *tsub)`
|
||||
|
||||
同步模式下,该函数用来获取订阅的结果。 用户应用程序将其置于一个循环之中。 如两次调用`taos_consume`的间隔小于订阅的轮询周期,API将会阻塞,直到时间间隔超过此周期。 如果数据库有新记录到达,该API将返回该最新的记录,否则返回一个没有记录的空结果集。 如果返回值为 `NULL`,说明系统出错。 异步模式下,用户程序不应调用此API。
|
||||
|
||||
**注意**:在调用 `taos_consume()` 之后,用户应用应确保尽快调用 `taos_fetch_row()` 或 `taos_fetch_block()` 来处理订阅结果,否则服务端会持续缓存查询结果数据等待客户端读取,极端情况下会导致服务端内存消耗殆尽,影响服务稳定性。
|
||||
|
||||
* `void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress)`
|
||||
|
||||
取消订阅。 如参数 `keepProgress` 不为0,API会保留订阅的进度信息,后续调用 `taos_subscribe` 时可以基于此进度继续;否则将删除进度信息,后续只能重新开始读取数据。
|
||||
|
@ -554,6 +557,13 @@ c1.close()
|
|||
conn.close()
|
||||
```
|
||||
|
||||
#### 关于纳秒 (nanosecond) 在 Python 连接器中的说明
|
||||
|
||||
由于目前 Python 对 nanosecond 支持的不完善(参见链接 1. 2. ),目前的实现方式是在 nanosecond 精度时返回整数,而不是 ms 和 us 返回的 datetime 类型,应用开发者需要自行处理,建议使用 pandas 的 to_datetime()。未来如果 Python 正式完整支持了纳秒,涛思数据可能会修改相关接口。
|
||||
|
||||
1. https://stackoverflow.com/questions/10611328/parsing-datetime-strings-containing-nanoseconds
|
||||
2. https://www.python.org/dev/peps/pep-0564/
|
||||
|
||||
#### 帮助信息
|
||||
|
||||
用户可通过python的帮助信息直接查看模块的使用信息,或者参考tests/examples/python中的示例程序。以下为部分常用类和方法:
|
||||
|
@ -897,6 +907,10 @@ go env -w GOPROXY=https://goproxy.io,direct
|
|||
|
||||
sql.Open内置的方法,Close closes the statement.
|
||||
|
||||
### 其他代码示例
|
||||
|
||||
[Consume Messages from Kafka](https://github.com/taosdata/go-demo-kafka) 是一个通过 Go 语言实现消费 Kafka 队列写入 TDengine 的示例程序,也可以作为通过 Go 连接 TDengine 的写法参考。
|
||||
|
||||
## <a class="anchor" id="nodejs"></a>Node.js Connector
|
||||
|
||||
Node.js连接器支持的系统有:
|
||||
|
|
|
@ -418,6 +418,19 @@ TDengine启动后,会自动创建一个监测数据库log,并自动将服务
|
|||
|
||||
这些监测信息的采集缺省是打开的,但可以修改配置文件里的选项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>文件目录结构
|
||||
|
||||
安装TDengine后,默认会在操作系统中生成下列目录或文件:
|
||||
|
@ -465,43 +478,44 @@ TDengine的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下
|
|||
|
||||
目前 TDengine 有将近 200 个内部保留关键字,这些关键字无论大小写均不可以用作库名、表名、STable 名、数据列名及标签列名等。这些关键字列表如下:
|
||||
|
||||
| 关键字列表 | | | | |
|
||||
| ---------- | ----------- | ------------ | ---------- | --------- |
|
||||
| ABLOCKS | CONNECTIONS | HAVING | MODULES | SMALLINT |
|
||||
| ABORT | COPY | ID | NCHAR | SPREAD |
|
||||
| ACCOUNT | COUNT | IF | NE | STABLE |
|
||||
| ACCOUNTS | CREATE | IGNORE | NONE | STABLES |
|
||||
| ADD | CTIME | IMMEDIATE | NOT | STAR |
|
||||
| AFTER | DATABASE | IMPORT | NOTNULL | STATEMENT |
|
||||
| ALL | DATABASES | IN | NOW | STDDEV |
|
||||
| ALTER | DAYS | INITIALLY | OF | STREAM |
|
||||
| AND | DEFERRED | INSERT | OFFSET | STREAMS |
|
||||
| AS | DELIMITERS | INSTEAD | OR | STRING |
|
||||
| ASC | DESC | INTEGER | ORDER | SUM |
|
||||
| ATTACH | DESCRIBE | INTERVAL | PASS | TABLE |
|
||||
| AVG | DETACH | INTO | PERCENTILE | TABLES |
|
||||
| BEFORE | DIFF | IP | PLUS | TAG |
|
||||
| BEGIN | DISTINCT | IS | PRAGMA | TAGS |
|
||||
| BETWEEN | DIVIDE | ISNULL | PREV | TBLOCKS |
|
||||
| BIGINT | DNODE | JOIN | PRIVILEGE | TBNAME |
|
||||
| BINARY | DNODES | KEEP | QUERIES | TIMES |
|
||||
| BITAND | DOT | KEY | QUERY | TIMESTAMP |
|
||||
| BITNOT | DOUBLE | KILL | RAISE | TINYINT |
|
||||
| BITOR | DROP | LAST | REM | TOP |
|
||||
| BOOL | EACH | LE | REPLACE | TOPIC |
|
||||
| BOTTOM | END | LEASTSQUARES | REPLICA | TRIGGER |
|
||||
| BY | EQ | LIKE | RESET | UMINUS |
|
||||
| CACHE | EXISTS | LIMIT | RESTRICT | UNION |
|
||||
| CASCADE | EXPLAIN | LINEAR | ROW | UPLUS |
|
||||
| CHANGE | FAIL | LOCAL | ROWS | USE |
|
||||
| CLOG | FILL | LP | RP | USER |
|
||||
| CLUSTER | FIRST | LSHIFT | RSHIFT | USERS |
|
||||
| COLON | FLOAT | LT | SCORES | USING |
|
||||
| COLUMN | FOR | MATCH | SELECT | VALUES |
|
||||
| COMMA | FROM | MAX | SEMI | VARIABLE |
|
||||
| COMP | GE | METRIC | SET | VGROUPS |
|
||||
| CONCAT | GLOB | METRICS | SHOW | VIEW |
|
||||
| CONFIGS | GRANTS | MIN | SLASH | WAVG |
|
||||
| CONFLICT | GROUP | MINUS | SLIDING | WHERE |
|
||||
| CONNECTION | GT | MNODES | SLIMIT | |
|
||||
| 关键字列表 | | | | |
|
||||
| ------------ | ------------ | ------------ | ------------ | ------------ |
|
||||
| ABORT | CREATE | IGNORE | NULL | STAR |
|
||||
| ACCOUNT | CTIME | IMMEDIATE | OF | STATE |
|
||||
| ACCOUNTS | DATABASE | IMPORT | OFFSET | STATEMENT |
|
||||
| ADD | DATABASES | IN | OR | STATE_WINDOW |
|
||||
| AFTER | DAYS | INITIALLY | ORDER | STORAGE |
|
||||
| ALL | DBS | INSERT | PARTITIONS | STREAM |
|
||||
| ALTER | DEFERRED | INSTEAD | PASS | STREAMS |
|
||||
| AND | DELIMITERS | INT | PLUS | STRING |
|
||||
| AS | DESC | INTEGER | PPS | SYNCDB |
|
||||
| ASC | DESCRIBE | INTERVAL | PRECISION | TABLE |
|
||||
| ATTACH | DETACH | INTO | PREV | TABLES |
|
||||
| BEFORE | DISTINCT | IS | PRIVILEGE | TAG |
|
||||
| BEGIN | DIVIDE | ISNULL | QTIME | TAGS |
|
||||
| BETWEEN | DNODE | JOIN | QUERIES | TBNAME |
|
||||
| BIGINT | DNODES | KEEP | QUERY | TIMES |
|
||||
| BINARY | DOT | KEY | QUORUM | TIMESTAMP |
|
||||
| BITAND | DOUBLE | KILL | RAISE | TINYINT |
|
||||
| BITNOT | DROP | LE | REM | TOPIC |
|
||||
| BITOR | EACH | LIKE | REPLACE | TOPICS |
|
||||
| BLOCKS | END | LIMIT | REPLICA | TRIGGER |
|
||||
| BOOL | EQ | LINEAR | RESET | TSERIES |
|
||||
| BY | EXISTS | LOCAL | RESTRICT | UMINUS |
|
||||
| CACHE | EXPLAIN | LP | ROW | UNION |
|
||||
| CACHELAST | FAIL | LSHIFT | RP | UNSIGNED |
|
||||
| CASCADE | FILE | LT | RSHIFT | UPDATE |
|
||||
| CHANGE | FILL | MATCH | SCORES | UPLUS |
|
||||
| CLUSTER | FLOAT | MAXROWS | SELECT | USE |
|
||||
| COLON | FOR | MINROWS | SEMI | USER |
|
||||
| COLUMN | FROM | MINUS | SESSION | USERS |
|
||||
| COMMA | FSYNC | MNODES | SET | USING |
|
||||
| COMP | GE | MODIFY | SHOW | VALUES |
|
||||
| COMPACT | GLOB | MODULES | SLASH | VARIABLE |
|
||||
| CONCAT | GRANTS | NCHAR | SLIDING | VARIABLES |
|
||||
| CONFLICT | GROUP | NE | SLIMIT | VGROUPS |
|
||||
| CONNECTION | GT | NONE | SMALLINT | VIEW |
|
||||
| CONNECTIONS | HAVING | NOT | SOFFSET | VNODES |
|
||||
| CONNS | ID | NOTNULL | STABLE | WAL |
|
||||
| COPY | IF | NOW | STABLES | WHERE |
|
||||
|
||||
|
|
|
@ -89,13 +89,13 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
|
|||
```mysql
|
||||
USE db_name;
|
||||
```
|
||||
使用/切换数据库
|
||||
使用/切换数据库(在 RESTful 连接方式下无效)。
|
||||
|
||||
- **删除数据库**
|
||||
```mysql
|
||||
DROP DATABASE [IF EXISTS] db_name;
|
||||
```
|
||||
删除数据库。所包含的全部数据表将被删除,谨慎使用
|
||||
删除数据库。指定 Database 所包含的全部数据表将被删除,谨慎使用!
|
||||
|
||||
- **修改数据库参数**
|
||||
```mysql
|
||||
|
@ -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 列名不能与其他列名相同;
|
||||
|
||||
3) TAGS 列名不能为预留关键字;
|
||||
3) TAGS 列名不能为预留关键字(参见:[参数限制与保留关键字](https://www.taosdata.com/cn/documentation/administrator#keywords) 章节);
|
||||
|
||||
4) TAGS 最多允许 128 个,至少 1 个,总长度不超过 16 KB。
|
||||
|
||||
|
@ -703,22 +703,24 @@ Query OK, 1 row(s) in set (0.001091s)
|
|||
|
||||
### 支持的条件过滤操作
|
||||
|
||||
| **Operation** | **Note** | **Applicable Data Types** |
|
||||
| --------------- | ----------------------------- | ------------------------------------- |
|
||||
| > | larger than | **`timestamp`** and all numeric types |
|
||||
| < | smaller than | **`timestamp`** and all numeric types |
|
||||
| >= | larger than or equal to | **`timestamp`** and all numeric types |
|
||||
| <= | smaller than or equal to | **`timestamp`** and all numeric types |
|
||||
| = | equal to | all types |
|
||||
| <> | not equal to | all types |
|
||||
| between and | within a certain range | **`timestamp`** and all numeric types |
|
||||
| % | match with any char sequences | **`binary`** **`nchar`** |
|
||||
| _ | match with a single char | **`binary`** **`nchar`** |
|
||||
| **Operation** | **Note** | **Applicable Data Types** |
|
||||
| --------------- | ----------------------------- | ----------------------------------------- |
|
||||
| > | larger than | **`timestamp`** and all numeric types |
|
||||
| < | smaller than | **`timestamp`** and all numeric types |
|
||||
| >= | larger than or equal to | **`timestamp`** and all numeric types |
|
||||
| <= | smaller than or equal to | **`timestamp`** and all numeric types |
|
||||
| = | equal to | all types |
|
||||
| <> | not equal to | all types |
|
||||
| between and | within a certain range | **`timestamp`** and all numeric types |
|
||||
| in | matches any value in a set | all types except first column `timestamp` |
|
||||
| % | match with any char sequences | **`binary`** **`nchar`** |
|
||||
| _ | match with a single char | **`binary`** **`nchar`** |
|
||||
|
||||
1. <> 算子也可以写为 != ,请注意,这个算子不能用于数据表第一列的 timestamp 字段。
|
||||
2. 同时进行多个字段的范围过滤,需要使用关键词 AND 来连接不同的查询条件,暂不支持 OR 连接的不同列之间的查询过滤条件。
|
||||
3. 针对单一字段的过滤,如果是时间过滤条件,则一条语句中只支持设定一个;但针对其他的(普通)列或标签列,则可以使用 `OR` 关键字进行组合条件的查询过滤。例如:((value > 20 AND value < 30) OR (value < 12)) 。
|
||||
4. 从 2.0.17 版本开始,条件过滤开始支持 BETWEEN AND 语法,例如 `WHERE col2 BETWEEN 1.5 AND 3.25` 表示查询条件为“1.5 ≤ col2 ≤ 3.25”。
|
||||
3. 针对单一字段的过滤,如果是时间过滤条件,则一条语句中只支持设定一个;但针对其他的(普通)列或标签列,则可以使用 `OR` 关键字进行组合条件的查询过滤。例如: `((value > 20 AND value < 30) OR (value < 12))`。
|
||||
4. 从 2.0.17.0 版本开始,条件过滤开始支持 BETWEEN AND 语法,例如 `WHERE col2 BETWEEN 1.5 AND 3.25` 表示查询条件为“1.5 ≤ col2 ≤ 3.25”。
|
||||
5. 从 2.1.4.0 版本开始,条件过滤开始支持 IN 算子,例如 `WHERE city IN ('Beijing', 'Shanghai')`。说明:BOOL 类型写作 `{true, false}` 或 `{0, 1}` 均可,但不能写作 0、1 之外的整数;FLOAT 和 DOUBLE 类型会受到浮点数精度影响,集合内的值在精度范围内认为和数据行的值完全相等才能匹配成功。<!-- REPLACE_OPEN_TO_ENTERPRISE__IN_OPERATOR_AND_UNSIGNED_INTEGER -->
|
||||
|
||||
<!--
|
||||
<a class="anchor" id="having"></a>
|
||||
|
@ -854,7 +856,23 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
|
|||
|
||||
应用字段:不能应用在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**
|
||||
```mysql
|
||||
|
@ -1203,13 +1221,14 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
|
|||
```
|
||||
|
||||
### 计算函数
|
||||
|
||||
- **DIFF**
|
||||
```mysql
|
||||
SELECT DIFF(field_name) FROM tb_name [WHERE clause];
|
||||
```
|
||||
功能说明:统计表中某列的值与前一行对应值的差。
|
||||
|
||||
返回结果数据类型: 同应用字段。
|
||||
返回结果数据类型:同应用字段。
|
||||
|
||||
应用字段:不能应用在timestamp、binary、nchar、bool类型字段。
|
||||
|
||||
|
@ -1227,13 +1246,27 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
|
|||
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**
|
||||
```mysql
|
||||
SELECT SPREAD(field_name) FROM { tb_name | stb_name } [WHERE clause];
|
||||
```
|
||||
功能说明:统计表/超级表中某列的最大值和最小值之差。
|
||||
|
||||
返回结果数据类型: 双精度浮点数。
|
||||
返回结果数据类型:双精度浮点数。
|
||||
|
||||
应用字段:不能应用在binary、nchar、bool类型字段。
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
|
||||
TDengine还没有一组专用的validation queries。然而建议你使用系统监测的数据库”log"来做。
|
||||
|
||||
<a class="anchor" id="update"></a>
|
||||
## 9. 我可以删除或更新一条记录吗?
|
||||
|
||||
TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。
|
||||
|
|
|
@ -515,6 +515,13 @@ c1.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
|
||||
|
||||
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) {
|
|||
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() {
|
||||
int32_t numOfMnodes = mnodeGetMnodesNum();
|
||||
if (numOfMnodes >= tsNumOfMnodes) return;
|
||||
|
@ -645,13 +658,7 @@ static void bnMonitorDnodeModule() {
|
|||
SDnodeObj *pDnode = tsBnDnodes.list[i];
|
||||
if (pDnode == NULL) break;
|
||||
|
||||
if (pDnode->isMgmt || pDnode->status == TAOS_DN_STATUS_DROPPING || pDnode->status == TAOS_DN_STATUS_OFFLINE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pDnode->alternativeRole == TAOS_DN_ALTERNATIVE_ROLE_VNODE) {
|
||||
continue;
|
||||
}
|
||||
if (!bnDnodeCanCreateMnode(pDnode)) continue;
|
||||
|
||||
mLInfo("dnode:%d, numOfMnodes:%d expect:%d, create mnode in this dnode", pDnode->dnodeId, numOfMnodes, tsNumOfMnodes);
|
||||
mnodeCreateMnode(pDnode->dnodeId, pDnode->dnodeEp, true);
|
||||
|
|
|
@ -898,7 +898,9 @@ SSDataBlock* doGlobalAggregate(void* param, bool* newgroup) {
|
|||
SSDataBlock* pBlock = NULL;
|
||||
while(1) {
|
||||
bool prev = *newgroup;
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
pBlock = upstream->exec(upstream, newgroup);
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
if (pBlock == NULL) {
|
||||
*newgroup = prev;
|
||||
break;
|
||||
|
@ -966,7 +968,9 @@ static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) {
|
|||
|
||||
SSDataBlock* pBlock = NULL;
|
||||
if (pInfo->currentGroupOffset == 0) {
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
if (pBlock == NULL) {
|
||||
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
|
||||
pOperator->status = OP_EXEC_DONE;
|
||||
|
@ -974,7 +978,9 @@ static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) {
|
|||
|
||||
if (*newgroup == false && pInfo->limit.limit > 0 && pInfo->rowsTotal >= pInfo->limit.limit) {
|
||||
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);
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
if (pBlock == NULL) {
|
||||
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
|
||||
pOperator->status = OP_EXEC_DONE;
|
||||
|
@ -986,7 +992,10 @@ static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) {
|
|||
return pBlock;
|
||||
}
|
||||
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
|
||||
pOperator->status = OP_EXEC_DONE;
|
||||
|
@ -1000,7 +1009,10 @@ static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) {
|
|||
}
|
||||
|
||||
while ((*newgroup) == false) {
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
|
||||
pOperator->status = OP_EXEC_DONE;
|
||||
|
|
|
@ -485,6 +485,7 @@ static int32_t tscGetDBInfo(SCreateBuilder *builder, char *result) {
|
|||
|
||||
char buf[TSDB_DB_NAME_LEN + 64] = {0};
|
||||
do {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
int32_t* lengths = taos_fetch_lengths(pSql);
|
||||
int32_t ret = tscGetNthFieldResult(row, fields, lengths, 0, buf);
|
||||
if (0 == ret && STR_NOCASE_EQUAL(buf, strlen(buf), builder->buf, strlen(builder->buf))) {
|
||||
|
|
|
@ -1580,7 +1580,6 @@ void tscImportDataFromFile(SSqlObj *pSql) {
|
|||
|
||||
SImportFileSupport *pSupporter = calloc(1, sizeof(SImportFileSupport));
|
||||
SSqlObj *pNew = createSubqueryObj(pSql, 0, parseFileSendDataBlock, pSupporter, TSDB_SQL_INSERT, NULL);
|
||||
pCmd->count = 1;
|
||||
|
||||
FILE *fp = fopen(pCmd->payload, "rb");
|
||||
if (fp == NULL) {
|
||||
|
|
|
@ -165,6 +165,7 @@ bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType,
|
|||
} else {
|
||||
tbufWriteUint32(&bw, colType);
|
||||
}
|
||||
|
||||
tbufWriteInt32(&bw, (int32_t)(pList->size));
|
||||
|
||||
for (int32_t i = 0; i < (int32_t)pList->size; i++) {
|
||||
|
@ -181,10 +182,11 @@ bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType,
|
|||
}
|
||||
tbufWriteInt64(&bw, var->i64);
|
||||
} 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;
|
||||
}
|
||||
tbufWriteUint64(&bw, var->u64);
|
||||
}
|
||||
} 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)) {
|
||||
tbufWriteDouble(&bw, (double)(var->i64));
|
||||
|
@ -914,8 +916,8 @@ static int32_t checkInvalidExprForTimeWindow(SSqlCmd* pCmd, SQueryInfo* pQueryIn
|
|||
}
|
||||
|
||||
int32_t validateIntervalNode(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode) {
|
||||
const char* msg1 = "sliding cannot be used without interval";
|
||||
const char* msg2 = "interval cannot be less than 10 ms";
|
||||
const char* msg3 = "sliding cannot be used without interval";
|
||||
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
|
||||
|
@ -924,7 +926,7 @@ int32_t validateIntervalNode(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNode* pS
|
|||
|
||||
if (!TPARSER_HAS_TOKEN(pSqlNode->interval.interval)) {
|
||||
if (TPARSER_HAS_TOKEN(pSqlNode->sliding)) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -945,7 +947,7 @@ int32_t validateIntervalNode(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNode* pS
|
|||
if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit != 'y') {
|
||||
|
||||
// interval cannot be less than 10 milliseconds
|
||||
if (convertTimePrecision(pQueryInfo->interval.interval, tinfo.precision, TSDB_TIME_PRECISION_MILLI) < tsMinIntervalTime) {
|
||||
if (convertTimePrecision(pQueryInfo->interval.interval, tinfo.precision, TSDB_TIME_PRECISION_MICRO) < tsMinIntervalTime) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
}
|
||||
|
@ -1309,15 +1311,8 @@ static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pC
|
|||
return false;
|
||||
}
|
||||
|
||||
/* timestamp in tag is not allowed */
|
||||
for (int32_t i = 0; i < numOfTags; ++i) {
|
||||
TAOS_FIELD* p = taosArrayGet(pTagsList, i);
|
||||
|
||||
//if (p->type == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
// invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4);
|
||||
// return false;
|
||||
//}
|
||||
|
||||
if (!isValidDataType(p->type)) {
|
||||
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
|
||||
return false;
|
||||
|
@ -2069,33 +2064,29 @@ static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS
|
|||
const char* name, int32_t resColIdx, SColumnIndex* pColIndex, bool finalResult) {
|
||||
const char* msg1 = "not support column types";
|
||||
|
||||
int16_t type = 0;
|
||||
int16_t bytes = 0;
|
||||
int32_t functionID = cvtFunc.execFuncId;
|
||||
|
||||
if (functionID == TSDB_FUNC_SPREAD) {
|
||||
int32_t f = cvtFunc.execFuncId;
|
||||
if (f == TSDB_FUNC_SPREAD) {
|
||||
int32_t t1 = pSchema->type;
|
||||
if (t1 == TSDB_DATA_TYPE_BINARY || t1 == TSDB_DATA_TYPE_NCHAR || t1 == TSDB_DATA_TYPE_BOOL) {
|
||||
if (IS_VAR_DATA_TYPE(t1) || t1 == TSDB_DATA_TYPE_BOOL) {
|
||||
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
return -1;
|
||||
} else {
|
||||
type = TSDB_DATA_TYPE_DOUBLE;
|
||||
bytes = tDataTypes[type].bytes;
|
||||
}
|
||||
} else {
|
||||
type = pSchema->type;
|
||||
bytes = pSchema->bytes;
|
||||
}
|
||||
|
||||
SExprInfo* pExpr = tscExprAppend(pQueryInfo, functionID, pColIndex, type, bytes, getNewResColId(pCmd), bytes, false);
|
||||
int16_t resType = 0;
|
||||
int16_t resBytes = 0;
|
||||
int32_t interBufSize = 0;
|
||||
|
||||
getResultDataInfo(pSchema->type, pSchema->bytes, f, 0, &resType, &resBytes, &interBufSize, 0, false);
|
||||
SExprInfo* pExpr = tscExprAppend(pQueryInfo, f, pColIndex, resType, resBytes, getNewResColId(pCmd), interBufSize, false);
|
||||
tstrncpy(pExpr->base.aliasName, name, tListLen(pExpr->base.aliasName));
|
||||
|
||||
if (cvtFunc.originFuncId == TSDB_FUNC_LAST_ROW && cvtFunc.originFuncId != functionID) {
|
||||
if (cvtFunc.originFuncId == TSDB_FUNC_LAST_ROW && cvtFunc.originFuncId != f) {
|
||||
pExpr->base.colInfo.flag |= TSDB_COL_NULL;
|
||||
}
|
||||
|
||||
// set reverse order scan data blocks for last query
|
||||
if (functionID == TSDB_FUNC_LAST) {
|
||||
if (f == TSDB_FUNC_LAST) {
|
||||
pExpr->base.numOfParams = 1;
|
||||
pExpr->base.param[0].i64 = TSDB_ORDER_DESC;
|
||||
pExpr->base.param[0].nType = TSDB_DATA_TYPE_INT;
|
||||
|
@ -2108,7 +2099,7 @@ static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS
|
|||
// if it is not in the final result, do not add it
|
||||
SColumnList ids = createColumnList(1, pColIndex->tableIndex, pColIndex->columnIndex);
|
||||
if (finalResult) {
|
||||
insertResultField(pQueryInfo, resColIdx, &ids, bytes, (int8_t)type, pExpr->base.aliasName, pExpr);
|
||||
insertResultField(pQueryInfo, resColIdx, &ids, resBytes, (int8_t)resType, pExpr->base.aliasName, pExpr);
|
||||
} else {
|
||||
tscColumnListInsert(pQueryInfo->colList, ids.ids[0].columnIndex, pExpr->base.uid, pSchema);
|
||||
}
|
||||
|
@ -2178,7 +2169,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
const char* msg3 = "illegal column name";
|
||||
const char* msg4 = "invalid table name";
|
||||
const char* msg5 = "parameter is out of range [0, 100]";
|
||||
const char* msg6 = "function applied to tags not allowed";
|
||||
const char* msg6 = "functions applied to tags are not allowed";
|
||||
const char* msg7 = "normal table can not apply this function";
|
||||
const char* msg8 = "multi-columns selection does not support alias column name";
|
||||
const char* msg9 = "diff/derivative can no be applied to unsigned numeric type";
|
||||
|
@ -2557,8 +2548,9 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
|
||||
tVariant* pVariant = &pParamElem[1].pNode->value;
|
||||
|
||||
int8_t resultType = pSchema->type;
|
||||
int16_t resultSize = pSchema->bytes;
|
||||
int16_t resultType = pSchema->type;
|
||||
int16_t resultSize = pSchema->bytes;
|
||||
int32_t interResult = 0;
|
||||
|
||||
char val[8] = {0};
|
||||
|
||||
|
@ -2571,8 +2563,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
|
||||
}
|
||||
|
||||
resultSize = sizeof(double);
|
||||
resultType = TSDB_DATA_TYPE_DOUBLE;
|
||||
getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &resultType, &resultSize, &interResult, 0, false);
|
||||
|
||||
/*
|
||||
* sql function transformation
|
||||
|
@ -2582,7 +2573,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
tscInsertPrimaryTsSourceColumn(pQueryInfo, pTableMetaInfo->pTableMeta->id.uid);
|
||||
colIndex += 1; // the first column is ts
|
||||
|
||||
pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd), resultSize, false);
|
||||
pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd), interResult, false);
|
||||
tscExprAddParams(&pExpr->base, val, TSDB_DATA_TYPE_DOUBLE, sizeof(double));
|
||||
} else {
|
||||
tVariantDump(pVariant, val, TSDB_DATA_TYPE_BIGINT, true);
|
||||
|
@ -2617,7 +2608,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
SColumnList ids = createColumnList(1, index.tableIndex, index.columnIndex);
|
||||
|
||||
if (finalResult) {
|
||||
insertResultField(pQueryInfo, colIndex, &ids, resultSize, resultType, pExpr->base.aliasName, pExpr);
|
||||
insertResultField(pQueryInfo, colIndex, &ids, resultSize, (int8_t)resultType, pExpr->base.aliasName, pExpr);
|
||||
} else {
|
||||
assert(ids.num == 1);
|
||||
tscColumnListInsert(pQueryInfo->colList, ids.ids[0].columnIndex, pExpr->base.uid, pSchema);
|
||||
|
@ -3091,9 +3082,9 @@ void tscRestoreFuncForSTableQuery(SQueryInfo* pQueryInfo) {
|
|||
}
|
||||
|
||||
bool hasUnsupportFunctionsForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
|
||||
const char* msg1 = "TWA/Diff/Derivative/Irate not allowed to apply to super table directly";
|
||||
const char* msg1 = "TWA/Diff/Derivative/Irate are not allowed to apply to super table directly";
|
||||
const char* msg2 = "TWA/Diff/Derivative/Irate only support group by tbname for super table query";
|
||||
const char* msg3 = "function not support for super table query";
|
||||
const char* msg3 = "functions not support for super table query";
|
||||
|
||||
// filter sql function not supported by metric query yet.
|
||||
size_t size = tscNumOfExprs(pQueryInfo);
|
||||
|
@ -3198,34 +3189,42 @@ int32_t validateGroupbyNode(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd
|
|||
const char* msg2 = "invalid column name in group by clause";
|
||||
const char* msg3 = "columns from one table allowed as group by columns";
|
||||
const char* msg4 = "join query does not support group by";
|
||||
const char* msg5 = "not allowed column type for group by";
|
||||
const char* msg6 = "tags not allowed for table query";
|
||||
const char* msg7 = "not support group by expression";
|
||||
const char* msg8 = "not allowed column type for group by";
|
||||
const char* msg9 = "tags not allowed for table query";
|
||||
const char* msg8 = "normal column can only locate at the end of group by clause";
|
||||
|
||||
// todo : handle two tables situation
|
||||
STableMetaInfo* pTableMetaInfo = NULL;
|
||||
|
||||
if (pList == NULL) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (pQueryInfo->colList == NULL) {
|
||||
pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES);
|
||||
}
|
||||
|
||||
pQueryInfo->groupbyExpr.numOfGroupCols = (int16_t)taosArrayGetSize(pList);
|
||||
if (pQueryInfo->groupbyExpr.numOfGroupCols > TSDB_MAX_TAGS) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (pQueryInfo->numOfTables > 1) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4);
|
||||
}
|
||||
|
||||
STableMeta* pTableMeta = NULL;
|
||||
SSchema* pSchema = NULL;
|
||||
SGroupbyExpr* pGroupExpr = &pQueryInfo->groupbyExpr;
|
||||
if (pGroupExpr->columnInfo == NULL) {
|
||||
pGroupExpr->columnInfo = taosArrayInit(4, sizeof(SColIndex));
|
||||
}
|
||||
|
||||
int32_t tableIndex = COLUMN_INDEX_INITIAL_VAL;
|
||||
if (pQueryInfo->colList == NULL) {
|
||||
pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES);
|
||||
}
|
||||
|
||||
if (pGroupExpr->columnInfo == NULL || pQueryInfo->colList == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
pGroupExpr->numOfGroupCols = (int16_t)taosArrayGetSize(pList);
|
||||
if (pGroupExpr->numOfGroupCols > TSDB_MAX_TAGS) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
SSchema *pSchema = NULL;
|
||||
int32_t tableIndex = COLUMN_INDEX_INITIAL_VAL;
|
||||
int32_t numOfGroupCols = 0;
|
||||
|
||||
size_t num = taosArrayGetSize(pList);
|
||||
for (int32_t i = 0; i < num; ++i) {
|
||||
|
@ -3246,28 +3245,20 @@ int32_t validateGroupbyNode(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd
|
|||
}
|
||||
|
||||
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
|
||||
pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
|
||||
int32_t numOfCols = tscGetNumOfColumns(pTableMeta);
|
||||
if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
pSchema = tGetTbnameColumnSchema();
|
||||
} else {
|
||||
pSchema = tscGetTableColumnSchema(pTableMeta, index.columnIndex);
|
||||
}
|
||||
|
||||
bool groupTag = false;
|
||||
if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX || index.columnIndex >= numOfCols) {
|
||||
groupTag = true;
|
||||
}
|
||||
int32_t numOfCols = tscGetNumOfColumns(pTableMeta);
|
||||
bool groupTag = (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX || index.columnIndex >= numOfCols);
|
||||
|
||||
SGroupbyExpr* pGroupExpr = &pQueryInfo->groupbyExpr;
|
||||
if (pGroupExpr->columnInfo == NULL) {
|
||||
pGroupExpr->columnInfo = taosArrayInit(4, sizeof(SColIndex));
|
||||
}
|
||||
|
||||
if (groupTag) {
|
||||
if (!UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg9);
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
|
||||
}
|
||||
|
||||
int32_t relIndex = index.columnIndex;
|
||||
|
@ -3284,7 +3275,7 @@ int32_t validateGroupbyNode(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd
|
|||
} else {
|
||||
// check if the column type is valid, here only support the bool/tinyint/smallint/bigint group by
|
||||
if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP || pSchema->type == TSDB_DATA_TYPE_FLOAT || pSchema->type == TSDB_DATA_TYPE_DOUBLE) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg8);
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
|
||||
}
|
||||
|
||||
tscColumnListInsert(pQueryInfo->colList, index.columnIndex, pTableMeta->id.uid, pSchema);
|
||||
|
@ -3294,10 +3285,20 @@ int32_t validateGroupbyNode(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd
|
|||
|
||||
taosArrayPush(pGroupExpr->columnInfo, &colIndex);
|
||||
pQueryInfo->groupbyExpr.orderType = TSDB_ORDER_ASC;
|
||||
numOfGroupCols++;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0 && num > 1) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
|
||||
}
|
||||
// 1. only one normal column allowed in the group by clause
|
||||
// 2. the normal column in the group by clause can only located in the end position
|
||||
if (numOfGroupCols > 1) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
|
||||
}
|
||||
|
||||
for(int32_t i = 0; i < num; ++i) {
|
||||
SColIndex* pIndex = taosArrayGet(pGroupExpr->columnInfo, i);
|
||||
if (TSDB_COL_IS_NORMAL_COL(pIndex->flag) && i != num - 1) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg8);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3343,6 +3344,7 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
|
|||
if (pRight->flags & (1 << EXPR_FLAG_NS_TIMESTAMP)) {
|
||||
pRight->value.i64 =
|
||||
convertTimePrecision(pRight->value.i64, TSDB_TIME_PRECISION_NANO, timePrecision);
|
||||
pRight->flags &= ~(1 << EXPR_FLAG_NS_TIMESTAMP);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4907,6 +4909,7 @@ int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t t
|
|||
*/
|
||||
if (pRight->flags & (1 << EXPR_FLAG_NS_TIMESTAMP)) {
|
||||
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);
|
||||
|
@ -5104,7 +5107,7 @@ static void setDefaultOrderInfo(SQueryInfo* pQueryInfo) {
|
|||
int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode, SSchema* pSchema) {
|
||||
const char* msg0 = "only support order by primary timestamp";
|
||||
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";
|
||||
|
||||
setDefaultOrderInfo(pQueryInfo);
|
||||
|
@ -5157,6 +5160,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
|||
|
||||
bool orderByTags = false;
|
||||
bool orderByTS = false;
|
||||
bool orderByGroupbyCol = false;
|
||||
|
||||
if (index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) {
|
||||
int32_t relTagIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
|
||||
|
@ -5176,11 +5180,18 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
|||
if (PRIMARYKEY_TIMESTAMP_COL_INDEX == index.columnIndex) {
|
||||
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);
|
||||
} 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);
|
||||
|
@ -5190,6 +5201,11 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
|||
|
||||
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
|
||||
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)) {
|
||||
/* order of top/bottom query in interval is not valid */
|
||||
SExprInfo* pExpr = tscExprGet(pQueryInfo, 0);
|
||||
|
@ -5222,6 +5238,9 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
|||
if (orderByTags) {
|
||||
pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
|
||||
pQueryInfo->groupbyExpr.orderType = pItem->sortOrder;
|
||||
} else if (orderByGroupbyCol){
|
||||
pQueryInfo->order.order = pItem->sortOrder;
|
||||
pQueryInfo->order.orderColId = index.columnIndex;
|
||||
} else {
|
||||
pQueryInfo->order.order = pItem->sortOrder;
|
||||
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
||||
|
@ -5247,9 +5266,20 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
|||
if (getColumnIndexByName(pCmd, &columnName, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
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)) {
|
||||
|
@ -5270,6 +5300,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
|||
|
||||
tVariantListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
|
||||
pQueryInfo->order.order = pItem->sortOrder;
|
||||
pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId;
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -6284,7 +6315,7 @@ static void updateTagPrjFunction(SQueryInfo* pQueryInfo) {
|
|||
*/
|
||||
static int32_t checkUpdateTagPrjFunctions(SQueryInfo* pQueryInfo, char* msg) {
|
||||
const char* msg1 = "only one selectivity function allowed in presence of tags function";
|
||||
const char* msg3 = "aggregation function should not be mixed up with projection";
|
||||
const char* msg2 = "aggregation function should not be mixed up with projection";
|
||||
|
||||
bool tagTsColExists = false;
|
||||
int16_t numOfSelectivity = 0;
|
||||
|
@ -6363,7 +6394,7 @@ static int32_t checkUpdateTagPrjFunctions(SQueryInfo* pQueryInfo, char* msg) {
|
|||
} else {
|
||||
if ((pQueryInfo->type & TSDB_QUERY_TYPE_PROJECTION_QUERY) != 0) {
|
||||
if (numOfAggregation > 0 && pQueryInfo->groupbyExpr.numOfGroupCols == 0) {
|
||||
return invalidOperationMsg(msg, msg3);
|
||||
return invalidOperationMsg(msg, msg2);
|
||||
}
|
||||
|
||||
if (numOfAggregation > 0 || numOfSelectivity > 0) {
|
||||
|
@ -7784,8 +7815,9 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
|||
const char* msg3 = "start(end) time of query range required or time range too large";
|
||||
const char* msg4 = "interval query not supported, since the result of sub query not include valid timestamp column";
|
||||
const char* msg5 = "only tag query not compatible with normal column filter";
|
||||
const char* msg6 = "not support stddev/percentile in outer query yet";
|
||||
const char* msg7 = "drivative requires timestamp column exists in subquery";
|
||||
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* msg8 = "condition missing for join query";
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
|
@ -7814,31 +7846,34 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
|||
pQueryInfo->numOfTables = 0;
|
||||
|
||||
// parse the subquery in the first place
|
||||
int32_t numOfSub = (int32_t) taosArrayGetSize(pSqlNode->from->list);
|
||||
for(int32_t i = 0; i < numOfSub; ++i) {
|
||||
int32_t numOfSub = (int32_t)taosArrayGetSize(pSqlNode->from->list);
|
||||
for (int32_t i = 0; i < numOfSub; ++i) {
|
||||
code = doValidateSubquery(pSqlNode, i, pSql, pQueryInfo, tscGetErrorMsgPayload(pCmd));
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32_t timeWindowQuery =
|
||||
(TPARSER_HAS_TOKEN(pSqlNode->interval.interval) || TPARSER_HAS_TOKEN(pSqlNode->sessionVal.gap));
|
||||
|
||||
if (validateSelectNodeList(pCmd, pQueryInfo, pSqlNode->pSelNodeList, false, false, timeWindowQuery) != TSDB_CODE_SUCCESS) {
|
||||
if (validateSelectNodeList(pCmd, pQueryInfo, pSqlNode->pSelNodeList, false, false, timeWindowQuery) !=
|
||||
TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
// parse the window_state
|
||||
if (validateStateWindowNode(pCmd, pQueryInfo, pSqlNode, false) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
// todo NOT support yet
|
||||
for(int32_t i = 0; i < tscNumOfExprs(pQueryInfo); ++i) {
|
||||
for (int32_t i = 0; i < tscNumOfExprs(pQueryInfo); ++i) {
|
||||
SExprInfo* pExpr = tscExprGet(pQueryInfo, i);
|
||||
int32_t f = pExpr->base.functionId;
|
||||
if (f == TSDB_FUNC_STDDEV || f == TSDB_FUNC_PERCT) {
|
||||
int32_t f = pExpr->base.functionId;
|
||||
if (f == TSDB_FUNC_STDDEV || f == TSDB_FUNC_PERCT || f == TSDB_FUNC_INTERP) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
|
||||
}
|
||||
}
|
||||
|
||||
if ((timeWindowQuery || pQueryInfo->stateWindow) && f == TSDB_FUNC_LAST) {
|
||||
pExpr->base.numOfParams = 1;
|
||||
|
@ -7847,14 +7882,19 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
|||
}
|
||||
}
|
||||
|
||||
// todo derivative function requires ts column exists in subquery
|
||||
STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, 0)->pTableMeta;
|
||||
SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, 0);
|
||||
SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, 0);
|
||||
|
||||
if (tscNumOfExprs(pQueryInfo) > 1) {
|
||||
SExprInfo* pExpr = tscExprGet(pQueryInfo, 1);
|
||||
if (pExpr->base.functionId == TSDB_FUNC_DERIVATIVE && pSchema->type != TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
|
||||
if (pSchema->type != TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
int32_t numOfExprs = (int32_t)tscNumOfExprs(pQueryInfo);
|
||||
|
||||
for (int32_t i = 0; i < numOfExprs; ++i) {
|
||||
SExprInfo* pExpr = tscExprGet(pQueryInfo, i);
|
||||
|
||||
int32_t f = pExpr->base.functionId;
|
||||
if (f == TSDB_FUNC_DERIVATIVE || f == TSDB_FUNC_TWA || f == TSDB_FUNC_IRATE) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7863,6 +7903,10 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
|||
if (validateWhereNode(pQueryInfo, &pSqlNode->pWhere, pSql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
} else {
|
||||
if (pQueryInfo->numOfTables > 1) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg8);
|
||||
}
|
||||
}
|
||||
|
||||
// validate the interval info
|
||||
|
|
|
@ -484,8 +484,8 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
|
|||
}
|
||||
|
||||
if (shouldFree) { // in case of table-meta/vgrouplist query, automatically free it
|
||||
taosRemoveRef(tscObjRef, handle);
|
||||
tscDebug("0x%"PRIx64" sqlObj is automatically freed", pSql->self);
|
||||
taosRemoveRef(tscObjRef, handle);
|
||||
}
|
||||
|
||||
taosReleaseRef(tscObjRef, handle);
|
||||
|
|
|
@ -3604,10 +3604,10 @@ void* createQInfoFromQueryNode(SQueryInfo* pQueryInfo, STableGroupInfo* pTableGr
|
|||
|
||||
// todo refactor: filter should not be applied here.
|
||||
createFilterInfo(pQueryAttr, 0);
|
||||
pQueryAttr->numOfFilterCols = 0;
|
||||
|
||||
SArray* pa = NULL;
|
||||
if (stage == MASTER_SCAN) {
|
||||
pQueryAttr->createFilterOperator = false; // no need for parent query
|
||||
pa = createExecOperatorPlan(pQueryAttr);
|
||||
} else {
|
||||
pa = createGlobalMergePlan(pQueryAttr);
|
||||
|
|
|
@ -825,7 +825,10 @@ static void fetchNextBlockIfCompleted(SOperatorInfo* pOperator, bool* newgroup)
|
|||
SJoinStatus* pStatus = &pJoinInfo->status[i];
|
||||
if (pStatus->pBlock == NULL || pStatus->index >= pStatus->pBlock->info.rows) {
|
||||
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);
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
pStatus->index = 0;
|
||||
|
||||
if (pStatus->pBlock == NULL) {
|
||||
|
@ -1304,7 +1307,7 @@ void tscResetSqlCmd(SSqlCmd* pCmd, bool clearCachedMeta) {
|
|||
if (pCmd->pTableMetaMap != NULL) {
|
||||
STableMetaVgroupInfo* p = taosHashIterate(pCmd->pTableMetaMap, NULL);
|
||||
while (p) {
|
||||
tfree(p->pVgroupInfo);
|
||||
tscVgroupInfoClear(p->pVgroupInfo);
|
||||
tfree(p->pTableMeta);
|
||||
p = taosHashIterate(pCmd->pTableMetaMap, p);
|
||||
}
|
||||
|
@ -3278,6 +3281,8 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, __async_cb_func_t
|
|||
pnCmd->insertParam.pTableNameList = NULL;
|
||||
pnCmd->insertParam.pTableBlockHashList = NULL;
|
||||
|
||||
memset(&pnCmd->insertParam.tagData, 0, sizeof(STagData));
|
||||
|
||||
if (tscAddQueryInfo(pnCmd) != TSDB_CODE_SUCCESS) {
|
||||
terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
goto _error;
|
||||
|
@ -3521,6 +3526,7 @@ void executeQuery(SSqlObj* pSql, SQueryInfo* pQueryInfo) {
|
|||
|
||||
pSql->pSubs = calloc(pSql->subState.numOfSub, POINTER_BYTES);
|
||||
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) {
|
||||
SQueryInfo* pSub = taosArrayGetP(pQueryInfo->pUpstream, i);
|
||||
|
@ -4077,7 +4083,10 @@ SVgroupsInfo* tscVgroupsInfoDup(SVgroupsInfo* pVgroupsInfo) {
|
|||
|
||||
size_t size = sizeof(SVgroupInfo) * pVgroupsInfo->numOfVgroups + sizeof(SVgroupsInfo);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "taos.h"
|
||||
#include "tglobal.h"
|
||||
|
@ -132,7 +133,7 @@ void validateResultFields() {
|
|||
taos_free_result(res);
|
||||
|
||||
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);
|
||||
ASSERT_EQ(taos_errno(res), 0);
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#include "os.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "os.h"
|
||||
#include "taos.h"
|
||||
#include "ttoken.h"
|
||||
#include "tutil.h"
|
||||
|
@ -15,10 +17,10 @@ int main(int argc, char** argv) {
|
|||
extern void deltaToUtcInitOnce();
|
||||
/* test parse time function */
|
||||
TEST(testCase, parse_time) {
|
||||
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "GMT-8");
|
||||
deltaToUtcInitOnce();
|
||||
|
||||
|
||||
char t1[] = "2018-1-1 1:1:1.952798";
|
||||
char t13[] = "1970-1-1 0:0:0";
|
||||
|
||||
|
@ -77,15 +79,15 @@ TEST(testCase, parse_time) {
|
|||
taosParseTime(t12, &time1, strlen(t12), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "UTC");
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "UTC");
|
||||
deltaToUtcInitOnce();
|
||||
|
||||
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 0);
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "Asia/Shanghai");
|
||||
deltaToUtcInitOnce();
|
||||
|
||||
|
||||
char t14[] = "1970-1-1T0:0:0Z";
|
||||
taosParseTime(t14, &time, strlen(t14), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 0);
|
||||
|
@ -135,7 +137,7 @@ TEST(testCase, parse_time) {
|
|||
|
||||
|
||||
//======================== add some case ============================//
|
||||
|
||||
|
||||
char b1[] = "9999-12-31 23:59:59.999";
|
||||
taosParseTime(b1, &time, strlen(b1), TSDB_TIME_PRECISION_MILLI,0);
|
||||
EXPECT_EQ(time, 253402271999999);
|
||||
|
@ -145,27 +147,27 @@ TEST(testCase, parse_time) {
|
|||
taosParseTime(b2, &time, strlen(b2), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 1577811661321);
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "America/New_York");
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "America/New_York");
|
||||
deltaToUtcInitOnce();
|
||||
|
||||
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 18000 * MILLISECOND_PER_SECOND);
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "Asia/Tokyo");
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "Asia/Tokyo");
|
||||
deltaToUtcInitOnce();
|
||||
|
||||
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, -32400 * MILLISECOND_PER_SECOND);
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "Asia/Shanghai");
|
||||
deltaToUtcInitOnce();
|
||||
|
||||
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, -28800 * MILLISECOND_PER_SECOND);
|
||||
|
||||
char t[] = "2021-01-08T02:11:40.000+00:00";
|
||||
taosParseTime(t, &time, strlen(t), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
printf("%ld\n", time);
|
||||
printf("%" PRId64 "\n", time);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ extern char tsMnodeTmpDir[];
|
|||
extern char tsDataDir[];
|
||||
extern char tsLogDir[];
|
||||
extern char tsScriptDir[];
|
||||
extern int64_t tsMsPerDay[3];
|
||||
extern int64_t tsTickPerDay[3];
|
||||
|
||||
// system info
|
||||
extern char tsOsName[];
|
||||
|
|
|
@ -84,8 +84,8 @@ int32_t tsMaxNumOfOrderedResults = 100000;
|
|||
// 10 ms for sliding time, the value will changed in case of time precision changed
|
||||
int32_t tsMinSlidingTime = 10;
|
||||
|
||||
// 10 ms for interval time range, changed accordingly
|
||||
int32_t tsMinIntervalTime = 10;
|
||||
// 1 us for interval time range, changed accordingly
|
||||
int32_t tsMinIntervalTime = 1;
|
||||
|
||||
// 20sec, the maximum value of stream computing delay, changed accordingly
|
||||
int32_t tsMaxStreamComputDelay = 20000;
|
||||
|
@ -204,7 +204,7 @@ SDiskCfg tsDiskCfg[TSDB_MAX_DISKS];
|
|||
* TSDB_TIME_PRECISION_MICRO: 86400000000L
|
||||
* TSDB_TIME_PRECISION_NANO: 86400000000000L
|
||||
*/
|
||||
int64_t tsMsPerDay[] = {86400000L, 86400000000L, 86400000000000L};
|
||||
int64_t tsTickPerDay[] = {86400000L, 86400000000L, 86400000000000L};
|
||||
|
||||
// system info
|
||||
char tsOsName[10] = "Linux";
|
||||
|
|
|
@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED)
|
|||
ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME}
|
||||
POST_BUILD
|
||||
COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.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
|
||||
COMMENT "build jdbc driver")
|
||||
ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME})
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>2.0.31</version>
|
||||
<version>2.0.32</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>JDBCDriver</name>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>2.0.31</version>
|
||||
<version>2.0.32</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>JDBCDriver</name>
|
||||
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
|
||||
|
@ -113,16 +113,16 @@
|
|||
<include>**/*Test.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/TSDBJNIConnectorTest.java</exclude>
|
||||
<exclude>**/UnsignedNumberJniTest.java</exclude>
|
||||
<exclude>**/DatetimeBefore1970Test.java</exclude>
|
||||
<exclude>**/AppMemoryLeakTest.java</exclude>
|
||||
<exclude>**/AuthenticationTest.java</exclude>
|
||||
<exclude>**/TaosInfoMonitorTest.java</exclude>
|
||||
<exclude>**/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java</exclude>
|
||||
<exclude>**/DatetimeBefore1970Test.java</exclude>
|
||||
<exclude>**/FailOverTest.java</exclude>
|
||||
<exclude>**/InvalidResultSetPointerTest.java</exclude>
|
||||
<exclude>**/RestfulConnectionTest.java</exclude>
|
||||
<exclude>**/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java</exclude>
|
||||
<exclude>**/TSDBJNIConnectorTest.java</exclude>
|
||||
<exclude>**/TaosInfoMonitorTest.java</exclude>
|
||||
<exclude>**/UnsignedNumberJniTest.java</exclude>
|
||||
</excludes>
|
||||
<testFailureIgnore>true</testFailureIgnore>
|
||||
</configuration>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.taosdata.jdbc;
|
||||
|
||||
import com.taosdata.jdbc.rs.enums.TimestampFormat;
|
||||
import com.taosdata.jdbc.enums.TimestampFormat;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.Enumeration;
|
||||
|
@ -306,9 +306,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
|
|||
|
||||
@Override
|
||||
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
|
||||
|
||||
switch (resultSetHoldability) {
|
||||
case ResultSet.HOLD_CURSORS_OVER_COMMIT:
|
||||
break;
|
||||
|
@ -322,11 +319,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
|
|||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
|
||||
throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
|
||||
switch (resultSetHoldability) {
|
||||
case ResultSet.HOLD_CURSORS_OVER_COMMIT:
|
||||
break;
|
||||
|
@ -425,7 +418,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
|
|||
status = resultSet.getInt("server_status()");
|
||||
resultSet.close();
|
||||
}
|
||||
return status == 1 ? true : false;
|
||||
return status == 1;
|
||||
});
|
||||
|
||||
boolean status = false;
|
||||
|
@ -434,9 +427,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
|
|||
status = future.get();
|
||||
else
|
||||
status = future.get(timeout, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
} catch (TimeoutException e) {
|
||||
future.cancel(true);
|
||||
|
@ -452,8 +443,7 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
|
|||
if (isClosed)
|
||||
throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED);
|
||||
|
||||
if (clientInfoProps != null)
|
||||
clientInfoProps.setProperty(name, value);
|
||||
clientInfoProps.setProperty(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -461,8 +451,8 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
|
|||
if (isClosed)
|
||||
throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED);
|
||||
|
||||
for (Enumeration<Object> enumer = properties.keys(); enumer.hasMoreElements(); ) {
|
||||
String name = (String) enumer.nextElement();
|
||||
for (Enumeration<Object> enumeration = properties.keys(); enumeration.hasMoreElements(); ) {
|
||||
String name = (String) enumeration.nextElement();
|
||||
clientInfoProps.put(name, properties.getProperty(name));
|
||||
}
|
||||
}
|
||||
|
@ -528,14 +518,13 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
|
|||
if (milliseconds < 0)
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE);
|
||||
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNetworkTimeout() throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
|
||||
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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_MINOR_VERSION = 0;
|
||||
|
||||
private String precision = "ms";
|
||||
private String database;
|
||||
private String precision = TSDBConstants.DEFAULT_PRECISION;
|
||||
|
||||
public boolean allProceduresAreCallable() throws SQLException {
|
||||
return false;
|
||||
|
@ -1223,7 +1222,6 @@ public abstract class AbstractDatabaseMetaData extends WrapperImpl implements Da
|
|||
ResultSet databases = stmt.executeQuery("show databases");
|
||||
while (databases.next()) {
|
||||
String dbname = databases.getString("name");
|
||||
this.database = dbname;
|
||||
this.precision = databases.getString("precision");
|
||||
if (dbname.equalsIgnoreCase(catalog))
|
||||
return true;
|
||||
|
|
|
@ -58,7 +58,7 @@ public abstract class AbstractDriver implements Driver {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ public abstract class AbstractDriver implements Driver {
|
|||
url = url.substring(0, indexOfColon);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
return urlProps;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.taosdata.jdbc;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.operations.Bool;
|
||||
|
||||
import java.sql.ParameterMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
package com.taosdata.jdbc;
|
||||
|
||||
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.Calendar;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
|
@ -130,7 +132,7 @@ public class DatabaseMetaDataResultSet extends AbstractResultSet {
|
|||
public Timestamp getTimestamp(int columnIndex) throws SQLException {
|
||||
int colType = columnMetaDataList.get(columnIndex - 1).getColType();
|
||||
int nativeType = TSDBConstants.jdbcType2TaosType(colType);
|
||||
return rowCursor.getTimestamp(columnIndex,nativeType);
|
||||
return rowCursor.getTimestamp(columnIndex, nativeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -145,9 +147,7 @@ public class DatabaseMetaDataResultSet extends AbstractResultSet {
|
|||
|
||||
@Override
|
||||
public int findColumn(String columnLabel) throws SQLException {
|
||||
Iterator<ColumnMetaData> colMetaDataIt = this.columnMetaDataList.iterator();
|
||||
while (colMetaDataIt.hasNext()) {
|
||||
ColumnMetaData colMetaData = colMetaDataIt.next();
|
||||
for (ColumnMetaData colMetaData : this.columnMetaDataList) {
|
||||
if (colMetaData.getColName() != null && colMetaData.getColName().equals(columnLabel)) {
|
||||
return colMetaData.getColIndex();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import java.util.Calendar;
|
|||
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
|
||||
* compatibility needs.
|
||||
*/
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.util.Properties;
|
|||
public class TSDBConnection extends AbstractConnection {
|
||||
|
||||
private TSDBJNIConnector connector;
|
||||
private TSDBDatabaseMetaData databaseMetaData;
|
||||
private final TSDBDatabaseMetaData databaseMetaData;
|
||||
private boolean batchFetch;
|
||||
|
||||
public Boolean getBatchFetch() {
|
||||
|
|
|
@ -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_UINT = 13; //unsigned int
|
||||
public static final int TSDB_DATA_TYPE_UBIGINT = 14; //unsigned bigint
|
||||
|
||||
// nchar column max length
|
||||
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 TINYINT_PRECISION = 4;
|
||||
public static final int SMALLINT_PRECISION = 6;
|
||||
|
@ -67,10 +68,12 @@ public abstract class TSDBConstants {
|
|||
public static final int DOUBLE_PRECISION = 22;
|
||||
public static final int TIMESTAMP_MS_PRECISION = 23;
|
||||
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 DOUBLE_SCALE = 31;
|
||||
|
||||
public static final String DEFAULT_PRECISION = "ms";
|
||||
|
||||
public static int typeName2JdbcType(String type) {
|
||||
switch (type.toUpperCase()) {
|
||||
case "TIMESTAMP":
|
||||
|
|
|
@ -20,8 +20,8 @@ import java.sql.SQLException;
|
|||
|
||||
public class TSDBDatabaseMetaData extends AbstractDatabaseMetaData {
|
||||
|
||||
private String url;
|
||||
private String userName;
|
||||
private final String url;
|
||||
private final String userName;
|
||||
private Connection conn;
|
||||
|
||||
public TSDBDatabaseMetaData(String url, String userName) {
|
||||
|
|
|
@ -176,7 +176,7 @@ public class TSDBDriver extends AbstractDriver {
|
|||
int beginningOfSlashes = url.indexOf("//");
|
||||
int index = url.indexOf("?");
|
||||
if (index != -1) {
|
||||
String paramString = url.substring(index + 1, url.length());
|
||||
String paramString = url.substring(index + 1);
|
||||
url = url.substring(0, index);
|
||||
StringTokenizer queryParams = new StringTokenizer(paramString, "&");
|
||||
while (queryParams.hasMoreElements()) {
|
||||
|
@ -213,7 +213,7 @@ public class TSDBDriver extends AbstractDriver {
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -233,7 +233,7 @@ public class TSDBDriver extends AbstractDriver {
|
|||
return false;
|
||||
}
|
||||
|
||||
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||
public Logger getParentLogger() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
public class TSDBError {
|
||||
private static Map<Integer, String> TSDBErrorMap = new HashMap<>();
|
||||
private static final Map<Integer, String> TSDBErrorMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED, "connection already closed");
|
||||
|
@ -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_TIMESTAMP_PERCISION, "unknown timestamp precision");
|
||||
|
||||
/**************************************************/
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error");
|
||||
/**************************************************/
|
||||
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_SUBSCRIBE_FAILED, "failed to create subscription");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNSUPPORTED_ENCODING, "Unsupported encoding");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_TDENGINE_ERROR, "internal error of database");
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.taosdata.jdbc;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
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_OUT_OF_MEMORY = 0x2359; // JNI alloc memory failed
|
||||
|
||||
private static final HashSet<Integer> errorNumbers;
|
||||
private static final Set<Integer> errorNumbers = new HashSet();
|
||||
|
||||
static {
|
||||
errorNumbers = new HashSet();
|
||||
errorNumbers.add(ERROR_CONNECTION_CLOSED);
|
||||
errorNumbers.add(ERROR_UNSUPPORTED_METHOD);
|
||||
errorNumbers.add(ERROR_INVALID_VARIABLE);
|
||||
|
@ -65,7 +65,6 @@ public class TSDBErrorNumbers {
|
|||
errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE);
|
||||
errorNumbers.add(ERROR_UNKNOWN_TIMESTAMP_PERCISION);
|
||||
|
||||
/*****************************************************/
|
||||
errorNumbers.add(ERROR_SUBSCRIBE_FAILED);
|
||||
errorNumbers.add(ERROR_UNSUPPORTED_ENCODING);
|
||||
errorNumbers.add(ERROR_JNI_TDENGINE_ERROR);
|
||||
|
|
|
@ -29,14 +29,9 @@ import java.util.List;
|
|||
public class TSDBJNIConnector {
|
||||
private static volatile Boolean isInitialized = false;
|
||||
|
||||
private TaosInfo taosInfo = TaosInfo.getInstance();
|
||||
|
||||
// Connection pointer used in C
|
||||
private long taos = TSDBConstants.JNI_NULL_POINTER;
|
||||
|
||||
// result set status in current connection
|
||||
private boolean isResultsetClosed;
|
||||
|
||||
private final TaosInfo taosInfo = TaosInfo.getInstance();
|
||||
private long taos = TSDBConstants.JNI_NULL_POINTER; // Connection pointer used in C
|
||||
private boolean isResultsetClosed; // result set status in current connection
|
||||
private int affectedRows = -1;
|
||||
|
||||
static {
|
||||
|
@ -96,11 +91,9 @@ public class TSDBJNIConnector {
|
|||
|
||||
/**
|
||||
* Execute DML/DDL operation
|
||||
*
|
||||
* @throws SQLException
|
||||
*/
|
||||
public long executeQuery(String sql) throws SQLException {
|
||||
Long pSql = 0l;
|
||||
long pSql = 0L;
|
||||
try {
|
||||
pSql = this.executeQueryImp(sql.getBytes(TaosGlobalConfig.getCharset()), this.taos);
|
||||
taosInfo.stmt_count_increment();
|
||||
|
@ -161,7 +154,7 @@ public class TSDBJNIConnector {
|
|||
private native long getResultSetImp(long connection, 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);
|
||||
|
@ -195,7 +188,7 @@ public class TSDBJNIConnector {
|
|||
*/
|
||||
public int getSchemaMetaData(long resultSet, List<ColumnMetaData> 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;
|
||||
}
|
||||
|
||||
|
@ -218,8 +211,9 @@ public class TSDBJNIConnector {
|
|||
|
||||
/**
|
||||
* Get Result Time Precision.
|
||||
*
|
||||
* @return 0: ms, 1: us, 2: ns
|
||||
*/
|
||||
*/
|
||||
public int getResultTimePrecision(long sqlObj) {
|
||||
return this.getResultTimePrecisionImp(this.taos, sqlObj);
|
||||
}
|
||||
|
@ -228,8 +222,6 @@ public class TSDBJNIConnector {
|
|||
|
||||
/**
|
||||
* Execute close operation from C to release connection pointer by JNI
|
||||
*
|
||||
* @throws SQLException
|
||||
*/
|
||||
public void closeConnection() throws SQLException {
|
||||
int code = this.closeConnectionImp(this.taos);
|
||||
|
@ -268,8 +260,6 @@ public class TSDBJNIConnector {
|
|||
|
||||
/**
|
||||
* Unsubscribe, close a subscription
|
||||
*
|
||||
* @param subscription
|
||||
*/
|
||||
void unsubscribe(long subscription, boolean isKeep) {
|
||||
unsubscribeImp(subscription, isKeep);
|
||||
|
@ -282,13 +272,13 @@ public class TSDBJNIConnector {
|
|||
*/
|
||||
public boolean validateCreateTableSql(String sql) {
|
||||
int res = validateCreateTableSqlImp(taos, sql.getBytes());
|
||||
return res != 0 ? false : true;
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
private native int validateCreateTableSqlImp(long connection, byte[] sqlBytes);
|
||||
|
||||
public long prepareStmt(String sql) throws SQLException {
|
||||
Long stmt;
|
||||
long stmt;
|
||||
try {
|
||||
stmt = prepareStmtImp(sql.getBytes(), this.taos);
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -62,8 +62,8 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
|
||||
if (parameterCnt > 1) {
|
||||
// the table name is also a parameter, so ignore it.
|
||||
this.colData = new ArrayList<ColumnInfo>();
|
||||
this.tableTags = new ArrayList<TableTagInfo>();
|
||||
this.colData = new ArrayList<>();
|
||||
this.tableTags = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
* the TDengine client. Thus, some simple parsers/filters are intentionally added in this JDBC implementation in
|
||||
* order to process those supported SQLs.
|
||||
*/
|
||||
private void preprocessSql() {
|
||||
/***** For processing some of Spark SQLs*****/
|
||||
/***For processing some of Spark SQLs*/
|
||||
// should replace it first
|
||||
this.rawSql = this.rawSql.replaceAll("or (.*) is null", "");
|
||||
this.rawSql = this.rawSql.replaceAll(" where ", " WHERE ");
|
||||
|
@ -125,7 +129,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
}
|
||||
rawSql = rawSql.replace(matcher.group(1), tableFullName);
|
||||
}
|
||||
/***** for inner queries *****/
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -519,12 +522,10 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
}
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private static class TableTagInfo {
|
||||
private boolean isNull;
|
||||
private Object value;
|
||||
private int type;
|
||||
private final Object value;
|
||||
private final int type;
|
||||
|
||||
public TableTagInfo(Object value, int type) {
|
||||
this.value = value;
|
||||
|
@ -538,8 +539,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
}
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
public void setTableName(String name) {
|
||||
this.tableName = name;
|
||||
}
|
||||
|
@ -627,7 +626,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
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) {
|
||||
ColumnInfo p = new ColumnInfo();
|
||||
p.setType(type);
|
||||
|
@ -718,8 +717,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
ByteBuffer isNullList = ByteBuffer.allocate(num * Integer.BYTES);
|
||||
isNullList.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
for (int i = 0; i < num; ++i) {
|
||||
TableTagInfo tag = this.tableTags.get(i);
|
||||
for (TableTagInfo tag : this.tableTags) {
|
||||
if (tag.isNull) {
|
||||
typeList.put((byte) tag.type);
|
||||
isNullList.putInt(1);
|
||||
|
@ -818,7 +816,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
typeList, lengthList, isNullList);
|
||||
}
|
||||
|
||||
ColumnInfo colInfo = (ColumnInfo) this.colData.get(0);
|
||||
ColumnInfo colInfo = this.colData.get(0);
|
||||
if (colInfo == null) {
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "column data not bind");
|
||||
}
|
||||
|
@ -954,7 +952,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "not support data types");
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
connector.bindColumnDataArray(this.nativeStmtHandle, colDataList, lengthList, isNullList, col1.type, col1.bytes, rows, i);
|
||||
}
|
||||
|
|
|
@ -339,11 +339,11 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
|
|||
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDBConstants.TSDB_DATA_TYPE_INT:
|
||||
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;
|
||||
case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
|
||||
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;
|
||||
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
||||
return new BigDecimal(((Timestamp) this.rowData.getObject(columnIndex)).getTime());
|
||||
|
|
|
@ -36,23 +36,20 @@ public class TSDBResultSetBlockData {
|
|||
private int rowIndex = 0;
|
||||
|
||||
private List<ColumnMetaData> columnMetaDataList;
|
||||
private ArrayList<Object> colData = null;
|
||||
private ArrayList<Object> colData;
|
||||
|
||||
public TSDBResultSetBlockData(List<ColumnMetaData> colMeta, int numOfCols) {
|
||||
this.columnMetaDataList = colMeta;
|
||||
this.colData = new ArrayList<Object>(numOfCols);
|
||||
this.colData = new ArrayList<>(numOfCols);
|
||||
}
|
||||
|
||||
public TSDBResultSetBlockData() {
|
||||
this.colData = new ArrayList<Object>();
|
||||
this.colData = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
int size = this.colData.size();
|
||||
if (this.colData != null) {
|
||||
this.colData.clear();
|
||||
}
|
||||
|
||||
this.colData.clear();
|
||||
setNumOfCols(size);
|
||||
}
|
||||
|
||||
|
@ -69,7 +66,7 @@ public class TSDBResultSetBlockData {
|
|||
}
|
||||
|
||||
public void setNumOfCols(int numOfCols) {
|
||||
this.colData = new ArrayList<Object>(numOfCols);
|
||||
this.colData = new ArrayList<>(numOfCols);
|
||||
this.colData.addAll(Collections.nCopies(numOfCols, null));
|
||||
}
|
||||
|
||||
|
@ -166,15 +163,10 @@ public class TSDBResultSetBlockData {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The original type may not be a string type, but will be converted to by
|
||||
* calling this method
|
||||
*
|
||||
* @param col column index
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public String getString(int col) throws SQLException {
|
||||
Object obj = get(col);
|
||||
|
@ -387,7 +379,7 @@ public class TSDBResultSetBlockData {
|
|||
return null;
|
||||
}
|
||||
|
||||
return (long) val;
|
||||
return val;
|
||||
}
|
||||
|
||||
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: {
|
||||
|
|
|
@ -41,10 +41,7 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD
|
|||
}
|
||||
|
||||
public boolean isSearchable(int column) throws SQLException {
|
||||
if (column == 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return column == 1;
|
||||
}
|
||||
|
||||
public boolean isCurrency(int column) throws SQLException {
|
||||
|
|
|
@ -19,14 +19,13 @@ import com.taosdata.jdbc.utils.NullType;
|
|||
import java.math.BigDecimal;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
public class TSDBResultSetRowData {
|
||||
|
||||
private ArrayList<Object> data;
|
||||
private int colSize;
|
||||
private final int colSize;
|
||||
|
||||
public TSDBResultSetRowData(int colSize) {
|
||||
this.colSize = colSize;
|
||||
|
@ -390,27 +389,27 @@ public class TSDBResultSetRowData {
|
|||
|
||||
switch (nativeType) {
|
||||
case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: {
|
||||
Byte value = new Byte(String.valueOf(obj));
|
||||
byte value = new Byte(String.valueOf(obj));
|
||||
if (value >= 0)
|
||||
return value.toString();
|
||||
return Byte.toString(value);
|
||||
return Integer.toString(value & 0xff);
|
||||
}
|
||||
case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: {
|
||||
Short value = new Short(String.valueOf(obj));
|
||||
short value = new Short(String.valueOf(obj));
|
||||
if (value >= 0)
|
||||
return value.toString();
|
||||
return Short.toString(value);
|
||||
return Integer.toString(value & 0xffff);
|
||||
}
|
||||
case TSDBConstants.TSDB_DATA_TYPE_UINT: {
|
||||
Integer value = new Integer(String.valueOf(obj));
|
||||
int value = new Integer(String.valueOf(obj));
|
||||
if (value >= 0)
|
||||
return value.toString();
|
||||
return Long.toString(value & 0xffffffffl);
|
||||
return Integer.toString(value);
|
||||
return Long.toString(value & 0xffffffffL);
|
||||
}
|
||||
case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: {
|
||||
Long value = new Long(String.valueOf(obj));
|
||||
long value = new Long(String.valueOf(obj));
|
||||
if (value >= 0)
|
||||
return value.toString();
|
||||
return Long.toString(value);
|
||||
long lowValue = value & 0x7fffffffffffffffL;
|
||||
return BigDecimal.valueOf(lowValue).add(BigDecimal.valueOf(Long.MAX_VALUE)).add(BigDecimal.valueOf(1)).toString();
|
||||
}
|
||||
|
@ -432,25 +431,26 @@ public class TSDBResultSetRowData {
|
|||
|
||||
/**
|
||||
* !!! this method is invoked by JNI method and the index start from 0 in C implementations
|
||||
*
|
||||
* @param precision 0 : ms, 1 : us, 2 : ns
|
||||
*/
|
||||
public void setTimestamp(int col, long ts, int precision) {
|
||||
long milliseconds = 0;
|
||||
int fracNanoseconds = 0;
|
||||
long milliseconds;
|
||||
int fracNanoseconds;
|
||||
switch (precision) {
|
||||
case 0: {
|
||||
milliseconds = ts;
|
||||
fracNanoseconds = (int)(ts*1_000_000%1_000_000_000);
|
||||
fracNanoseconds = (int) (ts * 1_000_000 % 1_000_000_000);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
milliseconds = ts/1_000;
|
||||
fracNanoseconds = (int)(ts*1_000%1_000_000_000);
|
||||
milliseconds = ts / 1_000;
|
||||
fracNanoseconds = (int) (ts * 1_000 % 1_000_000_000);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
milliseconds = ts/1_000_000;
|
||||
fracNanoseconds = (int)(ts%1_000_000_000);
|
||||
milliseconds = ts / 1_000_000;
|
||||
fracNanoseconds = (int) (ts % 1_000_000_000);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -467,12 +467,10 @@ public class TSDBResultSetRowData {
|
|||
Object obj = data.get(col - 1);
|
||||
if (obj == null)
|
||||
return null;
|
||||
switch (nativeType) {
|
||||
case TSDBConstants.TSDB_DATA_TYPE_BIGINT:
|
||||
return new Timestamp((Long) obj);
|
||||
default:
|
||||
return (Timestamp) obj;
|
||||
if (nativeType == TSDBConstants.TSDB_DATA_TYPE_BIGINT) {
|
||||
return new Timestamp((Long) obj);
|
||||
}
|
||||
return (Timestamp) obj;
|
||||
}
|
||||
|
||||
public Object getObject(int col) {
|
||||
|
|
|
@ -47,9 +47,6 @@ public class TSDBSubscribe {
|
|||
|
||||
/**
|
||||
* close subscription
|
||||
*
|
||||
* @param keepProgress
|
||||
* @throws SQLException
|
||||
*/
|
||||
public void close(boolean keepProgress) throws SQLException {
|
||||
if (this.connecter.isClosed())
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.taosdata.jdbc.rs.enums;
|
||||
package com.taosdata.jdbc.enums;
|
||||
|
||||
public enum TimestampFormat {
|
||||
STRING,
|
|
@ -16,7 +16,7 @@ public class RestfulConnection extends AbstractConnection {
|
|||
private final String host;
|
||||
private final int port;
|
||||
private final String url;
|
||||
private volatile String database;
|
||||
private final String database;
|
||||
private final String token;
|
||||
/******************************************************/
|
||||
private boolean isClosed;
|
||||
|
|
|
@ -13,7 +13,7 @@ import java.util.Calendar;
|
|||
|
||||
public class RestfulPreparedStatement extends RestfulStatement implements PreparedStatement {
|
||||
|
||||
private ParameterMetaData parameterMetaData;
|
||||
private final ParameterMetaData parameterMetaData;
|
||||
private final String rawSql;
|
||||
private Object[] parameters;
|
||||
private boolean isPrepared;
|
||||
|
|
|
@ -7,7 +7,7 @@ import com.google.common.primitives.Longs;
|
|||
import com.google.common.primitives.Shorts;
|
||||
import com.taosdata.jdbc.*;
|
||||
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 java.math.BigDecimal;
|
||||
|
@ -17,19 +17,20 @@ import java.time.ZoneOffset;
|
|||
import java.time.format.DateTimeParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
||||
private volatile boolean isClosed;
|
||||
private int pos = -1;
|
||||
|
||||
private final String database;
|
||||
private final Statement statement;
|
||||
// data
|
||||
private final ArrayList<ArrayList<Object>> resultSet = new ArrayList<>();
|
||||
private final List<List<Object>> resultSet = new ArrayList<>();
|
||||
// meta
|
||||
private ArrayList<String> columnNames = new ArrayList<>();
|
||||
private ArrayList<Field> columns = new ArrayList<>();
|
||||
private RestfulResultSetMetaData metaData;
|
||||
private final List<String> columnNames = new ArrayList<>();
|
||||
private final List<Field> columns = new ArrayList<>();
|
||||
private final RestfulResultSetMetaData metaData;
|
||||
|
||||
private volatile boolean isClosed;
|
||||
private int pos = -1;
|
||||
|
||||
/**
|
||||
* 由一个result的Json构造结果集,对应执行show databases, show tables等这些语句,返回结果集,但无法获取结果集对应的meta,统一当成String处理
|
||||
|
@ -37,35 +38,30 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
* @param resultJson: 包含data信息的结果集,有sql返回的结果集
|
||||
***/
|
||||
public RestfulResultSet(String database, Statement statement, JSONObject resultJson) throws SQLException {
|
||||
this.database = database;
|
||||
this.statement = statement;
|
||||
|
||||
// get head
|
||||
JSONArray head = resultJson.getJSONArray("head");
|
||||
// get column metadata
|
||||
JSONArray columnMeta = resultJson.getJSONArray("column_meta");
|
||||
// get row 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
|
||||
Integer rows = resultJson.getInteger("rows");
|
||||
|
||||
// parse column_meta
|
||||
if (columnMeta != null) {
|
||||
parseColumnMeta_new(columnMeta);
|
||||
} else {
|
||||
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
|
||||
resultSet.clear();
|
||||
for (int rowIndex = 0; rowIndex < data.size(); rowIndex++) {
|
||||
ArrayList row = new ArrayList();
|
||||
List<Object> row = new ArrayList();
|
||||
JSONArray jsonRow = data.getJSONArray(rowIndex);
|
||||
for (int colIndex = 0; colIndex < this.metaData.getColumnCount(); colIndex++) {
|
||||
row.add(parseColumnData(jsonRow, colIndex, columns.get(colIndex).taos_type));
|
||||
|
@ -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
|
||||
if (value < 1_0000_0000_0000_0L)
|
||||
return new Timestamp(value);
|
||||
long epochSec = value / 1000_000l;
|
||||
long nanoAdjustment = value % 1000_000l * 1000l;
|
||||
long epochSec = value / 1000_000L;
|
||||
long nanoAdjustment = value % 1000_000L * 1000L;
|
||||
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
}
|
||||
case UTC: {
|
||||
|
@ -244,10 +240,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
|
||||
pos++;
|
||||
if (pos <= resultSet.size() - 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return pos <= resultSet.size() - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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
|
||||
public String getString(int columnIndex) throws SQLException {
|
||||
checkAvailability(columnIndex, resultSet.get(pos).size());
|
||||
|
@ -288,7 +274,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
wasNull = false;
|
||||
if (value instanceof Boolean)
|
||||
return (boolean) value;
|
||||
return Boolean.valueOf(value.toString());
|
||||
return Boolean.parseBoolean(value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -443,9 +429,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
return null;
|
||||
if (value instanceof Timestamp)
|
||||
return new Date(((Timestamp) value).getTime());
|
||||
Date date = null;
|
||||
date = Utils.parseDate(value.toString());
|
||||
return date;
|
||||
return Utils.parseDate(value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -460,8 +444,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
Time time = null;
|
||||
try {
|
||||
time = Utils.parseTime(value.toString());
|
||||
} catch (DateTimeParseException e) {
|
||||
time = null;
|
||||
} catch (DateTimeParseException ignored) {
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
@ -525,9 +508,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
return null;
|
||||
|
||||
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)
|
||||
return new BigDecimal(Double.valueOf(value.toString()));
|
||||
return BigDecimal.valueOf(Double.parseDouble(value.toString()));
|
||||
if (value instanceof Timestamp)
|
||||
return new BigDecimal(((Timestamp) value).getTime());
|
||||
BigDecimal ret;
|
||||
|
@ -637,36 +620,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
if (isClosed())
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -710,5 +663,4 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
return isClosed;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -7,20 +7,17 @@ import java.sql.ResultSetMetaData;
|
|||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class RestfulResultSetMetaData extends WrapperImpl implements ResultSetMetaData {
|
||||
|
||||
private final String database;
|
||||
private List<RestfulResultSet.Field> fields;
|
||||
private final RestfulResultSet resultSet;
|
||||
private final List<RestfulResultSet.Field> fields;
|
||||
|
||||
public RestfulResultSetMetaData(String database, ArrayList<RestfulResultSet.Field> fields, RestfulResultSet resultSet) {
|
||||
public RestfulResultSetMetaData(String database, List<RestfulResultSet.Field> fields, RestfulResultSet resultSet) {
|
||||
this.database = database;
|
||||
this.fields = fields == null ? Collections.emptyList() : fields;
|
||||
this.resultSet = resultSet;
|
||||
}
|
||||
|
||||
public List<RestfulResultSet.Field> getFields() {
|
||||
|
@ -141,8 +138,8 @@ public class RestfulResultSetMetaData extends WrapperImpl implements ResultSetMe
|
|||
|
||||
@Override
|
||||
public String getColumnTypeName(int column) throws SQLException {
|
||||
int taos_type = fields.get(column - 1).taos_type;
|
||||
return TSDBConstants.taosType2JdbcTypeName(taos_type);
|
||||
int taosType = fields.get(column - 1).taos_type;
|
||||
return TSDBConstants.taosType2JdbcTypeName(taosType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -35,10 +35,6 @@ public class RestfulStatement extends AbstractStatement {
|
|||
if (!SqlSyntaxValidator.isValidForExecuteQuery(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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
|
||||
if (SqlSyntaxValidator.isDatabaseUnspecifiedUpdate(sql)) {
|
||||
return executeOneUpdate(url, sql);
|
||||
}
|
||||
|
||||
return executeOneUpdate(url, sql);
|
||||
}
|
||||
|
|
|
@ -27,19 +27,18 @@ public class HttpClientPoolUtil {
|
|||
private static final int DEFAULT_MAX_TOTAL = 1000;
|
||||
private static final int DEFAULT_HTTP_KEEP_TIME = 15000;
|
||||
|
||||
private static PoolingHttpClientConnectionManager connectionManager;
|
||||
private static CloseableHttpClient httpClient;
|
||||
|
||||
private static synchronized void initPools() {
|
||||
if (httpClient == null) {
|
||||
connectionManager = new PoolingHttpClientConnectionManager();
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
|
||||
connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
|
||||
connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL);
|
||||
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));
|
||||
int keepTime = DEFAULT_HTTP_KEEP_TIME * 1000;
|
||||
while (it.hasNext()) {
|
||||
|
|
|
@ -14,10 +14,6 @@
|
|||
*****************************************************************************/
|
||||
package com.taosdata.jdbc.utils;
|
||||
|
||||
import com.taosdata.jdbc.TSDBConnection;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
public class SqlSyntaxValidator {
|
||||
|
||||
private static final String[] SQL = {"select", "insert", "import", "create", "use", "alter", "drop", "set", "show", "describe"};
|
||||
|
@ -26,12 +22,6 @@ public class SqlSyntaxValidator {
|
|||
|
||||
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) {
|
||||
for (String prefix : updateSQL) {
|
||||
if (sql.trim().toLowerCase().startsWith(prefix))
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.google.common.collect.TreeRangeSet;
|
|||
import com.taosdata.jdbc.enums.TimestampPrecision;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Date;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
|
@ -160,7 +161,7 @@ public class Utils {
|
|||
String paraStr;
|
||||
if (para != null) {
|
||||
if (para instanceof byte[]) {
|
||||
paraStr = new String((byte[]) para, Charset.forName("UTF-8"));
|
||||
paraStr = new String((byte[]) para, StandardCharsets.UTF_8);
|
||||
} else {
|
||||
paraStr = para.toString();
|
||||
}
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
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 {
|
|||
conn.abort(null);
|
||||
}
|
||||
|
||||
@Test(expected = SQLFeatureNotSupportedException.class)
|
||||
@Test
|
||||
public void setNetworkTimeout() throws SQLException {
|
||||
conn.setNetworkTimeout(null, 1000);
|
||||
}
|
||||
|
||||
@Test(expected = SQLFeatureNotSupportedException.class)
|
||||
@Test
|
||||
public void getNetworkTimeout() throws SQLException {
|
||||
conn.getNetworkTimeout();
|
||||
int networkTimeout = conn.getNetworkTimeout();
|
||||
Assert.assertEquals(0, networkTimeout);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -14,24 +14,6 @@ public class TSDBStatementTest {
|
|||
private static Connection conn;
|
||||
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
|
||||
public void executeUpdate() {
|
||||
final String dbName = ("test_" + UUID.randomUUID()).replace("-", "_").substring(0, 32);
|
||||
|
@ -173,10 +155,6 @@ public class TSDBStatementTest {
|
|||
Assert.assertEquals(3, meta.getColumnCount());
|
||||
int count = 0;
|
||||
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++;
|
||||
}
|
||||
Assert.assertEquals(1, count);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.taosdata.jdbc.cases;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
@ -12,21 +13,19 @@ public class AppMemoryLeakTest {
|
|||
@Test(expected = SQLException.class)
|
||||
public void testCreateTooManyConnection() throws ClassNotFoundException, SQLException {
|
||||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||||
int conCnt = 0;
|
||||
while (true) {
|
||||
Connection conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata");
|
||||
System.out.println(conCnt++ + " : " + conn);
|
||||
Assert.assertNotNull(conn);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = Exception.class)
|
||||
public void testCreateTooManyStatement() throws ClassNotFoundException, SQLException {
|
||||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||||
int stmtCnt = 0;
|
||||
Connection conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata");
|
||||
while (true) {
|
||||
Statement stmt = conn.createStatement();
|
||||
System.out.println(++stmtCnt + " : " + stmt);
|
||||
Assert.assertNotNull(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.taosdata.jdbc.rs;
|
||||
package com.taosdata.jdbc.cases;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
|
@ -60,7 +60,6 @@ public class BatchInsertTest {
|
|||
final int index = i;
|
||||
executorService.execute(() -> {
|
||||
try {
|
||||
long startTime = System.currentTimeMillis();
|
||||
Statement statement = connection.createStatement(); // get statement
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("INSERT INTO " + tablePrefix + index + " VALUES");
|
||||
|
@ -73,8 +72,6 @@ public class BatchInsertTest {
|
|||
}
|
||||
statement.addBatch(sb.toString());
|
||||
statement.executeBatch();
|
||||
long endTime = System.currentTimeMillis();
|
||||
System.out.println("Thread " + index + " takes " + (endTime - startTime) + " microseconds");
|
||||
connection.commit();
|
||||
statement.close();
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -31,9 +31,6 @@ public class ConnectMultiTaosdByRestfulWithDifferentTokenTest {
|
|||
ResultSet rs = stmt.executeQuery("select server_status()");
|
||||
ResultSetMetaData meta = rs.getMetaData();
|
||||
while (rs.next()) {
|
||||
for (int i = 1; i <= meta.getColumnCount(); i++) {
|
||||
System.out.println(meta.getColumnLabel(i) + ": " + rs.getString(i));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
|
|
|
@ -1,64 +1,76 @@
|
|||
package com.taosdata.jdbc.cases;
|
||||
|
||||
import com.taosdata.jdbc.utils.TimestampUtil;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.*;
|
||||
|
||||
import java.sql.*;
|
||||
|
||||
public class DatetimeBefore1970Test {
|
||||
|
||||
private static Connection conn;
|
||||
private static final String host = "127.0.0.1";
|
||||
private Connection conn;
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
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('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 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) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("timestamp: " + Long.MAX_VALUE + ", string: " + TimestampUtil.longToDatetime(Long.MAX_VALUE));
|
||||
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() {
|
||||
@Before
|
||||
public void before() {
|
||||
try {
|
||||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||||
conn = DriverManager.getConnection("jdbc:TAOS://127.0.0.1:6030/?user=root&password=taosdata");
|
||||
conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata");
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("drop database if exists test_timestamp");
|
||||
stmt.execute("create database if not exists test_timestamp keep 36500");
|
||||
stmt.execute("use test_timestamp");
|
||||
stmt.execute("create table weather(ts timestamp,f1 float)");
|
||||
stmt.close();
|
||||
} catch (ClassNotFoundException | SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
@After
|
||||
public void after() {
|
||||
try {
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("drop database if exists test_timestamp");
|
||||
if (conn != null)
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
|
|
|
@ -20,7 +20,6 @@ public class ImportTest {
|
|||
@BeforeClass
|
||||
public static void before() {
|
||||
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");
|
||||
|
@ -33,8 +32,6 @@ public class ImportTest {
|
|||
stmt.close();
|
||||
|
||||
ts = System.currentTimeMillis();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -47,7 +44,6 @@ public class ImportTest {
|
|||
for (int i = 0; i < 50; i++) {
|
||||
ts++;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +80,6 @@ public class ImportTest {
|
|||
long t = (++ts) + a;
|
||||
sqlBuilder.append("(").append(t).append(",").append((100 + i)).append(",").append(i).append(") ");
|
||||
}
|
||||
System.out.println(sqlBuilder.toString());
|
||||
int rows = stmt.executeUpdate(sqlBuilder.toString());
|
||||
assertEquals(50, rows);
|
||||
} catch (SQLException e) {
|
||||
|
|
|
@ -41,7 +41,6 @@ public class MicroSecondPrecisionJNITest {
|
|||
rs.next();
|
||||
|
||||
Timestamp timestamp = rs.getTimestamp(1);
|
||||
System.out.println(timestamp);
|
||||
long ts = timestamp.getTime();
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
int nanos = timestamp.getNanos();
|
||||
|
|
|
@ -7,7 +7,7 @@ import org.junit.Test;
|
|||
import java.sql.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class MultiThreadsWithSameStatmentTest {
|
||||
public class MultiThreadsWithSameStatementTest {
|
||||
|
||||
|
||||
private class Service {
|
||||
|
@ -16,12 +16,11 @@ public class MultiThreadsWithSameStatmentTest {
|
|||
|
||||
public Service() {
|
||||
try {
|
||||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||||
conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata");
|
||||
stmt = conn.createStatement();
|
||||
stmt.execute("create database if not exists jdbctest");
|
||||
stmt.executeUpdate("create table if not exists jdbctest.weather (ts timestamp, f1 int)");
|
||||
} catch (ClassNotFoundException | SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -48,10 +47,6 @@ public class MultiThreadsWithSameStatmentTest {
|
|||
ResultSet resultSet = service.stmt.executeQuery("select * from jdbctest.weather");
|
||||
while (resultSet.next()) {
|
||||
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();
|
||||
service.release();
|
|
@ -17,11 +17,6 @@ public class NullValueInResultSetJNITest {
|
|||
ResultSet rs = stmt.executeQuery("select * from weather");
|
||||
ResultSetMetaData meta = rs.getMetaData();
|
||||
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) {
|
||||
|
|
|
@ -19,9 +19,7 @@ public class NullValueInResultSetRestfulTest {
|
|||
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) {
|
||||
|
|
|
@ -21,7 +21,6 @@ public class QueryDataTest {
|
|||
@Before
|
||||
public void createDatabase() {
|
||||
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");
|
||||
|
@ -36,7 +35,7 @@ public class QueryDataTest {
|
|||
String createTableSql = "create table " + stbName + "(ts timestamp, name binary(64))";
|
||||
statement.executeUpdate(createTableSql);
|
||||
|
||||
} catch (ClassNotFoundException | SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +43,6 @@ public class QueryDataTest {
|
|||
@Test
|
||||
public void testQueryBinaryData() throws SQLException {
|
||||
String insertSql = "insert into " + stbName + " values(now, 'taosdata')";
|
||||
System.out.println(insertSql);
|
||||
statement.executeUpdate(insertSql);
|
||||
|
||||
String querySql = "select * from " + stbName;
|
||||
|
@ -52,7 +50,6 @@ public class QueryDataTest {
|
|||
|
||||
while (rs.next()) {
|
||||
String name = rs.getString(2);
|
||||
System.out.println("name = " + name);
|
||||
assertEquals("taosdata", name);
|
||||
}
|
||||
rs.close();
|
||||
|
|
|
@ -31,7 +31,7 @@ public class ResultSetMetaShouldNotBeNullRestfulTest {
|
|||
|
||||
// then
|
||||
Assert.assertNotNull(metaData);
|
||||
Assert.assertEquals(0, columnCount);
|
||||
Assert.assertEquals(2, columnCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -53,7 +53,7 @@ public class ResultSetMetaShouldNotBeNullRestfulTest {
|
|||
// then
|
||||
Assert.assertEquals(true, execute);
|
||||
Assert.assertNotNull(metaData);
|
||||
Assert.assertEquals(0, columnCount);
|
||||
Assert.assertEquals(2, columnCount);
|
||||
}
|
||||
|
||||
@Before
|
||||
|
|
|
@ -19,7 +19,6 @@ public class SelectTest {
|
|||
@Before
|
||||
public void createDatabaseAndTable() {
|
||||
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");
|
||||
|
@ -31,8 +30,6 @@ public class SelectTest {
|
|||
stmt.execute("create database if not exists " + dbName);
|
||||
stmt.execute("create table if not exists " + dbName + "." + tName + " (ts timestamp, k int, v int)");
|
||||
stmt.close();
|
||||
} catch (ClassNotFoundException e) {
|
||||
return;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -47,7 +44,6 @@ public class SelectTest {
|
|||
for (int i = 0; i < 50; i++) {
|
||||
ts++;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ public class StableTest {
|
|||
@BeforeClass
|
||||
public static void createDatabase() {
|
||||
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");
|
||||
|
@ -34,8 +33,6 @@ public class StableTest {
|
|||
statement.execute("create database if not exists " + dbName);
|
||||
statement.execute("use " + dbName);
|
||||
statement.close();
|
||||
} catch (ClassNotFoundException e) {
|
||||
return;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -68,9 +65,6 @@ public class StableTest {
|
|||
String sql = "describe " + stbName;
|
||||
ResultSet rs = stmt.executeQuery(sql);
|
||||
while (rs.next()) {
|
||||
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
|
||||
System.out.println(i + ":" + rs.getString(i));
|
||||
}
|
||||
num++;
|
||||
}
|
||||
rs.close();
|
||||
|
@ -86,9 +80,6 @@ public class StableTest {
|
|||
try (Statement stmt = connection.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("describe t1");
|
||||
while (rs.next()) {
|
||||
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
|
||||
System.out.printf("%d: %s\n", i, rs.getString(i));
|
||||
}
|
||||
num++;
|
||||
}
|
||||
rs.close();
|
||||
|
|
|
@ -8,11 +8,6 @@ import java.sql.*;
|
|||
public class RestfulDriverTest {
|
||||
private static final String host = "127.0.0.1";
|
||||
|
||||
@Test
|
||||
public void connect() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptsURL() throws SQLException {
|
||||
Driver driver = new RestfulDriver();
|
||||
|
@ -27,9 +22,7 @@ public class RestfulDriverTest {
|
|||
Driver driver = new RestfulDriver();
|
||||
final String url = "";
|
||||
DriverPropertyInfo[] propertyInfo = driver.getPropertyInfo(url, null);
|
||||
for (DriverPropertyInfo prop : propertyInfo) {
|
||||
System.out.println(prop);
|
||||
}
|
||||
Assert.assertNotNull(propertyInfo);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -10,132 +10,151 @@ import java.util.Random;
|
|||
public class RestfulJDBCTest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
private static Connection connection;
|
||||
private Random random = new Random(System.currentTimeMillis());
|
||||
private final Random random = new Random(System.currentTimeMillis());
|
||||
private Connection connection;
|
||||
|
||||
/**
|
||||
* select * from log.log
|
||||
**/
|
||||
@Test
|
||||
public void testCase001() {
|
||||
try {
|
||||
Statement statement = connection.createStatement();
|
||||
ResultSet resultSet = statement.executeQuery("select * from log.log");
|
||||
ResultSetMetaData metaData = resultSet.getMetaData();
|
||||
while (resultSet.next()) {
|
||||
for (int i = 1; i <= metaData.getColumnCount(); i++) {
|
||||
String column = metaData.getColumnLabel(i);
|
||||
String value = resultSet.getString(i);
|
||||
System.out.print(column + ":" + value + "\t");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
statement.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// given
|
||||
String sql = "drop database if exists restful_test";
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
// then
|
||||
Assert.assertFalse(execute);
|
||||
|
||||
// given
|
||||
sql = "create database if not exists restful_test";
|
||||
// when
|
||||
execute = execute(connection, sql);
|
||||
// then
|
||||
Assert.assertFalse(execute);
|
||||
|
||||
// given
|
||||
sql = "use restful_test";
|
||||
// when
|
||||
execute = execute(connection, sql);
|
||||
// then
|
||||
Assert.assertFalse(execute);
|
||||
}
|
||||
|
||||
/**
|
||||
* create database
|
||||
*/
|
||||
@Test
|
||||
public void testCase002() {
|
||||
try (Statement stmt = connection.createStatement()) {
|
||||
stmt.execute("drop database if exists restful_test");
|
||||
stmt.execute("create database if not exists restful_test");
|
||||
stmt.execute("use restful_test");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create super table
|
||||
***/
|
||||
@Test
|
||||
public void testCase003() {
|
||||
try (Statement stmt = connection.createStatement()) {
|
||||
stmt.execute("create table weather(ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// given
|
||||
String sql = "create table weather(ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)";
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
// then
|
||||
Assert.assertFalse(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase004() {
|
||||
try (Statement stmt = connection.createStatement()) {
|
||||
for (int i = 1; i <= 100; i++) {
|
||||
stmt.execute("create table t" + i + " using weather tags('beijing', '" + i + "')");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
for (int i = 1; i <= 100; i++) {
|
||||
// given
|
||||
String sql = "create table t" + i + " using weather tags('beijing', '" + i + "')";
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
// then
|
||||
Assert.assertFalse(execute);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCase005() {
|
||||
try (Statement stmt = connection.createStatement()) {
|
||||
int rows = 0;
|
||||
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;
|
||||
}
|
||||
int rows = 0;
|
||||
for (int i = 0; i < 10; 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;
|
||||
}
|
||||
Assert.assertEquals(1000, rows);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Assert.assertEquals(1000, rows);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase006() {
|
||||
try (Statement stmt = connection.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("select * from weather");
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
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
|
||||
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()) {
|
||||
ResultSet rs = stmt.executeQuery("select * from weather");
|
||||
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();
|
||||
}
|
||||
return stmt.executeUpdate(sql);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private boolean execute(Connection connection, String sql) {
|
||||
try (Statement stmt = connection.createStatement()) {
|
||||
return stmt.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;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
try {
|
||||
connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=root&password=taosdata");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void before() throws ClassNotFoundException, SQLException {
|
||||
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
|
||||
connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=root&password=taosdata");
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void after() throws SQLException {
|
||||
if (connection != null)
|
||||
connection.close();
|
||||
@After
|
||||
public void after() {
|
||||
try {
|
||||
if (connection != null)
|
||||
connection.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,12 +27,9 @@ public class RestfulPreparedStatementTest {
|
|||
ResultSet rs = pstmt_select.executeQuery();
|
||||
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();
|
||||
}
|
||||
int columnCount = meta.getColumnCount();
|
||||
Assert.assertEquals(10, columnCount);
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -373,18 +370,19 @@ public class RestfulPreparedStatementTest {
|
|||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
try {
|
||||
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
|
||||
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");
|
||||
stmt.execute("create database if not exists test_pstmt");
|
||||
stmt.execute("use 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("create table t1 using weather tags('beijing')");
|
||||
}
|
||||
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("drop database if exists test_pstmt");
|
||||
stmt.execute("create database if not exists test_pstmt");
|
||||
stmt.execute("use 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("create table t1 using weather tags('beijing')");
|
||||
stmt.close();
|
||||
|
||||
pstmt_insert = conn.prepareStatement(sql_insert);
|
||||
pstmt_select = conn.prepareStatement(sql_select);
|
||||
} catch (ClassNotFoundException | SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.UUID;
|
|||
|
||||
public class RestfulStatementTest {
|
||||
private static final String host = "127.0.0.1";
|
||||
|
||||
private static Connection conn;
|
||||
private static Statement stmt;
|
||||
|
||||
|
@ -21,11 +22,11 @@ public class RestfulStatementTest {
|
|||
ResultSet rs = stmt.executeQuery("show databases");
|
||||
Assert.assertNotNull(rs);
|
||||
ResultSetMetaData meta = rs.getMetaData();
|
||||
int columnCount = meta.getColumnCount();
|
||||
Assert.assertTrue(columnCount > 1);
|
||||
while (rs.next()) {
|
||||
for (int i = 1; i <= meta.getColumnCount(); i++) {
|
||||
System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t");
|
||||
}
|
||||
System.out.println();
|
||||
Assert.assertEquals("name", meta.getColumnLabel(1));
|
||||
Assert.assertNotNull(rs.getString("name"));
|
||||
}
|
||||
rs.close();
|
||||
} catch (SQLException e) {
|
||||
|
@ -174,10 +175,10 @@ public class RestfulStatementTest {
|
|||
Assert.assertEquals(3, meta.getColumnCount());
|
||||
int count = 0;
|
||||
while (rs.next()) {
|
||||
for (int i = 1; i <= meta.getColumnCount(); i++) {
|
||||
System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t");
|
||||
}
|
||||
System.out.println();
|
||||
Assert.assertEquals("ts", meta.getColumnLabel(1));
|
||||
Assert.assertNotNull(rs.getTimestamp(1));
|
||||
Assert.assertEquals("temperature", meta.getColumnLabel(2));
|
||||
Assert.assertEquals(22.33, rs.getFloat(2), 0.001f);
|
||||
count++;
|
||||
}
|
||||
Assert.assertEquals(1, count);
|
||||
|
@ -388,15 +389,12 @@ public class RestfulStatementTest {
|
|||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
try {
|
||||
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
|
||||
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");
|
||||
conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata", properties);
|
||||
stmt = conn.createStatement();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -1,342 +1,586 @@
|
|||
package com.taosdata.jdbc.rs;
|
||||
|
||||
import com.taosdata.jdbc.utils.SQLExecutor;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.*;
|
||||
import org.junit.runners.MethodSorters;
|
||||
|
||||
import java.sql.*;
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class SQLTest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
private static Connection connection;
|
||||
|
||||
@Test
|
||||
public void testCase001() {
|
||||
// given
|
||||
String sql = "create database if not exists restful_test";
|
||||
SQLExecutor.execute(connection, sql);
|
||||
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
|
||||
// then
|
||||
Assert.assertFalse(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase002() {
|
||||
// given
|
||||
String sql = "use restful_test";
|
||||
SQLExecutor.execute(connection, sql);
|
||||
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
|
||||
// then
|
||||
Assert.assertFalse(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase003() {
|
||||
// given
|
||||
String sql = "show databases";
|
||||
SQLExecutor.executeWithResult(connection, sql);
|
||||
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
|
||||
// then
|
||||
Assert.assertTrue(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase004() {
|
||||
// given
|
||||
String sql = "show tables";
|
||||
SQLExecutor.executeWithResult(connection, sql);
|
||||
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
|
||||
// then
|
||||
Assert.assertTrue(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase005() {
|
||||
// given
|
||||
String sql = "show stables";
|
||||
SQLExecutor.executeWithResult(connection, sql);
|
||||
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
|
||||
// then
|
||||
Assert.assertTrue(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase006() {
|
||||
// given
|
||||
String sql = "show dnodes";
|
||||
SQLExecutor.executeWithResult(connection, sql);
|
||||
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
|
||||
// then
|
||||
Assert.assertTrue(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase007() {
|
||||
// given
|
||||
String sql = "show vgroups";
|
||||
SQLExecutor.executeWithResult(connection, sql);
|
||||
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
|
||||
// then
|
||||
Assert.assertTrue(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase008() {
|
||||
// given
|
||||
String sql = "drop table if exists restful_test.weather";
|
||||
SQLExecutor.execute(connection, sql);
|
||||
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
|
||||
// then
|
||||
Assert.assertFalse(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase009() {
|
||||
// given
|
||||
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
|
||||
public void testCase010() {
|
||||
// given
|
||||
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
|
||||
public void testCase011() {
|
||||
// given
|
||||
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
|
||||
public void testCase012() {
|
||||
// given
|
||||
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
|
||||
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)";
|
||||
SQLExecutor.executeUpdate(connection, sql);
|
||||
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
|
||||
// then
|
||||
Assert.assertFalse(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase014() {
|
||||
// given
|
||||
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
|
||||
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)";
|
||||
SQLExecutor.executeUpdate(connection, sql);
|
||||
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
|
||||
// then
|
||||
Assert.assertFalse(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
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)";
|
||||
SQLExecutor.executeUpdate(connection, sql);
|
||||
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
|
||||
// then
|
||||
Assert.assertFalse(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
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)";
|
||||
SQLExecutor.executeUpdate(connection, sql);
|
||||
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
|
||||
// then
|
||||
Assert.assertFalse(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase018() {
|
||||
// given
|
||||
String sql = "select * from restful_test.t1";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
// then
|
||||
Assert.assertTrue(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase019() {
|
||||
// given
|
||||
String sql = "select * from restful_test.weather";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
// then
|
||||
Assert.assertTrue(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase020() {
|
||||
// given
|
||||
String sql = "select ts, temperature from restful_test.t1";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
// then
|
||||
Assert.assertTrue(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase021() {
|
||||
// given
|
||||
String sql = "select ts, temperature from restful_test.weather";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
// then
|
||||
Assert.assertTrue(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase022() {
|
||||
// given
|
||||
String sql = "select temperature, ts from restful_test.t1";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
// then
|
||||
Assert.assertTrue(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase023() {
|
||||
// given
|
||||
String sql = "select temperature, ts from restful_test.weather";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
boolean execute = execute(connection, sql);
|
||||
// then
|
||||
Assert.assertTrue(execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase024() {
|
||||
// given
|
||||
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
|
||||
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)";
|
||||
SQLExecutor.executeUpdate(connection, sql);
|
||||
// when
|
||||
int affectedRows = executeUpdate(connection, sql);
|
||||
// then
|
||||
Assert.assertEquals(2, affectedRows);
|
||||
}
|
||||
|
||||
@Test
|
||||
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)";
|
||||
SQLExecutor.executeUpdate(connection, sql);
|
||||
|
||||
// when
|
||||
int affectedRows = executeUpdate(connection, sql);
|
||||
// then
|
||||
Assert.assertEquals(2, affectedRows);
|
||||
}
|
||||
|
||||
@Test
|
||||
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)";
|
||||
SQLExecutor.executeUpdate(connection, sql);
|
||||
// when
|
||||
int affectedRows = executeUpdate(connection, sql);
|
||||
// then
|
||||
Assert.assertEquals(4, affectedRows);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase028() {
|
||||
// given
|
||||
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
|
||||
public void testCase029() {
|
||||
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
|
||||
public void testCase030() {
|
||||
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
|
||||
public void testCase031() {
|
||||
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
|
||||
public void testCase032() {
|
||||
String sql = "select count(*) from restful_test.weather";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
ResultSet rs = executeQuery(connection, sql);
|
||||
// then
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase033() {
|
||||
String sql = "select first(*) from restful_test.weather";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
ResultSet rs = executeQuery(connection, sql);
|
||||
// then
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase034() {
|
||||
String sql = "select last(*) from restful_test.weather";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
ResultSet rs = executeQuery(connection, sql);
|
||||
// then
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase035() {
|
||||
String sql = "select last_row(*) from restful_test.weather";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
ResultSet rs = executeQuery(connection, sql);
|
||||
// then
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase036() {
|
||||
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
|
||||
public void testCase037() {
|
||||
String sql = "select database()";
|
||||
SQLExecutor.execute(connection, "use restful_test");
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
ResultSet rs = executeQuery(connection, sql);
|
||||
// then
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase038() {
|
||||
String sql = "select client_version()";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
ResultSet rs = executeQuery(connection, sql);
|
||||
// then
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase039() {
|
||||
String sql = "select server_status()";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
ResultSet rs = executeQuery(connection, sql);
|
||||
// then
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase040() {
|
||||
String sql = "select server_status() as status";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
ResultSet rs = executeQuery(connection, sql);
|
||||
// then
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase041() {
|
||||
String sql = "select tbname, location from restful_test.weather";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
ResultSet rs = executeQuery(connection, sql);
|
||||
// then
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase042() {
|
||||
String sql = "select count(tbname) from restful_test.weather";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
ResultSet rs = executeQuery(connection, sql);
|
||||
// then
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase043() {
|
||||
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
|
||||
public void testCase044() {
|
||||
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
|
||||
public void testCase045() {
|
||||
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
|
||||
public void testCase046() {
|
||||
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
|
||||
public void testCase047() {
|
||||
String sql = "select * from restful_test.weather limit 2";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
ResultSet rs = executeQuery(connection, sql);
|
||||
// then
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase048() {
|
||||
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
|
||||
public void testCase049() {
|
||||
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
|
||||
public void testCase050() {
|
||||
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
|
||||
public void testCase051() {
|
||||
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
|
||||
public void testCase052() {
|
||||
String sql = "select server_status()";
|
||||
SQLExecutor.executeQuery(connection, sql);
|
||||
// when
|
||||
ResultSet rs = executeQuery(connection, sql);
|
||||
// then
|
||||
Assert.assertNotNull(rs);
|
||||
}
|
||||
|
||||
@Test
|
||||
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)";
|
||||
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
|
||||
public static void before() throws ClassNotFoundException, SQLException {
|
||||
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
|
||||
public static void before() throws SQLException {
|
||||
connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=root&password=taosdata");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
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,28 +126,18 @@ function convertDouble(data, num_of_rows, nbytes = 0, offset = 0, micro = false)
|
|||
}
|
||||
return res;
|
||||
}
|
||||
function convertBinary(data, num_of_rows, nbytes = 0, offset = 0, micro = false) {
|
||||
data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset);
|
||||
let res = [];
|
||||
let currOffset = 0;
|
||||
while (currOffset < data.length) {
|
||||
let dataEntry = data.slice(currOffset, currOffset + nbytes);
|
||||
if (dataEntry[0] == FieldTypes.C_BINARY_NULL) {
|
||||
res.push(null);
|
||||
}
|
||||
else {
|
||||
res.push(ref.readCString(dataEntry));
|
||||
}
|
||||
currOffset += nbytes;
|
||||
}
|
||||
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"));
|
||||
|
||||
let currOffset = 0;
|
||||
while (currOffset < data.length) {
|
||||
let len = data.readIntLE(currOffset, 2);
|
||||
let dataEntry = data.slice(currOffset + 2, currOffset + len + 2); //one entry in a row under a column;
|
||||
res.push(dataEntry.toString("utf-8"));
|
||||
currOffset += nbytes;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -160,7 +150,7 @@ let convertFunctions = {
|
|||
[FieldTypes.C_BIGINT]: convertBigint,
|
||||
[FieldTypes.C_FLOAT]: convertFloat,
|
||||
[FieldTypes.C_DOUBLE]: convertDouble,
|
||||
[FieldTypes.C_BINARY]: convertBinary,
|
||||
[FieldTypes.C_BINARY]: convertNchar,
|
||||
[FieldTypes.C_TIMESTAMP]: convertTimestamp,
|
||||
[FieldTypes.C_NCHAR]: convertNchar
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "td2.0-connector",
|
||||
"version": "2.0.7",
|
||||
"version": "2.0.8",
|
||||
"description": "A Node.js connector for TDengine.",
|
||||
"main": "tdengine.js",
|
||||
"directories": {
|
||||
|
|
|
@ -31,6 +31,7 @@ void bnReset();
|
|||
int32_t bnAllocVnodes(struct SVgObj *pVgroup);
|
||||
int32_t bnAlterDnode(struct SDnodeObj *pDnode, int32_t vnodeId, int32_t dnodeId);
|
||||
int32_t bnDropDnode(struct SDnodeObj *pDnode);
|
||||
int32_t bnDnodeCanCreateMnode(struct SDnodeObj *pDnode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -636,6 +636,9 @@ static FILE * g_fpOfInsertResult = NULL;
|
|||
#define errorPrint(fmt, ...) \
|
||||
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) {
|
|||
return ;
|
||||
}
|
||||
|
||||
int totalLen = 0;
|
||||
int64_t totalLen = 0;
|
||||
|
||||
// fetch the records row by row
|
||||
while((row = taos_fetch_row(res))) {
|
||||
if ((strlen(pThreadInfo->filePath) > 0)
|
||||
&& (totalLen >= 100*1024*1024 - 32000)) {
|
||||
appendResultBufToFile(databuf, pThreadInfo);
|
||||
if (totalLen >= 100*1024*1024 - 32000) {
|
||||
if (strlen(pThreadInfo->filePath) > 0)
|
||||
appendResultBufToFile(databuf, pThreadInfo);
|
||||
totalLen = 0;
|
||||
memset(databuf, 0, 100*1024*1024);
|
||||
}
|
||||
num_rows++;
|
||||
char temp[16000] = {0};
|
||||
char temp[16000] = {0};
|
||||
int len = taos_print_row(temp, row, fields, num_fields);
|
||||
len += sprintf(temp + len, "\n");
|
||||
//printf("query result:%s\n", temp);
|
||||
memcpy(databuf + totalLen, temp, len);
|
||||
totalLen += len;
|
||||
verbosePrint("%s() LN%d, totalLen: %"PRId64"\n", __func__, __LINE__, totalLen);
|
||||
}
|
||||
|
||||
verbosePrint("%s() LN%d, databuf=%s resultFile=%s\n",
|
||||
|
@ -2573,7 +2577,7 @@ static int getSuperTableFromServer(TAOS * taos, char* dbName,
|
|||
fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
|
||||
tstrncpy(superTbls->tags[tagIndex].dataType,
|
||||
(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 =
|
||||
*((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
|
||||
tstrncpy(superTbls->tags[tagIndex].note,
|
||||
|
@ -2586,7 +2590,7 @@ static int getSuperTableFromServer(TAOS * taos, char* dbName,
|
|||
fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
|
||||
tstrncpy(superTbls->columns[columnIndex].dataType,
|
||||
(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 =
|
||||
*((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
|
||||
tstrncpy(superTbls->columns[columnIndex].note,
|
||||
|
@ -4407,14 +4411,12 @@ static bool getMetaFromQueryJsonFile(cJSON* root) {
|
|||
|
||||
cJSON* resubAfterConsume =
|
||||
cJSON_GetObjectItem(specifiedQuery, "resubAfterConsume");
|
||||
g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = -1;
|
||||
if ((resubAfterConsume)
|
||||
&& (resubAfterConsume->type == cJSON_Number)
|
||||
&& (resubAfterConsume->valueint >= 0)) {
|
||||
g_queryInfo.specifiedQueryInfo.resubAfterConsume[j]
|
||||
= 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");
|
||||
|
@ -4571,14 +4573,12 @@ static bool getMetaFromQueryJsonFile(cJSON* root) {
|
|||
|
||||
cJSON* superResubAfterConsume =
|
||||
cJSON_GetObjectItem(superQuery, "resubAfterConsume");
|
||||
g_queryInfo.superQueryInfo.resubAfterConsume = -1;
|
||||
if ((superResubAfterConsume)
|
||||
&& (superResubAfterConsume->type == cJSON_Number)
|
||||
&& (superResubAfterConsume->valueint >= 0)) {
|
||||
g_queryInfo.superQueryInfo.resubAfterConsume =
|
||||
superResubAfterConsume->valueint;
|
||||
} else if (!superResubAfterConsume) {
|
||||
// default value is -1, which mean do not resub
|
||||
g_queryInfo.superQueryInfo.resubAfterConsume = -1;
|
||||
}
|
||||
|
||||
// supert table sqls
|
||||
|
@ -7221,151 +7221,159 @@ static TAOS_SUB* subscribeImpl(
|
|||
}
|
||||
|
||||
if (tsub == NULL) {
|
||||
printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
|
||||
return NULL;
|
||||
errorPrint("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return tsub;
|
||||
}
|
||||
|
||||
static void *superSubscribe(void *sarg) {
|
||||
threadInfo *pThreadInfo = (threadInfo *)sarg;
|
||||
char subSqlstr[MAX_QUERY_SQL_LENGTH];
|
||||
TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT] = {0};
|
||||
uint64_t tsubSeq;
|
||||
threadInfo *pThreadInfo = (threadInfo *)sarg;
|
||||
char subSqlstr[MAX_QUERY_SQL_LENGTH];
|
||||
TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT] = {0};
|
||||
uint64_t tsubSeq;
|
||||
|
||||
if (pThreadInfo->ntables > MAX_QUERY_SQL_COUNT) {
|
||||
errorPrint("The table number(%"PRId64") of the thread is more than max query sql count: %d\n",
|
||||
pThreadInfo->ntables,
|
||||
MAX_QUERY_SQL_COUNT);
|
||||
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) {
|
||||
errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
|
||||
pThreadInfo->threadID, taos_errstr(NULL));
|
||||
return NULL;
|
||||
if (pThreadInfo->ntables > MAX_QUERY_SQL_COUNT) {
|
||||
errorPrint("The table number(%"PRId64") of the thread is more than max query sql count: %d\n",
|
||||
pThreadInfo->ntables, MAX_QUERY_SQL_COUNT);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
char sqlStr[MAX_TB_NAME_SIZE*2];
|
||||
sprintf(sqlStr, "use %s", g_queryInfo.dbName);
|
||||
if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
|
||||
taos_close(pThreadInfo->taos);
|
||||
errorPrint( "use database %s failed!\n\n",
|
||||
g_queryInfo.dbName);
|
||||
return NULL;
|
||||
}
|
||||
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) {
|
||||
errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
|
||||
pThreadInfo->threadID, taos_errstr(NULL));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char topic[32] = {0};
|
||||
for (uint64_t i = pThreadInfo->start_table_from;
|
||||
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);
|
||||
}
|
||||
|
||||
debugPrint("%s() LN%d, [%d] subSqlstr: %s\n",
|
||||
__func__, __LINE__, pThreadInfo->threadID, subSqlstr);
|
||||
tsub[tsubSeq] = subscribeImpl(
|
||||
STABLE_CLASS,
|
||||
pThreadInfo, subSqlstr, topic,
|
||||
g_queryInfo.superQueryInfo.subscribeRestart,
|
||||
g_queryInfo.superQueryInfo.subscribeInterval);
|
||||
if (NULL == tsub[tsubSeq]) {
|
||||
char sqlStr[MAX_TB_NAME_SIZE*2];
|
||||
sprintf(sqlStr, "use %s", g_queryInfo.dbName);
|
||||
if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
|
||||
taos_close(pThreadInfo->taos);
|
||||
errorPrint( "use database %s failed!\n\n",
|
||||
g_queryInfo.dbName);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// start loop to consume result
|
||||
int consumed[MAX_QUERY_SQL_COUNT];
|
||||
for (int i = 0; i < MAX_QUERY_SQL_COUNT; i++) {
|
||||
consumed[i] = 0;
|
||||
}
|
||||
TAOS_RES* res = NULL;
|
||||
char topic[32] = {0};
|
||||
for (uint64_t i = pThreadInfo->start_table_from;
|
||||
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);
|
||||
}
|
||||
|
||||
uint64_t st = 0, et = 0;
|
||||
verbosePrint("%s() LN%d, [%d] subSqlstr: %s\n",
|
||||
__func__, __LINE__, pThreadInfo->threadID, subSqlstr);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
while ((g_queryInfo.superQueryInfo.endAfterConsume == -1)
|
||||
|| (g_queryInfo.superQueryInfo.endAfterConsume <
|
||||
consumed[pThreadInfo->end_table_to - pThreadInfo->start_table_from])) {
|
||||
// start loop to consume result
|
||||
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])) {
|
||||
|
||||
verbosePrint("super endAfterConsume: %d, consumed: %d\n",
|
||||
g_queryInfo.superQueryInfo.endAfterConsume,
|
||||
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;
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
tsubSeq = i - pThreadInfo->start_table_from;
|
||||
taos_unsubscribe(tsub[tsubSeq], 0);
|
||||
}
|
||||
}
|
||||
taos_free_result(res);
|
||||
|
||||
for (uint64_t i = pThreadInfo->start_table_from;
|
||||
i <= pThreadInfo->end_table_to; i++) {
|
||||
tsubSeq = i - pThreadInfo->start_table_from;
|
||||
taos_unsubscribe(tsub[tsubSeq], 0);
|
||||
}
|
||||
|
||||
taos_close(pThreadInfo->taos);
|
||||
return NULL;
|
||||
taos_close(pThreadInfo->taos);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *specifiedSubscribe(void *sarg) {
|
||||
|
@ -7419,8 +7427,13 @@ static void *specifiedSubscribe(void *sarg) {
|
|||
|| (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] <
|
||||
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) {
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID] = taos_consume(
|
||||
|
@ -7462,7 +7475,6 @@ static void *specifiedSubscribe(void *sarg) {
|
|||
}
|
||||
}
|
||||
taos_free_result(g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]);
|
||||
taos_unsubscribe(g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->querySeq], 0);
|
||||
taos_close(pThreadInfo->taos);
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -1126,7 +1126,7 @@ int taosGetTableDes(
|
|||
strncpy(tableDes->cols[count].field, (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
|
||||
fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
|
||||
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]);
|
||||
strncpy(tableDes->cols[count].note, (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
|
||||
fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#define _DEFAULT_SOURCE
|
||||
#include "os.h"
|
||||
#include "tgrant.h"
|
||||
#include "tbn.h"
|
||||
#include "tglobal.h"
|
||||
#include "tconfig.h"
|
||||
#include "tutil.h"
|
||||
|
@ -632,7 +631,8 @@ static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) {
|
|||
}
|
||||
|
||||
int32_t numOfMnodes = mnodeGetMnodesNum();
|
||||
if (numOfMnodes < tsNumOfMnodes && numOfMnodes < mnodeGetOnlineDnodesNum() && !pDnode->isMgmt) {
|
||||
if (numOfMnodes < tsNumOfMnodes && numOfMnodes < mnodeGetOnlineDnodesNum()
|
||||
&& bnDnodeCanCreateMnode(pDnode)) {
|
||||
bnNotify();
|
||||
}
|
||||
|
||||
|
|
|
@ -1068,7 +1068,7 @@ static int32_t mnodeProcessCreateSuperTableMsg(SMnodeMsg *pMsg) {
|
|||
pStable->info.tableId = strdup(pCreate->tableName);
|
||||
pStable->info.type = TSDB_SUPER_TABLE;
|
||||
pStable->createdTime = taosGetTimestampMs();
|
||||
int64_t x = (us&0x000000FFFFFFFFFF);
|
||||
uint64_t x = (us&0x000000FFFFFFFFFF);
|
||||
x = x<<24;
|
||||
pStable->uid = x + ((sdbGetVersion() & ((1ul << 16) - 1ul)) << 8) + (taosRand() & ((1ul << 8) - 1ul));
|
||||
pStable->sversion = 0;
|
||||
|
@ -2075,7 +2075,9 @@ static int32_t mnodeDoCreateChildTable(SMnodeMsg *pMsg, int32_t tid) {
|
|||
} else {
|
||||
if (pTable->info.type == TSDB_SUPER_TABLE) {
|
||||
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 {
|
||||
pTable->uid = (((uint64_t)pTable->vgId) << 48) + ((((uint64_t)pTable->tid) & ((1ul << 24) - 1ul)) << 24) +
|
||||
((sdbGetVersion() & ((1ul << 16) - 1ul)) << 8) + (taosRand() & ((1ul << 8) - 1ul));
|
||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
#include "osMath.h"
|
||||
#include "osMemory.h"
|
||||
#include "osRand.h"
|
||||
#include "osSemphone.h"
|
||||
#include "osSemaphore.h"
|
||||
#include "osSignal.h"
|
||||
#include "osSleep.h"
|
||||
#include "osSocket.h"
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_OS_SEMPHONE_H
|
||||
#define TDENGINE_OS_SEMPHONE_H
|
||||
#ifndef TDENGINE_OS_SEMAPHORE_H
|
||||
#define TDENGINE_OS_SEMAPHORE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
|
@ -348,6 +348,7 @@ int64_t convertTimePrecision(int64_t time, int32_t fromPrecision, int32_t toPrec
|
|||
{1.0 / 1000000, 1.0 / 1000, 1.} };
|
||||
return (int64_t)((double)time * factors[fromPrecision][toPrecision]);
|
||||
}
|
||||
|
||||
static int32_t getDuration(int64_t val, char unit, int64_t* result, int32_t timePrecision) {
|
||||
|
||||
switch (unit) {
|
||||
|
|
|
@ -228,13 +228,11 @@ bool gcBuildQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result,
|
|||
case TSDB_DATA_TYPE_NCHAR:
|
||||
httpJsonStringForTransMean(jsonBuf, (char *)row[i], fields[i].bytes);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
if (precision == TSDB_TIME_PRECISION_MILLI) { // ms
|
||||
httpJsonInt64(jsonBuf, *((int64_t *)row[i]));
|
||||
} else {
|
||||
httpJsonInt64(jsonBuf, *((int64_t *)row[i]) / 1000);
|
||||
}
|
||||
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||
int64_t ts = convertTimePrecision(*((int64_t *)row[i]), precision, TSDB_TIME_PRECISION_MILLI);
|
||||
httpJsonInt64(jsonBuf, ts);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
httpJsonString(jsonBuf, "-", 1);
|
||||
break;
|
||||
|
|
|
@ -133,6 +133,28 @@ typedef struct STableQueryInfo {
|
|||
SResultRowInfo resInfo;
|
||||
} 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 {
|
||||
uint64_t loadStatisTime;
|
||||
uint64_t loadFileBlockTime;
|
||||
|
@ -154,6 +176,9 @@ typedef struct SQueryCostInfo {
|
|||
uint64_t tableInfoSize;
|
||||
uint64_t hashSize;
|
||||
uint64_t numOfTimeWindows;
|
||||
|
||||
SArray* queryProfEvents; //SArray<SQueryProfEvent>
|
||||
SHashObj* operatorProfResults; //map<operator_type, SQueryProfEvent>
|
||||
} SQueryCostInfo;
|
||||
|
||||
typedef struct {
|
||||
|
@ -192,6 +217,7 @@ typedef struct SQueryAttr {
|
|||
bool needReverseScan; // need reverse scan
|
||||
bool distinctTag; // distinct tag query
|
||||
bool stateWindow; // window State on sub/normal table
|
||||
bool createFilterOperator; // if filter operator is needed
|
||||
int32_t interBufSize; // intermediate buffer sizse
|
||||
|
||||
int32_t havingNum; // having expr number
|
||||
|
@ -285,7 +311,7 @@ enum OPERATOR_TYPE_E {
|
|||
OP_TagScan = 4,
|
||||
OP_TableBlockInfoScan= 5,
|
||||
OP_Aggregate = 6,
|
||||
OP_Arithmetic = 7,
|
||||
OP_Project = 7,
|
||||
OP_Groupby = 8,
|
||||
OP_Limit = 9,
|
||||
OP_SLimit = 10,
|
||||
|
@ -413,13 +439,13 @@ typedef struct SAggOperatorInfo {
|
|||
uint32_t seed;
|
||||
} SAggOperatorInfo;
|
||||
|
||||
typedef struct SArithOperatorInfo {
|
||||
typedef struct SProjectOperatorInfo {
|
||||
SOptrBasicInfo binfo;
|
||||
int32_t bufCapacity;
|
||||
uint32_t seed;
|
||||
|
||||
SSDataBlock *existDataBlock;
|
||||
} SArithOperatorInfo;
|
||||
} SProjectOperatorInfo;
|
||||
|
||||
typedef struct SLimitOperatorInfo {
|
||||
int64_t limit;
|
||||
|
@ -513,7 +539,7 @@ SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv*
|
|||
SOperatorInfo* createTableSeqScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv);
|
||||
|
||||
SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
|
||||
SOperatorInfo* createArithOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
|
||||
SOperatorInfo* createProjectOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
|
||||
SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream);
|
||||
SOperatorInfo* createTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
|
||||
SOperatorInfo* createSWindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
|
||||
|
@ -586,7 +612,12 @@ int32_t doDumpQueryResult(SQInfo *pQInfo, char *data);
|
|||
|
||||
size_t getResultSize(SQInfo *pQInfo, int64_t *numOfRows);
|
||||
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 freeQInfo(SQInfo *pQInfo);
|
||||
void freeQueryAttr(SQueryAttr *pQuery);
|
||||
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
} while (0);
|
||||
|
||||
void noop1(SQLFunctionCtx *UNUSED_PARAM(pCtx)) {}
|
||||
void noop2(SQLFunctionCtx *UNUSED_PARAM(pCtx), int32_t UNUSED_PARAM(index)) {}
|
||||
|
||||
void doFinalizer(SQLFunctionCtx *pCtx) { RESET_RESULT_INFO(GET_RES_INFO(pCtx)); }
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "qFill.h"
|
||||
#include "taosmsg.h"
|
||||
#include "tglobal.h"
|
||||
#include "talgo.h"
|
||||
|
||||
#include "exception.h"
|
||||
#include "hash.h"
|
||||
|
@ -26,6 +27,7 @@
|
|||
#include "queryLog.h"
|
||||
#include "tlosertree.h"
|
||||
#include "ttype.h"
|
||||
#include "tcompare.h"
|
||||
#include "tscompression.h"
|
||||
|
||||
#define IS_MASTER_SCAN(runtime) ((runtime)->scanFlag == MASTER_SCAN)
|
||||
|
@ -184,7 +186,7 @@ static int32_t getNumOfScanTimes(SQueryAttr* pQueryAttr);
|
|||
static void destroyBasicOperatorInfo(void* param, int32_t numOfOutput);
|
||||
static void destroySFillOperatorInfo(void* param, int32_t numOfOutput);
|
||||
static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput);
|
||||
static void destroyArithOperatorInfo(void* param, int32_t numOfOutput);
|
||||
static void destroyProjectOperatorInfo(void* param, int32_t numOfOutput);
|
||||
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput);
|
||||
static void destroySWindowOperatorInfo(void* param, int32_t numOfOutput);
|
||||
static void destroyStateWindowOperatorInfo(void* param, int32_t numOfOutput);
|
||||
|
@ -207,7 +209,66 @@ static void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowIn
|
|||
SQLFunctionCtx* pCtx, int32_t* rowCellInfoOffset, int32_t numOfOutput,
|
||||
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) {
|
||||
const static int32_t minSize = 8;
|
||||
|
||||
|
@ -912,7 +973,7 @@ void setInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlo
|
|||
doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order);
|
||||
}
|
||||
} else {
|
||||
if (/*pCtx[0].pInput == NULL && */pBlock->pDataBlock != NULL) {
|
||||
if (pBlock->pDataBlock != NULL) {
|
||||
doSetInputDataBlock(pOperator, pCtx, pBlock, order);
|
||||
} else {
|
||||
doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order);
|
||||
|
@ -978,7 +1039,7 @@ static void doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SQLFunction
|
|||
}
|
||||
}
|
||||
|
||||
static void arithmeticApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t numOfOutput) {
|
||||
static void projectApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t numOfOutput) {
|
||||
SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
|
||||
|
||||
for (int32_t k = 0; k < numOfOutput; ++k) {
|
||||
|
@ -1800,17 +1861,17 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf
|
|||
break;
|
||||
}
|
||||
|
||||
case OP_Arithmetic: { // TODO refactor to remove arith operator.
|
||||
case OP_Project: { // TODO refactor to remove arith operator.
|
||||
SOperatorInfo* prev = pRuntimeEnv->proot;
|
||||
if (i == 0) {
|
||||
pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, prev, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
|
||||
pRuntimeEnv->proot = createProjectOperatorInfo(pRuntimeEnv, prev, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
|
||||
if (pRuntimeEnv->proot != NULL && prev->operatorType != OP_DummyInput && prev->operatorType != OP_Join) { // TODO refactor
|
||||
setTableScanFilterOperatorInfo(prev->info, pRuntimeEnv->proot);
|
||||
}
|
||||
} else {
|
||||
prev = pRuntimeEnv->proot;
|
||||
assert(pQueryAttr->pExpr2 != NULL);
|
||||
pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, prev, pQueryAttr->pExpr2, pQueryAttr->numOfExpr2);
|
||||
pRuntimeEnv->proot = createProjectOperatorInfo(pRuntimeEnv, prev, pQueryAttr->pExpr2, pQueryAttr->numOfExpr2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3785,6 +3846,103 @@ int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutp
|
|||
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) {
|
||||
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
|
||||
SQueryCostInfo *pSummary = &pQInfo->summary;
|
||||
|
@ -3805,6 +3963,8 @@ void queryCostStatis(SQInfo *pQInfo) {
|
|||
pSummary->numOfTimeWindows = 0;
|
||||
}
|
||||
|
||||
calculateOperatorProfResults(pQInfo);
|
||||
|
||||
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,
|
||||
pQInfo->qId, pSummary->elapsedTime, pSummary->firstStageMergeTime, pSummary->totalBlocks, pSummary->loadBlockStatis,
|
||||
|
@ -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,
|
||||
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) {
|
||||
|
@ -4145,8 +4314,8 @@ static SFillColInfo* createFillColInfo(SExprInfo* pExpr, int32_t numOfOutput, in
|
|||
return pFillCol;
|
||||
}
|
||||
|
||||
int32_t doInitQInfo(SQInfo* pQInfo, STSBuf* pTsBuf, void* tsdb, void* sourceOptr, int32_t tbScanner,
|
||||
SArray* pOperator, void* param) {
|
||||
int32_t doInitQInfo(SQInfo* pQInfo, STSBuf* pTsBuf, void* tsdb, void* sourceOptr, int32_t tbScanner, SArray* pOperator,
|
||||
void* param) {
|
||||
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
|
||||
|
||||
SQueryAttr *pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
|
||||
|
@ -4213,6 +4382,15 @@ int32_t doInitQInfo(SQInfo* pQInfo, STSBuf* pTsBuf, void* tsdb, void* sourceOptr
|
|||
// create runtime environment
|
||||
int32_t numOfTables = (int32_t)pQueryAttr->tableGroupInfo.numOfTables;
|
||||
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);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
|
@ -4572,8 +4750,8 @@ void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInf
|
|||
pTableScanInfo->pResultRowInfo = &pInfo->resultRowInfo;
|
||||
pTableScanInfo->rowCellInfoOffset = pInfo->rowCellInfoOffset;
|
||||
|
||||
} else if (pDownstream->operatorType == OP_Arithmetic) {
|
||||
SArithOperatorInfo *pInfo = pDownstream->info;
|
||||
} else if (pDownstream->operatorType == OP_Project) {
|
||||
SProjectOperatorInfo *pInfo = pDownstream->info;
|
||||
|
||||
pTableScanInfo->pCtx = pInfo->binfo.pCtx;
|
||||
pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
|
||||
|
@ -4837,7 +5015,10 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) {
|
|||
SOperatorInfo* upstream = pOperator->upstream[0];
|
||||
|
||||
while(1) {
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
break;
|
||||
}
|
||||
|
@ -4892,7 +5073,10 @@ static SSDataBlock* doSTableAggregate(void* param, bool* newgroup) {
|
|||
SOperatorInfo* upstream = pOperator->upstream[0];
|
||||
|
||||
while(1) {
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
break;
|
||||
}
|
||||
|
@ -4928,23 +5112,23 @@ static SSDataBlock* doSTableAggregate(void* param, bool* newgroup) {
|
|||
return pInfo->pRes;
|
||||
}
|
||||
|
||||
static SSDataBlock* doArithmeticOperation(void* param, bool* newgroup) {
|
||||
static SSDataBlock* doProjectOperation(void* param, bool* newgroup) {
|
||||
SOperatorInfo* pOperator = (SOperatorInfo*) param;
|
||||
|
||||
SArithOperatorInfo* pArithInfo = pOperator->info;
|
||||
SProjectOperatorInfo* pProjectInfo = pOperator->info;
|
||||
SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
|
||||
SOptrBasicInfo *pInfo = &pArithInfo->binfo;
|
||||
SOptrBasicInfo *pInfo = &pProjectInfo->binfo;
|
||||
|
||||
SSDataBlock* pRes = pInfo->pRes;
|
||||
int32_t order = pRuntimeEnv->pQueryAttr->order.order;
|
||||
|
||||
pRes->info.rows = 0;
|
||||
|
||||
if (pArithInfo->existDataBlock) { // TODO refactor
|
||||
if (pProjectInfo->existDataBlock) { // TODO refactor
|
||||
STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
|
||||
|
||||
SSDataBlock* pBlock = pArithInfo->existDataBlock;
|
||||
pArithInfo->existDataBlock = NULL;
|
||||
SSDataBlock* pBlock = pProjectInfo->existDataBlock;
|
||||
pProjectInfo->existDataBlock = NULL;
|
||||
*newgroup = true;
|
||||
|
||||
// todo dynamic set tags
|
||||
|
@ -4954,9 +5138,9 @@ static SSDataBlock* doArithmeticOperation(void* param, bool* newgroup) {
|
|||
|
||||
// the pDataBlock are always the same one, no need to call this again
|
||||
setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
|
||||
updateOutputBuf(&pArithInfo->binfo, &pArithInfo->bufCapacity, pBlock->info.rows);
|
||||
updateOutputBuf(&pProjectInfo->binfo, &pProjectInfo->bufCapacity, pBlock->info.rows);
|
||||
|
||||
arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
|
||||
projectApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
|
||||
if (pTableQueryInfo != NULL) {
|
||||
updateTableIdInfo(pTableQueryInfo, pBlock, pRuntimeEnv->pTableRetrieveTsMap, order);
|
||||
}
|
||||
|
@ -4972,7 +5156,10 @@ static SSDataBlock* doArithmeticOperation(void* param, bool* newgroup) {
|
|||
bool prevVal = *newgroup;
|
||||
|
||||
// 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);
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
assert(*newgroup == false);
|
||||
|
||||
|
@ -4984,7 +5171,7 @@ static SSDataBlock* doArithmeticOperation(void* param, bool* newgroup) {
|
|||
// Return result of the previous group in the firstly.
|
||||
if (*newgroup) {
|
||||
if (pRes->info.rows > 0) {
|
||||
pArithInfo->existDataBlock = pBlock;
|
||||
pProjectInfo->existDataBlock = pBlock;
|
||||
clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
|
||||
return pInfo->pRes;
|
||||
} else { // init output buffer for a new group data
|
||||
|
@ -5004,9 +5191,9 @@ static SSDataBlock* doArithmeticOperation(void* param, bool* newgroup) {
|
|||
|
||||
// the pDataBlock are always the same one, no need to call this again
|
||||
setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
|
||||
updateOutputBuf(&pArithInfo->binfo, &pArithInfo->bufCapacity, pBlock->info.rows);
|
||||
updateOutputBuf(&pProjectInfo->binfo, &pProjectInfo->bufCapacity, pBlock->info.rows);
|
||||
|
||||
arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
|
||||
projectApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
|
||||
if (pTableQueryInfo != NULL) {
|
||||
updateTableIdInfo(pTableQueryInfo, pBlock, pRuntimeEnv->pTableRetrieveTsMap, order);
|
||||
}
|
||||
|
@ -5032,7 +5219,10 @@ static SSDataBlock* doLimit(void* param, bool* newgroup) {
|
|||
|
||||
SSDataBlock* pBlock = NULL;
|
||||
while (1) {
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
|
||||
pOperator->status = OP_EXEC_DONE;
|
||||
|
@ -5082,7 +5272,10 @@ static SSDataBlock* doFilter(void* param, bool* newgroup) {
|
|||
SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
|
||||
|
||||
while (1) {
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
SSDataBlock *pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
break;
|
||||
}
|
||||
|
@ -5127,7 +5320,10 @@ static SSDataBlock* doIntervalAgg(void* param, bool* newgroup) {
|
|||
SOperatorInfo* upstream = pOperator->upstream[0];
|
||||
|
||||
while(1) {
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
break;
|
||||
}
|
||||
|
@ -5180,7 +5376,10 @@ static SSDataBlock* doSTableIntervalAgg(void* param, bool* newgroup) {
|
|||
SOperatorInfo* upstream = pOperator->upstream[0];
|
||||
|
||||
while(1) {
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
break;
|
||||
}
|
||||
|
@ -5308,7 +5507,10 @@ static SSDataBlock* doStateWindowAgg(void *param, bool* newgroup) {
|
|||
STimeWindow win = pQueryAttr->window;
|
||||
SOperatorInfo* upstream = pOperator->upstream[0];
|
||||
while (1) {
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
break;
|
||||
}
|
||||
|
@ -5366,7 +5568,9 @@ static SSDataBlock* doSessionWindowAgg(void* param, bool* newgroup) {
|
|||
SOperatorInfo* upstream = pOperator->upstream[0];
|
||||
|
||||
while(1) {
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
if (pBlock == NULL) {
|
||||
break;
|
||||
}
|
||||
|
@ -5417,7 +5621,9 @@ static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) {
|
|||
SOperatorInfo* upstream = pOperator->upstream[0];
|
||||
|
||||
while(1) {
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
|
||||
publishOperatorProfEvent(upstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
if (pBlock == NULL) {
|
||||
break;
|
||||
}
|
||||
|
@ -5443,8 +5649,11 @@ static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) {
|
|||
}
|
||||
|
||||
initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo);
|
||||
if (!pRuntimeEnv->pQueryAttr->stableQuery) {
|
||||
sortGroupResByOrderList(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
|
||||
}
|
||||
toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
|
||||
|
||||
|
||||
if (pInfo->binfo.pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
|
||||
pOperator->status = OP_EXEC_DONE;
|
||||
}
|
||||
|
@ -5483,7 +5692,10 @@ static SSDataBlock* doFill(void* param, bool* newgroup) {
|
|||
}
|
||||
|
||||
while(1) {
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
SSDataBlock* pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (*newgroup) {
|
||||
assert(pBlock != NULL);
|
||||
}
|
||||
|
@ -5643,8 +5855,8 @@ static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) {
|
|||
tfree(pInfo->prevData);
|
||||
}
|
||||
|
||||
static void destroyArithOperatorInfo(void* param, int32_t numOfOutput) {
|
||||
SArithOperatorInfo* pInfo = (SArithOperatorInfo*) param;
|
||||
static void destroyProjectOperatorInfo(void* param, int32_t numOfOutput) {
|
||||
SProjectOperatorInfo* pInfo = (SProjectOperatorInfo*) param;
|
||||
doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
|
||||
}
|
||||
|
||||
|
@ -5690,8 +5902,8 @@ SOperatorInfo* createMultiTableAggOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SO
|
|||
return pOperator;
|
||||
}
|
||||
|
||||
SOperatorInfo* createArithOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
|
||||
SArithOperatorInfo* pInfo = calloc(1, sizeof(SArithOperatorInfo));
|
||||
SOperatorInfo* createProjectOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
|
||||
SProjectOperatorInfo* pInfo = calloc(1, sizeof(SProjectOperatorInfo));
|
||||
|
||||
pInfo->seed = rand();
|
||||
pInfo->bufCapacity = pRuntimeEnv->resultInfo.capacity;
|
||||
|
@ -5704,8 +5916,8 @@ SOperatorInfo* createArithOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorI
|
|||
setDefaultOutputBuf(pRuntimeEnv, pBInfo, pInfo->seed, MASTER_SCAN);
|
||||
|
||||
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
||||
pOperator->name = "ArithmeticOperator";
|
||||
pOperator->operatorType = OP_Arithmetic;
|
||||
pOperator->name = "ProjectOperator";
|
||||
pOperator->operatorType = OP_Project;
|
||||
pOperator->blockingOptr = false;
|
||||
pOperator->status = OP_IN_EXECUTING;
|
||||
pOperator->info = pInfo;
|
||||
|
@ -5713,8 +5925,8 @@ SOperatorInfo* createArithOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorI
|
|||
pOperator->numOfOutput = numOfOutput;
|
||||
pOperator->pRuntimeEnv = pRuntimeEnv;
|
||||
|
||||
pOperator->exec = doArithmeticOperation;
|
||||
pOperator->cleanup = destroyArithOperatorInfo;
|
||||
pOperator->exec = doProjectOperation;
|
||||
pOperator->cleanup = destroyProjectOperatorInfo;
|
||||
appendUpstream(pOperator, upstream);
|
||||
|
||||
return pOperator;
|
||||
|
@ -6153,7 +6365,10 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
|
|||
pRes->info.rows = 0;
|
||||
SSDataBlock* pBlock = NULL;
|
||||
while(1) {
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
|
||||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
|
||||
pOperator->status = OP_EXEC_DONE;
|
||||
|
@ -7039,6 +7254,8 @@ int32_t createFilterInfo(SQueryAttr* pQueryAttr, uint64_t qId) {
|
|||
doCreateFilterInfo(pQueryAttr->tableCols, pQueryAttr->numOfCols, pQueryAttr->numOfFilterCols,
|
||||
&pQueryAttr->pFilterInfo, qId);
|
||||
|
||||
pQueryAttr->createFilterOperator = true;
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -7477,6 +7694,9 @@ void freeQInfo(SQInfo *pQInfo) {
|
|||
tfree(pQInfo->pBuf);
|
||||
tfree(pQInfo->sql);
|
||||
|
||||
taosArrayDestroy(pQInfo->summary.queryProfEvents);
|
||||
taosHashCleanup(pQInfo->summary.operatorProfResults);
|
||||
|
||||
taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows);
|
||||
pQInfo->signature = 0;
|
||||
|
||||
|
|
|
@ -565,7 +565,7 @@ SArray* createExecOperatorPlan(SQueryAttr* pQueryAttr) {
|
|||
taosArrayPush(plan, &op);
|
||||
|
||||
if (pQueryAttr->pExpr2 != NULL) {
|
||||
op = OP_Arithmetic;
|
||||
op = OP_Project;
|
||||
taosArrayPush(plan, &op);
|
||||
}
|
||||
|
||||
|
@ -585,7 +585,7 @@ SArray* createExecOperatorPlan(SQueryAttr* pQueryAttr) {
|
|||
}
|
||||
|
||||
if (pQueryAttr->pExpr2 != NULL) {
|
||||
op = OP_Arithmetic;
|
||||
op = OP_Project;
|
||||
taosArrayPush(plan, &op);
|
||||
}
|
||||
} else if (pQueryAttr->sw.gap > 0) {
|
||||
|
@ -593,7 +593,7 @@ SArray* createExecOperatorPlan(SQueryAttr* pQueryAttr) {
|
|||
taosArrayPush(plan, &op);
|
||||
|
||||
if (pQueryAttr->pExpr2 != NULL) {
|
||||
op = OP_Arithmetic;
|
||||
op = OP_Project;
|
||||
taosArrayPush(plan, &op);
|
||||
}
|
||||
} else if (pQueryAttr->stateWindow) {
|
||||
|
@ -601,7 +601,7 @@ SArray* createExecOperatorPlan(SQueryAttr* pQueryAttr) {
|
|||
taosArrayPush(plan, &op);
|
||||
|
||||
if (pQueryAttr->pExpr2 != NULL) {
|
||||
op = OP_Arithmetic;
|
||||
op = OP_Project;
|
||||
taosArrayPush(plan, &op);
|
||||
}
|
||||
} else if (pQueryAttr->simpleAgg) {
|
||||
|
@ -619,15 +619,15 @@ SArray* createExecOperatorPlan(SQueryAttr* pQueryAttr) {
|
|||
}
|
||||
|
||||
if (pQueryAttr->pExpr2 != NULL && !pQueryAttr->stableQuery) {
|
||||
op = OP_Arithmetic;
|
||||
op = OP_Project;
|
||||
taosArrayPush(plan, &op);
|
||||
}
|
||||
} 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;
|
||||
taosArrayPush(plan, &op);
|
||||
} else {
|
||||
op = OP_Arithmetic;
|
||||
op = OP_Project;
|
||||
taosArrayPush(plan, &op);
|
||||
}
|
||||
}
|
||||
|
@ -665,7 +665,7 @@ SArray* createGlobalMergePlan(SQueryAttr* pQueryAttr) {
|
|||
}
|
||||
|
||||
if (pQueryAttr->pExpr2 != NULL) {
|
||||
op = OP_Arithmetic;
|
||||
op = OP_Project;
|
||||
taosArrayPush(plan, &op);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -232,6 +232,7 @@ bool qTableQuery(qinfo_t qinfo, uint64_t *qId) {
|
|||
// error occurs, record the error code and return to client
|
||||
int32_t ret = setjmp(pQInfo->runtimeEnv.env);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
publishQueryAbortEvent(pQInfo, ret);
|
||||
pQInfo->code = ret;
|
||||
qDebug("QInfo:0x%"PRIx64" query abort due to error/cancel occurs, code:%s", pQInfo->qId, tstrerror(pQInfo->code));
|
||||
return doBuildResCheck(pQInfo);
|
||||
|
@ -240,7 +241,9 @@ bool qTableQuery(qinfo_t qinfo, uint64_t *qId) {
|
|||
qDebug("QInfo:0x%"PRIx64" query task is launched", pQInfo->qId);
|
||||
|
||||
bool newgroup = false;
|
||||
publishOperatorProfEvent(pRuntimeEnv->proot, QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||
pRuntimeEnv->outputBuf = pRuntimeEnv->proot->exec(pRuntimeEnv->proot, &newgroup);
|
||||
publishOperatorProfEvent(pRuntimeEnv->proot, QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
pRuntimeEnv->resultInfo.total += GET_NUM_OF_RESULTS(pRuntimeEnv);
|
||||
|
||||
if (isQueryKilled(pQInfo)) {
|
||||
|
|
|
@ -350,8 +350,8 @@ static FORCE_INLINE int tsdbCopyDFileSet(SDFileSet* pSrc, SDFileSet* pDest) {
|
|||
}
|
||||
|
||||
static FORCE_INLINE void tsdbGetFidKeyRange(int days, int8_t precision, int fid, TSKEY* minKey, TSKEY* maxKey) {
|
||||
*minKey = fid * days * tsMsPerDay[precision];
|
||||
*maxKey = *minKey + days * tsMsPerDay[precision] - 1;
|
||||
*minKey = fid * days * tsTickPerDay[precision];
|
||||
*maxKey = *minKey + days * tsTickPerDay[precision] - 1;
|
||||
}
|
||||
|
||||
static FORCE_INLINE bool tsdbFSetIsOk(SDFileSet* pSet) {
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
#define TSDB_MAX_SUBBLOCKS 8
|
||||
static FORCE_INLINE int TSDB_KEY_FID(TSKEY key, int32_t days, int8_t precision) {
|
||||
if (key < 0) {
|
||||
return (int)((key + 1) / tsMsPerDay[precision] / days - 1);
|
||||
return (int)((key + 1) / tsTickPerDay[precision] / days - 1);
|
||||
} else {
|
||||
return (int)((key / tsMsPerDay[precision] / days));
|
||||
return (int)((key / tsTickPerDay[precision] / days));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,9 +363,9 @@ void tsdbGetRtnSnap(STsdbRepo *pRepo, SRtn *pRtn) {
|
|||
TSKEY minKey, midKey, maxKey, now;
|
||||
|
||||
now = taosGetTimestamp(pCfg->precision);
|
||||
minKey = now - pCfg->keep * tsMsPerDay[pCfg->precision];
|
||||
midKey = now - pCfg->keep2 * tsMsPerDay[pCfg->precision];
|
||||
maxKey = now - pCfg->keep1 * tsMsPerDay[pCfg->precision];
|
||||
minKey = now - pCfg->keep * tsTickPerDay[pCfg->precision];
|
||||
midKey = now - pCfg->keep2 * tsTickPerDay[pCfg->precision];
|
||||
maxKey = now - pCfg->keep1 * tsTickPerDay[pCfg->precision];
|
||||
|
||||
pRtn->minKey = minKey;
|
||||
pRtn->minFid = (int)(TSDB_KEY_FID(minKey, pCfg->daysPerFile, pCfg->precision));
|
||||
|
|
|
@ -632,8 +632,8 @@ static int tsdbScanAndConvertSubmitMsg(STsdbRepo *pRepo, SSubmitMsg *pMsg) {
|
|||
SSubmitBlkIter blkIter = {0};
|
||||
SDataRow row = NULL;
|
||||
TSKEY now = taosGetTimestamp(pRepo->config.precision);
|
||||
TSKEY minKey = now - tsMsPerDay[pRepo->config.precision] * pRepo->config.keep;
|
||||
TSKEY maxKey = now + tsMsPerDay[pRepo->config.precision] * pRepo->config.daysPerFile;
|
||||
TSKEY minKey = now - tsTickPerDay[pRepo->config.precision] * pRepo->config.keep;
|
||||
TSKEY maxKey = now + tsTickPerDay[pRepo->config.precision] * pRepo->config.daysPerFile;
|
||||
|
||||
terrno = TSDB_CODE_SUCCESS;
|
||||
pMsg->length = htonl(pMsg->length);
|
||||
|
|
|
@ -39,6 +39,12 @@ enum {
|
|||
TSDB_QUERY_TYPE_LAST = 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
TSDB_CACHED_TYPE_NONE = 0,
|
||||
TSDB_CACHED_TYPE_LASTROW = 1,
|
||||
TSDB_CACHED_TYPE_LAST = 2,
|
||||
};
|
||||
|
||||
typedef struct SQueryFilePos {
|
||||
int32_t fid;
|
||||
int32_t slot;
|
||||
|
@ -280,9 +286,13 @@ static SArray* createCheckInfoFromTableGroup(STsdbQueryHandle* pQueryHandle, STa
|
|||
info.tableId.uid = info.pTableObj->tableId.uid;
|
||||
|
||||
if (ASCENDING_TRAVERSE(pQueryHandle->order)) {
|
||||
assert(info.lastKey >= pQueryHandle->window.skey);
|
||||
if (info.lastKey == INT64_MIN || info.lastKey < pQueryHandle->window.skey) {
|
||||
info.lastKey = pQueryHandle->window.skey;
|
||||
}
|
||||
|
||||
assert(info.lastKey >= pQueryHandle->window.skey && info.lastKey <= pQueryHandle->window.ekey);
|
||||
} else {
|
||||
assert(info.lastKey <= pQueryHandle->window.skey);
|
||||
assert(info.lastKey >= pQueryHandle->window.ekey && info.lastKey <= pQueryHandle->window.skey);
|
||||
}
|
||||
|
||||
taosArrayPush(pTableCheckInfo, &info);
|
||||
|
@ -339,14 +349,57 @@ static SArray* createCheckInfoFromCheckInfo(STableCheckInfo* pCheckInfo, TSKEY s
|
|||
return pNew;
|
||||
}
|
||||
|
||||
static bool emptyQueryTimewindow(STsdbQueryHandle* pQueryHandle) {
|
||||
assert(pQueryHandle != NULL);
|
||||
|
||||
STimeWindow* w = &pQueryHandle->window;
|
||||
bool asc = ASCENDING_TRAVERSE(pQueryHandle->order);
|
||||
|
||||
return ((asc && w->skey > w->ekey) || (!asc && w->ekey > w->skey));
|
||||
}
|
||||
|
||||
// Update the query time window according to the data time to live(TTL) information, in order to avoid to return
|
||||
// the expired data to client, even it is queried already.
|
||||
static int64_t getEarliestValidTimestamp(STsdbRepo* pTsdb) {
|
||||
STsdbCfg* pCfg = &pTsdb->config;
|
||||
|
||||
int64_t now = taosGetTimestamp(pCfg->precision);
|
||||
return now - (tsTickPerDay[pCfg->precision] * pCfg->keep);
|
||||
}
|
||||
|
||||
static void setQueryTimewindow(STsdbQueryHandle* pQueryHandle, STsdbQueryCond* pCond) {
|
||||
pQueryHandle->window = pCond->twindow;
|
||||
|
||||
bool updateTs = false;
|
||||
int64_t startTs = getEarliestValidTimestamp(pQueryHandle->pTsdb);
|
||||
if (ASCENDING_TRAVERSE(pQueryHandle->order)) {
|
||||
if (startTs > pQueryHandle->window.skey) {
|
||||
pQueryHandle->window.skey = startTs;
|
||||
pCond->twindow.skey = startTs;
|
||||
updateTs = true;
|
||||
}
|
||||
} else {
|
||||
if (startTs > pQueryHandle->window.ekey) {
|
||||
pQueryHandle->window.ekey = startTs;
|
||||
pCond->twindow.ekey = startTs;
|
||||
updateTs = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (updateTs) {
|
||||
tsdbDebug("%p update the query time window, old:%" PRId64 " - %" PRId64 ", new:%" PRId64 " - %" PRId64
|
||||
", 0x%" PRIx64, pQueryHandle, pCond->twindow.skey, pCond->twindow.ekey, pQueryHandle->window.skey,
|
||||
pQueryHandle->window.ekey, pQueryHandle->qId);
|
||||
}
|
||||
}
|
||||
|
||||
static STsdbQueryHandle* tsdbQueryTablesImpl(STsdbRepo* tsdb, STsdbQueryCond* pCond, uint64_t qId, SMemRef* pMemRef) {
|
||||
STsdbQueryHandle* pQueryHandle = calloc(1, sizeof(STsdbQueryHandle));
|
||||
if (pQueryHandle == NULL) {
|
||||
goto out_of_memory;
|
||||
goto _end;
|
||||
}
|
||||
|
||||
pQueryHandle->order = pCond->order;
|
||||
pQueryHandle->window = pCond->twindow;
|
||||
pQueryHandle->pTsdb = tsdb;
|
||||
pQueryHandle->type = TSDB_QUERY_TYPE_ALL;
|
||||
pQueryHandle->cur.fid = INT32_MIN;
|
||||
|
@ -354,36 +407,33 @@ static STsdbQueryHandle* tsdbQueryTablesImpl(STsdbRepo* tsdb, STsdbQueryCond* pC
|
|||
pQueryHandle->checkFiles = true;
|
||||
pQueryHandle->activeIndex = 0; // current active table index
|
||||
pQueryHandle->qId = qId;
|
||||
pQueryHandle->outputCapacity = ((STsdbRepo*)tsdb)->config.maxRowsPerFileBlock;
|
||||
pQueryHandle->allocSize = 0;
|
||||
pQueryHandle->locateStart = false;
|
||||
pQueryHandle->pMemRef = pMemRef;
|
||||
pQueryHandle->loadType = pCond->type;
|
||||
|
||||
pQueryHandle->outputCapacity = ((STsdbRepo*)tsdb)->config.maxRowsPerFileBlock;
|
||||
pQueryHandle->loadExternalRow = pCond->loadExternalRows;
|
||||
pQueryHandle->currentLoadExternalRows = pCond->loadExternalRows;
|
||||
|
||||
pQueryHandle->loadType = pCond->type;
|
||||
|
||||
if (tsdbInitReadH(&pQueryHandle->rhelper, (STsdbRepo*)tsdb) != 0) {
|
||||
goto out_of_memory;
|
||||
goto _end;
|
||||
}
|
||||
|
||||
assert(pCond != NULL && pMemRef != NULL);
|
||||
if (ASCENDING_TRAVERSE(pCond->order)) {
|
||||
assert(pQueryHandle->window.skey <= pQueryHandle->window.ekey);
|
||||
} else {
|
||||
assert(pQueryHandle->window.skey >= pQueryHandle->window.ekey);
|
||||
}
|
||||
setQueryTimewindow(pQueryHandle, pCond);
|
||||
|
||||
if (pCond->numOfCols > 0) {
|
||||
// allocate buffer in order to load data blocks from file
|
||||
pQueryHandle->statis = calloc(pCond->numOfCols, sizeof(SDataStatis));
|
||||
if (pQueryHandle->statis == NULL) {
|
||||
goto out_of_memory;
|
||||
goto _end;
|
||||
}
|
||||
|
||||
pQueryHandle->pColumns =
|
||||
taosArrayInit(pCond->numOfCols, sizeof(SColumnInfoData)); // todo: use list instead of array?
|
||||
// todo: use list instead of array?
|
||||
pQueryHandle->pColumns = taosArrayInit(pCond->numOfCols, sizeof(SColumnInfoData));
|
||||
if (pQueryHandle->pColumns == NULL) {
|
||||
goto out_of_memory;
|
||||
goto _end;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < pCond->numOfCols; ++i) {
|
||||
|
@ -392,14 +442,16 @@ static STsdbQueryHandle* tsdbQueryTablesImpl(STsdbRepo* tsdb, STsdbQueryCond* pC
|
|||
colInfo.info = pCond->colList[i];
|
||||
colInfo.pData = calloc(1, EXTRA_BYTES + pQueryHandle->outputCapacity * pCond->colList[i].bytes);
|
||||
if (colInfo.pData == NULL) {
|
||||
goto out_of_memory;
|
||||
goto _end;
|
||||
}
|
||||
|
||||
taosArrayPush(pQueryHandle->pColumns, &colInfo);
|
||||
pQueryHandle->statis[i].colId = colInfo.info.colId;
|
||||
}
|
||||
|
||||
pQueryHandle->defaultLoadColumn = getDefaultLoadColumns(pQueryHandle, true);
|
||||
}
|
||||
|
||||
STsdbMeta* pMeta = tsdbGetMeta(tsdb);
|
||||
assert(pMeta != NULL);
|
||||
|
||||
|
@ -407,7 +459,7 @@ static STsdbQueryHandle* tsdbQueryTablesImpl(STsdbRepo* tsdb, STsdbQueryCond* pC
|
|||
if (pQueryHandle->pDataCols == NULL) {
|
||||
tsdbError("%p failed to malloc buf for pDataCols, %"PRIu64, pQueryHandle, pQueryHandle->qId);
|
||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||
goto out_of_memory;
|
||||
goto _end;
|
||||
}
|
||||
|
||||
tsdbInitDataBlockLoadInfo(&pQueryHandle->dataBlockLoadInfo);
|
||||
|
@ -415,7 +467,7 @@ static STsdbQueryHandle* tsdbQueryTablesImpl(STsdbRepo* tsdb, STsdbQueryCond* pC
|
|||
|
||||
return (TsdbQueryHandleT) pQueryHandle;
|
||||
|
||||
out_of_memory:
|
||||
_end:
|
||||
tsdbCleanupQueryHandle(pQueryHandle);
|
||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
|
@ -423,6 +475,9 @@ static STsdbQueryHandle* tsdbQueryTablesImpl(STsdbRepo* tsdb, STsdbQueryCond* pC
|
|||
|
||||
TsdbQueryHandleT* tsdbQueryTables(STsdbRepo* tsdb, STsdbQueryCond* pCond, STableGroupInfo* groupList, uint64_t qId, SMemRef* pRef) {
|
||||
STsdbQueryHandle* pQueryHandle = tsdbQueryTablesImpl(tsdb, pCond, qId, pRef);
|
||||
if (emptyQueryTimewindow(pQueryHandle)) {
|
||||
return (TsdbQueryHandleT*) pQueryHandle;
|
||||
}
|
||||
|
||||
STsdbMeta* pMeta = tsdbGetMeta(tsdb);
|
||||
assert(pMeta != NULL);
|
||||
|
@ -446,6 +501,15 @@ TsdbQueryHandleT* tsdbQueryTables(STsdbRepo* tsdb, STsdbQueryCond* pCond, STable
|
|||
void tsdbResetQueryHandle(TsdbQueryHandleT queryHandle, STsdbQueryCond *pCond) {
|
||||
STsdbQueryHandle* pQueryHandle = queryHandle;
|
||||
|
||||
if (emptyQueryTimewindow(pQueryHandle)) {
|
||||
if (pCond->order != pQueryHandle->order) {
|
||||
pQueryHandle->order = pCond->order;
|
||||
SWAP(pQueryHandle->window.skey, pQueryHandle->window.ekey, int64_t);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pQueryHandle->order = pCond->order;
|
||||
pQueryHandle->window = pCond->twindow;
|
||||
pQueryHandle->type = TSDB_QUERY_TYPE_ALL;
|
||||
|
@ -864,10 +928,10 @@ static int32_t getFileIdFromKey(TSKEY key, int32_t daysPerFile, int32_t precisio
|
|||
}
|
||||
|
||||
if (key < 0) {
|
||||
key -= (daysPerFile * tsMsPerDay[precision]);
|
||||
key -= (daysPerFile * tsTickPerDay[precision]);
|
||||
}
|
||||
|
||||
int64_t fid = (int64_t)(key / (daysPerFile * tsMsPerDay[precision])); // set the starting fileId
|
||||
int64_t fid = (int64_t)(key / (daysPerFile * tsTickPerDay[precision])); // set the starting fileId
|
||||
if (fid < 0L && llabs(fid) > INT32_MAX) { // data value overflow for INT32
|
||||
fid = INT32_MIN;
|
||||
}
|
||||
|
@ -1171,8 +1235,9 @@ static int32_t handleDataMergeIfNeeded(STsdbQueryHandle* pQueryHandle, SBlock* p
|
|||
static int32_t loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SBlock* pBlock, STableCheckInfo* pCheckInfo, bool* exists) {
|
||||
SQueryFilePos* cur = &pQueryHandle->cur;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
bool asc = ASCENDING_TRAVERSE(pQueryHandle->order);
|
||||
|
||||
if (ASCENDING_TRAVERSE(pQueryHandle->order)) {
|
||||
if (asc) {
|
||||
// query ended in/started from current block
|
||||
if (pQueryHandle->window.ekey < pBlock->keyLast || pCheckInfo->lastKey > pBlock->keyFirst) {
|
||||
if ((code = doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo, cur->slot)) != TSDB_CODE_SUCCESS) {
|
||||
|
@ -1193,7 +1258,7 @@ static int32_t loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SBlock* pBlock,
|
|||
assert(pCheckInfo->lastKey <= pBlock->keyLast);
|
||||
doMergeTwoLevelData(pQueryHandle, pCheckInfo, pBlock);
|
||||
} else { // the whole block is loaded in to buffer
|
||||
cur->pos = ASCENDING_TRAVERSE(pQueryHandle->order)? 0:(pBlock->numOfRows - 1);
|
||||
cur->pos = asc? 0:(pBlock->numOfRows - 1);
|
||||
code = handleDataMergeIfNeeded(pQueryHandle, pBlock, pCheckInfo);
|
||||
}
|
||||
} else { //desc order, query ended in current block
|
||||
|
@ -1213,7 +1278,7 @@ static int32_t loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SBlock* pBlock,
|
|||
assert(pCheckInfo->lastKey >= pBlock->keyFirst);
|
||||
doMergeTwoLevelData(pQueryHandle, pCheckInfo, pBlock);
|
||||
} else {
|
||||
cur->pos = ASCENDING_TRAVERSE(pQueryHandle->order)? 0:(pBlock->numOfRows-1);
|
||||
cur->pos = asc? 0:(pBlock->numOfRows-1);
|
||||
code = handleDataMergeIfNeeded(pQueryHandle, pBlock, pCheckInfo);
|
||||
}
|
||||
}
|
||||
|
@ -2684,13 +2749,19 @@ static bool loadDataBlockFromTableSeq(STsdbQueryHandle* pQueryHandle) {
|
|||
bool tsdbNextDataBlock(TsdbQueryHandleT pHandle) {
|
||||
STsdbQueryHandle* pQueryHandle = (STsdbQueryHandle*) pHandle;
|
||||
|
||||
if (emptyQueryTimewindow(pQueryHandle)) {
|
||||
tsdbDebug("%p query window not overlaps with the data set, no result returned, 0x%"PRIx64, pQueryHandle, pQueryHandle->qId);
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t stime = taosGetTimestampUs();
|
||||
int64_t elapsedTime = stime;
|
||||
|
||||
// TODO refactor: remove "type"
|
||||
if (pQueryHandle->type == TSDB_QUERY_TYPE_LAST) {
|
||||
if (pQueryHandle->cachelastrow == 1) {
|
||||
if (pQueryHandle->cachelastrow == TSDB_CACHED_TYPE_LASTROW) {
|
||||
return loadCachedLastRow(pQueryHandle);
|
||||
} else if (pQueryHandle->cachelastrow == 2) {
|
||||
} else if (pQueryHandle->cachelastrow == TSDB_CACHED_TYPE_LAST) {
|
||||
return loadCachedLast(pQueryHandle);
|
||||
}
|
||||
}
|
||||
|
@ -2896,7 +2967,7 @@ out:
|
|||
}
|
||||
|
||||
bool isTsdbCacheLastRow(TsdbQueryHandleT* pQueryHandle) {
|
||||
return ((STsdbQueryHandle *)pQueryHandle)->cachelastrow > 0;
|
||||
return ((STsdbQueryHandle *)pQueryHandle)->cachelastrow > TSDB_CACHED_TYPE_NONE;
|
||||
}
|
||||
|
||||
int32_t checkForCachedLastRow(STsdbQueryHandle* pQueryHandle, STableGroupInfo *groupList) {
|
||||
|
@ -2914,9 +2985,9 @@ int32_t checkForCachedLastRow(STsdbQueryHandle* pQueryHandle, STableGroupInfo *g
|
|||
if (((STable*)pInfo->pTable)->lastRow) {
|
||||
code = tsdbGetCachedLastRow(pInfo->pTable, NULL, &key);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
pQueryHandle->cachelastrow = 0;
|
||||
pQueryHandle->cachelastrow = TSDB_CACHED_TYPE_NONE;
|
||||
} else {
|
||||
pQueryHandle->cachelastrow = 1;
|
||||
pQueryHandle->cachelastrow = TSDB_CACHED_TYPE_LASTROW;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2936,12 +3007,11 @@ int32_t checkForCachedLast(STsdbQueryHandle* pQueryHandle) {
|
|||
int32_t code = 0;
|
||||
|
||||
if (pQueryHandle->pTsdb && atomic_load_8(&pQueryHandle->pTsdb->hasCachedLastColumn)){
|
||||
pQueryHandle->cachelastrow = 2;
|
||||
pQueryHandle->cachelastrow = TSDB_CACHED_TYPE_LAST;
|
||||
}
|
||||
|
||||
// update the tsdb query time range
|
||||
if (pQueryHandle->cachelastrow) {
|
||||
pQueryHandle->window = TSWINDOW_INITIALIZER;
|
||||
pQueryHandle->checkFiles = false;
|
||||
pQueryHandle->activeIndex = -1; // start from -1
|
||||
}
|
||||
|
@ -3548,7 +3618,6 @@ int32_t tsdbGetOneTableGroup(STsdbRepo* tsdb, uint64_t uid, TSKEY startKey, STab
|
|||
taosArrayPush(group, &info);
|
||||
|
||||
taosArrayPush(pGroupInfo->pGroupList, &group);
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
_error:
|
||||
|
@ -3637,15 +3706,21 @@ void tsdbCleanupQueryHandle(TsdbQueryHandleT queryHandle) {
|
|||
return;
|
||||
}
|
||||
|
||||
pQueryHandle->pTableCheckInfo = destroyTableCheckInfo(pQueryHandle->pTableCheckInfo);
|
||||
pQueryHandle->pColumns = doFreeColumnInfoData(pQueryHandle->pColumns);
|
||||
|
||||
taosArrayDestroy(pQueryHandle->defaultLoadColumn);
|
||||
tfree(pQueryHandle->pDataBlockInfo);
|
||||
tfree(pQueryHandle->statis);
|
||||
|
||||
// todo check error
|
||||
tsdbMayUnTakeMemSnapshot(pQueryHandle);
|
||||
if (!emptyQueryTimewindow(pQueryHandle)) {
|
||||
tsdbMayUnTakeMemSnapshot(pQueryHandle);
|
||||
} else {
|
||||
assert(pQueryHandle->pTableCheckInfo == NULL);
|
||||
}
|
||||
|
||||
if (pQueryHandle->pTableCheckInfo != NULL) {
|
||||
pQueryHandle->pTableCheckInfo = destroyTableCheckInfo(pQueryHandle->pTableCheckInfo);
|
||||
}
|
||||
|
||||
tsdbDestroyReadH(&pQueryHandle->rhelper);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif // TDENGINE_TAOSARRAY_H
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue