diff --git a/.gitmodules b/.gitmodules
index 7c84eac8a4ee7529005855bc836387561c49ae2d..156226d54486c17e64b9c514e47e3a7dc3fe6942 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,9 @@
[submodule "src/connector/grafanaplugin"]
path = src/connector/grafanaplugin
url = https://github.com/taosdata/grafanaplugin
+[submodule "tests/examples/rust"]
+ path = tests/examples/rust
+ url = https://github.com/songtianyi/tdengine-rust-bindings.git
+[submodule "src/connector/hivemq-tdengine-extension"]
+ path = src/connector/hivemq-tdengine-extension
+ url = https://github.com/huskar-t/hivemq-tdengine-extension.git
\ No newline at end of file
diff --git a/Jenkinsfile b/Jenkinsfile
index ea50d6ef5a13fed2114868f8a36cd0acace78dd5..dc7836c3daacaa457f721f9278687b99770fc394 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -27,6 +27,7 @@ pipeline {
cd debug
cmake .. > /dev/null
make > /dev/null
+ make install > /dev/null
cd ${WKC}/tests
#./test-all.sh smoke
./test-all.sh pytest
@@ -79,7 +80,20 @@ pipeline {
cmake .. > /dev/null
make > /dev/null
cd ${WKC}/tests/pytest
- ./crash_gen.sh -a -p -t 4 -s 2000
+ '''
+ catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
+ sh '''
+ cd ${WKC}/tests/pytest
+ ./crash_gen.sh -a -p -t 4 -s 2000
+ '''
+ }
+ catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
+ sh '''
+ cd ${WKC}/tests/pytest
+ ./handle_crash_gen_val_log.sh
+ '''
+ }
+ sh '''
date
cd ${WKC}/tests
./test-all.sh b2
@@ -124,14 +138,33 @@ pipeline {
sh'''
cd ${WORKSPACE}
git checkout develop
- cd tests/gotest
- bash batchtest.sh
- cd ${WORKSPACE}/tests/examples/JDBC/JDBCDemo/
- mvn clean package assembly:single >/dev/null
- java -jar target/jdbcChecker-SNAPSHOT-jar-with-dependencies.jar -host 127.0.0.1
- cd ${WORKSPACE}/tests/examples/python/PYTHONConnectorChecker
- python3 PythonChecker.py
'''
+ catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
+ sh '''
+ cd ${WORKSPACE}/tests/gotest
+ bash batchtest.sh
+ '''
+ }
+ catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
+ sh '''
+ cd ${WORKSPACE}/tests/examples/python/PYTHONConnectorChecker
+ python3 PythonChecker.py
+ '''
+ }
+ catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
+ sh '''
+ cd ${WORKSPACE}/tests/examples/JDBC/JDBCDemo/
+ mvn clean package assembly:single >/dev/null
+ java -jar target/jdbcChecker-SNAPSHOT-jar-with-dependencies.jar -host 127.0.0.1
+ '''
+ }
+ catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
+ sh '''
+ cd ${JENKINS_HOME}/workspace/C#NET/src/CheckC#
+ dotnet run
+ '''
+ }
+
}
}
@@ -139,5 +172,82 @@ pipeline {
}
}
-
+ post {
+ success {
+ emailext (
+ subject: "SUCCESSFUL: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'",
+ body: '''
+
+
+
+
+
+
+
+
+ 构建信息
+
|
+
+
+
+
+
+ - 构建名称>>分支:${PROJECT_NAME}
+ - 构建结果: Successful
+ - 构建编号:${BUILD_NUMBER}
+ - 触发用户:${CAUSE}
+ - 变更概要:${CHANGES}
+ - 构建地址:${BUILD_URL}
+ - 构建日志:${BUILD_URL}console
+ - 变更集:${JELLY_SCRIPT}
+
+
+ |
+
+
+
+ ''',
+ to: "yqliu@taosdata.com,pxiao@taosdata.com",
+ from: "support@taosdata.com"
+ )
+ }
+ failure {
+ emailext (
+ subject: "FAILED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'",
+ body: '''
+
+
+
+
+
+
+
+
+ 构建信息
+
|
+
+
+
+
+
+ - 构建名称>>分支:${PROJECT_NAME}
+ - 构建结果: Successful
+ - 构建编号:${BUILD_NUMBER}
+ - 触发用户:${CAUSE}
+ - 变更概要:${CHANGES}
+ - 构建地址:${BUILD_URL}
+ - 构建日志:${BUILD_URL}console
+ - 变更集:${JELLY_SCRIPT}
+
+
+ |
+
+
+
+ ''',
+ to: "yqliu@taosdata.com,pxiao@taosdata.com",
+ from: "support@taosdata.com"
+ )
+ }
+ }
}
\ No newline at end of file
diff --git a/alert/README.md b/alert/README.md
index 547f3a0381a74714b1f6c8c74b861678b3805619..b8b8c92a2797bf58ca9f80b1781fc1f5d7555f6b 100644
--- a/alert/README.md
+++ b/alert/README.md
@@ -61,7 +61,7 @@ The use of each configuration item is:
* **port**: This is the `http` service port which enables other application to manage rules by `restful API`.
* **database**: rules are stored in a `sqlite` database, this is the path of the database file (if the file does not exist, the alert application creates it automatically).
-* **tdengine**: connection string of `TDEngine` server, note the database name should be put in the `sql` field of a rule in most cases, thus it should NOT be included in the string.
+* **tdengine**: connection string of `TDEngine` server (please refer the documentation of GO connector for the detailed format of this string), note the database name should be put in the `sql` field of a rule in most cases, thus it should NOT be included in the string.
* **log > level**: log level, could be `production` or `debug`.
* **log > path**: log output file path.
* **receivers > alertManager**: the alert application pushes alerts to `AlertManager` at this URL.
diff --git a/alert/README_cn.md b/alert/README_cn.md
index 938b23a58406f5d6f279191a47dc957c446911ce..f659e997e3ea8ec8acef8cc3eb6e41a4c692a476 100644
--- a/alert/README_cn.md
+++ b/alert/README_cn.md
@@ -58,7 +58,7 @@ $ go build
* **port**:报警监测程序支持使用 `restful API` 对规则进行管理,这个参数用于配置 `http` 服务的侦听端口。
* **database**:报警监测程序将规则保存到了一个 `sqlite` 数据库中,这个参数用于指定数据库文件的路径(不需要提前创建这个文件,如果它不存在,程序会自动创建它)。
-* **tdengine**:`TDEngine` 的连接字符串,一般来说,数据库名应该在报警规则的 `sql` 语句中指定,所以这个字符串中 **不** 应包含数据库名。
+* **tdengine**:`TDEngine` 的连接字符串(这个字符串的详细格式说明请见 GO 连接器的文档),一般来说,数据库名应该在报警规则的 `sql` 语句中指定,所以这个字符串中 **不** 应包含数据库名。
* **log > level**:日志的记录级别,可选 `production` 或 `debug`。
* **log > path**:日志文件的路径。
* **receivers > alertManager**:报警监测程序会将报警推送到 `AlertManager`,在这里指定 `AlertManager` 的接收地址。
diff --git a/alert/app/rule.go b/alert/app/rule.go
index 44596ca26d7da0ddec55dfabc2930c7166dc3547..236e5bd75562d90cac8bb5e20608dc08e1298f56 100644
--- a/alert/app/rule.go
+++ b/alert/app/rule.go
@@ -84,6 +84,7 @@ func (alert *Alert) doRefresh(firing bool, rule *Rule) bool {
case firing && (alert.State == AlertStateWaiting):
alert.StartsAt = time.Now()
+ alert.EndsAt = time.Time{}
if rule.For.Nanoseconds() > 0 {
alert.State = AlertStatePending
return false
@@ -95,6 +96,7 @@ func (alert *Alert) doRefresh(firing bool, rule *Rule) bool {
return false
}
alert.StartsAt = alert.StartsAt.Add(rule.For.Duration)
+ alert.EndsAt = time.Time{}
alert.State = AlertStateFiring
case firing && (alert.State == AlertStateFiring):
diff --git a/cmake/install.inc b/cmake/install.inc
index dfca758b9362c96bec0ce45aa385d54a4e75a9e5..746e493a17cd09db6f8bffa4e3e4ac925fac2510 100755
--- a/cmake/install.inc
+++ b/cmake/install.inc
@@ -9,22 +9,23 @@ ELSEIF (TD_WINDOWS)
ELSE ()
SET(CMAKE_INSTALL_PREFIX C:/TDengine)
ENDIF ()
-
+
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/go DESTINATION connector)
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/nodejs DESTINATION connector)
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/python DESTINATION connector)
+ INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/C\# DESTINATION connector)
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/tests/examples DESTINATION .)
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/packaging/cfg DESTINATION .)
INSTALL(FILES ${TD_COMMUNITY_DIR}/src/inc/taos.h DESTINATION include)
INSTALL(FILES ${TD_COMMUNITY_DIR}/src/inc/taoserror.h DESTINATION include)
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.lib DESTINATION driver)
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.exp DESTINATION driver)
- INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.dll DESTINATION driver)
-
+ INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.dll DESTINATION driver)
+
IF (TD_POWER)
INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/power.exe DESTINATION .)
- ELSE ()
- INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taos.exe DESTINATION .)
+ ELSE ()
+ INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taos.exe DESTINATION .)
INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taosdemo.exe DESTINATION .)
ENDIF ()
diff --git a/cmake/version.inc b/cmake/version.inc
index a248f76f48ede5f1f483943c08fce6604756b6d4..2f0ec81aea2dcc932845537bcb37f5ab64d9bcb8 100644
--- a/cmake/version.inc
+++ b/cmake/version.inc
@@ -4,7 +4,7 @@ PROJECT(TDengine)
IF (DEFINED VERNUMBER)
SET(TD_VER_NUMBER ${VERNUMBER})
ELSE ()
- SET(TD_VER_NUMBER "2.0.6.0")
+ SET(TD_VER_NUMBER "2.0.8.0")
ENDIF ()
IF (DEFINED VERCOMPATIBLE)
diff --git a/documentation/webdocs/markdowndocs/administrator-ch.md b/documentation/webdocs/markdowndocs/administrator-ch.md
index 44b3ad46712019870be6fefb5234611f55f6e03e..79388a2edb9404a0f7b31b9182eb5ce2cb0d52be 100644
--- a/documentation/webdocs/markdowndocs/administrator-ch.md
+++ b/documentation/webdocs/markdowndocs/administrator-ch.md
@@ -87,6 +87,7 @@ TDengine系统后台服务由taosd提供,可以在配置文件taos.cfg里修
- httpPort: RESTful服务使用的端口号,所有的HTTP请求(TCP)都需要向该接口发起查询/写入请求。
- dataDir: 数据文件目录,所有的数据文件都将写入该目录。默认值:/var/lib/taos。
- logDir:日志文件目录,客户端和服务器的运行日志文件将写入该目录。默认值:/var/log/taos。
+- tempDir:临时文件目录,客户端和服务器的临时文件(主要是查询时用于保存中间结果的问题)将写入该目录。 默认值:Linux下为 /tmp/,Windows下为环境变量 tmp 或 temp 指向的目录。
- arbitrator:系统中裁决器的end point, 缺省值为空。
- role:dnode的可选角色。0-any; 既可作为mnode,也可分配vnode;1-mgmt;只能作为mnode,不能分配vnode;2-dnode;不能作为mnode,只能分配vnode
- debugFlag:运行日志开关。131(输出错误和警告日志),135( 输出错误、警告和调试日志),143( 输出错误、警告、调试和跟踪日志)。默认值:131或135(不同模块有不同的默认值)。
diff --git a/documentation20/webdocs/markdowndocs/Documentation-ch.md b/documentation20/webdocs/markdowndocs/Documentation-ch.md
index 077a0431383da8067b6bd33c4b7218627b7adbd0..f1f2d58f0562b831395e5177eb34ec3534aaa715 100644
--- a/documentation20/webdocs/markdowndocs/Documentation-ch.md
+++ b/documentation20/webdocs/markdowndocs/Documentation-ch.md
@@ -34,7 +34,8 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专
- [SQL写入](https://www.taosdata.com/cn/documentation20/insert/#SQL写入):使用SQL insert命令向一张或多张表写入单条或多条记录
- [Telegraf写入](https://www.taosdata.com/cn/documentation20/insert/#Telegraf直接写入):配置Telegraf, 不用任何代码,将采集数据直接写入
- [Prometheus写入](https://www.taosdata.com/cn/documentation20/insert/#Prometheus直接写入):配置Prometheus, 不用任何代码,将数据直接写入
-- [EMQ X Broker](https://www.taosdata.com/cn/documentation20/insert/#EMQ-X-Broker直接写入):配置EMQ X,不用任何代码,就可将MQTT数据直接写入
+- [EMQ X Broker](https://www.taosdata.com/cn/documentation20/insert/#EMQ-X-Broker直接写入):配置EMQ X,不用任何代码,就可将 MQTT 数据直接写入
+- [HiveMQ Broker](https://www.taosdata.com/cn/documentation20/insert/#HiveMQ-Broker直接写入):通过 HiveMQ Extension,不用任何代码,就可将 MQTT 数据直接写入
## [高效查询数据](https://www.taosdata.com/cn/documentation20/queries)
diff --git a/documentation20/webdocs/markdowndocs/Evaluation-ch.md b/documentation20/webdocs/markdowndocs/Evaluation-ch.md
index 9e7e0ec6aa8b60bfa9dbe603a45a265a1d1eba00..a92f97a8d9dfc9a47d5554daa076f4d2f0774c92 100644
--- a/documentation20/webdocs/markdowndocs/Evaluation-ch.md
+++ b/documentation20/webdocs/markdowndocs/Evaluation-ch.md
@@ -10,7 +10,7 @@ TDengine的模块之一是时序数据库。但除此之外,为减少研发的
* __硬件或云服务成本降至1/5__:由于超强性能,计算资源不到通用大数据方案的1/5;通过列式存储和先进的压缩算法,存储空间不到通用数据库的1/10。
* __全栈时序数据处理引擎__:将数据库、消息队列、缓存、流式计算等功能融为一体,应用无需再集成Kafka/Redis/HBase/Spark/HDFS等软件,大幅降低应用开发和维护的复杂度成本。
* __强大的分析功能__:无论是十年前还是一秒钟前的数据,指定时间范围即可查询。数据可在时间轴上或多个设备上进行聚合。即席查询可通过Shell, Python, R, Matlab随时进行。
-* __与第三方工具无缝连接__:不用一行代码,即可与Telegraf, Grafana, EMQ, Prometheus, Matlab, R等集成。后续将支持OPC, Hadoop, Spark等, BI工具也将无缝连接。
+* __与第三方工具无缝连接__:不用一行代码,即可与Telegraf, Grafana, EMQ, HiveMQ, Prometheus, Matlab, R等集成。后续将支持OPC, Hadoop, Spark等, BI工具也将无缝连接。
* __零运维成本、零学习成本__:安装集群简单快捷,无需分库分表,实时备份。类似标准SQL,支持RESTful, 支持Python/Java/C/C++/C#/Go/Node.js, 与MySQL相似,零学习成本。
采用TDengine,可将典型的物联网、车联网、工业互联网大数据平台的总拥有成本大幅降低。但需要指出的是,因充分利用了物联网时序数据的特点,它无法用来处理网络爬虫、微博、微信、电商、ERP、CRM等通用型数据。
diff --git a/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md b/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md
index 4082d72f112e8ff62d2e8b2c8b15391dd6f39d8a..760ebae4fc3b7ddd609d1bfb5689f51b05fc7cb7 100644
--- a/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md
+++ b/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md
@@ -90,7 +90,7 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic
```mysql
ALTER DATABASE db_name REPLICA 2;
```
- REPLICA参数是指修改数据库副本数,取值范围[1, 3]。在集群中使用,副本数必须小于dnode的数目。
+ REPLICA参数是指修改数据库副本数,取值范围[1, 3]。在集群中使用,副本数必须小于或等于dnode的数目。
```mysql
ALTER DATABASE db_name KEEP 365;
@@ -844,7 +844,7 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
- **PERCENTILE**
```mysql
- SELECT PERCENTILE(field_name, P) FROM { tb_name | stb_name } [WHERE clause];
+ SELECT PERCENTILE(field_name, P) FROM { tb_name } [WHERE clause];
```
功能说明:统计表中某列的值百分比分位数。
返回结果数据类型: 双精度浮点数Double。
@@ -1016,9 +1016,9 @@ SELECT AVG(current),MAX(current),LEASTSQUARES(current, start_val, step_val), PER
```
## TAOS SQL 边界限制
-- 数据库名最大长度为33
-- 表名最大长度为193,每行数据最大长度16k个字符
-- 列名最大长度为65,最多允许1024列,最少需要2列,第一列必须是时间戳
+- 数据库名最大长度为32
+- 表名最大长度为192,每行数据最大长度16k个字符
+- 列名最大长度为64,最多允许1024列,最少需要2列,第一列必须是时间戳
- 标签最多允许128个,可以0个,标签总长度不超过16k个字符
- SQL语句最大长度65480个字符,但可通过系统配置参数maxSQLLength修改,最长可配置为1M
- 库的数目,超级表的数目、表的数目,系统不做限制,仅受系统资源限制
diff --git a/documentation20/webdocs/markdowndocs/administrator-ch.md b/documentation20/webdocs/markdowndocs/administrator-ch.md
index 4b274e05e6e392879fc887ec1137968270a8e4b8..36466d2b7ea29307b5c17ad21b0db47a98598fa4 100644
--- a/documentation20/webdocs/markdowndocs/administrator-ch.md
+++ b/documentation20/webdocs/markdowndocs/administrator-ch.md
@@ -35,7 +35,7 @@ TDengine相对于通用数据库,有超高的压缩比,在绝大多数场景
Raw DataSize = numOfTables * rowSizePerTable * rowsPerTable
```
-示例:1000万台智能电表,每台电表每15分钟采集一次数据,每次采集的数据128字节,那么一年的原始数据量是:10000000\*128\*24\*60/15*365 = 44851T。TDengine大概需要消耗44851/5=8970T, 8.9P空间。
+示例:1000万台智能电表,每台电表每15分钟采集一次数据,每次采集的数据128字节,那么一年的原始数据量是:10000000\*128\*24\*60/15*365 = 44.8512T。TDengine大概需要消耗44.851/5=8.97024T空间。
用户可以通过参数keep,设置数据在磁盘中的最大保存时长。为进一步减少存储成本,TDengine还提供多级存储,最冷的数据可以存放在最廉价的存储介质上,应用的访问不用做任何调整,只是读取速度降低了。
@@ -253,7 +253,7 @@ ALTER USER PASS <'password'>;
修改用户密码, 为避免被转换为小写,密码需要用单引号引用,单引号为英文半角
```
-ALTER USER PRIVILEDGE ;
+ALTER USER PRIVILEGE ;
```
修改用户权限为:super/write/read,不需要添加单引号
diff --git a/documentation20/webdocs/markdowndocs/architecture-ch.md b/documentation20/webdocs/markdowndocs/architecture-ch.md
index d4705ccb05c092d8da38072368a167466bd78968..c9bfa30830fe7b2f3cd1364b589326255560ad83 100644
--- a/documentation20/webdocs/markdowndocs/architecture-ch.md
+++ b/documentation20/webdocs/markdowndocs/architecture-ch.md
@@ -4,16 +4,99 @@
### 物联网典型场景
在典型的物联网、车联网、运维监测场景中,往往有多种不同类型的数据采集设备,采集一个到多个不同的物理量。而同一种采集设备类型,往往又有多个具体的采集设备分布在不同的地点。大数据处理系统就是要将各种采集的数据汇总,然后进行计算和分析。对于同一类设备,其采集的数据都是很规则的。以智能电表为例,假设每个智能电表采集电流、电压、相位三个量,其采集的数据类似如下的表格:
-| Device ID | Time Stamp | current | voltage | phase | location | groupId |
-| :-------: | :-----------: | :-----: | :-----: | :---: | :--------------: | :-----: |
-| d1001 | 1538548685000 | 10.3 | 219 | 0.31 | Beijing.Chaoyang | 2 |
-| d1002 | 1538548684000 | 10.2 | 220 | 0.23 | Beijing.Chaoyang | 3 |
-| d1003 | 1538548686500 | 11.5 | 221 | 0.35 | Beijing.Haidian | 3 |
-| d1004 | 1538548685500 | 13.4 | 223 | 0.29 | Beijing.Haidian | 2 |
-| d1001 | 1538548695000 | 12.6 | 218 | 0.33 | Beijing.Chaoyang | 2 |
-| d1004 | 1538548696600 | 11.8 | 221 | 0.28 | Beijing.Haidian | 2 |
-| d1002 | 1538548696650 | 10.3 | 218 | 0.25 | Beijing.Chaoyang | 3 |
-| d1001 | 1538548696800 | 12.3 | 221 | 0.31 | Beijing.Chaoyang | 2 |
+
+
+ 设备ID |
+ 时间戳 |
+ 采集量 |
+ 标签 |
+
+
+
+Device ID |
+Time Stamp |
+current |
+voltage |
+phase |
+location |
+groupId |
+
+
+
+
+d1001 |
+1538548685000 |
+10.3 |
+219 |
+0.31 |
+Beijing.Chaoyang |
+2 |
+
+
+d1002 |
+1538548684000 |
+10.2 |
+220 |
+0.23 |
+Beijing.Chaoyang |
+3 |
+
+
+d1003 |
+1538548686500 |
+11.5 |
+221 |
+0.35 |
+Beijing.Haidian |
+3 |
+
+
+d1004 |
+1538548685500 |
+13.4 |
+223 |
+0.29 |
+Beijing.Haidian |
+2 |
+
+
+d1001 |
+1538548695000 |
+12.6 |
+218 |
+0.33 |
+Beijing.Chaoyang |
+2 |
+
+
+d1004 |
+1538548696600 |
+11.8 |
+221 |
+0.28 |
+Beijing.Haidian |
+2 |
+
+
+d1002 |
+1538548696650 |
+10.3 |
+218 |
+0.25 |
+Beijing.Chaoyang |
+3 |
+
+
+d1001 |
+1538548696800 |
+12.3 |
+221 |
+0.31 |
+Beijing.Chaoyang |
+2 |
+
+
+
表1:智能电表数据示例
@@ -221,7 +304,7 @@ TDengine采用时间驱动缓存管理策略(First-In-First-Out,FIFO),
TDengine通过查询函数向用户提供毫秒级的数据获取能力。直接将最近到达的数据保存在缓存中,可以更加快速地响应用户针对最近一条或一批数据的查询分析,整体上提供更快的数据库查询响应能力。从这个意义上来说,**可通过设置合适的配置参数将TDengine作为数据缓存来使用,而不需要再部署Redis或其他额外的缓存系统**,可有效地简化系统架构,降低运维的成本。需要注意的是,TDengine重启以后系统的缓存将被清空,之前缓存的数据均会被批量写入磁盘,缓存的数据将不会像专门的Key-value缓存系统再将之前缓存的数据重新加载到缓存中。
-每个vnode有自己独立的内存,而且由多个固定大小的内存块组成,不同vnode之间完全隔离。数据写入时,类似于日志的写法,数据被顺序追加写入内存,但每个vnode维护有自己的skip list,便于迅速查找。当一半以上的内存块写满时,启动落盘操作,而且后续写的操作在新的内存块进行。这样,一个vnode里有一半内存块是保留有最近的数据的,以达到缓存、快速查找的目的。一个vnode的内存块的个数由配置参数blocks决定,内存块的大小由配置参数cache决定。
+每个vnode有自己独立的内存,而且由多个固定大小的内存块组成,不同vnode之间完全隔离。数据写入时,类似于日志的写法,数据被顺序追加写入内存,但每个vnode维护有自己的skip list,便于迅速查找。当三分之一以上的内存块写满时,启动落盘操作,而且后续写的操作在新的内存块进行。这样,一个vnode里有三分之一内存块是保留有最近的数据的,以达到缓存、快速查找的目的。一个vnode的内存块的个数由配置参数blocks决定,内存块的大小由配置参数cache决定。
### 持久化存储
TDengine采用数据驱动的方式让缓存中的数据写入硬盘进行持久化存储。当vnode中缓存的数据达到一定规模时,为了不阻塞后续数据的写入,TDengine也会拉起落盘线程将缓存的数据写入持久化存储。TDengine在数据落盘时会打开新的数据库日志文件,在落盘成功后则会删除老的数据库日志文件,避免日志文件无限制的增长。
diff --git a/documentation20/webdocs/markdowndocs/connector-ch.md b/documentation20/webdocs/markdowndocs/connector-ch.md
index 0e29b324871e61d184fde17710c863f06b60bdcc..c5a955f43fcc30e70d8aac3919433c2e767f76ba 100644
--- a/documentation20/webdocs/markdowndocs/connector-ch.md
+++ b/documentation20/webdocs/markdowndocs/connector-ch.md
@@ -616,6 +616,43 @@ HTTP请求URL采用`sqlutc`时,返回结果集的时间戳将采用UTC时间
- httpEnableCompress: 是否支持压缩,默认不支持,目前TDengine仅支持gzip压缩格式
- httpDebugFlag: 日志开关,131:仅错误和报警信息,135:调试信息,143:非常详细的调试信息,默认131
+## CSharp Connector
+
+在Windows系统上,C#应用程序可以使用TDengine的原生C接口来执行所有数据库操作,后续版本将提供ORM(dapper)框架驱动。
+
+#### 安装TDengine客户端
+
+C#连接器需要使用`libtaos.so`和`taos.h`。因此,在使用C#连接器之前,需在程序运行的Windows环境安装TDengine的Windows客户端,以便获得相关驱动文件。
+
+安装完成后,在文件夹`C:/TDengine/examples/C#`中,将会看到两个文件
+
+- TDengineDriver.cs 调用taos.dll文件的Native C方法
+- TDengineTest.cs 参考程序示例
+
+在文件夹`C:\Windows\System32`,将会看到`taos.dll`文件
+
+#### 使用方法
+
+- 将C#接口文件TDengineDriver.cs加入到应用程序所在.NET项目中
+- 参考TDengineTest.cs来定义数据库连接参数,及执行数据插入、查询等操作的方法
+- 因为C#接口需要用到`taos.dll`文件,用户可以将`taos.dll`文件加入.NET解决方案中
+
+#### 注意事项
+
+- `taos.dll`文件使用x64平台编译,所以.NET项目在生成.exe文件时,“解决方案”/“项目”的“平台”请均选择“x64”。
+- 此.NET接口目前已经在Visual Studio 2013/2015/2017中验证过,其它VS版本尚待验证。
+
+#### 第三方驱动
+
+Maikebing.Data.Taos是一个TDengine的ADO.Net提供器,支持linux,windows。该开发包由热心贡献者`麦壳饼@@maikebing`提供,具体请参考
+
+```
+//接口下载
+https://github.com/maikebing/Maikebing.EntityFrameworkCore.Taos
+//用法说明
+https://www.taosdata.com/blog/2020/11/02/1901.html
+```
+
## Go Connector
diff --git a/documentation20/webdocs/markdowndocs/faq-ch.md b/documentation20/webdocs/markdowndocs/faq-ch.md
index 80deb889ef0eee8e9b47f86b5e58a76c6c070d5b..757b6d9929b68a90e7bc558b553233f24b09ba17 100644
--- a/documentation20/webdocs/markdowndocs/faq-ch.md
+++ b/documentation20/webdocs/markdowndocs/faq-ch.md
@@ -38,9 +38,9 @@
6. 检查防火墙设置,确认TCP/UDP 端口6030-6042 是打开的
-7. 对于Linux上的JDBC(ODBC, Python, Go等接口类似)连接, 确保*libtaos.so*在目录*/usr/local/lib/taos*里, 并且*/usr/local/lib/taos*在系统库函数搜索路径*LD_LIBRARY_PATH*里
+7. 对于Linux上的JDBC(ODBC, Python, Go等接口类似)连接, 确保*libtaos.so*在目录*/usr/local/taos/driver*里, 并且*/usr/local/taos/driver*在系统库函数搜索路径*LD_LIBRARY_PATH*里
-8. 对于windows上的JDBC, ODBC, Python, Go等连接,确保*driver/c/taos.dll*在你的系统搜索目录里 (建议*taos.dll*放在目录 *C:\Windows\System32*)
+8. 对于windows上的JDBC, ODBC, Python, Go等连接,确保*C:\TDengine\driver\taos.dll*在你的系统库函数搜索目录里 (建议*taos.dll*放在目录 *C:\Windows\System32*)
9. 如果仍不能排除连接故障,请使用命令行工具nc来分别判断指定端口的TCP和UDP连接是否通畅
检查UDP端口连接是否工作:`nc -vuz {hostIP} {port} `
diff --git a/documentation20/webdocs/markdowndocs/insert-ch.md b/documentation20/webdocs/markdowndocs/insert-ch.md
index fa53cbd62b17169c0f54877a62da8c48ac21edcf..77ba596d4ec6de76a39b878e57ea255b081fea45 100644
--- a/documentation20/webdocs/markdowndocs/insert-ch.md
+++ b/documentation20/webdocs/markdowndocs/insert-ch.md
@@ -1,6 +1,6 @@
# 高效写入数据
-TDengine支持多种接口写入数据,包括SQL, Prometheus, Telegraf, EMQ MQTT Broker, CSV文件等,后续还将提供Kafka, OPC等接口。数据可以单条插入,也可以批量插入,可以插入一个数据采集点的数据,也可以同时插入多个数据采集点的数据。支持多线程插入,支持时间乱序数据插入,也支持历史数据插入。
+TDengine支持多种接口写入数据,包括SQL, Prometheus, Telegraf, EMQ MQTT Broker, HiveMQ Broker, CSV文件等,后续还将提供Kafka, OPC等接口。数据可以单条插入,也可以批量插入,可以插入一个数据采集点的数据,也可以同时插入多个数据采集点的数据。支持多线程插入,支持时间乱序数据插入,也支持历史数据插入。
## SQL写入
@@ -218,7 +218,15 @@ use telegraf;
select * from cpu;
```
-## EMQ X Broker直接写入
-MQTT是一流行的物联网数据传输协议,[EMQ](https://github.com/emqx/emqx)是一开源的MQTT Broker软件,无需任何代码,只需要在EMQ Dashboard里使用“规则”做简单配置,即可将MQTT的数据直接写入TDengine。EMQ X 支持通过 发送到 Web 服务 的方式保存数据到 TDEngine,也在企业版上提供原生的 TDEngine 驱动实现直接保存。详细使用方法请参考 [EMQ 官方文档](https://docs.emqx.io/broker/latest/cn/rule/rule-example.html#%E4%BF%9D%E5%AD%98%E6%95%B0%E6%8D%AE%E5%88%B0-tdengine)。
+
+MQTT是一流行的物联网数据传输协议,TDengine 可以很方便的接入 MQTT Broker 接受的数据并写入到 TDengine。
+
+## EMQ Broker 直接写入
+
+[EMQ](https://github.com/emqx/emqx)是一开源的MQTT Broker软件,无需任何代码,只需要在EMQ Dashboard里使用“规则”做简单配置,即可将MQTT的数据直接写入TDengine。EMQ X 支持通过 发送到 Web 服务 的方式保存数据到 TDengine,也在企业版上提供原生的 TDEngine 驱动实现直接保存。详细使用方法请参考 [EMQ 官方文档](https://docs.emqx.io/broker/latest/cn/rule/rule-example.html#%E4%BF%9D%E5%AD%98%E6%95%B0%E6%8D%AE%E5%88%B0-tdengine)。
+
+## HiveMQ Broker 直接写入
+
+[HiveMQ](https://www.hivemq.com/) 是一个提供免费个人版和企业版的 MQTT 代理,主要用于企业和新兴的机器到机器M2M通讯和内部传输,满足可伸缩性、易管理和安全特性。HiveMQ 提供了开源的插件开发包。可以通过 HiveMQ extension - TDengine 保存数据到 TDengine。详细使用方法请参考 [HiveMQ extension - TDengine 说明文档](https://github.com/huskar-t/hivemq-tdengine-extension/blob/b62a26ecc164a310104df57691691b237e091c89/README.md)。
diff --git a/packaging/cfg/taos.cfg b/packaging/cfg/taos.cfg
index 974b2b05c12f9fd5a482ef0072a9dacc2d1f09dc..ca88bca3c863dcfd4a95497fc572499dc93f31f9 100644
--- a/packaging/cfg/taos.cfg
+++ b/packaging/cfg/taos.cfg
@@ -20,6 +20,9 @@
# data file's directory
# dataDir /var/lib/taos
+# temporary file's directory
+# tempDir /tmp/
+
# the arbitrator's fully qualified domain name (FQDN) for TDengine system, for cluster only
# arbitrator arbitrator_hostname:6042
@@ -256,3 +259,5 @@
# maximum display width of binary and nchar fields in the shell. The parts exceeding this limit will be hidden
# maxBinaryDisplayWidth 30
+# enable/disable telemetry reporting
+# telemetryReporting 1
\ No newline at end of file
diff --git a/packaging/deb/makedeb.sh b/packaging/deb/makedeb.sh
index 450c6a8f551fe7dd8dff5e53f5dad639aec4656e..edc7de96923266729d1985cb43abfa3003f9178e 100755
--- a/packaging/deb/makedeb.sh
+++ b/packaging/deb/makedeb.sh
@@ -48,6 +48,7 @@ cp ${compile_dir}/../packaging/deb/taosd ${pkg_dir}${install_home_pat
cp ${compile_dir}/../packaging/tools/post.sh ${pkg_dir}${install_home_path}/script
cp ${compile_dir}/../packaging/tools/preun.sh ${pkg_dir}${install_home_path}/script
cp ${compile_dir}/build/bin/taosdemo ${pkg_dir}${install_home_path}/bin
+cp ${compile_dir}/build/bin/taosdump ${pkg_dir}${install_home_path}/bin
cp ${compile_dir}/build/bin/taosd ${pkg_dir}${install_home_path}/bin
cp ${compile_dir}/build/bin/taos ${pkg_dir}${install_home_path}/bin
cp ${compile_dir}/build/lib/${libfile} ${pkg_dir}${install_home_path}/driver
@@ -58,7 +59,7 @@ cp -r ${top_dir}/src/connector/grafanaplugin ${pkg_dir}${install_home_pat
cp -r ${top_dir}/src/connector/python ${pkg_dir}${install_home_path}/connector
cp -r ${top_dir}/src/connector/go ${pkg_dir}${install_home_path}/connector
cp -r ${top_dir}/src/connector/nodejs ${pkg_dir}${install_home_path}/connector
-cp ${compile_dir}/build/lib/taos-jdbcdriver*dist.* ${pkg_dir}${install_home_path}/connector
+cp ${compile_dir}/build/lib/taos-jdbcdriver*dist.* ${pkg_dir}${install_home_path}/connector ||:
cp -r ${compile_dir}/../packaging/deb/DEBIAN ${pkg_dir}/
chmod 755 ${pkg_dir}/DEBIAN/*
diff --git a/packaging/release.sh b/packaging/release.sh
index 7542a5b4cafb69d5cee16bddfc9a5651eb717b92..68f947ccab3ef18a1b351b91a58db64a8f465c8e 100755
--- a/packaging/release.sh
+++ b/packaging/release.sh
@@ -156,9 +156,15 @@ build_time=$(date +"%F %R")
# get commint id from git
gitinfo=$(git rev-parse --verify HEAD)
-enterprise_dir="${top_dir}/../enterprise"
-cd ${enterprise_dir}
-gitinfoOfInternal=$(git rev-parse --verify HEAD)
+
+if [[ "$verMode" == "cluster" ]]; then
+ enterprise_dir="${top_dir}/../enterprise"
+ cd ${enterprise_dir}
+ gitinfoOfInternal=$(git rev-parse --verify HEAD)
+else
+ gitinfoOfInternal=NULL
+fi
+
cd ${curr_dir}
# 2. cmake executable file
@@ -193,23 +199,35 @@ cd ${curr_dir}
# 3. Call the corresponding script for packaging
if [ "$osType" != "Darwin" ]; then
if [[ "$verMode" != "cluster" ]] && [[ "$cpuType" == "x64" ]] && [[ "$dbName" == "taos" ]]; then
- echo "====do deb package for the ubuntu system===="
- output_dir="${top_dir}/debs"
- if [ -d ${output_dir} ]; then
- ${csudo} rm -rf ${output_dir}
+ ret='0'
+ command -v dpkg >/dev/null 2>&1 || { ret='1'; }
+ if [ "$ret" -eq 0 ]; then
+ echo "====do deb package for the ubuntu system===="
+ output_dir="${top_dir}/debs"
+ if [ -d ${output_dir} ]; then
+ ${csudo} rm -rf ${output_dir}
+ fi
+ ${csudo} mkdir -p ${output_dir}
+ cd ${script_dir}/deb
+ ${csudo} ./makedeb.sh ${compile_dir} ${output_dir} ${verNumber} ${cpuType} ${osType} ${verMode} ${verType}
+ else
+ echo "==========dpkg command not exist, so not release deb package!!!"
fi
- ${csudo} mkdir -p ${output_dir}
- cd ${script_dir}/deb
- ${csudo} ./makedeb.sh ${compile_dir} ${output_dir} ${verNumber} ${cpuType} ${osType} ${verMode} ${verType}
-
- echo "====do rpm package for the centos system===="
- output_dir="${top_dir}/rpms"
- if [ -d ${output_dir} ]; then
- ${csudo} rm -rf ${output_dir}
+
+ ret='0'
+ command -v rpmbuild >/dev/null 2>&1 || { ret='1'; }
+ if [ "$ret" -eq 0 ]; then
+ echo "====do rpm package for the centos system===="
+ output_dir="${top_dir}/rpms"
+ if [ -d ${output_dir} ]; then
+ ${csudo} rm -rf ${output_dir}
+ fi
+ ${csudo} mkdir -p ${output_dir}
+ cd ${script_dir}/rpm
+ ${csudo} ./makerpm.sh ${compile_dir} ${output_dir} ${verNumber} ${cpuType} ${osType} ${verMode} ${verType}
+ else
+ echo "==========rpmbuild command not exist, so not release rpm package!!!"
fi
- ${csudo} mkdir -p ${output_dir}
- cd ${script_dir}/rpm
- ${csudo} ./makerpm.sh ${compile_dir} ${output_dir} ${verNumber} ${cpuType} ${osType} ${verMode} ${verType}
fi
echo "====do tar.gz package for all systems===="
diff --git a/packaging/rpm/tdengine.spec b/packaging/rpm/tdengine.spec
index 4e40263dc4ebaf6b566d20890ecd97f64e160340..8c23ab802d54088dafc4b4c6a5d1b6241c881f2e 100644
--- a/packaging/rpm/tdengine.spec
+++ b/packaging/rpm/tdengine.spec
@@ -2,7 +2,7 @@
%define cfg_install_dir /etc/taos
%define __strip /bin/true
-Name: TDengine
+Name: tdengine
Version: %{_version}
Release: 3%{?dist}
Summary: tdengine from taosdata
@@ -58,6 +58,7 @@ cp %{_compiledir}/../packaging/tools/preun.sh %{buildroot}%{homepath}/scri
cp %{_compiledir}/build/bin/taos %{buildroot}%{homepath}/bin
cp %{_compiledir}/build/bin/taosd %{buildroot}%{homepath}/bin
cp %{_compiledir}/build/bin/taosdemo %{buildroot}%{homepath}/bin
+cp %{_compiledir}/build/bin/taosdump %{buildroot}%{homepath}/bin
cp %{_compiledir}/build/lib/${libfile} %{buildroot}%{homepath}/driver
cp %{_compiledir}/../src/inc/taos.h %{buildroot}%{homepath}/include
cp %{_compiledir}/../src/inc/taoserror.h %{buildroot}%{homepath}/include
@@ -65,7 +66,7 @@ cp -r %{_compiledir}/../src/connector/grafanaplugin %{buildroot}%{homepath}/conn
cp -r %{_compiledir}/../src/connector/python %{buildroot}%{homepath}/connector
cp -r %{_compiledir}/../src/connector/go %{buildroot}%{homepath}/connector
cp -r %{_compiledir}/../src/connector/nodejs %{buildroot}%{homepath}/connector
-cp %{_compiledir}/build/lib/taos-jdbcdriver*dist.* %{buildroot}%{homepath}/connector
+cp %{_compiledir}/build/lib/taos-jdbcdriver*dist.* %{buildroot}%{homepath}/connector ||:
cp -r %{_compiledir}/../tests/examples/* %{buildroot}%{homepath}/examples
#Scripts executed before installation
@@ -134,6 +135,7 @@ if [ $1 -eq 0 ];then
${csudo} rm -f ${bin_link_dir}/taos || :
${csudo} rm -f ${bin_link_dir}/taosd || :
${csudo} rm -f ${bin_link_dir}/taosdemo || :
+ #${csudo} rm -f ${bin_link_dir}/taosdump || :
${csudo} rm -f ${cfg_link_dir}/* || :
${csudo} rm -f ${inc_link_dir}/taos.h || :
${csudo} rm -f ${inc_link_dir}/taoserror.h || :
diff --git a/packaging/tools/get_client.sh b/packaging/tools/get_client.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0d34ecb311fb4b941d6f6773d1c3c921a9bd9886
--- /dev/null
+++ b/packaging/tools/get_client.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+
+log_dir=$1
+result_file=$2
+
+if [ ! -n "$1" ];then
+ echo "Pleas input the director of taosdlog."
+ echo "usage: ./get_client.sh "
+ exit 1
+else
+ log_dir=$1
+fi
+
+if [ ! -n "$2" ];then
+ result_file=clientInfo.txt
+else
+ result_file=$2
+fi
+
+grep "new TCP connection" ${log_dir}/taosdlog.* | sed -e "s/0x.* from / /"|sed -e "s/,.*$//"|sed -e "s/:[0-9]*$//"|sort -r|uniq -f 2|sort -k 3 -r|uniq -f 2 > ${result_file}
diff --git a/packaging/tools/install.sh b/packaging/tools/install.sh
index aedfb0a6834afbf3c0c8c822b056ea5705f8d2ff..ddf7114f08387c2277df47e9174948e479d432ba 100755
--- a/packaging/tools/install.sh
+++ b/packaging/tools/install.sh
@@ -312,7 +312,7 @@ function install_data() {
}
function install_connector() {
- ${csudo} cp -rf ${script_dir}/connector/* ${install_main_dir}/connector
+ ${csudo} cp -rf ${script_dir}/connector/ ${install_main_dir}/
}
function install_examples() {
diff --git a/packaging/tools/install_client.sh b/packaging/tools/install_client.sh
index 24586d3390fe5c4f38b6292442fed2936d5ea7a6..34a9bfaecb4d0366008ea9b78a60434297ea9f51 100755
--- a/packaging/tools/install_client.sh
+++ b/packaging/tools/install_client.sh
@@ -163,7 +163,7 @@ function install_log() {
}
function install_connector() {
- ${csudo} cp -rf ${script_dir}/connector/* ${install_main_dir}/connector
+ ${csudo} cp -rf ${script_dir}/connector/ ${install_main_dir}/
}
function install_examples() {
diff --git a/packaging/tools/make_install.sh b/packaging/tools/make_install.sh
index eff70d8035af0291f6dc7040ec13632fec4fa3be..831012851ad70d05080bfae161c0b925d5215ae9 100755
--- a/packaging/tools/make_install.sh
+++ b/packaging/tools/make_install.sh
@@ -278,11 +278,11 @@ function install_service_on_sysvinit() {
# Install taosd service
if ((${os_type}==1)); then
- ${csudo} cp -f ${script_dir}/../deb/init.d/taosd ${install_main_dir}/init.d
- ${csudo} cp ${script_dir}/../deb/init.d/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd
+ ${csudo} cp -f ${script_dir}/../deb/taosd ${install_main_dir}/init.d
+ ${csudo} cp ${script_dir}/../deb/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd
elif ((${os_type}==2)); then
- ${csudo} cp -f ${script_dir}/../rpm/init.d/taosd ${install_main_dir}/init.d
- ${csudo} cp ${script_dir}/../rpm/init.d/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd
+ ${csudo} cp -f ${script_dir}/../rpm/taosd ${install_main_dir}/init.d
+ ${csudo} cp ${script_dir}/../rpm/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd
fi
#restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start"
diff --git a/packaging/tools/makeclient.sh b/packaging/tools/makeclient.sh
index e17c678f263cb6b7a0ccbc32250265b9bc5cbd0e..ee79a560407c650de8c511964f611cf8cacfd2d5 100755
--- a/packaging/tools/makeclient.sh
+++ b/packaging/tools/makeclient.sh
@@ -45,7 +45,7 @@ if [ "$osType" != "Darwin" ]; then
strip ${build_dir}/bin/taos
bin_files="${build_dir}/bin/taos ${script_dir}/remove_client.sh"
else
- bin_files="${build_dir}/bin/taos ${build_dir}/bin/taosdemo ${script_dir}/remove_client.sh ${script_dir}/set_core.sh"
+ bin_files="${build_dir}/bin/taos ${build_dir}/bin/taosdump ${build_dir}/bin/taosdemo ${script_dir}/remove_client.sh ${script_dir}/set_core.sh ${script_dir}/get_client.sh"
fi
lib_files="${build_dir}/lib/libtaos.so.${version}"
else
@@ -110,7 +110,7 @@ mkdir -p ${install_dir}/connector
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
if [ "$osType" != "Darwin" ]; then
- cp ${build_dir}/lib/*.jar ${install_dir}/connector
+ cp ${build_dir}/lib/*.jar ${install_dir}/connector ||:
fi
cp -r ${connector_dir}/grafanaplugin ${install_dir}/connector/
cp -r ${connector_dir}/python ${install_dir}/connector/
diff --git a/packaging/tools/makeclient_power.sh b/packaging/tools/makeclient_power.sh
index faa5a03f52b4c9b56981a6b1c0918e543262b3bb..fdb3e0e5cc8c7add9c8ea8cdc9224964b3c80153 100755
--- a/packaging/tools/makeclient_power.sh
+++ b/packaging/tools/makeclient_power.sh
@@ -76,8 +76,10 @@ if [ "$osType" != "Darwin" ]; then
else
cp ${build_dir}/bin/taos ${install_dir}/bin/power
cp ${script_dir}/remove_power.sh ${install_dir}/bin
- cp ${build_dir}/bin/taosdemo ${install_dir}/bin/powerdemo
+ cp ${build_dir}/bin/taosdemo ${install_dir}/bin/powerdemo
+ cp ${build_dir}/bin/taosdump ${install_dir}/bin/powerdump
cp ${script_dir}/set_core.sh ${install_dir}/bin
+ cp ${script_dir}/get_client.sh ${install_dir}/bin
fi
else
cp ${bin_files} ${install_dir}/bin
@@ -135,7 +137,7 @@ mkdir -p ${install_dir}/connector
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
if [ "$osType" != "Darwin" ]; then
- cp ${build_dir}/lib/*.jar ${install_dir}/connector
+ cp ${build_dir}/lib/*.jar ${install_dir}/connector ||:
fi
cp -r ${connector_dir}/grafanaplugin ${install_dir}/connector/
cp -r ${connector_dir}/python ${install_dir}/connector/
diff --git a/packaging/tools/makepkg.sh b/packaging/tools/makepkg.sh
index 75b45b544e0a4abbf709cc4c5b3a3b55dc315f0f..5ae5cbbcdc00c1fd862501a6eb0dccd3ac0fa007 100755
--- a/packaging/tools/makepkg.sh
+++ b/packaging/tools/makepkg.sh
@@ -36,7 +36,7 @@ if [ "$pagMode" == "lite" ]; then
strip ${build_dir}/bin/taos
bin_files="${build_dir}/bin/taosd ${build_dir}/bin/taos ${script_dir}/remove.sh"
else
- bin_files="${build_dir}/bin/taosd ${build_dir}/bin/taos ${build_dir}/bin/taosdemo ${build_dir}/bin/tarbitrator ${script_dir}/remove.sh ${script_dir}/set_core.sh"
+ bin_files="${build_dir}/bin/taosd ${build_dir}/bin/taos ${build_dir}/bin/taosdump ${build_dir}/bin/taosdemo ${build_dir}/bin/tarbitrator ${script_dir}/remove.sh ${script_dir}/set_core.sh ${script_dir}/get_client.sh"
fi
lib_files="${build_dir}/lib/libtaos.so.${version}"
@@ -124,7 +124,7 @@ cp ${lib_files} ${install_dir}/driver
connector_dir="${code_dir}/connector"
mkdir -p ${install_dir}/connector
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
- cp ${build_dir}/lib/*.jar ${install_dir}/connector
+ cp ${build_dir}/lib/*.jar ${install_dir}/connector ||:
cp -r ${connector_dir}/grafanaplugin ${install_dir}/connector/
cp -r ${connector_dir}/python ${install_dir}/connector/
cp -r ${connector_dir}/go ${install_dir}/connector
diff --git a/packaging/tools/makepkg_power.sh b/packaging/tools/makepkg_power.sh
index 2c02b99787c6d5ad6234de2319bf78b0b09d7e8a..13849484695f98a5fc206d88ec6a5de0cc930a9b 100755
--- a/packaging/tools/makepkg_power.sh
+++ b/packaging/tools/makepkg_power.sh
@@ -77,8 +77,10 @@ else
cp ${build_dir}/bin/taosd ${install_dir}/bin/powerd
cp ${script_dir}/remove_power.sh ${install_dir}/bin
cp ${build_dir}/bin/taosdemo ${install_dir}/bin/powerdemo
+ cp ${build_dir}/bin/taosdump ${install_dir}/bin/powerdump
cp ${build_dir}/bin/tarbitrator ${install_dir}/bin
cp ${script_dir}/set_core.sh ${install_dir}/bin
+ cp ${script_dir}/get_client.sh ${install_dir}/bin
fi
chmod a+x ${install_dir}/bin/* || :
@@ -156,7 +158,7 @@ cp ${lib_files} ${install_dir}/driver
connector_dir="${code_dir}/connector"
mkdir -p ${install_dir}/connector
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
- cp ${build_dir}/lib/*.jar ${install_dir}/connector
+ cp ${build_dir}/lib/*.jar ${install_dir}/connector ||:
cp -r ${connector_dir}/grafanaplugin ${install_dir}/connector/
cp -r ${connector_dir}/python ${install_dir}/connector/
cp -r ${connector_dir}/go ${install_dir}/connector
diff --git a/packaging/tools/post.sh b/packaging/tools/post.sh
index d91daaa5c44488e34dea7ec2ddec0863699446f2..00705fad778c065eddbd7cb65a2f9c5583a9997b 100755
--- a/packaging/tools/post.sh
+++ b/packaging/tools/post.sh
@@ -81,8 +81,10 @@ function install_lib() {
${csudo} ln -s ${lib_dir}/libtaos.* ${lib_link_dir}/libtaos.so.1
${csudo} ln -s ${lib_link_dir}/libtaos.so.1 ${lib_link_dir}/libtaos.so
- ${csudo} ln -s ${lib_dir}/libtaos.* ${lib64_link_dir}/libtaos.so.1 || :
- ${csudo} ln -s ${lib64_link_dir}/libtaos.so.1 ${lib64_link_dir}/libtaos.so || :
+ if [[ -d ${lib64_link_dir} && ! -e ${lib64_link_dir}/libtaos.so ]]; then
+ ${csudo} ln -s ${lib_dir}/libtaos.* ${lib64_link_dir}/libtaos.so.1 || :
+ ${csudo} ln -s ${lib64_link_dir}/libtaos.so.1 ${lib64_link_dir}/libtaos.so || :
+ fi
}
function install_bin() {
@@ -121,8 +123,11 @@ function install_config() {
echo -e -n "${GREEN}Enter FQDN:port (like h1.taosdata.com:6030) of an existing TDengine cluster node to join${NC}"
echo
echo -e -n "${GREEN}OR leave it blank to build one${NC}:"
- read firstEp
- while true; do
+ #read firstEp
+ if exec < /dev/tty; then
+ read firstEp;
+ fi
+ while true; do
if [ ! -z "$firstEp" ]; then
# check the format of the firstEp
#if [[ $firstEp == $FQDN_PATTERN ]]; then
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index 233b7a15b4a9383ee65dac8c9c0dc107fb66dd0a..059c0650c2bbba99694253a73b59d77cd16f06bf 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -1,6 +1,6 @@
name: tdengine
base: core18
-version: '2.0.6.0'
+version: '2.0.8.0'
icon: snap/gui/t-dengine.svg
summary: an open-source big data platform designed and optimized for IoT.
description: |
@@ -72,7 +72,7 @@ parts:
- usr/bin/taosd
- usr/bin/taos
- usr/bin/taosdemo
- - usr/lib/libtaos.so.2.0.6.0
+ - usr/lib/libtaos.so.2.0.8.0
- usr/lib/libtaos.so.1
- usr/lib/libtaos.so
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f619edd221c005a8d8e707afa5271072b032f74a..a2600785c35a80d040b9f91137c630d7761cef7e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -20,6 +20,6 @@ ADD_SUBDIRECTORY(tsdb)
ADD_SUBDIRECTORY(wal)
ADD_SUBDIRECTORY(cq)
ADD_SUBDIRECTORY(dnode)
-ADD_SUBDIRECTORY(connector/odbc)
+#ADD_SUBDIRECTORY(connector/odbc)
ADD_SUBDIRECTORY(connector/jdbc)
diff --git a/src/balance/src/balance.c b/src/balance/src/balance.c
index 0e9bb85b25defd169fea8711d3e0b40304500de4..df78f4fe270d34d17e436e80322f6c81b68d0d2c 100644
--- a/src/balance/src/balance.c
+++ b/src/balance/src/balance.c
@@ -490,7 +490,7 @@ static bool balanceMontiorDropping() {
if (pDnode->status == TAOS_DN_STATUS_OFFLINE) {
if (pDnode->lastAccess + tsOfflineThreshold > tsAccessSquence) continue;
- if (strcmp(pDnode->dnodeEp, dnodeGetMnodeMasterEp()) == 0) continue;
+ if (dnodeIsMasterEp(pDnode->dnodeEp)) continue;
if (mnodeGetDnodesNum() <= 1) continue;
mLInfo("dnode:%d, set to removing state for it offline:%d seconds", pDnode->dnodeId,
@@ -571,8 +571,8 @@ static void balanceCheckDnodeAccess() {
if (pDnode->status != TAOS_DN_STATUS_DROPPING && pDnode->status != TAOS_DN_STATUS_OFFLINE) {
pDnode->status = TAOS_DN_STATUS_OFFLINE;
pDnode->offlineReason = TAOS_DN_OFF_STATUS_MSG_TIMEOUT;
- mInfo("dnode:%d, set to offline state, access seq:%d, last seq:%d", pDnode->dnodeId, tsAccessSquence,
- pDnode->lastAccess);
+ mInfo("dnode:%d, set to offline state, access seq:%d last seq:%d laststat:%d", pDnode->dnodeId, tsAccessSquence,
+ pDnode->lastAccess, pDnode->status);
balanceSetVgroupOffline(pDnode);
}
}
diff --git a/src/client/inc/tscLocalMerge.h b/src/client/inc/tscLocalMerge.h
index 5baa66a9e0229f35c431cea7a0d2dbb9e2ffb0e2..2c7c2f51d02ea1b9943004fc62f8e48f2034d0fe 100644
--- a/src/client/inc/tscLocalMerge.h
+++ b/src/client/inc/tscLocalMerge.h
@@ -62,11 +62,11 @@ typedef struct SLocalReducer {
bool hasUnprocessedRow;
tOrderDescriptor * pDesc;
SColumnModel * resColModel;
+ SColumnModel* finalModel;
tExtMemBuffer ** pExtMemBuffer; // disk-based buffer
SFillInfo* pFillInfo; // interpolation support structure
- char * pFinalRes; // result data after interpo
- tFilePage * discardData;
- SResultInfo * pResInfo;
+ char* pFinalRes; // result data after interpo
+ tFilePage* discardData;
bool discard;
int32_t offset; // limit offset value
bool orderPrjOnSTable; // projection query on stable
@@ -75,7 +75,8 @@ typedef struct SLocalReducer {
typedef struct SRetrieveSupport {
tExtMemBuffer ** pExtMemBuffer; // for build loser tree
tOrderDescriptor *pOrderDescriptor;
- SColumnModel * pFinalColModel; // colModel for final result
+ SColumnModel* pFinalColModel; // colModel for final result
+ SColumnModel* pFFColModel;
int32_t subqueryIndex; // index of current vnode in vnode list
SSqlObj * pParentSql;
tFilePage * localBuffer; // temp buffer, there is a buffer for each vnode to
@@ -83,9 +84,9 @@ typedef struct SRetrieveSupport {
} SRetrieveSupport;
int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOrderDescriptor **pDesc,
- SColumnModel **pFinalModel, uint32_t nBufferSize);
+ SColumnModel **pFinalModel, SColumnModel** pFFModel, uint32_t nBufferSize);
-void tscLocalReducerEnvDestroy(tExtMemBuffer **pMemBuffer, tOrderDescriptor *pDesc, SColumnModel *pFinalModel,
+void tscLocalReducerEnvDestroy(tExtMemBuffer **pMemBuffer, tOrderDescriptor *pDesc, SColumnModel *pFinalModel, SColumnModel* pFFModel,
int32_t numOfVnodes);
int32_t saveToBuffer(tExtMemBuffer *pMemoryBuf, tOrderDescriptor *pDesc, tFilePage *pPage, void *data,
@@ -97,7 +98,7 @@ int32_t tscFlushTmpBuffer(tExtMemBuffer *pMemoryBuf, tOrderDescriptor *pDesc, tF
* create local reducer to launch the second-stage reduce process at client site
*/
void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrderDescriptor *pDesc,
- SColumnModel *finalModel, SSqlObj* pSql);
+ SColumnModel *finalModel, SColumnModel *pFFModel, SSqlObj* pSql);
void tscDestroyLocalReducer(SSqlObj *pSql);
diff --git a/src/client/inc/tscSubquery.h b/src/client/inc/tscSubquery.h
index bc01de110345e4c90cf5c15d3d7f6b010cb7308d..f7832c9818226d19ba1e20cb47fa17c5bfb0f611 100644
--- a/src/client/inc/tscSubquery.h
+++ b/src/client/inc/tscSubquery.h
@@ -23,7 +23,7 @@ extern "C" {
#include "tscUtil.h"
#include "tsclient.h"
-void tscFetchDatablockFromSubquery(SSqlObj* pSql);
+void tscFetchDatablockForSubquery(SSqlObj* pSql);
void tscSetupOutputColumnIndex(SSqlObj* pSql);
void tscJoinQueryCallback(void* param, TAOS_RES* tres, int code);
@@ -39,7 +39,9 @@ int32_t tscHandleMultivnodeInsert(SSqlObj *pSql);
int32_t tscHandleInsertRetry(SSqlObj* pSql);
void tscBuildResFromSubqueries(SSqlObj *pSql);
-TAOS_ROW doSetResultRowData(SSqlObj *pSql, bool finalResult);
+TAOS_ROW doSetResultRowData(SSqlObj *pSql);
+
+char *getArithmeticInputSrc(void *param, const char *name, int32_t colId);
#ifdef __cplusplus
}
diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h
index 3df493349e387c1dd33a945886389218f7f7cf0f..bde27d2932a5bacd09864c76ee81faa6adef04a7 100644
--- a/src/client/inc/tscUtil.h
+++ b/src/client/inc/tscUtil.h
@@ -75,6 +75,7 @@ typedef struct SJoinSupporter {
SArray* exprList;
SFieldInfo fieldsInfo;
STagCond tagCond;
+ SSqlGroupbyExpr groupInfo; // group by info
struct STSBuf* pTSBuf; // the TSBuf struct that holds the compressed timestamp array
FILE* f; // temporary file in order to create TSBuf
char path[PATH_MAX]; // temporary file path, todo dynamic allocate memory
@@ -82,11 +83,12 @@ typedef struct SJoinSupporter {
char* pIdTagList; // result of first stage tags
int32_t totalLen;
int32_t num;
+ SArray* pVgroupTables;
} SJoinSupporter;
typedef struct SVgroupTableInfo {
- SCMVgroupInfo vgInfo;
- SArray* itemList; //SArray
+ SVgroupInfo vgInfo;
+ SArray* itemList; //SArray
} SVgroupTableInfo;
static FORCE_INLINE SQueryInfo* tscGetQueryInfoDetail(SSqlCmd* pCmd, int32_t subClauseIndex) {
@@ -123,6 +125,7 @@ int32_t tscGetDataBlockFromList(void* pHashList, SArray* pDataBlockList, int64_t
*/
bool tscIsPointInterpQuery(SQueryInfo* pQueryInfo);
bool tscIsTWAQuery(SQueryInfo* pQueryInfo);
+bool tscIsSecondStageQuery(SQueryInfo* pQueryInfo);
bool tscNonOrderedProjectionQueryOnSTable(SQueryInfo *pQueryInfo, int32_t tableIndex);
bool tscOrderedProjectionQueryOnSTable(SQueryInfo* pQueryInfo, int32_t tableIndex);
@@ -156,7 +159,7 @@ SInternalField* tscFieldInfoGetInternalField(SFieldInfo* pFieldInfo, int32_t ind
TAOS_FIELD* tscFieldInfoGetField(SFieldInfo* pFieldInfo, int32_t index);
void tscFieldInfoUpdateOffset(SQueryInfo* pQueryInfo);
-void tscFieldInfoUpdateOffsetForInterResult(SQueryInfo* pQueryInfo);
+void tscFieldInfoUpdateOffset(SQueryInfo* pQueryInfo);
int16_t tscFieldInfoGetOffset(SQueryInfo* pQueryInfo, int32_t index);
void tscFieldInfoClear(SFieldInfo* pFieldInfo);
@@ -165,15 +168,15 @@ static FORCE_INLINE int32_t tscNumOfFields(SQueryInfo* pQueryInfo) { return pQue
int32_t tscFieldInfoCompare(const SFieldInfo* pFieldInfo1, const SFieldInfo* pFieldInfo2);
-void addExprParams(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes, int16_t tableIndex);
+void addExprParams(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes);
int32_t tscGetResRowLength(SArray* pExprList);
SSqlExpr* tscSqlExprInsert(SQueryInfo* pQueryInfo, int32_t index, int16_t functionId, SColumnIndex* pColIndex, int16_t type,
- int16_t size, int16_t interSize, bool isTagCol);
+ int16_t size, int16_t resColId, int16_t interSize, bool isTagCol);
SSqlExpr* tscSqlExprAppend(SQueryInfo* pQueryInfo, int16_t functionId, SColumnIndex* pColIndex, int16_t type,
- int16_t size, int16_t interSize, bool isTagCol);
+ int16_t size, int16_t resColId, int16_t interSize, bool isTagCol);
SSqlExpr* tscSqlExprUpdate(SQueryInfo* pQueryInfo, int32_t index, int16_t functionId, int16_t srcColumnIndex, int16_t type,
int16_t size);
@@ -215,7 +218,7 @@ SQueryInfo *tscGetQueryInfoDetailSafely(SSqlCmd *pCmd, int32_t subClauseIndex);
void tscClearTableMetaInfo(STableMetaInfo* pTableMetaInfo, bool removeFromCache);
STableMetaInfo* tscAddTableMetaInfo(SQueryInfo* pQueryInfo, const char* name, STableMeta* pTableMeta,
- SVgroupsInfo* vgroupList, SArray* pTagCols);
+ SVgroupsInfo* vgroupList, SArray* pTagCols, SArray* pVgroupTables);
STableMetaInfo* tscAddEmptyMetaInfo(SQueryInfo *pQueryInfo);
int32_t tscAddSubqueryInfo(SSqlCmd *pCmd);
@@ -224,6 +227,9 @@ void tscInitQueryInfo(SQueryInfo* pQueryInfo);
void tscClearSubqueryInfo(SSqlCmd* pCmd);
void tscFreeVgroupTableInfo(SArray* pVgroupTables);
+SArray* tscVgroupTableInfoClone(SArray* pVgroupTables);
+void tscRemoveVgroupTableGroup(SArray* pVgroupTable, int32_t index);
+void tscVgroupTableCopy(SVgroupTableInfo* info, SVgroupTableInfo* pInfo);
int tscGetSTableVgroupInfo(SSqlObj* pSql, int32_t clauseIndex);
int tscGetTableMeta(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo);
@@ -234,7 +240,7 @@ void tscDoQuery(SSqlObj* pSql);
SVgroupsInfo* tscVgroupInfoClone(SVgroupsInfo *pInfo);
void* tscVgroupInfoClear(SVgroupsInfo *pInfo);
-void tscSCMVgroupInfoCopy(SCMVgroupInfo* dst, const SCMVgroupInfo* src);
+void tscSVgroupInfoCopy(SVgroupInfo* dst, const SVgroupInfo* src);
/**
* The create object function must be successful expect for the out of memory issue.
*
@@ -262,6 +268,7 @@ void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t sub
void doAddGroupColumnForSubquery(SQueryInfo* pQueryInfo, int32_t tagIndex);
int16_t tscGetJoinTagColIdByUid(STagCond* pTagCond, uint64_t uid);
+int16_t tscGetTagColIndexById(STableMeta* pTableMeta, int16_t colId);
void tscPrintSelectClause(SSqlObj* pSql, int32_t subClauseIndex);
@@ -275,6 +282,7 @@ int tscSetMgmtEpSetFromCfg(const char *first, const char *second);
bool tscSetSqlOwner(SSqlObj* pSql);
void tscClearSqlOwner(SSqlObj* pSql);
+int32_t doArithmeticCalculate(SQueryInfo* pQueryInfo, tFilePage* pOutput, int32_t rowSize, int32_t finalRowSize);
void* malloc_throw(size_t size);
void* calloc_throw(size_t nmemb, size_t size);
diff --git a/src/client/inc/tschemautil.h b/src/client/inc/tschemautil.h
index 67942ad42a0942756efe18e44eff711df59ba1d9..f6dc45398f35c38598f3f3132b2f6f5601a4ed68 100644
--- a/src/client/inc/tschemautil.h
+++ b/src/client/inc/tschemautil.h
@@ -77,7 +77,7 @@ SSchema *tscGetTableColumnSchema(const STableMeta *pMeta, int32_t colIndex);
* @param colId
* @return
*/
-SSchema* tscGetTableColumnSchemaById(STableMeta* pTableMeta, int16_t colId);
+SSchema* tscGetColumnSchemaById(STableMeta* pTableMeta, int16_t colId);
/**
* check if the schema is valid or not, including following aspects:
@@ -107,9 +107,6 @@ SSchema tscGetTbnameColumnSchema();
*/
STableMeta* tscCreateTableMetaFromMsg(STableMetaMsg* pTableMetaMsg, size_t* size);
-//todo tags value as well as the table id structure needs refactor
-char *tsGetTagsValue(STableMeta *pMeta);
-
#ifdef __cplusplus
}
#endif
diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h
index fa215db2702f63aff4c704f8393255a94987d681..ff36cf0f5ac31ecf3baa4abae5697e08a1c8bc0b 100644
--- a/src/client/inc/tsclient.h
+++ b/src/client/inc/tsclient.h
@@ -30,6 +30,7 @@ extern "C" {
#include "tsqlfunction.h"
#include "tutil.h"
#include "tcache.h"
+#include "tref.h"
#include "qExecutor.h"
#include "qSqlparser.h"
@@ -89,12 +90,12 @@ typedef struct STableComInfo {
int32_t rowSize;
} STableComInfo;
-typedef struct SCMCorVgroupInfo {
- int32_t version;
- int8_t inUse;
- int8_t numOfEps;
- SEpAddr1 epAddr[TSDB_MAX_REPLICA];
-} SCMCorVgroupInfo;
+typedef struct SCorVgroupInfo {
+ int32_t version;
+ int8_t inUse;
+ int8_t numOfEps;
+ SEpAddr1 epAddr[TSDB_MAX_REPLICA];
+} SCorVgroupInfo;
typedef struct STableMeta {
STableComInfo tableInfo;
@@ -102,8 +103,8 @@ typedef struct STableMeta {
int16_t sversion;
int16_t tversion;
char sTableId[TSDB_TABLE_FNAME_LEN];
- SCMVgroupInfo vgroupInfo;
- SCMCorVgroupInfo corVgroupInfo;
+ SVgroupInfo vgroupInfo;
+ SCorVgroupInfo corVgroupInfo;
STableId id;
SSchema schema[]; // if the table is TSDB_CHILD_TABLE, schema is acquired by super table meta info
} STableMeta;
@@ -127,7 +128,7 @@ typedef struct STableMetaInfo {
typedef struct SSqlExpr {
char aliasName[TSDB_COL_NAME_LEN]; // as aliasName
SColIndex colInfo;
- int64_t uid; // refactor use the pointer
+ uint64_t uid; // refactor use the pointer
int16_t functionId; // function id in aAgg array
int16_t resType; // return value type
int16_t resBytes; // length of return value
@@ -135,6 +136,7 @@ typedef struct SSqlExpr {
int16_t numOfParams; // argument value of each function
tVariant param[3]; // parameters are not more than 3
int32_t offset; // sub result column value of arithmetic expression.
+ int16_t resColId; // result column id
} SSqlExpr;
typedef struct SColumnIndex {
@@ -250,6 +252,7 @@ typedef struct SQueryInfo {
int64_t clauseLimit; // limit for current sub clause
int64_t prjOffset; // offset value in the original sql expression, only applied at client side
int32_t udColumnId; // current user-defined constant output field column id, monotonically decreases from TSDB_UD_COLUMN_INDEX
+ int16_t resColumnId; // result column id
} SQueryInfo;
typedef struct {
@@ -290,32 +293,32 @@ typedef struct SResRec {
} SResRec;
typedef struct {
- int64_t numOfRows; // num of results in current retrieved
- int64_t numOfRowsGroup; // num of results of current group
- int64_t numOfTotal; // num of total results
- int64_t numOfClauseTotal; // num of total result in current subclause
- char * pRsp;
- int32_t rspType;
- int32_t rspLen;
- uint64_t qhandle;
- int64_t uid;
- int64_t useconds;
- int64_t offset; // offset value from vnode during projection query of stable
- int32_t row;
- int16_t numOfCols;
- int16_t precision;
- bool completed;
- int32_t code;
- int32_t numOfGroups;
- SResRec * pGroupRec;
- char * data;
- TAOS_ROW tsrow;
- int32_t* length; // length for each field for current row
- char ** buffer; // Buffer used to put multibytes encoded using unicode (wchar_t)
- SColumnIndex * pColumnIndex;
+ int32_t numOfRows; // num of results in current retrieval
+ int64_t numOfRowsGroup; // num of results of current group
+ int64_t numOfTotal; // num of total results
+ int64_t numOfClauseTotal; // num of total result in current subclause
+ char * pRsp;
+ int32_t rspType;
+ int32_t rspLen;
+ uint64_t qhandle;
+ int64_t useconds;
+ int64_t offset; // offset value from vnode during projection query of stable
+ int32_t row;
+ int16_t numOfCols;
+ int16_t precision;
+ bool completed;
+ int32_t code;
+ int32_t numOfGroups;
+ SResRec * pGroupRec;
+ char * data;
+ TAOS_ROW tsrow;
+ TAOS_ROW urow;
+ int32_t* length; // length for each field for current row
+ char ** buffer; // Buffer used to put multibytes encoded using unicode (wchar_t)
+ SColumnIndex* pColumnIndex;
+
SArithmeticSupport* pArithSup; // support the arithmetic expression calculation on agg functions
-
- struct SLocalReducer *pLocalReducer;
+ struct SLocalReducer* pLocalReducer;
} SSqlRes;
typedef struct STscObj {
@@ -329,6 +332,7 @@ typedef struct STscObj {
char writeAuth : 1;
char superAuth : 1;
uint32_t connId;
+ uint64_t rid; // ref ID returned by taosAddRef
struct SSqlObj * pHb;
struct SSqlObj * sqlList;
struct SSqlStream *streamList;
@@ -338,16 +342,16 @@ typedef struct STscObj {
} STscObj;
typedef struct SSubqueryState {
- int32_t numOfRemain; // the number of remain unfinished subquery
- int32_t numOfSub; // the number of total sub-queries
- uint64_t numOfRetrievedRows; // total number of points in this query
+ int32_t numOfRemain; // the number of remain unfinished subquery
+ int32_t numOfSub; // the number of total sub-queries
+ uint64_t numOfRetrievedRows; // total number of points in this query
} SSubqueryState;
typedef struct SSqlObj {
void *signature;
pthread_t owner; // owner of sql object, by which it is executed
STscObj *pTscObj;
- void *pRpcCtx;
+ int64_t rpcRid;
void (*fp)();
void (*fetchFp)();
void *param;
@@ -421,6 +425,7 @@ int32_t tscTansformSQLFuncForSTableQuery(SQueryInfo *pQueryInfo);
void tscRestoreSQLFuncForSTableQuery(SQueryInfo *pQueryInfo);
int32_t tscCreateResPointerInfo(SSqlRes *pRes, SQueryInfo *pQueryInfo);
+void tscSetResRawPtr(SSqlRes* pRes, SQueryInfo* pQueryInfo);
void tscResetSqlCmdObj(SSqlCmd *pCmd, bool removeFromCache);
@@ -430,14 +435,6 @@ void tscResetSqlCmdObj(SSqlCmd *pCmd, bool removeFromCache);
*/
void tscFreeSqlResult(SSqlObj *pSql);
-/**
- * only free part of resources allocated during query.
- * TODO remove it later
- * Note: this function is multi-thread safe.
- * @param pObj
- */
-void tscPartiallyFreeSqlObj(SSqlObj *pSql);
-
/**
* free sql object, release allocated resource
* @param pObj
@@ -446,7 +443,7 @@ void tscFreeSqlObj(SSqlObj *pSql);
void tscFreeRegisteredSqlObj(void *pSql);
void tscFreeTableMetaHelper(void *pTableMeta);
-void tscCloseTscObj(STscObj *pObj);
+void tscCloseTscObj(void *pObj);
// todo move to taos? or create a new file: taos_internal.h
TAOS *taos_connect_a(char *ip, char *user, char *pass, char *db, uint16_t port, void (*fp)(void *, TAOS_RES *, int),
@@ -468,17 +465,17 @@ int32_t tscSQLSyntaxErrMsg(char* msg, const char* additionalInfo, const char* s
int32_t tscToSQLCmd(SSqlObj *pSql, struct SSqlInfo *pInfo);
-static FORCE_INLINE void tscGetResultColumnChr(SSqlRes* pRes, SFieldInfo* pFieldInfo, int32_t columnIndex) {
+static FORCE_INLINE void tscGetResultColumnChr(SSqlRes* pRes, SFieldInfo* pFieldInfo, int32_t columnIndex, int32_t offset) {
SInternalField* pInfo = (SInternalField*) TARRAY_GET_ELEM(pFieldInfo->internalField, columnIndex);
- assert(pInfo->pSqlExpr != NULL);
- int32_t type = pInfo->pSqlExpr->resType;
- int32_t bytes = pInfo->pSqlExpr->resBytes;
+ int32_t type = pInfo->field.type;
+ int32_t bytes = pInfo->field.bytes;
- char* pData = pRes->data + (int32_t)(pInfo->pSqlExpr->offset * pRes->numOfRows + bytes * pRes->row);
+ char* pData = pRes->data + (int32_t)(offset * pRes->numOfRows + bytes * pRes->row);
+ UNUSED(pData);
- // user defined constant value output columns
- if (TSDB_COL_IS_UD_COL(pInfo->pSqlExpr->colInfo.flag)) {
+// user defined constant value output columns
+ if (pInfo->pSqlExpr != NULL && TSDB_COL_IS_UD_COL(pInfo->pSqlExpr->colInfo.flag)) {
if (type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_BINARY) {
pData = pInfo->pSqlExpr->param[1].pz;
pRes->length[columnIndex] = pInfo->pSqlExpr->param[1].nLen;
@@ -516,13 +513,14 @@ extern void * tscQhandle;
extern int tscKeepConn[];
extern int tsInsertHeadSize;
extern int tscNumOfThreads;
+extern int tscRefId;
extern SRpcCorEpSet tscMgmtEpSet;
extern int (*tscBuildMsg[TSDB_SQL_MAX])(SSqlObj *pSql, SSqlInfo *pInfo);
-int32_t tscCompareTidTags(const void* p1, const void* p2);
void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArray* tables);
+int16_t getNewResColId(SQueryInfo* pQueryInfo);
#ifdef __cplusplus
}
diff --git a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h
index eaea91d1bfb0197a36fe67d78a09ab190e7e3aeb..582bd6bac03ce0049c7c22fe58fa4fa6eb8c69fb 100644
--- a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h
+++ b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h
@@ -129,6 +129,14 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaData
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp
(JNIEnv *, jobject, jlong, jlong, jobject);
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: fetchBlockImp
+ * Signature: (JJLcom/taosdata/jdbc/TSDBResultSetBlockData;)I
+ */
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp
+ (JNIEnv *, jobject, jlong, jlong, jobject);
+
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: closeConnectionImp
diff --git a/src/client/src/TSDBJNIConnector.c b/src/client/src/TSDBJNIConnector.c
index 4e2272eb0566569754df5ef6201f3d190f2789c1..a8829499a324605036beefad62d83eccf4d1c65b 100644
--- a/src/client/src/TSDBJNIConnector.c
+++ b/src/client/src/TSDBJNIConnector.c
@@ -17,7 +17,6 @@
#include "taos.h"
#include "tlog.h"
#include "tscUtil.h"
-#include "tsclient.h"
#include "com_taosdata_jdbc_TSDBJNIConnector.h"
@@ -57,6 +56,10 @@ jmethodID g_rowdataSetStringFp;
jmethodID g_rowdataSetTimestampFp;
jmethodID g_rowdataSetByteArrayFp;
+jmethodID g_blockdataSetByteArrayFp;
+jmethodID g_blockdataSetNumOfRowsFp;
+jmethodID g_blockdataSetNumOfColsFp;
+
#define JNI_SUCCESS 0
#define JNI_TDENGINE_ERROR -1
#define JNI_CONNECTION_NULL -2
@@ -66,7 +69,7 @@ jmethodID g_rowdataSetByteArrayFp;
#define JNI_FETCH_END -6
#define JNI_OUT_OF_MEMORY -7
-void jniGetGlobalMethod(JNIEnv *env) {
+static void jniGetGlobalMethod(JNIEnv *env) {
// make sure init function executed once
switch (atomic_val_compare_exchange_32(&__init, 0, 1)) {
case 0:
@@ -114,10 +117,31 @@ void jniGetGlobalMethod(JNIEnv *env) {
g_rowdataSetByteArrayFp = (*env)->GetMethodID(env, g_rowdataClass, "setByteArray", "(I[B)V");
(*env)->DeleteLocalRef(env, rowdataClass);
+ jclass blockdataClass = (*env)->FindClass(env, "com/taosdata/jdbc/TSDBResultSetBlockData");
+ jclass g_blockdataClass = (*env)->NewGlobalRef(env, blockdataClass);
+ g_blockdataSetByteArrayFp = (*env)->GetMethodID(env, g_blockdataClass, "setByteArray", "(II[B)V");
+ g_blockdataSetNumOfRowsFp = (*env)->GetMethodID(env, g_blockdataClass, "setNumOfRows", "(I)V");
+ g_blockdataSetNumOfColsFp = (*env)->GetMethodID(env, g_blockdataClass, "setNumOfCols", "(I)V");
+ (*env)->DeleteLocalRef(env, blockdataClass);
+
atomic_store_32(&__init, 2);
jniDebug("native method register finished");
}
+static int32_t check_for_params(jobject jobj, jlong conn, jlong res) {
+ if ((TAOS*) conn == NULL) {
+ jniError("jobj:%p, connection is closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ if ((TAOS_RES *) res == NULL) {
+ jniError("jobj:%p, conn:%p, res is null", jobj, (TAOS*) conn);
+ return JNI_RESULT_SET_NULL;
+ }
+
+ return JNI_SUCCESS;
+}
+
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setAllocModeImp(JNIEnv *env, jobject jobj, jint jMode,
jstring jPath, jboolean jAutoDump) {
if (jPath != NULL) {
@@ -192,39 +216,37 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions(JNIEnv
JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEnv *env, jobject jobj, jstring jhost,
jint jport, jstring jdbName, jstring juser,
jstring jpass) {
- jlong ret = 0;
+ jlong ret = 0;
const char *host = NULL;
- const char *dbname = NULL;
const char *user = NULL;
const char *pass = NULL;
+ const char *dbname = NULL;
if (jhost != NULL) {
host = (*env)->GetStringUTFChars(env, jhost, NULL);
}
+
if (jdbName != NULL) {
dbname = (*env)->GetStringUTFChars(env, jdbName, NULL);
}
+
if (juser != NULL) {
user = (*env)->GetStringUTFChars(env, juser, NULL);
}
+
if (jpass != NULL) {
pass = (*env)->GetStringUTFChars(env, jpass, NULL);
}
if (user == NULL) {
- jniDebug("jobj:%p, user is null, use default user %s", jobj, TSDB_DEFAULT_USER);
+ jniDebug("jobj:%p, user not specified, use default user %s", jobj, TSDB_DEFAULT_USER);
}
+
if (pass == NULL) {
- jniDebug("jobj:%p, pass is null, use default password", jobj);
+ jniDebug("jobj:%p, pass not specified, use default password", jobj);
}
- /*
- * set numOfThreadsPerCore = 0
- * means only one thread for client side scheduler
- */
- tsNumOfThreadsPerCore = 0.0;
-
- ret = (jlong)taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, (uint16_t)jport);
+ ret = (jlong) taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, (uint16_t)jport);
if (ret == 0) {
jniError("jobj:%p, conn:%p, connect to database failed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret,
(char *)host, (char *)user, (char *)dbname, (int32_t)jport);
@@ -233,10 +255,21 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEn
(char *)host, (char *)user, (char *)dbname, (int32_t)jport);
}
- if (host != NULL) (*env)->ReleaseStringUTFChars(env, jhost, host);
- if (dbname != NULL) (*env)->ReleaseStringUTFChars(env, jdbName, dbname);
- if (user != NULL) (*env)->ReleaseStringUTFChars(env, juser, user);
- if (pass != NULL) (*env)->ReleaseStringUTFChars(env, jpass, pass);
+ if (host != NULL) {
+ (*env)->ReleaseStringUTFChars(env, jhost, host);
+ }
+
+ if (dbname != NULL) {
+ (*env)->ReleaseStringUTFChars(env, jdbName, dbname);
+ }
+
+ if (user != NULL) {
+ (*env)->ReleaseStringUTFChars(env, juser, user);
+ }
+
+ if (pass != NULL) {
+ (*env)->ReleaseStringUTFChars(env, jpass, pass);
+ }
return ret;
}
@@ -245,64 +278,53 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp(
jbyteArray jsql, jlong con) {
TAOS *tscon = (TAOS *)con;
if (tscon == NULL) {
- jniError("jobj:%p, connection is already closed", jobj);
+ jniError("jobj:%p, connection already closed", jobj);
return JNI_CONNECTION_NULL;
}
if (jsql == NULL) {
- jniError("jobj:%p, conn:%p, sql is null", jobj, tscon);
+ jniError("jobj:%p, conn:%p, empty sql string", jobj, tscon);
return JNI_SQL_NULL;
}
jsize len = (*env)->GetArrayLength(env, jsql);
- char *dst = (char *)calloc(1, sizeof(char) * (len + 1));
- if (dst == NULL) {
- jniError("jobj:%p, conn:%p, can not alloc memory", jobj, tscon);
+ char *str = (char *) calloc(1, sizeof(char) * (len + 1));
+ if (str == NULL) {
+ jniError("jobj:%p, conn:%p, alloc memory failed", jobj, tscon);
return JNI_OUT_OF_MEMORY;
}
- (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)dst);
+ (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)str);
if ((*env)->ExceptionCheck(env)) {
// todo handle error
}
- jniDebug("jobj:%p, conn:%p, sql:%s", jobj, tscon, dst);
-
- SSqlObj *pSql = taos_query(tscon, dst);
+ SSqlObj *pSql = taos_query(tscon, str);
int32_t code = taos_errno(pSql);
if (code != TSDB_CODE_SUCCESS) {
jniError("jobj:%p, conn:%p, code:%s, msg:%s", jobj, tscon, tstrerror(code), taos_errstr(pSql));
} else {
- int32_t affectRows = 0;
if (pSql->cmd.command == TSDB_SQL_INSERT) {
- affectRows = taos_affected_rows(pSql);
+ int32_t affectRows = taos_affected_rows(pSql);
jniDebug("jobj:%p, conn:%p, code:%s, affect rows:%d", jobj, tscon, tstrerror(code), affectRows);
} else {
jniDebug("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code));
}
}
- free(dst);
- return (jlong)pSql;
+ free(str);
+ return (jlong) pSql;
}
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrCodeImp(JNIEnv *env, jobject jobj, jlong con, jlong tres) {
- TAOS *tscon = (TAOS *)con;
- if (tscon == NULL) {
- jniError("jobj:%p, connection is closed", jobj);
- return (jint)TSDB_CODE_TSC_INVALID_CONNECTION;
+ int32_t code = check_for_params(jobj, con, tres);
+ if (code != JNI_SUCCESS) {
+ return code;
}
- if ((void *)tres == NULL) {
- jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon);
- return JNI_RESULT_SET_NULL;
- }
-
- TAOS_RES *pSql = (TAOS_RES *)tres;
-
- return (jint)taos_errno(pSql);
+ return (jint)taos_errno((TAOS_RES*) tres);
}
JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp(JNIEnv *env, jobject jobj, jlong tres) {
@@ -313,23 +335,16 @@ JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp(J
JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp(JNIEnv *env, jobject jobj, jlong con,
jlong tres) {
TAOS *tscon = (TAOS *)con;
- if (tscon == NULL) {
- jniError("jobj:%p, connection is closed", jobj);
- return JNI_CONNECTION_NULL;
- }
-
- if ((void *)tres == NULL) {
- jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon);
- return JNI_RESULT_SET_NULL;
+ int32_t code = check_for_params(jobj, con, tres);
+ if (code != JNI_SUCCESS) {
+ return code;
}
SSqlObj *pSql = (TAOS_RES *)tres;
- STscObj *pObj = pSql->pTscObj;
-
if (tscIsUpdateQuery(pSql)) {
- jniDebug("jobj:%p, conn:%p, update query, no resultset, %p", jobj, pObj, (void *)tres);
+ jniDebug("jobj:%p, conn:%p, update query, no resultset, %p", jobj, tscon, (void *)tres);
} else {
- jniDebug("jobj:%p, conn:%p, get resultset, %p", jobj, pObj, (void *)tres);
+ jniDebug("jobj:%p, conn:%p, get resultset, %p", jobj, tscon, (void *)tres);
}
return tres;
@@ -337,15 +352,9 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp(
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_isUpdateQueryImp(JNIEnv *env, jobject jobj, jlong con,
jlong tres) {
- TAOS *tscon = (TAOS *)con;
- if (tscon == NULL) {
- jniError("jobj:%p, connection is closed", jobj);
- return JNI_CONNECTION_NULL;
- }
-
- if ((void *)tres == NULL) {
- jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon);
- return JNI_RESULT_SET_NULL;
+ int32_t code = check_for_params(jobj, con, tres);
+ if (code != JNI_SUCCESS) {
+ return code;
}
SSqlObj *pSql = (TAOS_RES *)tres;
@@ -355,37 +364,27 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_isUpdateQueryImp(
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp(JNIEnv *env, jobject jobj, jlong con,
jlong res) {
- TAOS *tscon = (TAOS *)con;
- if (tscon == NULL) {
- jniError("jobj:%p, connection is closed", jobj);
- return JNI_CONNECTION_NULL;
- }
-
- if ((void *)res == NULL) {
- jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon);
- return JNI_RESULT_SET_NULL;
+ int32_t code = check_for_params(jobj, con, res);
+ if (code != JNI_SUCCESS) {
+ return code;
}
taos_free_result((void *)res);
- jniDebug("jobj:%p, conn:%p, free resultset:%p", jobj, tscon, (void *)res);
+ jniDebug("jobj:%p, conn:%p, free resultset:%p", jobj, (TAOS*) con, (void *)res);
+
return JNI_SUCCESS;
}
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsImp(JNIEnv *env, jobject jobj, jlong con,
jlong res) {
TAOS *tscon = (TAOS *)con;
- if (tscon == NULL) {
- jniError("jobj:%p, connection is closed", jobj);
- return JNI_CONNECTION_NULL;
- }
-
- if ((void *)res == NULL) {
- jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon);
- return JNI_RESULT_SET_NULL;
+ int32_t code = check_for_params(jobj, con, res);
+ if (code != JNI_SUCCESS) {
+ return code;
}
jint ret = taos_affected_rows((SSqlObj *)res);
- jniDebug("jobj:%p, conn:%p, sql:%p, res: %p, affect rows:%d", jobj, tscon, (void *)con, (void *)res, (int32_t)ret);
+ jniDebug("jobj:%p, conn:%p, sql:%p, res: %p, affect rows:%d", jobj, tscon, (TAOS *)con, (TAOS_RES *)res, (int32_t)ret);
return ret;
}
@@ -394,27 +393,20 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaData
jlong con, jlong res,
jobject arrayListObj) {
TAOS *tscon = (TAOS *)con;
- if (tscon == NULL) {
- jniError("jobj:%p, connection is closed", jobj);
- return JNI_CONNECTION_NULL;
- }
-
- TAOS_RES *result = (TAOS_RES *)res;
- if (result == NULL) {
- jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon);
- return JNI_RESULT_SET_NULL;
+ int32_t code = check_for_params(jobj, con, res);
+ if (code != JNI_SUCCESS) {
+ return code;
}
- TAOS_FIELD *fields = taos_fetch_fields(result);
- int num_fields = taos_num_fields(result);
-
- // jobject arrayListObj = (*env)->NewObject(env, g_arrayListClass, g_arrayListConstructFp, "");
+ TAOS_RES* tres = (TAOS_RES*) res;
+ TAOS_FIELD *fields = taos_fetch_fields(tres);
+ int32_t num_fields = taos_num_fields(tres);
if (num_fields == 0) {
- jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, (void *)res, num_fields);
+ jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, tres, num_fields);
return JNI_NUM_OF_FIELDS_0;
} else {
- jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, (void *)res, num_fields);
+ jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, tres, num_fields);
for (int i = 0; i < num_fields; ++i) {
jobject metadataObj = (*env)->NewObject(env, g_metadataClass, g_metadataConstructFp);
(*env)->SetIntField(env, metadataObj, g_metadataColtypeField, fields[i].type);
@@ -457,21 +449,21 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
}
TAOS_FIELD *fields = taos_fetch_fields(result);
- int num_fields = taos_num_fields(result);
- if (num_fields == 0) {
- jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, (void*)res, num_fields);
+ int32_t numOfFields = taos_num_fields(result);
+ if (numOfFields == 0) {
+ jniError("jobj:%p, conn:%p, resultset:%p, fields size %d", jobj, tscon, (void*)res, numOfFields);
return JNI_NUM_OF_FIELDS_0;
}
TAOS_ROW row = taos_fetch_row(result);
if (row == NULL) {
- int tserrno = taos_errno(result);
- if (tserrno == 0) {
- jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, (void*)res, num_fields);
+ int code = taos_errno(result);
+ if (code == TSDB_CODE_SUCCESS) {
+ jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, (void*)res, numOfFields);
return JNI_FETCH_END;
} else {
- jniDebug("jobj:%p, conn:%p, interruptted query", jobj, tscon);
+ jniDebug("jobj:%p, conn:%p, interrupted query", jobj, tscon);
return JNI_RESULT_SET_NULL;
}
}
@@ -480,7 +472,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
char tmp[TSDB_MAX_BYTES_PER_ROW] = {0};
- for (int i = 0; i < num_fields; i++) {
+ for (int i = 0; i < numOfFields; i++) {
if (row[i] == NULL) {
continue;
}
@@ -534,6 +526,45 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
return JNI_SUCCESS;
}
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong res, jobject rowobj) {
+ TAOS * tscon = (TAOS *)con;
+ int32_t code = check_for_params(jobj, con, res);
+ if (code != JNI_SUCCESS) {
+ return code;
+ }
+
+ TAOS_RES * tres = (TAOS_RES *)res;
+ TAOS_FIELD *fields = taos_fetch_fields(tres);
+
+ int32_t numOfFields = taos_num_fields(tres);
+ assert(numOfFields > 0);
+
+ TAOS_ROW row = NULL;
+ int32_t numOfRows = taos_fetch_block(tres, &row);
+ if (numOfRows == 0) {
+ code = taos_errno(tres);
+ if (code == JNI_SUCCESS) {
+ jniDebug("jobj:%p, conn:%p, resultset:%p, numOfFields:%d, no data to retrieve", jobj, tscon, (void *)res,
+ numOfFields);
+ return JNI_FETCH_END;
+ } else {
+ jniDebug("jobj:%p, conn:%p, query interrupted", jobj, tscon);
+ return JNI_RESULT_SET_NULL;
+ }
+ }
+
+ (*env)->CallVoidMethod(env, rowobj, g_blockdataSetNumOfRowsFp, (jint)numOfRows);
+ (*env)->CallVoidMethod(env, rowobj, g_blockdataSetNumOfColsFp, (jint)numOfFields);
+
+ for (int i = 0; i < numOfFields; i++) {
+ (*env)->CallVoidMethod(env, rowobj, g_blockdataSetByteArrayFp, i, fields[i].bytes * numOfRows,
+ jniFromNCharToByteArray(env, (char *)row[i], fields[i].bytes * numOfRows));
+ }
+
+ return JNI_SUCCESS;
+}
+
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeConnectionImp(JNIEnv *env, jobject jobj,
jlong con) {
TAOS *tscon = (TAOS *)con;
@@ -589,7 +620,6 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_consumeImp(JNIEn
jniGetGlobalMethod(env);
TAOS_SUB *tsub = (TAOS_SUB *)sub;
-
TAOS_RES *res = taos_consume(tsub);
if (res == NULL) {
@@ -621,16 +651,16 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_validateCreateTab
jsize len = (*env)->GetArrayLength(env, jsql);
- char *dst = (char *)calloc(1, sizeof(char) * (len + 1));
- (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)dst);
+ char *str = (char *)calloc(1, sizeof(char) * (len + 1));
+ (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)str);
if ((*env)->ExceptionCheck(env)) {
// todo handle error
}
- int code = taos_validate_sql(tscon, dst);
+ int code = taos_validate_sql(tscon, str);
jniDebug("jobj:%p, conn:%p, code is %d", jobj, tscon, code);
- free(dst);
+ free(str);
return code;
}
diff --git a/src/client/src/tscAsync.c b/src/client/src/tscAsync.c
index c996bb2a76ff505fca4e09cd8763b324e5c4cb8d..3ff8a68d8f07f776dbb03b4b55b830b7e37dfdff 100644
--- a/src/client/src/tscAsync.c
+++ b/src/client/src/tscAsync.c
@@ -91,8 +91,8 @@ void taos_query_a(TAOS *taos, const char *sqlstr, __async_cb_func_t fp, void *pa
int32_t sqlLen = (int32_t)strlen(sqlstr);
if (sqlLen > tsMaxSQLStringLen) {
tscError("sql string exceeds max length:%d", tsMaxSQLStringLen);
- terrno = TSDB_CODE_TSC_INVALID_SQL;
- tscQueueAsyncError(fp, param, TSDB_CODE_TSC_INVALID_SQL);
+ terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT;
+ tscQueueAsyncError(fp, param, terrno);
return;
}
@@ -176,7 +176,7 @@ static void tscProcessAsyncRetrieveImpl(void *param, TAOS_RES *tres, int numOfRo
}
if (pCmd->command == TSDB_SQL_TABLE_JOIN_RETRIEVE) {
- tscFetchDatablockFromSubquery(pSql);
+ tscFetchDatablockForSubquery(pSql);
} else {
tscProcessSql(pSql);
}
@@ -226,7 +226,7 @@ void taos_fetch_rows_a(TAOS_RES *taosa, __async_cb_func_t fp, void *param) {
// handle the sub queries of join query
if (pCmd->command == TSDB_SQL_TABLE_JOIN_RETRIEVE) {
- tscFetchDatablockFromSubquery(pSql);
+ tscFetchDatablockForSubquery(pSql);
} else if (pRes->completed) {
if(pCmd->command == TSDB_SQL_FETCH || (pCmd->command >= TSDB_SQL_SERV_STATUS && pCmd->command <= TSDB_SQL_CURRENT_USER)) {
if (hasMoreVnodesToTry(pSql)) { // sequentially retrieve data from remain vnodes.
@@ -351,7 +351,7 @@ void tscProcessFetchRow(SSchedMsg *pMsg) {
SInternalField* pSup = taosArrayGet(pQueryInfo->fieldsInfo.internalField, i);
if (pSup->pSqlExpr != NULL) {
- tscGetResultColumnChr(pRes, &pQueryInfo->fieldsInfo, i);
+ tscGetResultColumnChr(pRes, &pQueryInfo->fieldsInfo, i, 0);
} else {
// todo add
}
@@ -405,7 +405,8 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
SSqlRes *pRes = &pSql->res;
pRes->code = code;
- const char* msg = (pCmd->command == TSDB_SQL_STABLEVGROUP)? "vgroup-list":"table-meta";
+ SSqlObj *sub = (SSqlObj*) res;
+ const char* msg = (sub->cmd.command == TSDB_SQL_STABLEVGROUP)? "vgroup-list":"table-meta";
if (code != TSDB_CODE_SUCCESS) {
tscError("%p get %s failed, code:%s", pSql, msg, tstrerror(code));
goto _error;
@@ -427,8 +428,12 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
} else {
assert(code == TSDB_CODE_SUCCESS);
}
-
- assert((tscGetNumOfTags(pTableMetaInfo->pTableMeta) != 0) && pSql->param != NULL);
+
+ // param already freed by other routine and pSql in tscCache when ctrl + c
+ if (atomic_load_ptr(&pSql->param) == NULL) {
+ return;
+ }
+ assert((tscGetNumOfTags(pTableMetaInfo->pTableMeta) != 0));
SRetrieveSupport *trs = (SRetrieveSupport *)pSql->param;
SSqlObj * pParObj = trs->pParentSql;
@@ -437,6 +442,20 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
assert(pParObj->signature == pParObj && trs->subqueryIndex == pTableMetaInfo->vgroupIndex &&
pTableMetaInfo->vgroupIndex >= 0 && pTableMetaInfo->vgroupList != NULL);
+ // tscProcessSql can add error into async res
+ tscProcessSql(pSql);
+ return;
+ } else if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY)) {
+ tscDebug("%p update table meta in local cache, continue to process sql and send corresponding tid_tag query", pSql);
+ STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+ code = tscGetTableMeta(pSql, pTableMetaInfo);
+ if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
+ return;
+ } else {
+ assert(code == TSDB_CODE_SUCCESS);
+ }
+
+ assert((tscGetNumOfTags(pTableMetaInfo->pTableMeta) != 0));
// tscProcessSql can add error into async res
tscProcessSql(pSql);
return;
@@ -461,7 +480,6 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
tscResetSqlCmdObj(pCmd, false);
code = tsParseSql(pSql, true);
-
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
return;
} else if (code != TSDB_CODE_SUCCESS) {
diff --git a/src/client/src/tscFunctionImpl.c b/src/client/src/tscFunctionImpl.c
index 1b4f92d3fc9fc78951e23eaec4c438d7522bf7f1..d39b833374b4891358053788a1afbf9246dfb0dd 100644
--- a/src/client/src/tscFunctionImpl.c
+++ b/src/client/src/tscFunctionImpl.c
@@ -28,6 +28,7 @@
#include "tscompression.h"
#include "tsqlfunction.h"
#include "tutil.h"
+#include "ttype.h"
#define GET_INPUT_CHAR(x) (((char *)((x)->aInputElemBuf)) + ((x)->startOffset) * ((x)->inputBytes))
#define GET_INPUT_CHAR_INDEX(x, y) (GET_INPUT_CHAR(x) + (y) * (x)->inputBytes)
@@ -99,7 +100,7 @@ typedef struct SSumInfo {
// the attribute of hasResult is not needed since the num attribute would server as this purpose
typedef struct SAvgInfo {
double sum;
- int64_t num; // num servers as the hasResult attribute in other struct
+ int64_t num;
} SAvgInfo;
typedef struct SStddevInfo {
@@ -129,11 +130,11 @@ typedef struct STopBotInfo {
} STopBotInfo;
// leastsquares do not apply to super table
-typedef struct SLeastsquareInfo {
+typedef struct SLeastsquaresInfo {
double mat[2][3];
double startVal;
int64_t num;
-} SLeastsquareInfo;
+} SLeastsquaresInfo;
typedef struct SAPercentileInfo {
SHistogramInfo *pHisto;
@@ -167,7 +168,13 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_INTERP) {
*type = (int16_t)dataType;
*bytes = (int16_t)dataBytes;
- *interBytes = *bytes + sizeof(SResultInfo);
+
+ if (functionId == TSDB_FUNC_INTERP) {
+ *interBytes = sizeof(SInterpInfoDetail);
+ } else {
+ *interBytes = 0;
+ }
+
return TSDB_CODE_SUCCESS;
}
@@ -175,21 +182,21 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
if (functionId == TSDB_FUNC_TID_TAG) { // todo use struct
*type = TSDB_DATA_TYPE_BINARY;
*bytes = (int16_t)(dataBytes + sizeof(int16_t) + sizeof(int64_t) + sizeof(int32_t) + sizeof(int32_t) + VARSTR_HEADER_SIZE);
- *interBytes = *bytes;
+ *interBytes = 0;
return TSDB_CODE_SUCCESS;
}
if (functionId == TSDB_FUNC_COUNT) {
*type = TSDB_DATA_TYPE_BIGINT;
*bytes = sizeof(int64_t);
- *interBytes = *bytes;
+ *interBytes = 0;
return TSDB_CODE_SUCCESS;
}
if (functionId == TSDB_FUNC_ARITHM) {
*type = TSDB_DATA_TYPE_DOUBLE;
*bytes = sizeof(double);
- *interBytes = *bytes;
+ *interBytes = 0;
return TSDB_CODE_SUCCESS;
}
@@ -298,7 +305,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
} else if (functionId == TSDB_FUNC_FIRST || functionId == TSDB_FUNC_LAST) {
*type = (int16_t)dataType;
*bytes = (int16_t)dataBytes;
- *interBytes = dataBytes + sizeof(SResultInfo);
+ *interBytes = dataBytes;
} else if (functionId == TSDB_FUNC_SPREAD) {
*type = (int16_t)TSDB_DATA_TYPE_DOUBLE;
*bytes = sizeof(double);
@@ -309,8 +316,8 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
*interBytes = (int16_t)sizeof(SPercentileInfo);
} else if (functionId == TSDB_FUNC_LEASTSQR) {
*type = TSDB_DATA_TYPE_BINARY;
- *bytes = TSDB_AVG_FUNCTION_INTER_BUFFER_SIZE; // string
- *interBytes = *bytes + sizeof(SResultInfo);
+ *bytes = MAX(TSDB_AVG_FUNCTION_INTER_BUFFER_SIZE, sizeof(SLeastsquaresInfo)); // string
+ *interBytes = *bytes;
} else if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_LAST_DST) {
*type = TSDB_DATA_TYPE_BINARY;
*bytes = (int16_t)(dataBytes + sizeof(SFirstLastInfo));
@@ -334,28 +341,20 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
return TSDB_CODE_SUCCESS;
}
-void setResultInfoBuf(SResultInfo *pResInfo, int32_t size, bool superTable, char* buf) {
- assert(pResInfo->interResultBuf == NULL);
-
- pResInfo->bufLen = size;
- pResInfo->superTableQ = superTable;
- pResInfo->interResultBuf = buf;
-}
-
// set the query flag to denote that query is completed
static void no_next_step(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->complete = true;
}
static bool function_setup(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
if (pResInfo->initialized) {
return false;
}
memset(pCtx->aOutputBuf, 0, (size_t)pCtx->outputBytes);
- initResultInfo(pResInfo);
+ initResultInfo(pResInfo, pCtx->interBufBytes);
return true;
}
@@ -367,7 +366,7 @@ static bool function_setup(SQLFunctionCtx *pCtx) {
* @param pCtx
*/
static void function_finalizer(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
if (pResInfo->hasResult != DATA_SET_FLAG) {
if (pCtx->outputType == TSDB_DATA_TYPE_BINARY || pCtx->outputType == TSDB_DATA_TYPE_NCHAR) {
setVardataNull(pCtx->aOutputBuf, pCtx->outputType);
@@ -431,7 +430,7 @@ static void count_function_f(SQLFunctionCtx *pCtx, int32_t index) {
*((int64_t *)pCtx->aOutputBuf) += 1;
// do not need it actually
- SResultInfo *pInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pInfo = GET_RES_INFO(pCtx);
pInfo->hasResult = DATA_SET_FLAG;
}
@@ -592,8 +591,8 @@ static void sum_function(SQLFunctionCtx *pCtx) {
do_sum(pCtx);
// keep the result data in output buffer, not in the intermediate buffer
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- if (pResInfo->hasResult == DATA_SET_FLAG && pResInfo->superTableQ) {
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ if (pResInfo->hasResult == DATA_SET_FLAG && pCtx->stableQuery) {
// set the flag for super table query
SSumInfo *pSum = (SSumInfo *)pCtx->aOutputBuf;
pSum->hasResult = DATA_SET_FLAG;
@@ -604,8 +603,8 @@ static void sum_function_f(SQLFunctionCtx *pCtx, int32_t index) {
do_sum_f(pCtx, index);
// keep the result data in output buffer, not in the intermediate buffer
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- if (pResInfo->hasResult == DATA_SET_FLAG && pResInfo->superTableQ) {
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ if (pResInfo->hasResult == DATA_SET_FLAG && pCtx->stableQuery) {
SSumInfo *pSum = (SSumInfo *)pCtx->aOutputBuf;
pSum->hasResult = DATA_SET_FLAG;
}
@@ -615,8 +614,7 @@ static int32_t sum_merge_impl(const SQLFunctionCtx *pCtx) {
int32_t notNullElems = 0;
GET_TRUE_DATA_TYPE();
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- assert(pResInfo->superTableQ);
+ assert(pCtx->stableQuery);
for (int32_t i = 0; i < pCtx->size; ++i) {
char * input = GET_INPUT_CHAR_INDEX(pCtx, i);
@@ -661,7 +659,7 @@ static void sum_func_second_merge(SQLFunctionCtx *pCtx) {
int32_t notNullElems = sum_merge_impl(pCtx);
SET_VAL(pCtx, notNullElems, 1);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
if (notNullElems > 0) {
pResInfo->hasResult = DATA_SET_FLAG;
@@ -683,7 +681,7 @@ static int32_t firstFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, i
}
// no result for first query, data block is required
- if (GET_RES_INFO(pCtx)->numOfRes <= 0) {
+ if (GET_RES_INFO(pCtx) == NULL || GET_RES_INFO(pCtx)->numOfRes <= 0) {
return BLK_DATA_ALL_NEEDED;
} else {
return BLK_DATA_NO_NEEDED;
@@ -695,7 +693,7 @@ static int32_t lastFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, in
return BLK_DATA_NO_NEEDED;
}
- if (GET_RES_INFO(pCtx)->numOfRes <= 0) {
+ if (GET_RES_INFO(pCtx) == NULL || GET_RES_INFO(pCtx)->numOfRes <= 0) {
return BLK_DATA_ALL_NEEDED;
} else {
return BLK_DATA_NO_NEEDED;
@@ -755,9 +753,9 @@ static void avg_function(SQLFunctionCtx *pCtx) {
int32_t notNullElems = 0;
// NOTE: keep the intermediate result into the interResultBuf
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
- SAvgInfo *pAvgInfo = (SAvgInfo *)pResInfo->interResultBuf;
+ SAvgInfo *pAvgInfo = (SAvgInfo *)GET_ROWCELL_INTERBUF(pResInfo);
double * pVal = &pAvgInfo->sum;
if (pCtx->preAggVals.isSet) {
@@ -800,8 +798,8 @@ static void avg_function(SQLFunctionCtx *pCtx) {
}
// keep the data into the final output buffer for super table query since this execution may be the last one
- if (pResInfo->superTableQ) {
- memcpy(pCtx->aOutputBuf, pResInfo->interResultBuf, sizeof(SAvgInfo));
+ if (pCtx->stableQuery) {
+ memcpy(pCtx->aOutputBuf, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SAvgInfo));
}
}
@@ -814,9 +812,9 @@ static void avg_function_f(SQLFunctionCtx *pCtx, int32_t index) {
SET_VAL(pCtx, 1, 1);
// NOTE: keep the intermediate result into the interResultBuf
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
- SAvgInfo *pAvgInfo = (SAvgInfo *)pResInfo->interResultBuf;
+ SAvgInfo *pAvgInfo = (SAvgInfo *)GET_ROWCELL_INTERBUF(pResInfo);
if (pCtx->inputType == TSDB_DATA_TYPE_TINYINT) {
pAvgInfo->sum += GET_INT8_VAL(pData);
@@ -839,16 +837,16 @@ static void avg_function_f(SQLFunctionCtx *pCtx, int32_t index) {
pResInfo->hasResult = DATA_SET_FLAG;
// keep the data into the final output buffer for super table query since this execution may be the last one
- if (pResInfo->superTableQ) {
- memcpy(pCtx->aOutputBuf, pResInfo->interResultBuf, sizeof(SAvgInfo));
+ if (pCtx->stableQuery) {
+ memcpy(pCtx->aOutputBuf, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SAvgInfo));
}
}
static void avg_func_merge(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- assert(pResInfo->superTableQ);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ assert(pCtx->stableQuery);
- SAvgInfo *pAvgInfo = (SAvgInfo *)pResInfo->interResultBuf;
+ SAvgInfo *pAvgInfo = (SAvgInfo *)GET_ROWCELL_INTERBUF(pResInfo);
char * input = GET_INPUT_CHAR(pCtx);
for (int32_t i = 0; i < pCtx->size; ++i, input += pCtx->inputBytes) {
@@ -864,12 +862,12 @@ static void avg_func_merge(SQLFunctionCtx *pCtx) {
// if the data set hasResult is not set, the result is null
if (pAvgInfo->num > 0) {
pResInfo->hasResult = DATA_SET_FLAG;
- memcpy(pCtx->aOutputBuf, pResInfo->interResultBuf, sizeof(SAvgInfo));
+ memcpy(pCtx->aOutputBuf, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SAvgInfo));
}
}
static void avg_func_second_merge(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
double *sum = (double*) pCtx->aOutputBuf;
char * input = GET_INPUT_CHAR(pCtx);
@@ -883,7 +881,7 @@ static void avg_func_second_merge(SQLFunctionCtx *pCtx) {
*sum += pInput->sum;
// keep the number of data into the temp buffer
- *(int64_t *)pResInfo->interResultBuf += pInput->num;
+ *(int64_t *)GET_ROWCELL_INTERBUF(pResInfo) += pInput->num;
}
}
@@ -891,21 +889,21 @@ static void avg_func_second_merge(SQLFunctionCtx *pCtx) {
* the average value is calculated in finalize routine, since current routine does not know the exact number of points
*/
static void avg_finalizer(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
if (pCtx->currentStage == SECONDARY_STAGE_MERGE) {
assert(pCtx->inputType == TSDB_DATA_TYPE_BINARY);
- if (GET_INT64_VAL(pResInfo->interResultBuf) <= 0) {
+ if (GET_INT64_VAL(GET_ROWCELL_INTERBUF(pResInfo)) <= 0) {
setNull(pCtx->aOutputBuf, pCtx->outputType, pCtx->outputBytes);
return; // empty table
}
- *(double *)pCtx->aOutputBuf = (*(double *)pCtx->aOutputBuf) / *(int64_t *)pResInfo->interResultBuf;
+ *(double *)pCtx->aOutputBuf = (*(double *)pCtx->aOutputBuf) / *(int64_t *)GET_ROWCELL_INTERBUF(pResInfo);
} else { // this is the secondary merge, only in the secondary merge, the input type is TSDB_DATA_TYPE_BINARY
assert(pCtx->inputType >= TSDB_DATA_TYPE_TINYINT && pCtx->inputType <= TSDB_DATA_TYPE_DOUBLE);
- SAvgInfo *pAvgInfo = (SAvgInfo *)pResInfo->interResultBuf;
+ SAvgInfo *pAvgInfo = (SAvgInfo *)GET_ROWCELL_INTERBUF(pResInfo);
if (pAvgInfo->num == 0) { // all data are NULL or empty table
setNull(pCtx->aOutputBuf, pCtx->outputType, pCtx->outputBytes);
@@ -1116,11 +1114,11 @@ static void min_function(SQLFunctionCtx *pCtx) {
SET_VAL(pCtx, notNullElems, 1);
if (notNullElems > 0) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
// set the flag for super table query
- if (pResInfo->superTableQ) {
+ if (pCtx->stableQuery) {
*(pCtx->aOutputBuf + pCtx->inputBytes) = DATA_SET_FLAG;
}
}
@@ -1133,11 +1131,11 @@ static void max_function(SQLFunctionCtx *pCtx) {
SET_VAL(pCtx, notNullElems, 1);
if (notNullElems > 0) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
// set the flag for super table query
- if (pResInfo->superTableQ) {
+ if (pCtx->stableQuery) {
*(pCtx->aOutputBuf + pCtx->inputBytes) = DATA_SET_FLAG;
}
}
@@ -1148,8 +1146,7 @@ static int32_t minmax_merge_impl(SQLFunctionCtx *pCtx, int32_t bytes, char *outp
GET_TRUE_DATA_TYPE();
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- assert(pResInfo->superTableQ);
+ assert(pCtx->stableQuery);
for (int32_t i = 0; i < pCtx->size; ++i) {
char *input = GET_INPUT_CHAR_INDEX(pCtx, i);
@@ -1210,7 +1207,7 @@ static void min_func_merge(SQLFunctionCtx *pCtx) {
SET_VAL(pCtx, notNullElems, 1);
- if (notNullElems > 0) { // for super table query, SResultInfo is not used
+ if (notNullElems > 0) { // for super table query, SResultRowCellInfo is not used
char *flag = pCtx->aOutputBuf + pCtx->inputBytes;
*flag = DATA_SET_FLAG;
}
@@ -1221,7 +1218,7 @@ static void min_func_second_merge(SQLFunctionCtx *pCtx) {
SET_VAL(pCtx, notNullElems, 1);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
if (notNullElems > 0) {
pResInfo->hasResult = DATA_SET_FLAG;
}
@@ -1242,7 +1239,7 @@ static void max_func_second_merge(SQLFunctionCtx *pCtx) {
SET_VAL(pCtx, numOfElem, 1);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
if (numOfElem > 0) {
pResInfo->hasResult = DATA_SET_FLAG;
}
@@ -1297,8 +1294,8 @@ static void max_function_f(SQLFunctionCtx *pCtx, int32_t index) {
SET_VAL(pCtx, 1, 1);
minMax_function_f(pCtx, index, 0);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- if (pResInfo->hasResult == DATA_SET_FLAG && pResInfo->superTableQ) {
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ if (pResInfo->hasResult == DATA_SET_FLAG && pCtx->stableQuery) {
char *flag = pCtx->aOutputBuf + pCtx->inputBytes;
*flag = DATA_SET_FLAG;
}
@@ -1313,8 +1310,8 @@ static void min_function_f(SQLFunctionCtx *pCtx, int32_t index) {
SET_VAL(pCtx, 1, 1);
minMax_function_f(pCtx, index, 1);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- if (pResInfo->hasResult == DATA_SET_FLAG && pResInfo->superTableQ) {
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ if (pResInfo->hasResult == DATA_SET_FLAG && pCtx->stableQuery) {
char *flag = pCtx->aOutputBuf + pCtx->inputBytes;
*flag = DATA_SET_FLAG;
}
@@ -1330,7 +1327,7 @@ static void min_function_f(SQLFunctionCtx *pCtx, int32_t index) {
static void stddev_function(SQLFunctionCtx *pCtx) {
// the second stage to calculate standard deviation
- SStddevInfo *pStd = GET_RES_INFO(pCtx)->interResultBuf;
+ SStddevInfo *pStd = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
if (pStd->stage == 0) { // the first stage is to calculate average value
avg_function(pCtx);
@@ -1381,8 +1378,8 @@ static void stddev_function(SQLFunctionCtx *pCtx) {
static void stddev_function_f(SQLFunctionCtx *pCtx, int32_t index) {
// the second stage to calculate standard deviation
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- SStddevInfo *pStd = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SStddevInfo *pStd = GET_ROWCELL_INTERBUF(pResInfo);
/* the first stage is to calculate average value */
if (pStd->stage == 0) {
@@ -1433,8 +1430,8 @@ static void stddev_next_step(SQLFunctionCtx *pCtx) {
* the stddevInfo and the average info struct share the same buffer area
* And the position of each element in their struct is exactly the same matched
*/
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- SStddevInfo *pStd = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SStddevInfo *pStd = GET_ROWCELL_INTERBUF(pResInfo);
if (pStd->stage == 0) {
/*
@@ -1449,7 +1446,7 @@ static void stddev_next_step(SQLFunctionCtx *pCtx) {
pResInfo->initialized = true; // set it initialized to avoid re-initialization
// save average value into tmpBuf, for second stage scan
- SAvgInfo *pAvg = pResInfo->interResultBuf;
+ SAvgInfo *pAvg = GET_ROWCELL_INTERBUF(pResInfo);
pStd->avg = GET_DOUBLE_VAL(pCtx->aOutputBuf);
assert((isnan(pAvg->sum) && pAvg->num == 0) || (pStd->num == pAvg->num && pStd->avg == pAvg->sum));
@@ -1459,7 +1456,7 @@ static void stddev_next_step(SQLFunctionCtx *pCtx) {
}
static void stddev_finalizer(SQLFunctionCtx *pCtx) {
- SStddevInfo *pStd = (SStddevInfo *)GET_RES_INFO(pCtx)->interResultBuf;
+ SStddevInfo *pStd = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
if (pStd->num <= 0) {
setNull(pCtx->aOutputBuf, pCtx->outputType, pCtx->outputBytes);
@@ -1505,7 +1502,7 @@ static void first_function(SQLFunctionCtx *pCtx) {
TSKEY k = pCtx->ptsList[i];
DO_UPDATE_TAG_COLUMNS(pCtx, k);
- SResultInfo *pInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pInfo = GET_RES_INFO(pCtx);
pInfo->hasResult = DATA_SET_FLAG;
pInfo->complete = true;
@@ -1532,7 +1529,7 @@ static void first_function_f(SQLFunctionCtx *pCtx, int32_t index) {
TSKEY ts = pCtx->ptsList[index];
DO_UPDATE_TAG_COLUMNS(pCtx, ts);
- SResultInfo *pInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pInfo = GET_RES_INFO(pCtx);
pInfo->hasResult = DATA_SET_FLAG;
pInfo->complete = true; // get the first not-null data, completed
}
@@ -1576,7 +1573,7 @@ static void first_dist_function(SQLFunctionCtx *pCtx) {
first_data_assign_impl(pCtx, data, i);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
notNullElems++;
@@ -1604,8 +1601,7 @@ static void first_dist_function_f(SQLFunctionCtx *pCtx, int32_t index) {
static void first_dist_func_merge(SQLFunctionCtx *pCtx) {
char *pData = GET_INPUT_CHAR(pCtx);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- assert(pCtx->size == 1 && pResInfo->superTableQ);
+ assert(pCtx->size == 1 && pCtx->stableQuery);
SFirstLastInfo *pInput = (SFirstLastInfo *)(pData + pCtx->inputBytes);
if (pInput->hasResult != DATA_SET_FLAG) {
@@ -1620,8 +1616,8 @@ static void first_dist_func_merge(SQLFunctionCtx *pCtx) {
}
static void first_dist_func_second_merge(SQLFunctionCtx *pCtx) {
- assert(pCtx->resultInfo->superTableQ);
-
+ assert(pCtx->stableQuery);
+
char * pData = GET_INPUT_CHAR(pCtx);
SFirstLastInfo *pInput = (SFirstLastInfo*) (pData + pCtx->outputBytes);
if (pInput->hasResult != DATA_SET_FLAG) {
@@ -1668,7 +1664,7 @@ static void last_function(SQLFunctionCtx *pCtx) {
TSKEY ts = pCtx->ptsList[i];
DO_UPDATE_TAG_COLUMNS(pCtx, ts);
- SResultInfo *pInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pInfo = GET_RES_INFO(pCtx);
pInfo->hasResult = DATA_SET_FLAG;
pInfo->complete = true; // set query completed on this column
@@ -1691,7 +1687,7 @@ static void last_function_f(SQLFunctionCtx *pCtx, int32_t index) {
TSKEY ts = pCtx->ptsList[index];
DO_UPDATE_TAG_COLUMNS(pCtx, ts);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
pResInfo->complete = true; // set query completed
}
@@ -1740,7 +1736,7 @@ static void last_dist_function(SQLFunctionCtx *pCtx) {
last_data_assign_impl(pCtx, data, i);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
notNullElems++;
@@ -1776,8 +1772,7 @@ static void last_dist_function_f(SQLFunctionCtx *pCtx, int32_t index) {
static void last_dist_func_merge(SQLFunctionCtx *pCtx) {
char *pData = GET_INPUT_CHAR(pCtx);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- assert(pCtx->size == 1 && pResInfo->superTableQ);
+ assert(pCtx->size == 1 && pCtx->stableQuery);
// the input data is null
SFirstLastInfo *pInput = (SFirstLastInfo *)(pData + pCtx->inputBytes);
@@ -1833,11 +1828,11 @@ static void last_row_function(SQLFunctionCtx *pCtx) {
// assign the last element in current data block
assignVal(pCtx->aOutputBuf, pData + (pCtx->size - 1) * pCtx->inputBytes, pCtx->inputBytes, pCtx->inputType);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
// set the result to final result buffer in case of super table query
- if (pResInfo->superTableQ) {
+ if (pCtx->stableQuery) {
SLastrowInfo *pInfo1 = (SLastrowInfo *)(pCtx->aOutputBuf + pCtx->inputBytes);
pInfo1->ts = pCtx->ptsList[pCtx->size - 1];
pInfo1->hasResult = DATA_SET_FLAG;
@@ -1852,7 +1847,7 @@ static void last_row_function(SQLFunctionCtx *pCtx) {
static void last_row_finalizer(SQLFunctionCtx *pCtx) {
// do nothing at the first stage
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
if (pResInfo->hasResult != DATA_SET_FLAG) {
if (pCtx->outputType == TSDB_DATA_TYPE_BINARY || pCtx->outputType == TSDB_DATA_TYPE_NCHAR) {
setVardataNull(pCtx->aOutputBuf, pCtx->outputType);
@@ -2044,8 +2039,8 @@ static int32_t resDataAscComparFn(const void *pLeft, const void *pRight) {
static int32_t resDataDescComparFn(const void *pLeft, const void *pRight) { return -resDataAscComparFn(pLeft, pRight); }
static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- STopBotInfo *pRes = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ STopBotInfo *pRes = GET_ROWCELL_INTERBUF(pResInfo);
tValuePair **tvp = pRes->res;
@@ -2123,7 +2118,7 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) {
}
}
- taosTFree(pData);
+ tfree(pData);
}
/*
@@ -2135,18 +2130,18 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) {
* top/bottom use the intermediate result buffer to keep the intermediate result
*/
static STopBotInfo *getTopBotOutputInfo(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
// only the first_stage_merge is directly written data into final output buffer
- if (pResInfo->superTableQ && pCtx->currentStage != SECONDARY_STAGE_MERGE) {
+ if (pCtx->stableQuery && pCtx->currentStage != SECONDARY_STAGE_MERGE) {
return (STopBotInfo*) pCtx->aOutputBuf;
} else { // during normal table query and super table at the secondary_stage, result is written to intermediate buffer
- return pResInfo->interResultBuf;
+ return GET_ROWCELL_INTERBUF(pResInfo);
}
}
bool topbot_datablock_filter(SQLFunctionCtx *pCtx, int32_t functionId, const char *minval, const char *maxval) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
if (pResInfo == NULL) {
return true;
}
@@ -2252,7 +2247,7 @@ static void top_function(SQLFunctionCtx *pCtx) {
SET_VAL(pCtx, notNullElems, 1);
if (notNullElems > 0) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
}
}
@@ -2270,7 +2265,7 @@ static void top_function_f(SQLFunctionCtx *pCtx, int32_t index) {
do_top_function_add(pRes, (int32_t)pCtx->param[0].i64Key, pData, pCtx->ptsList[index], pCtx->inputType, &pCtx->tagInfo, NULL,
0);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
}
@@ -2285,8 +2280,7 @@ static void top_func_merge(SQLFunctionCtx *pCtx) {
// remmap the input buffer may cause the struct pointer invalid, so rebuild the STopBotInfo is necessary
buildTopBotStruct(pInput, pCtx);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- assert(pResInfo->superTableQ && pCtx->outputType == TSDB_DATA_TYPE_BINARY && pCtx->size == 1);
+ assert(pCtx->stableQuery && pCtx->outputType == TSDB_DATA_TYPE_BINARY && pCtx->size == 1);
STopBotInfo *pOutput = getTopBotOutputInfo(pCtx);
@@ -2314,7 +2308,7 @@ static void top_func_second_merge(SQLFunctionCtx *pCtx) {
SET_VAL(pCtx, pInput->num, pOutput->num);
if (pOutput->num > 0) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
}
}
@@ -2343,7 +2337,7 @@ static void bottom_function(SQLFunctionCtx *pCtx) {
SET_VAL(pCtx, notNullElems, 1);
if (notNullElems > 0) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
}
}
@@ -2359,7 +2353,7 @@ static void bottom_function_f(SQLFunctionCtx *pCtx, int32_t index) {
do_bottom_function_add(pRes, (int32_t)pCtx->param[0].i64Key, pData, pCtx->ptsList[index], pCtx->inputType, &pCtx->tagInfo,
NULL, 0);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
}
@@ -2374,8 +2368,7 @@ static void bottom_func_merge(SQLFunctionCtx *pCtx) {
// remmap the input buffer may cause the struct pointer invalid, so rebuild the STopBotInfo is necessary
buildTopBotStruct(pInput, pCtx);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- assert(pResInfo->superTableQ && pCtx->outputType == TSDB_DATA_TYPE_BINARY && pCtx->size == 1);
+ assert(pCtx->stableQuery && pCtx->outputType == TSDB_DATA_TYPE_BINARY && pCtx->size == 1);
STopBotInfo *pOutput = getTopBotOutputInfo(pCtx);
@@ -2403,16 +2396,16 @@ static void bottom_func_second_merge(SQLFunctionCtx *pCtx) {
SET_VAL(pCtx, pInput->num, pOutput->num);
if (pOutput->num > 0) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
}
}
static void top_bottom_func_finalizer(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
// data in temporary list is less than the required number of results, not enough qualified number of results
- STopBotInfo *pRes = pResInfo->interResultBuf;
+ STopBotInfo *pRes = GET_ROWCELL_INTERBUF(pResInfo);
if (pRes->num == 0) { // no result
assert(pResInfo->hasResult != DATA_SET_FLAG);
// TODO:
@@ -2443,8 +2436,8 @@ static bool percentile_function_setup(SQLFunctionCtx *pCtx) {
}
// in the first round, get the min-max value of all involved data
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- SPercentileInfo *pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SPercentileInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
SET_DOUBLE_VAL(&pInfo->minval, DBL_MAX);
SET_DOUBLE_VAL(&pInfo->maxval, -DBL_MAX);
pInfo->numOfElems = 0;
@@ -2455,18 +2448,28 @@ static bool percentile_function_setup(SQLFunctionCtx *pCtx) {
static void percentile_function(SQLFunctionCtx *pCtx) {
int32_t notNullElems = 0;
- SResultInfo * pResInfo = GET_RES_INFO(pCtx);
- SPercentileInfo *pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx);
+ SPercentileInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
// the first stage, only acquire the min/max value
if (pInfo->stage == 0) {
if (pCtx->preAggVals.isSet) {
- if (GET_DOUBLE_VAL(&pInfo->minval) > pCtx->preAggVals.statis.min) {
- SET_DOUBLE_VAL(&pInfo->minval, (double)pCtx->preAggVals.statis.min);
+ double tmin = 0.0, tmax = 0.0;
+ if (pCtx->inputType >= TSDB_DATA_TYPE_TINYINT && pCtx->inputType <= TSDB_DATA_TYPE_BIGINT) {
+ tmin = (double)GET_INT64_VAL(&pCtx->preAggVals.statis.min);
+ tmax = (double)GET_INT64_VAL(&pCtx->preAggVals.statis.max);
+ } else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE || pCtx->inputType == TSDB_DATA_TYPE_FLOAT) {
+ tmin = GET_DOUBLE_VAL(&pCtx->preAggVals.statis.min);
+ tmax = GET_DOUBLE_VAL(&pCtx->preAggVals.statis.max);
+ } else {
+ assert(true);
+ }
+ if (GET_DOUBLE_VAL(&pInfo->minval) > tmin) {
+ SET_DOUBLE_VAL(&pInfo->minval, tmin);
}
- if (GET_DOUBLE_VAL(&pInfo->maxval) < pCtx->preAggVals.statis.max) {
- SET_DOUBLE_VAL(&pInfo->maxval, (double)pCtx->preAggVals.statis.max);
+ if (GET_DOUBLE_VAL(&pInfo->maxval) < tmax) {
+ SET_DOUBLE_VAL(&pInfo->maxval, tmax);
}
pInfo->numOfElems += (pCtx->size - pCtx->preAggVals.statis.numOfNull);
@@ -2477,28 +2480,8 @@ static void percentile_function(SQLFunctionCtx *pCtx) {
continue;
}
- // TODO extract functions
double v = 0;
- switch (pCtx->inputType) {
- case TSDB_DATA_TYPE_TINYINT:
- v = GET_INT8_VAL(data);
- break;
- case TSDB_DATA_TYPE_SMALLINT:
- v = GET_INT16_VAL(data);
- break;
- case TSDB_DATA_TYPE_BIGINT:
- v = (double)(GET_INT64_VAL(data));
- break;
- case TSDB_DATA_TYPE_FLOAT:
- v = GET_FLOAT_VAL(data);
- break;
- case TSDB_DATA_TYPE_DOUBLE:
- v = GET_DOUBLE_VAL(data);
- break;
- default:
- v = GET_INT32_VAL(data);
- break;
- }
+ GET_TYPED_DATA(v, double, pCtx->inputType, data);
if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
SET_DOUBLE_VAL(&pInfo->minval, v);
@@ -2536,33 +2519,13 @@ static void percentile_function_f(SQLFunctionCtx *pCtx, int32_t index) {
return;
}
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
-
- SPercentileInfo *pInfo = (SPercentileInfo *)pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SPercentileInfo *pInfo = (SPercentileInfo *)GET_ROWCELL_INTERBUF(pResInfo);
if (pInfo->stage == 0) {
- // TODO extract functions
+
double v = 0;
- switch (pCtx->inputType) {
- case TSDB_DATA_TYPE_TINYINT:
- v = GET_INT8_VAL(pData);
- break;
- case TSDB_DATA_TYPE_SMALLINT:
- v = GET_INT16_VAL(pData);
- break;
- case TSDB_DATA_TYPE_BIGINT:
- v = (double)(GET_INT64_VAL(pData));
- break;
- case TSDB_DATA_TYPE_FLOAT:
- v = GET_FLOAT_VAL(pData);
- break;
- case TSDB_DATA_TYPE_DOUBLE:
- v = GET_DOUBLE_VAL(pData);
- break;
- default:
- v = GET_INT32_VAL(pData);
- break;
- }
+ GET_TYPED_DATA(v, double, pCtx->inputType, pData);
if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
SET_DOUBLE_VAL(&pInfo->minval, v);
@@ -2585,8 +2548,8 @@ static void percentile_function_f(SQLFunctionCtx *pCtx, int32_t index) {
static void percentile_finalizer(SQLFunctionCtx *pCtx) {
double v = pCtx->param[0].nType == TSDB_DATA_TYPE_INT ? pCtx->param[0].i64Key : pCtx->param[0].dKey;
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- tMemBucket * pMemBucket = ((SPercentileInfo *)pResInfo->interResultBuf)->pMemBucket;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ tMemBucket * pMemBucket = ((SPercentileInfo *)GET_ROWCELL_INTERBUF(pResInfo))->pMemBucket;
if (pMemBucket->total > 0) { // check for null
*(double *)pCtx->aOutputBuf = getPercentile(pMemBucket, v);
@@ -2599,8 +2562,8 @@ static void percentile_finalizer(SQLFunctionCtx *pCtx) {
}
static void percentile_next_step(SQLFunctionCtx *pCtx) {
- SResultInfo * pResInfo = GET_RES_INFO(pCtx);
- SPercentileInfo *pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx);
+ SPercentileInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
if (pInfo->stage == 0) {
// all data are null, set it completed
@@ -2617,12 +2580,12 @@ static void percentile_next_step(SQLFunctionCtx *pCtx) {
//////////////////////////////////////////////////////////////////////////////////
static SAPercentileInfo *getAPerctInfo(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
- if (pResInfo->superTableQ && pCtx->currentStage != SECONDARY_STAGE_MERGE) {
+ if (pCtx->stableQuery && pCtx->currentStage != SECONDARY_STAGE_MERGE) {
return (SAPercentileInfo*) pCtx->aOutputBuf;
} else {
- return pResInfo->interResultBuf;
+ return GET_ROWCELL_INTERBUF(pResInfo);
}
}
@@ -2641,7 +2604,7 @@ static bool apercentile_function_setup(SQLFunctionCtx *pCtx) {
static void apercentile_function(SQLFunctionCtx *pCtx) {
int32_t notNullElems = 0;
- SResultInfo * pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx);
SAPercentileInfo *pInfo = getAPerctInfo(pCtx);
for (int32_t i = 0; i < pCtx->size; ++i) {
@@ -2651,29 +2614,9 @@ static void apercentile_function(SQLFunctionCtx *pCtx) {
}
notNullElems += 1;
+
double v = 0;
-
- switch (pCtx->inputType) {
- case TSDB_DATA_TYPE_TINYINT:
- v = GET_INT8_VAL(data);
- break;
- case TSDB_DATA_TYPE_SMALLINT:
- v = GET_INT16_VAL(data);
- break;
- case TSDB_DATA_TYPE_BIGINT:
- v = (double)(GET_INT64_VAL(data));
- break;
- case TSDB_DATA_TYPE_FLOAT:
- v = GET_FLOAT_VAL(data);
- break;
- case TSDB_DATA_TYPE_DOUBLE:
- v = GET_DOUBLE_VAL(data);
- break;
- default:
- v = GET_INT32_VAL(data);
- break;
- }
-
+ GET_TYPED_DATA(v, double, pCtx->inputType, data);
tHistogramAdd(&pInfo->pHisto, v);
}
@@ -2694,30 +2637,11 @@ static void apercentile_function_f(SQLFunctionCtx *pCtx, int32_t index) {
return;
}
- SResultInfo * pResInfo = GET_RES_INFO(pCtx);
- SAPercentileInfo *pInfo = getAPerctInfo(pCtx); // pResInfo->interResultBuf;
+ SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx);
+ SAPercentileInfo *pInfo = getAPerctInfo(pCtx);
double v = 0;
- switch (pCtx->inputType) {
- case TSDB_DATA_TYPE_TINYINT:
- v = GET_INT8_VAL(pData);
- break;
- case TSDB_DATA_TYPE_SMALLINT:
- v = GET_INT16_VAL(pData);
- break;
- case TSDB_DATA_TYPE_BIGINT:
- v = (double)(GET_INT64_VAL(pData));
- break;
- case TSDB_DATA_TYPE_FLOAT:
- v = GET_FLOAT_VAL(pData);
- break;
- case TSDB_DATA_TYPE_DOUBLE:
- v = GET_DOUBLE_VAL(pData);
- break;
- default:
- v = GET_INT32_VAL(pData);
- break;
- }
+ GET_TYPED_DATA(v, double, pCtx->inputType, pData);
tHistogramAdd(&pInfo->pHisto, v);
@@ -2726,8 +2650,8 @@ static void apercentile_function_f(SQLFunctionCtx *pCtx, int32_t index) {
}
static void apercentile_func_merge(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- assert(pResInfo->superTableQ);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ assert(pCtx->stableQuery);
SAPercentileInfo *pInput = (SAPercentileInfo *)GET_INPUT_CHAR(pCtx);
@@ -2771,20 +2695,21 @@ static void apercentile_func_second_merge(SQLFunctionCtx *pCtx) {
}
SAPercentileInfo *pOutput = getAPerctInfo(pCtx);
- SHistogramInfo * pHisto = pOutput->pHisto;
+ SHistogramInfo *pHisto = pOutput->pHisto;
if (pHisto->numOfElems <= 0) {
memcpy(pHisto, pInput->pHisto, sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
pHisto->elems = (SHistBin*) ((char *)pHisto + sizeof(SHistogramInfo));
} else {
+ //TODO(dengyihao): avoid memcpy
pHisto->elems = (SHistBin*) ((char *)pHisto + sizeof(SHistogramInfo));
-
SHistogramInfo *pRes = tHistogramMerge(pHisto, pInput->pHisto, MAX_HISTOGRAM_BIN);
- tHistogramDestroy(&pOutput->pHisto);
- pOutput->pHisto = pRes;
+ memcpy(pHisto, pRes, sizeof(SHistogramInfo) + sizeof(SHistBin) * MAX_HISTOGRAM_BIN);
+ pHisto->elems = (SHistBin*) ((char *)pHisto + sizeof(SHistogramInfo));
+ tHistogramDestroy(&pRes);
}
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
pResInfo->hasResult = DATA_SET_FLAG;
SET_VAL(pCtx, 1, 1);
}
@@ -2792,8 +2717,8 @@ static void apercentile_func_second_merge(SQLFunctionCtx *pCtx) {
static void apercentile_finalizer(SQLFunctionCtx *pCtx) {
double v = (pCtx->param[0].nType == TSDB_DATA_TYPE_INT) ? pCtx->param[0].i64Key : pCtx->param[0].dKey;
- SResultInfo * pResInfo = GET_RES_INFO(pCtx);
- SAPercentileInfo *pOutput = pResInfo->interResultBuf;
+ SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx);
+ SAPercentileInfo *pOutput = GET_ROWCELL_INTERBUF(pResInfo);
if (pCtx->currentStage == SECONDARY_STAGE_MERGE) {
if (pResInfo->hasResult == DATA_SET_FLAG) { // check for null
@@ -2830,8 +2755,8 @@ static bool leastsquares_function_setup(SQLFunctionCtx *pCtx) {
return false;
}
- SResultInfo * pResInfo = GET_RES_INFO(pCtx);
- SLeastsquareInfo *pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx);
+ SLeastsquaresInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
// 2*3 matrix
pInfo->startVal = pCtx->param[0].dKey;
@@ -2857,8 +2782,8 @@ static bool leastsquares_function_setup(SQLFunctionCtx *pCtx) {
}
static void leastsquares_function(SQLFunctionCtx *pCtx) {
- SResultInfo * pResInfo = GET_RES_INFO(pCtx);
- SLeastsquareInfo *pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx);
+ SLeastsquaresInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
double(*param)[3] = pInfo->mat;
double x = pInfo->startVal;
@@ -2928,40 +2853,40 @@ static void leastsquares_function_f(SQLFunctionCtx *pCtx, int32_t index) {
return;
}
- SResultInfo * pResInfo = GET_RES_INFO(pCtx);
- SLeastsquareInfo *pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SLeastsquaresInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
double(*param)[3] = pInfo->mat;
switch (pCtx->inputType) {
case TSDB_DATA_TYPE_INT: {
int32_t *p = pData;
- LEASTSQR_CAL(param, pInfo->startVal, p, index, pCtx->param[1].dKey);
+ LEASTSQR_CAL(param, pInfo->startVal, p, 0, pCtx->param[1].dKey);
break;
};
case TSDB_DATA_TYPE_TINYINT: {
int8_t *p = pData;
- LEASTSQR_CAL(param, pInfo->startVal, p, index, pCtx->param[1].dKey);
+ LEASTSQR_CAL(param, pInfo->startVal, p, 0, pCtx->param[1].dKey);
break;
}
case TSDB_DATA_TYPE_SMALLINT: {
int16_t *p = pData;
- LEASTSQR_CAL(param, pInfo->startVal, p, index, pCtx->param[1].dKey);
+ LEASTSQR_CAL(param, pInfo->startVal, p, 0, pCtx->param[1].dKey);
break;
}
case TSDB_DATA_TYPE_BIGINT: {
int64_t *p = pData;
- LEASTSQR_CAL(param, pInfo->startVal, p, index, pCtx->param[1].dKey);
+ LEASTSQR_CAL(param, pInfo->startVal, p, 0, pCtx->param[1].dKey);
break;
}
case TSDB_DATA_TYPE_FLOAT: {
float *p = pData;
- LEASTSQR_CAL(param, pInfo->startVal, p, index, pCtx->param[1].dKey);
+ LEASTSQR_CAL(param, pInfo->startVal, p, 0, pCtx->param[1].dKey);
break;
}
case TSDB_DATA_TYPE_DOUBLE: {
double *p = pData;
- LEASTSQR_CAL(param, pInfo->startVal, p, index, pCtx->param[1].dKey);
+ LEASTSQR_CAL(param, pInfo->startVal, p, 0, pCtx->param[1].dKey);
break;
}
default:
@@ -2978,16 +2903,11 @@ static void leastsquares_function_f(SQLFunctionCtx *pCtx, int32_t index) {
static void leastsquares_finalizer(SQLFunctionCtx *pCtx) {
// no data in query
- SResultInfo * pResInfo = GET_RES_INFO(pCtx);
- SLeastsquareInfo *pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx);
+ SLeastsquaresInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
if (pInfo->num == 0) {
- if (pCtx->outputType == TSDB_DATA_TYPE_BINARY || pCtx->outputType == TSDB_DATA_TYPE_NCHAR) {
- setVardataNull(pCtx->aOutputBuf, pCtx->outputType);
- } else {
- setNull(pCtx->aOutputBuf, pCtx->outputType, pCtx->outputBytes);
- }
-
+ setNull(pCtx->aOutputBuf, pCtx->outputType, pCtx->outputBytes);
return;
}
@@ -3044,7 +2964,7 @@ static void col_project_function(SQLFunctionCtx *pCtx) {
}
static void col_project_function_f(SQLFunctionCtx *pCtx, int32_t index) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
if (pCtx->numOfParams == 2) { // the number of output rows should not affect the final number of rows, so set it to be 0
return;
}
@@ -3476,7 +3396,7 @@ static bool spread_function_setup(SQLFunctionCtx *pCtx) {
return false;
}
- SSpreadInfo *pInfo = GET_RES_INFO(pCtx)->interResultBuf;
+ SSpreadInfo *pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
// this is the server-side setup function in client-side, the secondary merge do not need this procedure
if (pCtx->currentStage == SECONDARY_STAGE_MERGE) {
@@ -3491,8 +3411,8 @@ static bool spread_function_setup(SQLFunctionCtx *pCtx) {
}
static void spread_function(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- SSpreadInfo *pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SSpreadInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
int32_t numOfElems = 0;
@@ -3558,8 +3478,8 @@ static void spread_function(SQLFunctionCtx *pCtx) {
}
// keep the data into the final output buffer for super table query since this execution may be the last one
- if (pResInfo->superTableQ) {
- memcpy(pCtx->aOutputBuf, pResInfo->interResultBuf, sizeof(SSpreadInfo));
+ if (pCtx->stableQuery) {
+ memcpy(pCtx->aOutputBuf, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SSpreadInfo));
}
}
@@ -3571,8 +3491,8 @@ static void spread_function_f(SQLFunctionCtx *pCtx, int32_t index) {
SET_VAL(pCtx, 1, 1);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- SSpreadInfo *pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SSpreadInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
double val = 0.0;
if (pCtx->inputType == TSDB_DATA_TYPE_TINYINT) {
@@ -3601,16 +3521,16 @@ static void spread_function_f(SQLFunctionCtx *pCtx, int32_t index) {
pResInfo->hasResult = DATA_SET_FLAG;
pInfo->hasResult = DATA_SET_FLAG;
- if (pResInfo->superTableQ) {
- memcpy(pCtx->aOutputBuf, pResInfo->interResultBuf, sizeof(SSpreadInfo));
+ if (pCtx->stableQuery) {
+ memcpy(pCtx->aOutputBuf, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SSpreadInfo));
}
}
void spread_func_merge(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- assert(pResInfo->superTableQ);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ assert(pCtx->stableQuery);
- SSpreadInfo *pResData = pResInfo->interResultBuf;
+ SSpreadInfo *pResData = GET_ROWCELL_INTERBUF(pResInfo);
int32_t notNullElems = 0;
for (int32_t i = 0; i < pCtx->size; ++i) {
@@ -3634,7 +3554,7 @@ void spread_func_merge(SQLFunctionCtx *pCtx) {
}
if (notNullElems > 0) {
- memcpy(pCtx->aOutputBuf, pResInfo->interResultBuf, sizeof(SSpreadInfo));
+ memcpy(pCtx->aOutputBuf, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SSpreadInfo));
pResInfo->hasResult = DATA_SET_FLAG;
}
}
@@ -3665,7 +3585,7 @@ void spread_function_finalizer(SQLFunctionCtx *pCtx) {
* here we do not check the input data types, because in case of metric query,
* the type of intermediate data is binary
*/
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
if (pCtx->currentStage == SECONDARY_STAGE_MERGE) {
assert(pCtx->inputType == TSDB_DATA_TYPE_BINARY);
@@ -3680,7 +3600,7 @@ void spread_function_finalizer(SQLFunctionCtx *pCtx) {
assert((pCtx->inputType >= TSDB_DATA_TYPE_TINYINT && pCtx->inputType <= TSDB_DATA_TYPE_DOUBLE) ||
(pCtx->inputType == TSDB_DATA_TYPE_TIMESTAMP));
- SSpreadInfo *pInfo = GET_RES_INFO(pCtx)->interResultBuf;
+ SSpreadInfo *pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
if (pInfo->hasResult != DATA_SET_FLAG) {
setNull(pCtx->aOutputBuf, pCtx->outputType, pCtx->outputBytes);
return;
@@ -3704,8 +3624,8 @@ static bool twa_function_setup(SQLFunctionCtx *pCtx) {
return false;
}
- SResultInfo *pResInfo = GET_RES_INFO(pCtx); //->aOutputBuf + pCtx->outputBytes;
- STwaInfo * pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); //->aOutputBuf + pCtx->outputBytes;
+ STwaInfo * pInfo = GET_ROWCELL_INTERBUF(pResInfo);
pInfo->lastKey = INT64_MIN;
pInfo->type = pCtx->inputType;
@@ -3744,8 +3664,8 @@ static void twa_function(SQLFunctionCtx *pCtx) {
int32_t notNullElems = 0;
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- STwaInfo * pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ STwaInfo * pInfo = GET_ROWCELL_INTERBUF(pResInfo);
int32_t i = 0;
@@ -3798,7 +3718,7 @@ static void twa_function(SQLFunctionCtx *pCtx) {
pResInfo->hasResult = DATA_SET_FLAG;
}
- if (pResInfo->superTableQ) {
+ if (pCtx->stableQuery) {
memcpy(pCtx->aOutputBuf, pInfo, sizeof(STwaInfo));
}
@@ -3815,8 +3735,8 @@ static void twa_function_f(SQLFunctionCtx *pCtx, int32_t index) {
TSKEY *primaryKey = pCtx->ptsList;
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- STwaInfo *pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ STwaInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
if (pInfo->lastKey == INT64_MIN) {
pInfo->lastKey = pCtx->nStartQueryTimestamp;
@@ -3838,14 +3758,13 @@ static void twa_function_f(SQLFunctionCtx *pCtx, int32_t index) {
// pCtx->numOfIteratedElems += 1;
pResInfo->hasResult = DATA_SET_FLAG;
- if (pResInfo->superTableQ) {
- memcpy(pCtx->aOutputBuf, pResInfo->interResultBuf, sizeof(STwaInfo));
+ if (pCtx->stableQuery) {
+ memcpy(pCtx->aOutputBuf, GET_ROWCELL_INTERBUF(pResInfo), sizeof(STwaInfo));
}
}
static void twa_func_merge(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- assert(pResInfo->superTableQ);
+ assert(pCtx->stableQuery);
STwaInfo *pBuf = (STwaInfo *)pCtx->aOutputBuf;
char * indicator = pCtx->aInputElemBuf;
@@ -3885,16 +3804,16 @@ static void twa_func_merge(SQLFunctionCtx *pCtx) {
*/
void twa_function_copy(SQLFunctionCtx *pCtx) {
assert(pCtx->inputType == TSDB_DATA_TYPE_BINARY);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
- memcpy(pResInfo->interResultBuf, pCtx->aInputElemBuf, (size_t)pCtx->inputBytes);
+ memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->aInputElemBuf, (size_t)pCtx->inputBytes);
pResInfo->hasResult = ((STwaInfo *)pCtx->aInputElemBuf)->hasResult;
}
void twa_function_finalizer(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
- STwaInfo *pInfo = (STwaInfo *)pResInfo->interResultBuf;
+ STwaInfo *pInfo = (STwaInfo *)GET_ROWCELL_INTERBUF(pResInfo);
assert(pInfo->EKey >= pInfo->lastKey && pInfo->hasResult == pResInfo->hasResult);
if (pInfo->hasResult != DATA_SET_FLAG) {
@@ -3922,8 +3841,8 @@ void twa_function_finalizer(SQLFunctionCtx *pCtx) {
*/
static void interp_function(SQLFunctionCtx *pCtx) {
// at this point, the value is existed, return directly
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- SInterpInfoDetail* pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SInterpInfoDetail* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
if (pCtx->size == 1) {
char *pData = GET_INPUT_CHAR(pCtx);
@@ -3977,7 +3896,7 @@ static void interp_function(SQLFunctionCtx *pCtx) {
if (isNull(data1, srcType) || isNull(data2, srcType)) {
setNull(pCtx->aOutputBuf, srcType, pCtx->inputBytes);
} else {
- taosDoLinearInterpolation(pCtx->outputType, &point1, &point2, &point);
+ taosGetLinearInterpolationVal(pCtx->outputType, &point1, &point2, &point);
}
} else if (srcType == TSDB_DATA_TYPE_FLOAT) {
point1.val = data1;
@@ -3986,7 +3905,7 @@ static void interp_function(SQLFunctionCtx *pCtx) {
if (isNull(data1, srcType) || isNull(data2, srcType)) {
setNull(pCtx->aOutputBuf, srcType, pCtx->inputBytes);
} else {
- taosDoLinearInterpolation(pCtx->outputType, &point1, &point2, &point);
+ taosGetLinearInterpolationVal(pCtx->outputType, &point1, &point2, &point);
}
} else {
@@ -3998,7 +3917,6 @@ static void interp_function(SQLFunctionCtx *pCtx) {
}
}
}
-
}
SET_VAL(pCtx, pCtx->size, 1);
@@ -4009,8 +3927,8 @@ static bool ts_comp_function_setup(SQLFunctionCtx *pCtx) {
return false; // not initialized since it has been initialized
}
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- STSCompInfo *pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ STSCompInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
pInfo->pTSBuf = tsBufCreate(false, pCtx->order);
pInfo->pTSBuf->tsOrder = pCtx->order;
@@ -4018,18 +3936,18 @@ static bool ts_comp_function_setup(SQLFunctionCtx *pCtx) {
}
static void ts_comp_function(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- STSBuf * pTSbuf = ((STSCompInfo *)(pResInfo->interResultBuf))->pTSBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ STSBuf * pTSbuf = ((STSCompInfo *)(GET_ROWCELL_INTERBUF(pResInfo)))->pTSBuf;
const char *input = GET_INPUT_CHAR(pCtx);
// primary ts must be existed, so no need to check its existance
if (pCtx->order == TSDB_ORDER_ASC) {
- tsBufAppend(pTSbuf, 0, &pCtx->tag, input, pCtx->size * TSDB_KEYSIZE);
+ tsBufAppend(pTSbuf, (int32_t)pCtx->param[0].i64Key, &pCtx->tag, input, pCtx->size * TSDB_KEYSIZE);
} else {
for (int32_t i = pCtx->size - 1; i >= 0; --i) {
char *d = GET_INPUT_CHAR_INDEX(pCtx, i);
- tsBufAppend(pTSbuf, 0, &pCtx->tag, d, TSDB_KEYSIZE);
+ tsBufAppend(pTSbuf, (int32_t)pCtx->param[0].i64Key, &pCtx->tag, d, (int32_t)TSDB_KEYSIZE);
}
}
@@ -4043,21 +3961,21 @@ static void ts_comp_function_f(SQLFunctionCtx *pCtx, int32_t index) {
return;
}
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- STSCompInfo *pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ STSCompInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
STSBuf *pTSbuf = pInfo->pTSBuf;
- tsBufAppend(pTSbuf, 0, &pCtx->tag, pData, TSDB_KEYSIZE);
+ tsBufAppend(pTSbuf, (int32_t)pCtx->param[0].i64Key, &pCtx->tag, pData, TSDB_KEYSIZE);
SET_VAL(pCtx, pCtx->size, 1);
pResInfo->hasResult = DATA_SET_FLAG;
}
static void ts_comp_finalize(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
- STSCompInfo *pInfo = pResInfo->interResultBuf;
+ STSCompInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
STSBuf * pTSbuf = pInfo->pTSBuf;
tsBufFlush(pTSbuf);
@@ -4106,8 +4024,8 @@ static bool rate_function_setup(SQLFunctionCtx *pCtx) {
return false;
}
- SResultInfo *pResInfo = GET_RES_INFO(pCtx); //->aOutputBuf + pCtx->outputBytes;
- SRateInfo * pInfo = pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); //->aOutputBuf + pCtx->outputBytes;
+ SRateInfo * pInfo = GET_ROWCELL_INTERBUF(pResInfo);
pInfo->CorrectionValue = 0;
pInfo->firstKey = INT64_MIN;
@@ -4126,8 +4044,8 @@ static bool rate_function_setup(SQLFunctionCtx *pCtx) {
static void rate_function(SQLFunctionCtx *pCtx) {
int32_t notNullElems = 0;
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- SRateInfo *pRateInfo = (SRateInfo *)pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SRateInfo *pRateInfo = (SRateInfo *)GET_ROWCELL_INTERBUF(pResInfo);
TSKEY *primaryKey = pCtx->ptsList;
tscDebug("%p rate_function() size:%d, hasNull:%d", pCtx, pCtx->size, pCtx->hasNull);
@@ -4142,22 +4060,7 @@ static void rate_function(SQLFunctionCtx *pCtx) {
notNullElems++;
int64_t v = 0;
- switch (pCtx->inputType) {
- case TSDB_DATA_TYPE_TINYINT:
- v = (int64_t)GET_INT8_VAL(pData);
- break;
- case TSDB_DATA_TYPE_SMALLINT:
- v = (int64_t)GET_INT16_VAL(pData);
- break;
- case TSDB_DATA_TYPE_INT:
- v = (int64_t)GET_INT32_VAL(pData);
- break;
- case TSDB_DATA_TYPE_BIGINT:
- v = (int64_t)GET_INT64_VAL(pData);
- break;
- default:
- assert(0);
- }
+ GET_TYPED_DATA(v, int64_t, pCtx->inputType, pData);
if ((INT64_MIN == pRateInfo->firstValue) || (INT64_MIN == pRateInfo->firstKey)) {
pRateInfo->firstValue = v;
@@ -4190,8 +4093,8 @@ static void rate_function(SQLFunctionCtx *pCtx) {
}
// keep the data into the final output buffer for super table query since this execution may be the last one
- if (pResInfo->superTableQ) {
- memcpy(pCtx->aOutputBuf, pResInfo->interResultBuf, sizeof(SRateInfo));
+ if (pCtx->stableQuery) {
+ memcpy(pCtx->aOutputBuf, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SRateInfo));
}
}
@@ -4202,27 +4105,12 @@ static void rate_function_f(SQLFunctionCtx *pCtx, int32_t index) {
}
// NOTE: keep the intermediate result into the interResultBuf
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- SRateInfo *pRateInfo = (SRateInfo *)pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SRateInfo *pRateInfo = (SRateInfo *)GET_ROWCELL_INTERBUF(pResInfo);
TSKEY *primaryKey = pCtx->ptsList;
int64_t v = 0;
- switch (pCtx->inputType) {
- case TSDB_DATA_TYPE_TINYINT:
- v = (int64_t)GET_INT8_VAL(pData);
- break;
- case TSDB_DATA_TYPE_SMALLINT:
- v = (int64_t)GET_INT16_VAL(pData);
- break;
- case TSDB_DATA_TYPE_INT:
- v = (int64_t)GET_INT32_VAL(pData);
- break;
- case TSDB_DATA_TYPE_BIGINT:
- v = (int64_t)GET_INT64_VAL(pData);
- break;
- default:
- assert(0);
- }
+ GET_TYPED_DATA(v, int64_t, pCtx->inputType, pData);
if ((INT64_MIN == pRateInfo->firstValue) || (INT64_MIN == pRateInfo->firstKey)) {
pRateInfo->firstValue = v;
@@ -4247,20 +4135,18 @@ static void rate_function_f(SQLFunctionCtx *pCtx, int32_t index) {
pResInfo->hasResult = DATA_SET_FLAG;
// keep the data into the final output buffer for super table query since this execution may be the last one
- if (pResInfo->superTableQ) {
- memcpy(pCtx->aOutputBuf, pResInfo->interResultBuf, sizeof(SRateInfo));
+ if (pCtx->stableQuery) {
+ memcpy(pCtx->aOutputBuf, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SRateInfo));
}
}
static void rate_func_merge(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- assert(pResInfo->superTableQ);
+ assert(pCtx->stableQuery);
tscDebug("rate_func_merge() size:%d", pCtx->size);
- //SRateInfo *pRateInfo = (SRateInfo *)pResInfo->interResultBuf;
SRateInfo *pBuf = (SRateInfo *)pCtx->aOutputBuf;
char *indicator = pCtx->aInputElemBuf;
@@ -4293,8 +4179,8 @@ static void rate_func_merge(SQLFunctionCtx *pCtx) {
static void rate_func_copy(SQLFunctionCtx *pCtx) {
assert(pCtx->inputType == TSDB_DATA_TYPE_BINARY);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- memcpy(pResInfo->interResultBuf, pCtx->aInputElemBuf, (size_t)pCtx->inputBytes);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->aInputElemBuf, (size_t)pCtx->inputBytes);
pResInfo->hasResult = ((SRateInfo*)pCtx->aInputElemBuf)->hasResult;
SRateInfo* pRateInfo = (SRateInfo*)pCtx->aInputElemBuf;
@@ -4305,8 +4191,8 @@ static void rate_func_copy(SQLFunctionCtx *pCtx) {
static void rate_finalizer(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- SRateInfo *pRateInfo = (SRateInfo *)pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SRateInfo *pRateInfo = (SRateInfo *)GET_ROWCELL_INTERBUF(pResInfo);
tscDebug("%p isIRate:%d firstKey:%" PRId64 " lastKey:%" PRId64 " firstValue:%" PRId64 " lastValue:%" PRId64 " CorrectionValue:%" PRId64 " hasResult:%d",
pCtx, pRateInfo->isIRate, pRateInfo->firstKey, pRateInfo->lastKey, pRateInfo->firstValue, pRateInfo->lastValue, pRateInfo->CorrectionValue, pRateInfo->hasResult);
@@ -4331,8 +4217,8 @@ static void rate_finalizer(SQLFunctionCtx *pCtx) {
static void irate_function(SQLFunctionCtx *pCtx) {
int32_t notNullElems = 0;
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- SRateInfo *pRateInfo = (SRateInfo *)pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SRateInfo *pRateInfo = (SRateInfo *)GET_ROWCELL_INTERBUF(pResInfo);
TSKEY *primaryKey = pCtx->ptsList;
tscDebug("%p irate_function() size:%d, hasNull:%d", pCtx, pCtx->size, pCtx->hasNull);
@@ -4351,22 +4237,7 @@ static void irate_function(SQLFunctionCtx *pCtx) {
notNullElems++;
int64_t v = 0;
- switch (pCtx->inputType) {
- case TSDB_DATA_TYPE_TINYINT:
- v = (int64_t)GET_INT8_VAL(pData);
- break;
- case TSDB_DATA_TYPE_SMALLINT:
- v = (int64_t)GET_INT16_VAL(pData);
- break;
- case TSDB_DATA_TYPE_INT:
- v = (int64_t)GET_INT32_VAL(pData);
- break;
- case TSDB_DATA_TYPE_BIGINT:
- v = (int64_t)GET_INT64_VAL(pData);
- break;
- default:
- assert(0);
- }
+ GET_TYPED_DATA(v, int64_t, pCtx->inputType, pData);
// TODO: calc once if only call this function once ????
if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->lastValue)) {
@@ -4394,8 +4265,8 @@ static void irate_function(SQLFunctionCtx *pCtx) {
}
// keep the data into the final output buffer for super table query since this execution may be the last one
- if (pResInfo->superTableQ) {
- memcpy(pCtx->aOutputBuf, pResInfo->interResultBuf, sizeof(SRateInfo));
+ if (pCtx->stableQuery) {
+ memcpy(pCtx->aOutputBuf, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SRateInfo));
}
}
@@ -4406,28 +4277,13 @@ static void irate_function_f(SQLFunctionCtx *pCtx, int32_t index) {
}
// NOTE: keep the intermediate result into the interResultBuf
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- SRateInfo *pRateInfo = (SRateInfo *)pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SRateInfo *pRateInfo = (SRateInfo *)GET_ROWCELL_INTERBUF(pResInfo);
TSKEY *primaryKey = pCtx->ptsList;
int64_t v = 0;
- switch (pCtx->inputType) {
- case TSDB_DATA_TYPE_TINYINT:
- v = (int64_t)GET_INT8_VAL(pData);
- break;
- case TSDB_DATA_TYPE_SMALLINT:
- v = (int64_t)GET_INT16_VAL(pData);
- break;
- case TSDB_DATA_TYPE_INT:
- v = (int64_t)GET_INT32_VAL(pData);
- break;
- case TSDB_DATA_TYPE_BIGINT:
- v = (int64_t)GET_INT64_VAL(pData);
- break;
- default:
- assert(0);
- }
-
+ GET_TYPED_DATA(v, int64_t, pCtx->inputType, pData);
+
pRateInfo->firstKey = pRateInfo->lastKey;
pRateInfo->firstValue = pRateInfo->lastValue;
@@ -4443,16 +4299,16 @@ static void irate_function_f(SQLFunctionCtx *pCtx, int32_t index) {
pResInfo->hasResult = DATA_SET_FLAG;
// keep the data into the final output buffer for super table query since this execution may be the last one
- if (pResInfo->superTableQ) {
- memcpy(pCtx->aOutputBuf, pResInfo->interResultBuf, sizeof(SRateInfo));
+ if (pCtx->stableQuery) {
+ memcpy(pCtx->aOutputBuf, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SRateInfo));
}
}
static void do_sumrate_merge(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- assert(pResInfo->superTableQ);
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ assert(pCtx->stableQuery);
- SRateInfo *pRateInfo = (SRateInfo *)pResInfo->interResultBuf;
+ SRateInfo *pRateInfo = (SRateInfo *)GET_ROWCELL_INTERBUF(pResInfo);
char * input = GET_INPUT_CHAR(pCtx);
for (int32_t i = 0; i < pCtx->size; ++i, input += pCtx->inputBytes) {
@@ -4476,7 +4332,7 @@ static void do_sumrate_merge(SQLFunctionCtx *pCtx) {
if (DATA_SET_FLAG == pRateInfo->hasResult) {
pResInfo->hasResult = DATA_SET_FLAG;
SET_VAL(pCtx, pRateInfo->num, 1);
- memcpy(pCtx->aOutputBuf, pResInfo->interResultBuf, sizeof(SRateInfo));
+ memcpy(pCtx->aOutputBuf, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SRateInfo));
}
}
@@ -4491,10 +4347,10 @@ static void sumrate_func_second_merge(SQLFunctionCtx *pCtx) {
}
static void sumrate_finalizer(SQLFunctionCtx *pCtx) {
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- SRateInfo *pRateInfo = (SRateInfo *)pResInfo->interResultBuf;
+ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
+ SRateInfo *pRateInfo = (SRateInfo *)GET_ROWCELL_INTERBUF(pResInfo);
- tscDebug("%p sumrate_finalizer() superTableQ:%d num:%" PRId64 " sum:%f hasResult:%d", pCtx, pResInfo->superTableQ, pRateInfo->num, pRateInfo->sum, pRateInfo->hasResult);
+ tscDebug("%p sumrate_finalizer() superTableQ:%d num:%" PRId64 " sum:%f hasResult:%d", pCtx, pCtx->stableQuery, pRateInfo->num, pRateInfo->sum, pRateInfo->hasResult);
if (pRateInfo->hasResult != DATA_SET_FLAG) {
setNull(pCtx->aOutputBuf, TSDB_DATA_TYPE_DOUBLE, sizeof(double));
diff --git a/src/client/src/tscLocal.c b/src/client/src/tscLocal.c
index b4c3f3549b1576b3ff83300d4f10d9e07778530d..538e652f3c6577098363565a4e76fa637b60709c 100644
--- a/src/client/src/tscLocal.c
+++ b/src/client/src/tscLocal.c
@@ -49,82 +49,6 @@ typedef struct SCreateBuilder {
} SCreateBuilder;
static void tscSetLocalQueryResult(SSqlObj *pSql, const char *val, const char *columnName, int16_t type, size_t valueLength);
-static int32_t getToStringLength(const char *pData, int32_t length, int32_t type) {
- char buf[512] = {0};
-
- int32_t len = 0;
- int32_t MAX_BOOL_TYPE_LENGTH = 5; // max(strlen("true"), strlen("false"));
- switch (type) {
- case TSDB_DATA_TYPE_BINARY:
- return length;
- case TSDB_DATA_TYPE_NCHAR:
- return length;
- case TSDB_DATA_TYPE_DOUBLE: {
- double dv = 0;
- dv = GET_DOUBLE_VAL(pData);
- len = sprintf(buf, "%lf", dv);
- if (strncasecmp("nan", buf, 3) == 0) {
- len = 4;
- }
- } break;
- case TSDB_DATA_TYPE_FLOAT: {
- float fv = 0;
- fv = GET_FLOAT_VAL(pData);
- len = sprintf(buf, "%f", fv);
- if (strncasecmp("nan", buf, 3) == 0) {
- len = 4;
- }
- } break;
- case TSDB_DATA_TYPE_TIMESTAMP:
- case TSDB_DATA_TYPE_BIGINT:
- len = sprintf(buf, "%" PRId64, *(int64_t *)pData);
- break;
- case TSDB_DATA_TYPE_BOOL:
- len = MAX_BOOL_TYPE_LENGTH;
- break;
- default:
- len = sprintf(buf, "%d", *(int32_t *)pData);
- break;
- };
- return len;
-}
-
-/*
- * we need to convert all data into string, so we need to sprintf all kinds of
- * non-string data into string, and record its length to get the right
- * maximum length. The length may be less or greater than its original binary length:
- * For example:
- * length((short) 1) == 1, less than sizeof(short)
- * length((uint64_t) 123456789011) > 12, greater than sizsof(uint64_t)
- */
-static int32_t tscMaxLengthOfTagsFields(SSqlObj *pSql) {
- STableMeta *pMeta = tscGetTableMetaInfoFromCmd(&pSql->cmd, 0, 0)->pTableMeta;
-
- if (pMeta->tableType == TSDB_SUPER_TABLE || pMeta->tableType == TSDB_NORMAL_TABLE ||
- pMeta->tableType == TSDB_STREAM_TABLE) {
- return 0;
- }
-
- char * pTagValue = tsGetTagsValue(pMeta);
- SSchema *pTagsSchema = tscGetTableTagSchema(pMeta);
-
- int32_t len = getToStringLength(pTagValue, pTagsSchema[0].bytes, pTagsSchema[0].type);
-
- pTagValue += pTagsSchema[0].bytes;
- int32_t numOfTags = tscGetNumOfTags(pMeta);
-
- for (int32_t i = 1; i < numOfTags; ++i) {
- int32_t tLen = getToStringLength(pTagValue, pTagsSchema[i].bytes, pTagsSchema[i].type);
- if (len < tLen) {
- len = tLen;
- }
-
- pTagValue += pTagsSchema[i].bytes;
- }
-
- return len;
-}
-
static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) {
SSqlRes *pRes = &pSql->res;
@@ -186,8 +110,7 @@ static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) {
return 0;
}
- // the following is handle display tags value for meters created according to metric
- char *pTagValue = tsGetTagsValue(pMeta);
+ // the following is handle display tags for table created according to super table
for (int32_t i = numOfRows; i < totalNumOfRows; ++i) {
// field name
TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 0);
@@ -219,8 +142,6 @@ static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) {
char *target = pRes->data + tscFieldInfoGetOffset(pQueryInfo, 3) * totalNumOfRows + pField->bytes * i;
const char *src = "TAG";
STR_WITH_MAXSIZE_TO_VARSTR(target, src, pField->bytes);
-
- pTagValue += pSchema[i].bytes;
}
return 0;
@@ -241,7 +162,7 @@ static int32_t tscBuildTableSchemaResultFields(SSqlObj *pSql, int32_t numOfCols,
SInternalField* pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY,
- (TSDB_COL_NAME_LEN - 1) + VARSTR_HEADER_SIZE, (TSDB_COL_NAME_LEN - 1), false);
+ (TSDB_COL_NAME_LEN - 1) + VARSTR_HEADER_SIZE, -1000, (TSDB_COL_NAME_LEN - 1), false);
rowLen += ((TSDB_COL_NAME_LEN - 1) + VARSTR_HEADER_SIZE);
@@ -251,7 +172,7 @@ static int32_t tscBuildTableSchemaResultFields(SSqlObj *pSql, int32_t numOfCols,
pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, (int16_t)(typeColLength + VARSTR_HEADER_SIZE),
- typeColLength, false);
+ -1000, typeColLength, false);
rowLen += typeColLength + VARSTR_HEADER_SIZE;
@@ -261,7 +182,7 @@ static int32_t tscBuildTableSchemaResultFields(SSqlObj *pSql, int32_t numOfCols,
pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_INT, sizeof(int32_t),
- sizeof(int32_t), false);
+ -1000, sizeof(int32_t), false);
rowLen += sizeof(int32_t);
@@ -271,7 +192,7 @@ static int32_t tscBuildTableSchemaResultFields(SSqlObj *pSql, int32_t numOfCols,
pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, (int16_t)(noteColLength + VARSTR_HEADER_SIZE),
- noteColLength, false);
+ -1000, noteColLength, false);
rowLen += noteColLength + VARSTR_HEADER_SIZE;
return rowLen;
@@ -286,10 +207,10 @@ static int32_t tscProcessDescribeTable(SSqlObj *pSql) {
const int32_t TYPE_COLUMN_LENGTH = 16;
const int32_t NOTE_COLUMN_MIN_LENGTH = 8;
- int32_t noteFieldLen = tscMaxLengthOfTagsFields(pSql);
- if (noteFieldLen == 0) {
- noteFieldLen = NOTE_COLUMN_MIN_LENGTH;
- }
+ int32_t noteFieldLen = NOTE_COLUMN_MIN_LENGTH;//tscMaxLengthOfTagsFields(pSql);
+// if (noteFieldLen == 0) {
+// noteFieldLen = NOTE_COLUMN_MIN_LENGTH;
+// }
int32_t rowLen = tscBuildTableSchemaResultFields(pSql, NUM_OF_DESC_TABLE_COLUMNS, TYPE_COLUMN_LENGTH, noteFieldLen);
tscFieldInfoUpdateOffset(pQueryInfo);
@@ -420,7 +341,7 @@ TAOS_ROW tscFetchRow(void *param) {
return NULL;
}
- void* data = doSetResultRowData(pSql, true);
+ void* data = doSetResultRowData(pSql);
tscClearSqlOwner(pSql);
return data;
@@ -486,8 +407,7 @@ static int32_t tscSCreateBuildResultFields(SSqlObj *pSql, BuildType type, const
}
SInternalField* pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
- pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY,
- f.bytes, f.bytes - VARSTR_HEADER_SIZE, false);
+ pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, f.bytes, -1000, f.bytes - VARSTR_HEADER_SIZE, false);
rowLen += f.bytes;
@@ -501,7 +421,7 @@ static int32_t tscSCreateBuildResultFields(SSqlObj *pSql, BuildType type, const
pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY,
- (int16_t)(ddlLen + VARSTR_HEADER_SIZE), ddlLen, false);
+ (int16_t)(ddlLen + VARSTR_HEADER_SIZE), -1000, ddlLen, false);
rowLen += ddlLen + VARSTR_HEADER_SIZE;
@@ -698,7 +618,11 @@ static int32_t tscRebuildDDLForNormalTable(SSqlObj *pSql, const char *tableName,
for (int32_t i = 0; i < numOfRows; ++i) {
uint8_t type = pSchema[i].type;
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
- snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s %s(%d),", pSchema[i].name,tDataTypeDesc[pSchema[i].type].aName,pSchema->bytes);
+ int32_t bytes = pSchema[i].bytes - VARSTR_HEADER_SIZE;
+ if (type == TSDB_DATA_TYPE_NCHAR) {
+ bytes = bytes/TSDB_NCHAR_SIZE;
+ }
+ snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s %s(%d),", pSchema[i].name, tDataTypeDesc[pSchema[i].type].aName, bytes);
} else {
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s %s,", pSchema[i].name, tDataTypeDesc[pSchema[i].type].aName);
}
@@ -721,7 +645,11 @@ static int32_t tscRebuildDDLForSuperTable(SSqlObj *pSql, const char *tableName,
for (int32_t i = 0; i < numOfRows; ++i) {
uint8_t type = pSchema[i].type;
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
- snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result),"%s %s(%d),", pSchema[i].name,tDataTypeDesc[pSchema[i].type].aName,pSchema->bytes);
+ int32_t bytes = pSchema[i].bytes - VARSTR_HEADER_SIZE;
+ if (type == TSDB_DATA_TYPE_NCHAR) {
+ bytes = bytes/TSDB_NCHAR_SIZE;
+ }
+ snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result),"%s %s(%d),", pSchema[i].name,tDataTypeDesc[pSchema[i].type].aName, bytes);
} else {
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s %s,", pSchema[i].name, tDataTypeDesc[type].aName);
}
@@ -731,7 +659,11 @@ static int32_t tscRebuildDDLForSuperTable(SSqlObj *pSql, const char *tableName,
for (int32_t i = numOfRows; i < totalRows; i++) {
uint8_t type = pSchema[i].type;
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
- snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s %s(%d),", pSchema[i].name,tDataTypeDesc[pSchema[i].type].aName,pSchema->bytes);
+ int32_t bytes = pSchema[i].bytes - VARSTR_HEADER_SIZE;
+ if (type == TSDB_DATA_TYPE_NCHAR) {
+ bytes = bytes/TSDB_NCHAR_SIZE;
+ }
+ snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s %s(%d),", pSchema[i].name,tDataTypeDesc[pSchema[i].type].aName, bytes);
} else {
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s %s,", pSchema[i].name, tDataTypeDesc[type].aName);
}
diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c
index 44ccb2471aa980d789c8557aca7981b6981df02f..3c7d46f914dd2632ac97cbcb728898ff9a657e82 100644
--- a/src/client/src/tscLocalMerge.c
+++ b/src/client/src/tscLocalMerge.c
@@ -13,14 +13,15 @@
* along with this program. If not, see .
*/
+#include "tscLocalMerge.h"
+#include "tscSubquery.h"
#include "os.h"
+#include "qAst.h"
#include "tlosertree.h"
+#include "tscLog.h"
#include "tscUtil.h"
#include "tschemautil.h"
#include "tsclient.h"
-#include "tutil.h"
-#include "tscLog.h"
-#include "tscLocalMerge.h"
typedef struct SCompareParam {
SLocalDataSource **pLocalData;
@@ -97,14 +98,14 @@ static void tscInitSqlContext(SSqlCmd *pCmd, SLocalReducer *pReducer, tOrderDesc
pCtx->param[2].i64Key = pQueryInfo->order.order;
pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
pCtx->param[1].i64Key = pQueryInfo->order.orderColId;
+ } else if (functionId == TSDB_FUNC_APERCT) {
+ pCtx->param[0].i64Key = pExpr->param[0].i64Key;
+ pCtx->param[0].nType = pExpr->param[0].nType;
}
- SResultInfo *pResInfo = &pReducer->pResInfo[i];
- pResInfo->bufLen = pExpr->interBytes;
- pResInfo->interResultBuf = calloc(1, (size_t) pResInfo->bufLen);
-
- pCtx->resultInfo = &pReducer->pResInfo[i];
- pCtx->resultInfo->superTableQ = true;
+ pCtx->interBufBytes = pExpr->interBytes;
+ pCtx->resultInfo = calloc(1, pCtx->interBufBytes + sizeof(SResultRowCellInfo));
+ pCtx->stableQuery = true;
}
int16_t n = 0;
@@ -132,40 +133,53 @@ static void tscInitSqlContext(SSqlCmd *pCmd, SLocalReducer *pReducer, tOrderDesc
}
static SFillColInfo* createFillColInfo(SQueryInfo* pQueryInfo) {
- int32_t numOfCols = (int32_t)tscSqlExprNumOfExprs(pQueryInfo);
+ int32_t numOfCols = (int32_t)tscNumOfFields(pQueryInfo);
int32_t offset = 0;
SFillColInfo* pFillCol = calloc(numOfCols, sizeof(SFillColInfo));
for(int32_t i = 0; i < numOfCols; ++i) {
- SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
-
- pFillCol[i].col.bytes = pExpr->resBytes;
- pFillCol[i].col.type = (int8_t)pExpr->resType;
- pFillCol[i].col.colId = pExpr->colInfo.colId;
- pFillCol[i].flag = pExpr->colInfo.flag;
- pFillCol[i].col.offset = offset;
- pFillCol[i].functionId = pExpr->functionId;
- pFillCol[i].fillVal.i = pQueryInfo->fillVal[i];
- offset += pExpr->resBytes;
+ SInternalField* pIField = taosArrayGet(pQueryInfo->fieldsInfo.internalField, i);
+
+ if (pIField->pArithExprInfo == NULL) {
+ SSqlExpr* pExpr = pIField->pSqlExpr;
+
+ pFillCol[i].col.bytes = pExpr->resBytes;
+ pFillCol[i].col.type = (int8_t)pExpr->resType;
+ pFillCol[i].col.colId = pExpr->colInfo.colId;
+ pFillCol[i].flag = pExpr->colInfo.flag;
+ pFillCol[i].col.offset = offset;
+ pFillCol[i].functionId = pExpr->functionId;
+ pFillCol[i].fillVal.i = pQueryInfo->fillVal[i];
+ } else {
+ pFillCol[i].col.bytes = pIField->field.bytes;
+ pFillCol[i].col.type = (int8_t)pIField->field.type;
+ pFillCol[i].col.colId = -100;
+ pFillCol[i].flag = TSDB_COL_NORMAL;
+ pFillCol[i].col.offset = offset;
+ pFillCol[i].functionId = -1;
+ pFillCol[i].fillVal.i = pQueryInfo->fillVal[i];
+ }
+
+ offset += pFillCol[i].col.bytes;
}
return pFillCol;
}
void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrderDescriptor *pDesc,
- SColumnModel *finalmodel, SSqlObj* pSql) {
+ SColumnModel *finalmodel, SColumnModel *pFFModel, SSqlObj* pSql) {
SSqlCmd* pCmd = &pSql->cmd;
SSqlRes* pRes = &pSql->res;
if (pMemBuffer == NULL) {
- tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, numOfBuffer);
+ tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, pFFModel, numOfBuffer);
tscError("%p pMemBuffer is NULL", pMemBuffer);
pRes->code = TSDB_CODE_TSC_APP_ERROR;
return;
}
if (pDesc->pColumnModel == NULL) {
- tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, numOfBuffer);
+ tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, pFFModel, numOfBuffer);
tscError("%p no local buffer or intermediate result format model", pSql);
pRes->code = TSDB_CODE_TSC_APP_ERROR;
return;
@@ -183,7 +197,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
}
if (numOfFlush == 0 || numOfBuffer == 0) {
- tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, numOfBuffer);
+ tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, pFFModel, numOfBuffer);
tscDebug("%p retrieved no data", pSql);
return;
}
@@ -192,7 +206,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
tscError("%p Invalid value of buffer capacity %d and page size %d ", pSql, pDesc->pColumnModel->capacity,
pMemBuffer[0]->pageSize);
- tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, numOfBuffer);
+ tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, pFFModel, numOfBuffer);
pRes->code = TSDB_CODE_TSC_APP_ERROR;
return;
}
@@ -203,7 +217,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
if (pReducer == NULL) {
tscError("%p failed to create local merge structure, out of memory", pSql);
- tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, numOfBuffer);
+ tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, pFFModel, numOfBuffer);
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
return;
}
@@ -227,7 +241,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
if (ds == NULL) {
tscError("%p failed to create merge structure", pSql);
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
- taosTFree(pReducer);
+ tfree(pReducer);
return;
}
@@ -254,7 +268,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
if (ds->filePage.num == 0) { // no data in this flush, the index does not increase
tscDebug("%p flush data is empty, ignore %d flush record", pSql, idx);
- taosTFree(ds);
+ tfree(ds);
continue;
}
@@ -264,7 +278,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
// no data actually, no need to merge result.
if (idx == 0) {
- taosTFree(pReducer);
+ tfree(pReducer);
return;
}
@@ -272,7 +286,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
SCompareParam *param = malloc(sizeof(SCompareParam));
if (param == NULL) {
- taosTFree(pReducer);
+ tfree(pReducer);
return;
}
@@ -286,8 +300,8 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
pRes->code = tLoserTreeCreate(&pReducer->pLoserTree, pReducer->numOfBuffer, param, treeComparator);
if (pReducer->pLoserTree == NULL || pRes->code != 0) {
- taosTFree(param);
- taosTFree(pReducer);
+ tfree(param);
+ tfree(pReducer);
return;
}
@@ -320,6 +334,8 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
pReducer->resColModel = finalmodel;
pReducer->resColModel->capacity = pReducer->nResultBufSize;
+ pReducer->finalModel = pFFModel;
+
assert(pReducer->finalRowSize > 0);
if (pReducer->finalRowSize > 0) {
pReducer->resColModel->capacity /= pReducer->finalRowSize;
@@ -330,22 +346,19 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
if (pReducer->pTempBuffer == NULL || pReducer->discardData == NULL || pReducer->pResultBuf == NULL ||
/*pReducer->pBufForInterpo == NULL || */pReducer->pFinalRes == NULL || pReducer->prevRowOfInput == NULL) {
- taosTFree(pReducer->pTempBuffer);
- taosTFree(pReducer->discardData);
- taosTFree(pReducer->pResultBuf);
- taosTFree(pReducer->pFinalRes);
- taosTFree(pReducer->prevRowOfInput);
- taosTFree(pReducer->pLoserTree);
- taosTFree(param);
- taosTFree(pReducer);
+ tfree(pReducer->pTempBuffer);
+ tfree(pReducer->discardData);
+ tfree(pReducer->pResultBuf);
+ tfree(pReducer->pFinalRes);
+ tfree(pReducer->prevRowOfInput);
+ tfree(pReducer->pLoserTree);
+ tfree(param);
+ tfree(pReducer);
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
return;
}
- size_t numOfCols = tscSqlExprNumOfExprs(pQueryInfo);
-
pReducer->pTempBuffer->num = 0;
- pReducer->pResInfo = calloc(numOfCols, sizeof(SResultInfo));
tscCreateResPointerInfo(pRes, pQueryInfo);
tscInitSqlContext(pCmd, pReducer, pDesc);
@@ -373,8 +386,8 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
if (pQueryInfo->fillType != TSDB_FILL_NONE) {
SFillColInfo* pFillCol = createFillColInfo(pQueryInfo);
pReducer->pFillInfo = taosInitFillInfo(pQueryInfo->order.order, revisedSTime, pQueryInfo->groupbyExpr.numOfGroupCols,
- 4096, (int32_t)numOfCols, pQueryInfo->interval.sliding, pQueryInfo->interval.slidingUnit,
- tinfo.precision, pQueryInfo->fillType, pFillCol);
+ 4096, (int32_t)pQueryInfo->fieldsInfo.numOfOutput, pQueryInfo->interval.sliding, pQueryInfo->interval.slidingUnit,
+ tinfo.precision, pQueryInfo->fillType, pFillCol, pSql);
}
}
@@ -489,47 +502,41 @@ void tscDestroyLocalReducer(SSqlObj *pSql) {
tscDebug("%p waiting for delete procedure, status: %d", pSql, status);
}
- pLocalReducer->pFillInfo = taosDestoryFillInfo(pLocalReducer->pFillInfo);
+ pLocalReducer->pFillInfo = taosDestroyFillInfo(pLocalReducer->pFillInfo);
if (pLocalReducer->pCtx != NULL) {
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
+ int32_t numOfExprs = (int32_t) tscSqlExprNumOfExprs(pQueryInfo);
+ for (int32_t i = 0; i < numOfExprs; ++i) {
SQLFunctionCtx *pCtx = &pLocalReducer->pCtx[i];
tVariantDestroy(&pCtx->tag);
+ tfree(pCtx->resultInfo);
+
if (pCtx->tagInfo.pTagCtxList != NULL) {
- taosTFree(pCtx->tagInfo.pTagCtxList);
+ tfree(pCtx->tagInfo.pTagCtxList);
}
}
- taosTFree(pLocalReducer->pCtx);
+ tfree(pLocalReducer->pCtx);
}
- taosTFree(pLocalReducer->prevRowOfInput);
-
- taosTFree(pLocalReducer->pTempBuffer);
- taosTFree(pLocalReducer->pResultBuf);
+ tfree(pLocalReducer->prevRowOfInput);
- if (pLocalReducer->pResInfo != NULL) {
- size_t num = tscSqlExprNumOfExprs(pQueryInfo);
- for (int32_t i = 0; i < num; ++i) {
- taosTFree(pLocalReducer->pResInfo[i].interResultBuf);
- }
-
- taosTFree(pLocalReducer->pResInfo);
- }
+ tfree(pLocalReducer->pTempBuffer);
+ tfree(pLocalReducer->pResultBuf);
if (pLocalReducer->pLoserTree) {
- taosTFree(pLocalReducer->pLoserTree->param);
- taosTFree(pLocalReducer->pLoserTree);
+ tfree(pLocalReducer->pLoserTree->param);
+ tfree(pLocalReducer->pLoserTree);
}
- taosTFree(pLocalReducer->pFinalRes);
- taosTFree(pLocalReducer->discardData);
+ tfree(pLocalReducer->pFinalRes);
+ tfree(pLocalReducer->discardData);
- tscLocalReducerEnvDestroy(pLocalReducer->pExtMemBuffer, pLocalReducer->pDesc, pLocalReducer->resColModel,
+ tscLocalReducerEnvDestroy(pLocalReducer->pExtMemBuffer, pLocalReducer->pDesc, pLocalReducer->resColModel, pLocalReducer->finalModel,
pLocalReducer->numOfVnode);
for (int32_t i = 0; i < pLocalReducer->numOfBuffer; ++i) {
- taosTFree(pLocalReducer->pLocalDataSrc[i]);
+ tfree(pLocalReducer->pLocalDataSrc[i]);
}
pLocalReducer->numOfBuffer = 0;
@@ -563,7 +570,8 @@ static int32_t createOrderDescriptor(tOrderDescriptor **pOrderDesc, SSqlCmd *pCm
if (numOfGroupByCols > 0) {
if (pQueryInfo->groupbyExpr.numOfGroupCols > 0) {
- int32_t startCols = pQueryInfo->fieldsInfo.numOfOutput - pQueryInfo->groupbyExpr.numOfGroupCols;
+ int32_t numOfInternalOutput = (int32_t) tscSqlExprNumOfExprs(pQueryInfo);
+ int32_t startCols = numOfInternalOutput - pQueryInfo->groupbyExpr.numOfGroupCols;
// the last "pQueryInfo->groupbyExpr.numOfGroupCols" columns are order-by columns
for (int32_t i = 0; i < pQueryInfo->groupbyExpr.numOfGroupCols; ++i) {
@@ -596,7 +604,7 @@ static int32_t createOrderDescriptor(tOrderDescriptor **pOrderDesc, SSqlCmd *pCm
}
*pOrderDesc = tOrderDesCreate(orderColIndexList, numOfGroupByCols, pModel, pQueryInfo->order.order);
- taosTFree(orderColIndexList);
+ tfree(orderColIndexList);
if (*pOrderDesc == NULL) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
@@ -649,7 +657,7 @@ bool isSameGroup(SSqlCmd *pCmd, SLocalReducer *pReducer, char *pPrev, tFilePage
}
int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOrderDescriptor **pOrderDesc,
- SColumnModel **pFinalModel, uint32_t nBufferSizes) {
+ SColumnModel **pFinalModel, SColumnModel** pFFModel, uint32_t nBufferSizes) {
SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res;
@@ -682,6 +690,8 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
pSchema[i].bytes = pExpr->resBytes;
pSchema[i].type = (int8_t)pExpr->resType;
+ tstrncpy(pSchema[i].name, pExpr->aliasName, tListLen(pSchema[i].name));
+
rlen += pExpr->resBytes;
}
@@ -698,7 +708,8 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
pg *= 2;
}
- size_t numOfSubs = pTableMetaInfo->vgroupList->numOfVgroups;
+ size_t numOfSubs = pSql->subState.numOfSub;
+ assert(numOfSubs <= pTableMetaInfo->vgroupList->numOfVgroups);
for (int32_t i = 0; i < numOfSubs; ++i) {
(*pMemBuffer)[i] = createExtMemBuffer(nBufferSizes, rlen, pg, pModel);
(*pMemBuffer)[i]->flushModel = MULTIPLE_APPEND_MODEL;
@@ -706,7 +717,7 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
if (createOrderDescriptor(pOrderDesc, pCmd, pModel) != TSDB_CODE_SUCCESS) {
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
- taosTFree(pSchema);
+ tfree(pSchema);
return pRes->code;
}
@@ -743,8 +754,20 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
}
*pFinalModel = createColumnModel(pSchema, (int32_t)size, capacity);
- taosTFree(pSchema);
+ memset(pSchema, 0, sizeof(SSchema) * size);
+ size = tscNumOfFields(pQueryInfo);
+
+ for(int32_t i = 0; i < size; ++i) {
+ SInternalField* pField = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i);
+ pSchema[i].bytes = pField->field.bytes;
+ pSchema[i].type = pField->field.type;
+ tstrncpy(pSchema[i].name, pField->field.name, tListLen(pSchema[i].name));
+ }
+
+ *pFFModel = createColumnModel(pSchema, (int32_t) size, capacity);
+
+ tfree(pSchema);
return TSDB_CODE_SUCCESS;
}
@@ -754,16 +777,18 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
* @param pFinalModel
* @param numOfVnodes
*/
-void tscLocalReducerEnvDestroy(tExtMemBuffer **pMemBuffer, tOrderDescriptor *pDesc, SColumnModel *pFinalModel,
+void tscLocalReducerEnvDestroy(tExtMemBuffer **pMemBuffer, tOrderDescriptor *pDesc, SColumnModel *pFinalModel, SColumnModel *pFFModel,
int32_t numOfVnodes) {
destroyColumnModel(pFinalModel);
+ destroyColumnModel(pFFModel);
+
tOrderDescDestroy(pDesc);
for (int32_t i = 0; i < numOfVnodes; ++i) {
pMemBuffer[i] = destoryExtMemBuffer(pMemBuffer[i]);
}
- taosTFree(pMemBuffer);
+ tfree(pMemBuffer);
}
/**
@@ -859,17 +884,17 @@ static void genFinalResWithoutFill(SSqlRes* pRes, SLocalReducer *pLocalReducer,
tFilePage * pBeforeFillData = pLocalReducer->pResultBuf;
pRes->data = pLocalReducer->pFinalRes;
- pRes->numOfRows = pBeforeFillData->num;
+ pRes->numOfRows = (int32_t) pBeforeFillData->num;
if (pQueryInfo->limit.offset > 0) {
if (pQueryInfo->limit.offset < pRes->numOfRows) {
- int32_t prevSize = (int32_t)pBeforeFillData->num;
- tColModelErase(pLocalReducer->resColModel, pBeforeFillData, prevSize, 0, (int32_t)pQueryInfo->limit.offset - 1);
+ int32_t prevSize = (int32_t) pBeforeFillData->num;
+ tColModelErase(pLocalReducer->finalModel, pBeforeFillData, prevSize, 0, (int32_t)pQueryInfo->limit.offset - 1);
/* remove the hole in column model */
- tColModelCompact(pLocalReducer->resColModel, pBeforeFillData, prevSize);
+ tColModelCompact(pLocalReducer->finalModel, pBeforeFillData, prevSize);
- pRes->numOfRows -= pQueryInfo->limit.offset;
+ pRes->numOfRows -= (int32_t) pQueryInfo->limit.offset;
pQueryInfo->limit.offset = 0;
} else {
pQueryInfo->limit.offset -= pRes->numOfRows;
@@ -889,7 +914,7 @@ static void genFinalResWithoutFill(SSqlRes* pRes, SLocalReducer *pLocalReducer,
pRes->numOfRows -= overflow;
pBeforeFillData->num -= overflow;
- tColModelCompact(pLocalReducer->resColModel, pBeforeFillData, prevSize);
+ tColModelCompact(pLocalReducer->finalModel, pBeforeFillData, prevSize);
// set remain data to be discarded, and reset the interpolation information
savePrevRecordAndSetupFillInfo(pLocalReducer, pQueryInfo, pLocalReducer->pFillInfo);
@@ -923,7 +948,7 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO
}
while (1) {
- int64_t newRows = taosGenerateDataBlock(pFillInfo, pResPages, pLocalReducer->resColModel->capacity);
+ int64_t newRows = taosFillResultDataBlock(pFillInfo, pResPages, pLocalReducer->resColModel->capacity);
if (pQueryInfo->limit.offset < newRows) {
newRows -= pQueryInfo->limit.offset;
@@ -937,7 +962,7 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO
}
pRes->data = pLocalReducer->pFinalRes;
- pRes->numOfRows = newRows;
+ pRes->numOfRows = (int32_t) newRows;
pQueryInfo->limit.offset = 0;
break;
@@ -952,7 +977,7 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO
}
// all output in current group are completed
- int32_t totalRemainRows = (int32_t)getFilledNumOfRes(pFillInfo, actualETime, pLocalReducer->resColModel->capacity);
+ int32_t totalRemainRows = (int32_t)getNumOfResWithFill(pFillInfo, actualETime, pLocalReducer->resColModel->capacity);
if (totalRemainRows <= 0) {
break;
}
@@ -973,10 +998,11 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO
savePrevRecordAndSetupFillInfo(pLocalReducer, pQueryInfo, pFillInfo);
}
+ int32_t offset = 0;
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
- int16_t offset = getColumnModelOffset(pLocalReducer->resColModel, i);
memcpy(pRes->data + offset * pRes->numOfRows, pResPages[i]->data, (size_t)(pField->bytes * pRes->numOfRows));
+ offset += pField->bytes;
}
pRes->numOfRowsGroup += pRes->numOfRows;
@@ -985,10 +1011,10 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO
pBeforeFillData->num = 0;
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
- taosTFree(pResPages[i]);
+ tfree(pResPages[i]);
}
- taosTFree(pResPages);
+ tfree(pResPages);
}
static void savePreviousRow(SLocalReducer *pLocalReducer, tFilePage *tmpBuffer) {
@@ -1071,7 +1097,7 @@ static int64_t getNumOfResultLocal(SQueryInfo *pQueryInfo, SQLFunctionCtx *pCtx)
continue;
}
- SResultInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
+ SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
if (maxOutput < pResInfo->numOfRes) {
maxOutput = pResInfo->numOfRes;
}
@@ -1229,6 +1255,10 @@ bool genFinalResults(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool noMoreCur
tColModelCompact(pModel, pResBuf, pModel->capacity);
+ if (tscIsSecondStageQuery(pQueryInfo)) {
+ pLocalReducer->finalRowSize = doArithmeticCalculate(pQueryInfo, pResBuf, pModel->rowSize, pLocalReducer->finalRowSize);
+ }
+
#ifdef _DEBUG_VIEW
printf("final result before interpo:\n");
// tColModelDisplay(pLocalReducer->resColModel, pLocalReducer->pBufForInterpo, pResBuf->num, pResBuf->num);
@@ -1252,10 +1282,11 @@ bool genFinalResults(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool noMoreCur
return true;
}
-void resetOutputBuf(SQueryInfo *pQueryInfo, SLocalReducer *pLocalReducer) { // reset output buffer to the beginning
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
- pLocalReducer->pCtx[i].aOutputBuf =
- pLocalReducer->pResultBuf->data + tscFieldInfoGetOffset(pQueryInfo, i) * pLocalReducer->resColModel->capacity;
+void resetOutputBuf(SQueryInfo *pQueryInfo, SLocalReducer *pLocalReducer) {// reset output buffer to the beginning
+ size_t t = tscSqlExprNumOfExprs(pQueryInfo);
+ for (int32_t i = 0; i < t; ++i) {
+ SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
+ pLocalReducer->pCtx[i].aOutputBuf = pLocalReducer->pResultBuf->data + pExpr->offset * pLocalReducer->resColModel->capacity;
}
memset(pLocalReducer->pResultBuf, 0, pLocalReducer->nResultBufSize + sizeof(tFilePage));
@@ -1300,7 +1331,7 @@ static bool doBuildFilledResultForGroup(SSqlObj *pSql) {
int64_t etime = *(int64_t *)(pFinalDataBuf->data + TSDB_KEYSIZE * (pFillInfo->numOfRows - 1));
// the first column must be the timestamp column
- int32_t rows = (int32_t)getFilledNumOfRes(pFillInfo, etime, pLocalReducer->resColModel->capacity);
+ int32_t rows = (int32_t) getNumOfResWithFill(pFillInfo, etime, pLocalReducer->resColModel->capacity);
if (rows > 0) { // do fill gap
doFillResult(pSql, pLocalReducer, false);
}
@@ -1329,7 +1360,7 @@ static bool doHandleLastRemainData(SSqlObj *pSql) {
((pRes->numOfRowsGroup < pQueryInfo->limit.limit && pQueryInfo->limit.limit > 0) || (pQueryInfo->limit.limit < 0))) {
int64_t etime = (pQueryInfo->order.order == TSDB_ORDER_ASC)? pQueryInfo->window.ekey : pQueryInfo->window.skey;
- int32_t rows = (int32_t)getFilledNumOfRes(pFillInfo, etime, pLocalReducer->resColModel->capacity);
+ int32_t rows = (int32_t)getNumOfResWithFill(pFillInfo, etime, pLocalReducer->resColModel->capacity);
if (rows > 0) {
doFillResult(pSql, pLocalReducer, true);
}
@@ -1500,8 +1531,7 @@ int32_t tscDoLocalMerge(SSqlObj *pSql) {
if (pLocalReducer->discard && sameGroup) {
pLocalReducer->hasUnprocessedRow = false;
tmpBuffer->num = 0;
- } else {
- // current row does not belongs to the previous group, so it is not be handled yet.
+ } else { // current row does not belongs to the previous group, so it is not be handled yet.
pLocalReducer->hasUnprocessedRow = true;
}
@@ -1595,3 +1625,46 @@ void tscInitResObjForLocalQuery(SSqlObj *pObj, int32_t numOfRes, int32_t rowLen)
pRes->pLocalReducer->pResultBuf->num = numOfRes;
pRes->data = pRes->pLocalReducer->pResultBuf->data;
}
+
+int32_t doArithmeticCalculate(SQueryInfo* pQueryInfo, tFilePage* pOutput, int32_t rowSize, int32_t finalRowSize) {
+ char* pbuf = calloc(1, pOutput->num * rowSize);
+
+ size_t size = tscNumOfFields(pQueryInfo);
+ SArithmeticSupport arithSup = {0};
+
+ // todo refactor
+ arithSup.offset = 0;
+ arithSup.numOfCols = (int32_t) tscSqlExprNumOfExprs(pQueryInfo);
+ arithSup.exprList = pQueryInfo->exprList;
+ arithSup.data = calloc(arithSup.numOfCols, POINTER_BYTES);
+
+ for(int32_t k = 0; k < arithSup.numOfCols; ++k) {
+ SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, k);
+ arithSup.data[k] = (pOutput->data + pOutput->num* pExpr->offset);
+ }
+
+ int32_t offset = 0;
+
+ for (int i = 0; i < size; ++i) {
+ SInternalField* pSup = TARRAY_GET_ELEM(pQueryInfo->fieldsInfo.internalField, i);
+
+ // calculate the result from several other columns
+ if (pSup->pArithExprInfo != NULL) {
+ arithSup.pArithExpr = pSup->pArithExprInfo;
+ tExprTreeCalcTraverse(arithSup.pArithExpr->pExpr, (int32_t) pOutput->num, pbuf + pOutput->num*offset, &arithSup, TSDB_ORDER_ASC, getArithmeticInputSrc);
+ } else {
+ SSqlExpr* pExpr = pSup->pSqlExpr;
+ memcpy(pbuf + pOutput->num * offset, pExpr->offset * pOutput->num + pOutput->data, pExpr->resBytes * pOutput->num);
+ }
+
+ offset += pSup->field.bytes;
+ }
+
+ assert(finalRowSize <= rowSize);
+ memcpy(pOutput->data, pbuf, pOutput->num * offset);
+
+ tfree(pbuf);
+ tfree(arithSup.data);
+
+ return offset;
+}
\ No newline at end of file
diff --git a/src/client/src/tscParseInsert.c b/src/client/src/tscParseInsert.c
index ac34d26d2fe747773a550dd76ac7e967a592199e..a44a158f93095c752f6aa203eb35e58e1d7ba2a0 100644
--- a/src/client/src/tscParseInsert.c
+++ b/src/client/src/tscParseInsert.c
@@ -702,7 +702,7 @@ static int32_t doParseInsertStatement(SSqlObj *pSql, void *pTableList, char **st
}
int32_t code = TSDB_CODE_TSC_INVALID_SQL;
- char * tmpTokenBuf = calloc(1, 4096); // used for deleting Escape character: \\, \', \"
+ char * tmpTokenBuf = calloc(1, 16*1024); // used for deleting Escape character: \\, \', \"
if (NULL == tmpTokenBuf) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
@@ -1148,6 +1148,10 @@ int tsParseInsertSql(SSqlObj *pSql) {
index = 0;
sToken = tStrGetToken(str, &index, false, 0, NULL);
+ if (sToken.type != TK_STRING && sToken.type != TK_ID) {
+ code = tscInvalidSQLErrMsg(pCmd->payload, "file path is required following keyword FILE", sToken.z);
+ goto _error;
+ }
str += index;
if (sToken.n == 0) {
code = tscInvalidSQLErrMsg(pCmd->payload, "file path is required following keyword FILE", sToken.z);
@@ -1309,7 +1313,7 @@ int tsParseSql(SSqlObj *pSql, bool initial) {
if ((!pCmd->parseFinished) && (!initial)) {
tscDebug("%p resume to parse sql: %s", pSql, pCmd->curSql);
}
-
+
ret = tscAllocPayload(&pSql->cmd, TSDB_DEFAULT_PAYLOAD_SIZE);
if (TSDB_CODE_SUCCESS != ret) {
return ret;
@@ -1406,7 +1410,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int code) {
assert(taos_errno(pSql) == code);
taos_free_result(pSql);
- taosTFree(pSupporter);
+ tfree(pSupporter);
fclose(fp);
pParentSql->res.code = code;
@@ -1445,7 +1449,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int code) {
char *tokenBuf = calloc(1, 4096);
- while ((readLen = taosGetline(&line, &n, fp)) != -1) {
+ while ((readLen = tgetline(&line, &n, fp)) != -1) {
if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
line[--readLen] = 0;
}
@@ -1470,7 +1474,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int code) {
}
}
- taosTFree(tokenBuf);
+ tfree(tokenBuf);
free(line);
if (count > 0) {
@@ -1483,7 +1487,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int code) {
} else {
taos_free_result(pSql);
- taosTFree(pSupporter);
+ tfree(pSupporter);
fclose(fp);
pParentSql->fp = pParentSql->fetchFp;
@@ -1513,7 +1517,7 @@ void tscProcessMultiVnodesImportFromFile(SSqlObj *pSql) {
pSql->res.code = TAOS_SYSTEM_ERROR(errno);
tscError("%p failed to open file %s to load data from file, code:%s", pSql, pCmd->payload, tstrerror(pSql->res.code));
- taosTFree(pSupporter)
+ tfree(pSupporter)
tscQueueAsyncRes(pSql);
return;
diff --git a/src/client/src/tscPrepare.c b/src/client/src/tscPrepare.c
index 1739e4348ca2d1e90e4cdc292a14c7dcc5dde2da..68f2ecbf0e194bc13362b0af965959367a9f86b8 100644
--- a/src/client/src/tscPrepare.c
+++ b/src/client/src/tscPrepare.c
@@ -268,7 +268,6 @@ static int doBindParam(char* data, SParamInfo* param, TAOS_BIND* bind) {
if (1) {
// allow user bind param data with different type
- short size = 0;
union {
int8_t v1;
int16_t v2;
@@ -600,7 +599,7 @@ static int doBindParam(char* data, SParamInfo* param, TAOS_BIND* bind) {
if ((*bind->length) > (uintptr_t)param->bytes) {
return TSDB_CODE_TSC_INVALID_VALUE;
}
- size = (short)*bind->length;
+ short size = (short)*bind->length;
STR_WITH_SIZE_TO_VARSTR(data + param->offset, bind->buffer, size);
return TSDB_CODE_SUCCESS;
} break;
diff --git a/src/client/src/tscProfile.c b/src/client/src/tscProfile.c
index eb6843b0e4fd844c9d13da7f55dca47008f62a79..acc5acd786bfe00036e539a104da04af1485a263 100644
--- a/src/client/src/tscProfile.c
+++ b/src/client/src/tscProfile.c
@@ -222,7 +222,7 @@ void tscKillStream(STscObj *pObj, uint32_t killId) {
}
int tscBuildQueryStreamDesc(void *pMsg, STscObj *pObj) {
- SCMHeartBeatMsg *pHeartbeat = pMsg;
+ SHeartBeatMsg *pHeartbeat = pMsg;
int allocedQueriesNum = pHeartbeat->numOfQueries;
int allocedStreamsNum = pHeartbeat->numOfStreams;
@@ -277,7 +277,7 @@ int tscBuildQueryStreamDesc(void *pMsg, STscObj *pObj) {
}
int32_t msgLen = pHeartbeat->numOfQueries * sizeof(SQueryDesc) + pHeartbeat->numOfStreams * sizeof(SStreamDesc) +
- sizeof(SCMHeartBeatMsg);
+ sizeof(SHeartBeatMsg);
pHeartbeat->connId = htonl(pObj->connId);
pHeartbeat->numOfQueries = htonl(pHeartbeat->numOfQueries);
pHeartbeat->numOfStreams = htonl(pHeartbeat->numOfStreams);
diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c
index e2573f7e19303966e9f17a2731444bf9fca7ab87..15d2647c5117d0bffe6dd301fb503f7e9d54235f 100644
--- a/src/client/src/tscSQLParser.c
+++ b/src/client/src/tscSQLParser.c
@@ -16,6 +16,7 @@
#define _BSD_SOURCE
#define _XOPEN_SOURCE 500
#define _DEFAULT_SOURCE
+#define _GNU_SOURCE
#include "os.h"
#include "qAst.h"
@@ -51,26 +52,29 @@ typedef struct SConvertFunc {
int32_t originFuncId;
int32_t execFuncId;
} SConvertFunc;
-static SSqlExpr* doAddProjectCol(SQueryInfo* pQueryInfo, int32_t outputIndex, int32_t colIndex, int32_t tableIndex);
+
+static SSqlExpr* doAddProjectCol(SQueryInfo* pQueryInfo, int32_t colIndex, int32_t tableIndex);
static int32_t setShowInfo(SSqlObj* pSql, SSqlInfo* pInfo);
static char* getAccountId(SSqlObj* pSql);
-static bool has(tFieldList* pFieldList, int32_t startIdx, const char* name);
+static bool has(SArray* pFieldList, int32_t startIdx, const char* name);
static void getCurrentDBName(SSqlObj* pSql, SStrToken* pDBToken);
static bool hasSpecifyDB(SStrToken* pTableName);
-static bool validateTableColumnInfo(tFieldList* pFieldList, SSqlCmd* pCmd);
-static bool validateTagParams(tFieldList* pTagsList, tFieldList* pFieldList, SSqlCmd* pCmd);
+static bool validateTableColumnInfo(SArray* pFieldList, SSqlCmd* pCmd);
+static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pCmd);
static int32_t setObjFullName(char* fullName, const char* account, SStrToken* pDB, SStrToken* tableName, int32_t* len);
static void getColumnName(tSQLExprItem* pItem, char* resultFieldName, int32_t nameLength);
-static void getRevisedName(char* resultFieldName, int32_t functionId, int32_t maxLen, char* columnName);
static int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t colIndex, tSQLExprItem* pItem, bool finalResult);
static int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnList* pIdList, int16_t bytes,
int8_t type, char* fieldName, SSqlExpr* pSqlExpr);
-static int32_t changeFunctionID(int32_t optr, int16_t* functionId);
+
+static int32_t convertFunctionId(int32_t optr, int16_t* functionId);
+static uint8_t convertOptr(SStrToken *pToken);
+
static int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery);
static bool validateIpAddress(const char* ip, size_t size);
@@ -78,11 +82,11 @@ static bool hasUnsupportFunctionsForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQuer
static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery);
static void setColumnOffsetValueInResultset(SQueryInfo* pQueryInfo);
-static int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd* pCmd);
+static int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd);
-static int32_t parseIntervalClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
+static int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
static int32_t parseOffsetClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
-static int32_t parseSlidingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
+static int32_t parseSlidingClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
static int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExprItem* pItem);
@@ -114,7 +118,7 @@ static int32_t optrToString(tSQLExpr* pExpr, char** exprString);
static int32_t getTableIndexImpl(SStrToken* pTableToken, SQueryInfo* pQueryInfo, SColumnIndex* pIndex);
static int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo);
static int32_t doLocalQueryProcess(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
-static int32_t tscCheckCreateDbParams(SSqlCmd* pCmd, SCMCreateDbMsg* pCreate);
+static int32_t tscCheckCreateDbParams(SSqlCmd* pCmd, SCreateDbMsg* pCreate);
static SColumnList getColumnList(int32_t num, int16_t tableIndex, int32_t columnIndex);
@@ -124,6 +128,49 @@ static int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo);
static int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index);
static int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pSqlExpr, SQueryInfo* pQueryInfo, SArray* pCols, int64_t *uid);
+int16_t getNewResColId(SQueryInfo* pQueryInfo) {
+ return pQueryInfo->resColumnId--;
+}
+
+static uint8_t convertOptr(SStrToken *pToken) {
+ switch (pToken->type) {
+ case TK_LT:
+ return TSDB_RELATION_LESS;
+ case TK_LE:
+ return TSDB_RELATION_LESS_EQUAL;
+ case TK_GT:
+ return TSDB_RELATION_GREATER;
+ case TK_GE:
+ return TSDB_RELATION_GREATER_EQUAL;
+ case TK_NE:
+ return TSDB_RELATION_NOT_EQUAL;
+ case TK_AND:
+ return TSDB_RELATION_AND;
+ case TK_OR:
+ return TSDB_RELATION_OR;
+ case TK_EQ:
+ return TSDB_RELATION_EQUAL;
+ case TK_PLUS:
+ return TSDB_BINARY_OP_ADD;
+ case TK_MINUS:
+ return TSDB_BINARY_OP_SUBTRACT;
+ case TK_STAR:
+ return TSDB_BINARY_OP_MULTIPLY;
+ case TK_SLASH:
+ case TK_DIVIDE:
+ return TSDB_BINARY_OP_DIVIDE;
+ case TK_REM:
+ return TSDB_BINARY_OP_REMAINDER;
+ case TK_LIKE:
+ return TSDB_RELATION_LIKE;
+ case TK_ISNULL:
+ return TSDB_RELATION_ISNULL;
+ case TK_NOTNULL:
+ return TSDB_RELATION_NOTNULL;
+ default: { return 0; }
+ }
+}
+
/*
* Used during parsing query sql. Since the query sql usually small in length, error position
* is not needed in the final error message.
@@ -417,7 +464,7 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
char* pMsg = pCmd->payload;
- SCMCfgDnodeMsg* pCfg = (SCMCfgDnodeMsg*)pMsg;
+ SCfgDnodeMsg* pCfg = (SCfgDnodeMsg*)pMsg;
pDCL->a[0].n = strdequote(pDCL->a[0].z);
strncpy(pCfg->ep, pDCL->a[0].z, pDCL->a[0].n);
@@ -616,14 +663,20 @@ static bool isTopBottomQuery(SQueryInfo* pQueryInfo) {
return false;
}
-int32_t parseIntervalClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
+int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
const char* msg1 = "invalid query expression";
const char* msg2 = "interval cannot be less than 10 ms";
+ const char* msg3 = "sliding cannot be used without interval";
+
+ SSqlCmd* pCmd = &pSql->cmd;
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
if (pQuerySql->interval.type == 0 || pQuerySql->interval.n == 0) {
+ if (pQuerySql->sliding.n > 0) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
+ }
return TSDB_CODE_SUCCESS;
}
@@ -656,7 +709,7 @@ int32_t parseIntervalClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ
return TSDB_CODE_TSC_INVALID_SQL;
}
- if (parseSlidingClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
+ if (parseSlidingClause(pSql, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
@@ -709,7 +762,7 @@ int32_t parseIntervalClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ
return TSDB_CODE_TSC_INVALID_SQL;
}
- if (parseSlidingClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
+ if (parseSlidingClause(pSql, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
@@ -767,13 +820,15 @@ int32_t parseOffsetClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQue
return TSDB_CODE_SUCCESS;
}
-int32_t parseSlidingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
+int32_t parseSlidingClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
const char* msg0 = "sliding value too small";
const char* msg1 = "sliding value no larger than the interval value";
const char* msg2 = "sliding value can not less than 1% of interval value";
- const char* msg3 = "does not support sliding when interval is natual month/year";
+ const char* msg3 = "does not support sliding when interval is natural month/year";
+// const char* msg4 = "sliding not support yet in ordinary query";
const static int32_t INTERVAL_SLIDING_FACTOR = 100;
+ SSqlCmd* pCmd = &pSql->cmd;
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
@@ -806,6 +861,10 @@ int32_t parseSlidingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
+// if (pQueryInfo->interval.sliding != pQueryInfo->interval.interval && pSql->pStream == NULL) {
+// return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
+// }
+
return TSDB_CODE_SUCCESS;
}
@@ -852,7 +911,7 @@ int32_t tscSetTableFullName(STableMetaInfo* pTableMetaInfo, SStrToken* pzTableNa
return TSDB_CODE_SUCCESS;
}
-static bool validateTableColumnInfo(tFieldList* pFieldList, SSqlCmd* pCmd) {
+static bool validateTableColumnInfo(SArray* pFieldList, SSqlCmd* pCmd) {
assert(pFieldList != NULL);
const char* msg = "illegal number of columns";
@@ -864,35 +923,28 @@ static bool validateTableColumnInfo(tFieldList* pFieldList, SSqlCmd* pCmd) {
const char* msg6 = "invalid column name";
// number of fields no less than 2
- if (pFieldList->nField <= 1 || pFieldList->nField > TSDB_MAX_COLUMNS) {
+ size_t numOfCols = taosArrayGetSize(pFieldList);
+ if (numOfCols <= 1 || numOfCols > TSDB_MAX_COLUMNS) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg);
return false;
}
// first column must be timestamp
- if (pFieldList->p[0].type != TSDB_DATA_TYPE_TIMESTAMP) {
+ TAOS_FIELD* pField = taosArrayGet(pFieldList, 0);
+ if (pField->type != TSDB_DATA_TYPE_TIMESTAMP) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
return false;
}
int32_t nLen = 0;
- for (int32_t i = 0; i < pFieldList->nField; ++i) {
- if (pFieldList->p[i].bytes == 0) {
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ pField = taosArrayGet(pFieldList, i);
+
+ if (pField->bytes == 0) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
return false;
}
- nLen += pFieldList->p[i].bytes;
- }
- // max row length must be less than TSDB_MAX_BYTES_PER_ROW
- if (nLen > TSDB_MAX_BYTES_PER_ROW) {
- invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
- return false;
- }
-
- // field name must be unique
- for (int32_t i = 0; i < pFieldList->nField; ++i) {
- TAOS_FIELD* pField = &pFieldList->p[i];
if (pField->type < TSDB_DATA_TYPE_BOOL || pField->type > TSDB_DATA_TYPE_NCHAR) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
return false;
@@ -909,16 +961,25 @@ static bool validateTableColumnInfo(tFieldList* pFieldList, SSqlCmd* pCmd) {
return false;
}
- if (has(pFieldList, i + 1, pFieldList->p[i].name) == true) {
+ // field name must be unique
+ if (has(pFieldList, i + 1, pField->name) == true) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
return false;
}
+
+ nLen += pField->bytes;
+ }
+
+ // max row length must be less than TSDB_MAX_BYTES_PER_ROW
+ if (nLen > TSDB_MAX_BYTES_PER_ROW) {
+ invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
+ return false;
}
return true;
}
-static bool validateTagParams(tFieldList* pTagsList, tFieldList* pFieldList, SSqlCmd* pCmd) {
+static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pCmd) {
assert(pTagsList != NULL);
const char* msg1 = "invalid number of tag columns";
@@ -930,18 +991,21 @@ static bool validateTagParams(tFieldList* pTagsList, tFieldList* pFieldList, SSq
const char* msg7 = "invalid binary/nchar tag length";
// number of fields at least 1
- if (pTagsList->nField < 1 || pTagsList->nField > TSDB_MAX_TAGS) {
+ size_t numOfTags = taosArrayGetSize(pTagsList);
+ if (numOfTags < 1 || numOfTags > TSDB_MAX_TAGS) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
return false;
}
int32_t nLen = 0;
- for (int32_t i = 0; i < pTagsList->nField; ++i) {
- if (pTagsList->p[i].bytes == 0) {
+ for (int32_t i = 0; i < numOfTags; ++i) {
+ TAOS_FIELD* p = taosArrayGet(pTagsList, i);
+ if (p->bytes == 0) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7);
return false;
}
- nLen += pTagsList->p[i].bytes;
+
+ nLen += p->bytes;
}
// max tag row length must be less than TSDB_MAX_TAGS_LEN
@@ -951,37 +1015,41 @@ static bool validateTagParams(tFieldList* pTagsList, tFieldList* pFieldList, SSq
}
// field name must be unique
- for (int32_t i = 0; i < pTagsList->nField; ++i) {
- if (has(pFieldList, 0, pTagsList->p[i].name) == true) {
+ for (int32_t i = 0; i < numOfTags; ++i) {
+ TAOS_FIELD* p = taosArrayGet(pTagsList, i);
+
+ if (has(pFieldList, 0, p->name) == true) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
return false;
}
}
/* timestamp in tag is not allowed */
- for (int32_t i = 0; i < pTagsList->nField; ++i) {
- if (pTagsList->p[i].type == TSDB_DATA_TYPE_TIMESTAMP) {
+ for (int32_t i = 0; i < numOfTags; ++i) {
+ TAOS_FIELD* p = taosArrayGet(pTagsList, i);
+
+ if (p->type == TSDB_DATA_TYPE_TIMESTAMP) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
return false;
}
- if (pTagsList->p[i].type < TSDB_DATA_TYPE_BOOL || pTagsList->p[i].type > TSDB_DATA_TYPE_NCHAR) {
+ if (p->type < TSDB_DATA_TYPE_BOOL || p->type > TSDB_DATA_TYPE_NCHAR) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
return false;
}
- if ((pTagsList->p[i].type == TSDB_DATA_TYPE_BINARY && pTagsList->p[i].bytes <= 0) ||
- (pTagsList->p[i].type == TSDB_DATA_TYPE_NCHAR && pTagsList->p[i].bytes <= 0)) {
+ if ((p->type == TSDB_DATA_TYPE_BINARY && p->bytes <= 0) ||
+ (p->type == TSDB_DATA_TYPE_NCHAR && p->bytes <= 0)) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7);
return false;
}
- if (validateColumnName(pTagsList->p[i].name) != TSDB_CODE_SUCCESS) {
+ if (validateColumnName(p->name) != TSDB_CODE_SUCCESS) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
return false;
}
- if (has(pTagsList, i + 1, pTagsList->p[i].name) == true) {
+ if (has(pTagsList, i + 1, p->name) == true) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
return false;
}
@@ -1128,9 +1196,10 @@ bool validateOneColumn(SSqlCmd* pCmd, TAOS_FIELD* pColField) {
}
/* is contained in pFieldList or not */
-static bool has(tFieldList* pFieldList, int32_t startIdx, const char* name) {
- for (int32_t j = startIdx; j < pFieldList->nField; ++j) {
- TAOS_FIELD* field = pFieldList->p + j;
+static bool has(SArray* pFieldList, int32_t startIdx, const char* name) {
+ size_t numOfCols = taosArrayGetSize(pFieldList);
+ for (int32_t j = startIdx; j < numOfCols; ++j) {
+ TAOS_FIELD* field = taosArrayGet(pFieldList, j);
if (strncasecmp(name, field->name, sizeof(field->name) - 1) == 0) return true;
}
@@ -1210,8 +1279,9 @@ static void tscInsertPrimaryTSSourceColumn(SQueryInfo* pQueryInfo, SColumnIndex*
SColumnIndex tsCol = {.tableIndex = pIndex->tableIndex, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX};
tscColumnListInsert(pQueryInfo->colList, &tsCol);
}
+
static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t exprIndex, tSQLExprItem* pItem) {
- const char* msg1 = "invalid column name, or illegal column type";
+ const char* msg1 = "invalid column name, illegal column type, or columns in arithmetic expression from two tables";
const char* msg2 = "invalid arithmetic expression in select clause";
const char* msg3 = "tag columns can not be used in arithmetic expression";
const char* msg4 = "columns from different table mixed up in arithmetic expression";
@@ -1241,7 +1311,7 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
SColumnIndex index = {.tableIndex = tableIndex};
SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_ARITHM, &index, TSDB_DATA_TYPE_DOUBLE, sizeof(double),
- sizeof(double), false);
+ -1000, sizeof(double), false);
char* name = (pItem->aliasName != NULL)? pItem->aliasName:pItem->pNode->token.z;
size_t len = MIN(sizeof(pExpr->aliasName), pItem->pNode->token.n + 1);
@@ -1257,6 +1327,7 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
+ // check for if there is a tag in the arithmetic express
size_t numOfNode = taosArrayGetSize(colList);
for(int32_t k = 0; k < numOfNode; ++k) {
SColIndex* pIndex = taosArrayGet(colList, k);
@@ -1282,9 +1353,9 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
char* c = tbufGetData(&bw, false);
// set the serialized binary string as the parameter of arithmetic expression
- addExprParams(pExpr, c, TSDB_DATA_TYPE_BINARY, (int32_t)len, index.tableIndex);
-
+ addExprParams(pExpr, c, TSDB_DATA_TYPE_BINARY, (int32_t)len);
insertResultField(pQueryInfo, exprIndex, &columnList, sizeof(double), TSDB_DATA_TYPE_DOUBLE, pExpr->aliasName, pExpr);
+
// add ts column
tscInsertPrimaryTSSourceColumn(pQueryInfo, &index);
@@ -1316,6 +1387,10 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
pArithExprInfo->interBytes = sizeof(double);
pArithExprInfo->type = TSDB_DATA_TYPE_DOUBLE;
+ pArithExprInfo->base.functionId = TSDB_FUNC_ARITHM;
+ pArithExprInfo->base.numOfParams = 1;
+ pArithExprInfo->base.resColId = getNewResColId(pQueryInfo);
+
int32_t ret = exprTreeFromSqlExpr(pCmd, &pArithExprInfo->pExpr, pItem->pNode, pQueryInfo, NULL, &pArithExprInfo->uid);
if (ret != TSDB_CODE_SUCCESS) {
tExprTreeDestroy(&pArithExprInfo->pExpr, NULL);
@@ -1324,14 +1399,30 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
pInfo->pArithExprInfo = pArithExprInfo;
}
+
+ SBufferWriter bw = tbufInitWriter(NULL, false);
+
+ TRY(0) {
+ exprTreeToBinary(&bw, pInfo->pArithExprInfo->pExpr);
+ } CATCH(code) {
+ tbufCloseWriter(&bw);
+ UNUSED(code);
+ // TODO: other error handling
+ } END_TRY
+
+ SSqlFuncMsg* pFuncMsg = &pInfo->pArithExprInfo->base;
+ pFuncMsg->arg[0].argBytes = (int16_t) tbufTell(&bw);
+ pFuncMsg->arg[0].argValue.pz = tbufGetData(&bw, true);
+ pFuncMsg->arg[0].argType = TSDB_DATA_TYPE_BINARY;
+
+// tbufCloseWriter(&bw); // TODO there is a memory leak
}
return TSDB_CODE_SUCCESS;
}
-
static void addProjectQueryCol(SQueryInfo* pQueryInfo, int32_t startPos, SColumnIndex* pIndex, tSQLExprItem* pItem) {
- SSqlExpr* pExpr = doAddProjectCol(pQueryInfo, startPos, pIndex->columnIndex, pIndex->tableIndex);
+ SSqlExpr* pExpr = doAddProjectCol(pQueryInfo, pIndex->columnIndex, pIndex->tableIndex);
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, pIndex->tableIndex);
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
@@ -1363,13 +1454,13 @@ static void addPrimaryTsColIntoResult(SQueryInfo* pQueryInfo) {
}
}
- SColumnIndex index = {0};
// set the constant column value always attached to first table.
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, PRIMARYKEY_TIMESTAMP_COL_INDEX);
// add the timestamp column into the output columns
+ SColumnIndex index = {0}; // primary timestamp column info
int32_t numOfCols = (int32_t)tscSqlExprNumOfExprs(pQueryInfo);
tscAddSpecialColumnForSelect(pQueryInfo, numOfCols, TSDB_FUNC_PRJ, &index, pSchema, TSDB_COL_NORMAL);
@@ -1476,7 +1567,7 @@ int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnLi
return TSDB_CODE_SUCCESS;
}
-SSqlExpr* doAddProjectCol(SQueryInfo* pQueryInfo, int32_t outputIndex, int32_t colIndex, int32_t tableIndex) {
+SSqlExpr* doAddProjectCol(SQueryInfo* pQueryInfo, int32_t colIndex, int32_t tableIndex) {
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, tableIndex);
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
int32_t numOfCols = tscGetNumOfColumns(pTableMeta);
@@ -1488,20 +1579,22 @@ SSqlExpr* doAddProjectCol(SQueryInfo* pQueryInfo, int32_t outputIndex, int32_t c
if (functionId == TSDB_FUNC_TAGPRJ) {
index.columnIndex = colIndex - tscGetNumOfColumns(pTableMeta);
-
tscColumnListInsert(pTableMetaInfo->tagColList, &index);
} else {
index.columnIndex = colIndex;
}
-
- return tscSqlExprAppend(pQueryInfo, functionId, &index, pSchema->type, pSchema->bytes,
- pSchema->bytes, functionId == TSDB_FUNC_TAGPRJ);
+
+ int16_t colId = getNewResColId(pQueryInfo);
+ return tscSqlExprAppend(pQueryInfo, functionId, &index, pSchema->type, pSchema->bytes, colId, pSchema->bytes,
+ (functionId == TSDB_FUNC_TAGPRJ));
}
SSqlExpr* tscAddSpecialColumnForSelect(SQueryInfo* pQueryInfo, int32_t outputColIndex, int16_t functionId,
SColumnIndex* pIndex, SSchema* pColSchema, int16_t flag) {
+ int16_t colId = getNewResColId(pQueryInfo);
+
SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, outputColIndex, functionId, pIndex, pColSchema->type,
- pColSchema->bytes, pColSchema->bytes, TSDB_COL_IS_TAG(flag));
+ pColSchema->bytes, colId, pColSchema->bytes, TSDB_COL_IS_TAG(flag));
tstrncpy(pExpr->aliasName, pColSchema->name, sizeof(pExpr->aliasName));
SColumnList ids = getColumnList(1, pIndex->tableIndex, pIndex->columnIndex);
@@ -1537,7 +1630,7 @@ static int32_t doAddProjectionExprAndResultFields(SQueryInfo* pQueryInfo, SColum
}
for (int32_t j = 0; j < numOfTotalColumns; ++j) {
- SSqlExpr* pExpr = doAddProjectCol(pQueryInfo, startPos + j, j, pIndex->tableIndex);
+ SSqlExpr* pExpr = doAddProjectCol(pQueryInfo, j, pIndex->tableIndex);
tstrncpy(pExpr->aliasName, pSchema[j].name, sizeof(pExpr->aliasName));
pIndex->columnIndex = j;
@@ -1625,16 +1718,15 @@ int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t
}
static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSchema* pSchema, SConvertFunc cvtFunc,
- char* aliasName, int32_t resColIdx, SColumnIndex* pColIndex, bool finalResult) {
+ 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;
- char columnName[TSDB_COL_NAME_LEN] = {0};
int32_t functionID = cvtFunc.execFuncId;
if (functionID == TSDB_FUNC_SPREAD) {
- int32_t t1 = pSchema[pColIndex->columnIndex].type;
+ int32_t t1 = pSchema->type;
if (t1 == TSDB_DATA_TYPE_BINARY || t1 == TSDB_DATA_TYPE_NCHAR || t1 == TSDB_DATA_TYPE_BOOL) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
return -1;
@@ -1643,18 +1735,12 @@ static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS
bytes = tDataTypeDesc[type].nSize;
}
} else {
- type = pSchema[pColIndex->columnIndex].type;
- bytes = pSchema[pColIndex->columnIndex].bytes;
+ type = pSchema->type;
+ bytes = pSchema->bytes;
}
- if (aliasName != NULL) {
- tstrncpy(columnName, aliasName, sizeof(columnName));
- } else {
- getRevisedName(columnName, cvtFunc.originFuncId, sizeof(columnName) - 1, pSchema[pColIndex->columnIndex].name);
- }
-
- SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionID, pColIndex, type, bytes, bytes, false);
- tstrncpy(pExpr->aliasName, columnName, sizeof(pExpr->aliasName));
+ SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionID, pColIndex, type, bytes, getNewResColId(pQueryInfo), bytes, false);
+ tstrncpy(pExpr->aliasName, name, tListLen(pExpr->aliasName));
if (cvtFunc.originFuncId == TSDB_FUNC_LAST_ROW && cvtFunc.originFuncId != functionID) {
pExpr->colInfo.flag |= TSDB_COL_NULL;
@@ -1674,7 +1760,7 @@ static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS
// if it is not in the final result, do not add it
SColumnList ids = getColumnList(1, pColIndex->tableIndex, pColIndex->columnIndex);
if (finalResult) {
- insertResultField(pQueryInfo, resColIdx, &ids, bytes, (int8_t)type, columnName, pExpr);
+ insertResultField(pQueryInfo, resColIdx, &ids, bytes, (int8_t)type, pExpr->aliasName, pExpr);
} else {
tscColumnListInsert(pQueryInfo->colList, &(ids.ids[0]));
}
@@ -1682,6 +1768,23 @@ static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS
return TSDB_CODE_SUCCESS;
}
+void setResultColName(char* name, tSQLExprItem* pItem, int32_t functionId, SStrToken* pToken) {
+ if (pItem->aliasName != NULL) {
+ tstrncpy(name, pItem->aliasName, TSDB_COL_NAME_LEN);
+ } else {
+ char uname[TSDB_COL_NAME_LEN] = {0};
+ int32_t len = MIN(pToken->n + 1, TSDB_COL_NAME_LEN);
+ tstrncpy(uname, pToken->z, len);
+
+ int32_t size = TSDB_COL_NAME_LEN + tListLen(aAggs[functionId].aName) + 2 + 1;
+ char tmp[TSDB_COL_NAME_LEN + tListLen(aAggs[functionId].aName) + 2 + 1] = {0};
+
+ snprintf(tmp, size, "%s(%s)", aAggs[functionId].aName, uname);
+
+ tstrncpy(name, tmp, TSDB_COL_NAME_LEN);
+ }
+}
+
int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t colIndex, tSQLExprItem* pItem, bool finalResult) {
STableMetaInfo* pTableMetaInfo = NULL;
int32_t optr = pItem->pNode->nSQLOptr;
@@ -1704,7 +1807,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
}
int16_t functionID = 0;
- if (changeFunctionID(optr, &functionID) != TSDB_CODE_SUCCESS) {
+ if (convertFunctionId(optr, &functionID) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
@@ -1730,7 +1833,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
index = (SColumnIndex){0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
int32_t size = tDataTypeDesc[TSDB_DATA_TYPE_BIGINT].nSize;
- pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, size, false);
+ pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false);
} else if (sqlOptr == TK_INTEGER) { // select count(1) from table1
char buf[8] = {0};
int64_t val = -1;
@@ -1742,7 +1845,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
if (val == 1) {
index = (SColumnIndex){0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
int32_t size = tDataTypeDesc[TSDB_DATA_TYPE_BIGINT].nSize;
- pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, size, false);
+ pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false);
} else {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
@@ -1762,12 +1865,12 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
}
int32_t size = tDataTypeDesc[TSDB_DATA_TYPE_BIGINT].nSize;
- pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, size, isTag);
+ pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, isTag);
}
} else { // count(*) is equalled to count(primary_timestamp_key)
index = (SColumnIndex){0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
int32_t size = tDataTypeDesc[TSDB_DATA_TYPE_BIGINT].nSize;
- pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, size, false);
+ pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false);
}
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
@@ -1840,7 +1943,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
int32_t intermediateResSize = 0;
int16_t functionID = 0;
- if (changeFunctionID(optr, &functionID) != TSDB_CODE_SUCCESS) {
+ if (convertFunctionId(optr, &functionID) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
@@ -1854,7 +1957,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
colIndex += 1;
SColumnIndex indexTS = {.tableIndex = index.tableIndex, .columnIndex = 0};
SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &indexTS, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE,
- TSDB_KEYSIZE, false);
+ getNewResColId(pQueryInfo), TSDB_KEYSIZE, false);
SColumnList ids = getColumnList(1, 0, 0);
insertResultField(pQueryInfo, 0, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, aAggs[TSDB_FUNC_TS_DUMMY].aName, pExpr);
@@ -1865,7 +1968,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
- SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, resultType, resultSize, resultSize, false);
+ SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, resultType, resultSize, getNewResColId(pQueryInfo), resultSize, false);
if (optr == TK_LEASTSQUARES) {
/* set the leastsquares parameters */
@@ -1874,14 +1977,14 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
return TSDB_CODE_TSC_INVALID_SQL;
}
- addExprParams(pExpr, val, TSDB_DATA_TYPE_DOUBLE, DOUBLE_BYTES, 0);
+ addExprParams(pExpr, val, TSDB_DATA_TYPE_DOUBLE, DOUBLE_BYTES);
memset(val, 0, tListLen(val));
if (tVariantDump(&pParamElem[2].pNode->val, val, TSDB_DATA_TYPE_DOUBLE, true) < 0) {
return TSDB_CODE_TSC_INVALID_SQL;
}
- addExprParams(pExpr, val, TSDB_DATA_TYPE_DOUBLE, sizeof(double), 0);
+ addExprParams(pExpr, val, TSDB_DATA_TYPE_DOUBLE, sizeof(double));
}
SColumnList ids = {0};
@@ -1911,7 +2014,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
bool requireAllFields = (pItem->pNode->pParam == NULL);
int16_t functionID = 0;
- if (changeFunctionID(optr, &functionID) != TSDB_CODE_SUCCESS) {
+ if (convertFunctionId(optr, &functionID) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg9);
}
@@ -1939,8 +2042,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
- if (pParamElem->pNode->nSQLOptr == TK_ALL) {
- // select table.*
+ if (pParamElem->pNode->nSQLOptr == TK_ALL) { // select table.*
SStrToken tmpToken = pParamElem->pNode->colInfo;
if (getTableIndexByName(&tmpToken, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
@@ -1950,9 +2052,13 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
SSchema* pSchema = tscGetTableSchema(pTableMetaInfo->pTableMeta);
+ char name[TSDB_COL_NAME_LEN] = {0};
for (int32_t j = 0; j < tscGetNumOfColumns(pTableMetaInfo->pTableMeta); ++j) {
index.columnIndex = j;
- if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, pItem->aliasName, colIndex++, &index, finalResult) != 0) {
+ SStrToken t = {.z = pSchema[j].name, .n = (uint32_t)strnlen(pSchema[j].name, TSDB_COL_NAME_LEN)};
+ setResultColName(name, pItem, cvtFunc.originFuncId, &t);
+
+ if (setExprInfoForFunctions(pCmd, pQueryInfo, &pSchema[j], cvtFunc, name, colIndex++, &index, finalResult) != 0) {
return TSDB_CODE_TSC_INVALID_SQL;
}
}
@@ -1963,14 +2069,18 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
}
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
- SSchema* pSchema = tscGetTableSchema(pTableMetaInfo->pTableMeta);
// functions can not be applied to tags
if ((index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) || (index.columnIndex < 0)) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
- if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, pItem->aliasName, colIndex + i, &index, finalResult) != 0) {
+ char name[TSDB_COL_NAME_LEN] = {0};
+
+ SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex);
+ setResultColName(name, pItem, cvtFunc.originFuncId, &pParamElem->pNode->colInfo);
+
+ if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, name, colIndex + i, &index, finalResult) != 0) {
return TSDB_CODE_TSC_INVALID_SQL;
}
@@ -2007,7 +2117,12 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
for (int32_t i = 0; i < tscGetNumOfColumns(pTableMetaInfo->pTableMeta); ++i) {
SColumnIndex index = {.tableIndex = j, .columnIndex = i};
- if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, pItem->aliasName, colIndex, &index, finalResult) != 0) {
+
+ char name[TSDB_COL_NAME_LEN] = {0};
+ SStrToken t = {.z = pSchema[i].name, .n = (uint32_t)strnlen(pSchema[i].name, TSDB_COL_NAME_LEN)};
+ setResultColName(name, pItem, cvtFunc.originFuncId, &t);
+
+ if (setExprInfoForFunctions(pCmd, pQueryInfo, &pSchema[index.columnIndex], cvtFunc, name, colIndex, &index, finalResult) != 0) {
return TSDB_CODE_TSC_INVALID_SQL;
}
@@ -2088,14 +2203,14 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
* for dp = 100, it is max,
*/
int16_t functionId = 0;
- if (changeFunctionID(optr, &functionId) != TSDB_CODE_SUCCESS) {
+ if (convertFunctionId(optr, &functionId) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
tscInsertPrimaryTSSourceColumn(pQueryInfo, &index);
colIndex += 1; // the first column is ts
- pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, resultSize, false);
- addExprParams(pExpr, val, TSDB_DATA_TYPE_DOUBLE, sizeof(double), 0);
+ pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pQueryInfo), resultSize, false);
+ addExprParams(pExpr, val, TSDB_DATA_TYPE_DOUBLE, sizeof(double));
} else {
tVariantDump(pVariant, val, TSDB_DATA_TYPE_BIGINT, true);
@@ -2105,15 +2220,15 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
}
int16_t functionId = 0;
- if (changeFunctionID(optr, &functionId) != TSDB_CODE_SUCCESS) {
+ if (convertFunctionId(optr, &functionId) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
// todo REFACTOR
// set the first column ts for top/bottom query
SColumnIndex index1 = {0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
- pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS, &index1, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE,
- TSDB_KEYSIZE, false);
+ pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS, &index1, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, getNewResColId(pQueryInfo),
+ TSDB_KEYSIZE, false);
tstrncpy(pExpr->aliasName, aAggs[TSDB_FUNC_TS].aName, sizeof(pExpr->aliasName));
const int32_t TS_COLUMN_INDEX = PRIMARYKEY_TIMESTAMP_COL_INDEX;
@@ -2123,8 +2238,8 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
colIndex += 1; // the first column is ts
- pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, resultSize, false);
- addExprParams(pExpr, val, TSDB_DATA_TYPE_BIGINT, sizeof(int64_t), 0);
+ pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pQueryInfo), resultSize, false);
+ addExprParams(pExpr, val, TSDB_DATA_TYPE_BIGINT, sizeof(int64_t));
}
memset(pExpr->aliasName, 0, tListLen(pExpr->aliasName));
@@ -2240,10 +2355,6 @@ void getColumnName(tSQLExprItem* pItem, char* resultFieldName, int32_t nameLengt
}
}
-void getRevisedName(char* resultFieldName, int32_t functionId, int32_t maxLen, char* columnName) {
- snprintf(resultFieldName, maxLen, "%s(%s)", aAggs[functionId].aName, columnName);
-}
-
static bool isTablenameToken(SStrToken* token) {
SStrToken tmpToken = *token;
SStrToken tableToken = {0};
@@ -2321,6 +2432,8 @@ int32_t getTableIndexImpl(SStrToken* pTableToken, SQueryInfo* pQueryInfo, SColum
if (pTableToken->n == 0) { // only one table and no table name prefix in column name
if (pQueryInfo->numOfTables == 1) {
pIndex->tableIndex = 0;
+ } else {
+ pIndex->tableIndex = COLUMN_INDEX_INITIAL_VAL;
}
return TSDB_CODE_SUCCESS;
@@ -2368,7 +2481,7 @@ int32_t getColumnIndexByName(SSqlCmd* pCmd, const SStrToken* pToken, SQueryInfo*
return doGetColumnIndexByName(pCmd, &tmpToken, pQueryInfo, pIndex);
}
-int32_t changeFunctionID(int32_t optr, int16_t* functionId) {
+int32_t convertFunctionId(int32_t optr, int16_t* functionId) {
switch (optr) {
case TK_COUNT:
*functionId = TSDB_FUNC_COUNT;
@@ -2612,7 +2725,7 @@ int32_t tscTansformSQLFuncForSTableQuery(SQueryInfo* pQueryInfo) {
}
}
- tscFieldInfoUpdateOffsetForInterResult(pQueryInfo);
+ tscFieldInfoUpdateOffset(pQueryInfo);
return TSDB_CODE_SUCCESS;
}
@@ -2686,7 +2799,10 @@ bool hasUnsupportFunctionsForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo)
static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery) {
int32_t startIdx = 0;
-
+
+ size_t numOfExpr = tscSqlExprNumOfExprs(pQueryInfo);
+ assert(numOfExpr > 0);
+
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, startIdx);
int32_t functionID = pExpr->functionId;
@@ -2725,10 +2841,11 @@ static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery) {
return true;
}
-int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd* pCmd) {
+int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd) {
const char* msg1 = "too many columns in group by clause";
const char* msg2 = "invalid column name in group by clause";
-// const char* msg3 = "group by columns must belong to one table";
+ const char* msg3 = "columns from one table allowed as group by columns";
+ const char* msg4 = "join query does not support group by";
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";
@@ -2744,19 +2861,26 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd*
pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES);
}
- pQueryInfo->groupbyExpr.numOfGroupCols = pList->nExpr;
- if (pList->nExpr > TSDB_MAX_TAGS) {
+ pQueryInfo->groupbyExpr.numOfGroupCols = (int16_t)taosArrayGetSize(pList);
+ if (pQueryInfo->groupbyExpr.numOfGroupCols > TSDB_MAX_TAGS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
+ if (pQueryInfo->numOfTables > 1) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
+ }
+
STableMeta* pTableMeta = NULL;
SSchema* pSchema = NULL;
SSchema s = tscGetTbnameColumnSchema();
int32_t tableIndex = COLUMN_INDEX_INITIAL_VAL;
-
- for (int32_t i = 0; i < pList->nExpr; ++i) {
- tVariant* pVar = &pList->a[i].pVar;
+
+ size_t num = taosArrayGetSize(pList);
+ for (int32_t i = 0; i < num; ++i) {
+ tVariantListItem * pItem = taosArrayGet(pList, i);
+ tVariant* pVar = &pItem->pVar;
+
SStrToken token = {pVar->nLen, pVar->nType, pVar->pz};
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
@@ -2764,7 +2888,11 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd*
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- tableIndex = index.tableIndex;
+ if (tableIndex == COLUMN_INDEX_INITIAL_VAL) {
+ tableIndex = index.tableIndex;
+ } else if (tableIndex != index.tableIndex) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
+ }
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
pTableMeta = pTableMetaInfo->pTableMeta;
@@ -2803,7 +2931,7 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd*
tscColumnListInsert(pTableMetaInfo->tagColList, &index);
} else {
// check if the column type is valid, here only support the bool/tinyint/smallint/bigint group by
- if (pSchema->type > TSDB_DATA_TYPE_BINARY) {
+ if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP || pSchema->type == TSDB_DATA_TYPE_FLOAT || pSchema->type == TSDB_DATA_TYPE_DOUBLE) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg8);
}
@@ -2813,7 +2941,7 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd*
taosArrayPush(pGroupExpr->columnInfo, &colIndex);
pQueryInfo->groupbyExpr.orderType = TSDB_ORDER_ASC;
- if (i == 0 && pList->nExpr > 1) {
+ if (i == 0 && num > 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7);
}
}
@@ -2825,7 +2953,7 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd*
void setColumnOffsetValueInResultset(SQueryInfo* pQueryInfo) {
if (QUERY_IS_STABLE_QUERY(pQueryInfo->type)) {
- tscFieldInfoUpdateOffsetForInterResult(pQueryInfo);
+ tscFieldInfoUpdateOffset(pQueryInfo);
} else {
tscFieldInfoUpdateOffset(pQueryInfo);
}
@@ -3349,7 +3477,8 @@ int32_t doArithmeticExprToString(tSQLExpr* pExpr, char** exprString) {
return TSDB_CODE_SUCCESS;
}
-static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, int32_t* type) {
+static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList,
+ int32_t* type, uint64_t* uid) {
if (pExpr->nSQLOptr == TK_ID) {
if (*type == NON_ARITHMEIC_EXPR) {
*type = NORMAL_ARITHMETIC;
@@ -3398,13 +3527,22 @@ static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQuer
}
// Not supported data type in arithmetic expression
+ uint64_t id = -1;
for(int32_t i = 0; i < inc; ++i) {
SSqlExpr* p1 = tscSqlExprGet(pQueryInfo, i + outputIndex);
int16_t t = p1->resType;
if (t == TSDB_DATA_TYPE_BINARY || t == TSDB_DATA_TYPE_NCHAR || t == TSDB_DATA_TYPE_BOOL || t == TSDB_DATA_TYPE_TIMESTAMP) {
return TSDB_CODE_TSC_INVALID_SQL;
}
+
+ if (i == 0) {
+ id = p1->uid;
+ } else if (id != p1->uid){
+ return TSDB_CODE_TSC_INVALID_SQL;
+ }
}
+
+ *uid = id;
}
return TSDB_CODE_SUCCESS;
@@ -3416,13 +3554,16 @@ static int32_t validateArithmeticSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryI
}
tSQLExpr* pLeft = pExpr->pLeft;
+ uint64_t uidLeft = 0;
+ uint64_t uidRight = 0;
+
if (pLeft->nSQLOptr >= TK_PLUS && pLeft->nSQLOptr <= TK_REM) {
int32_t ret = validateArithmeticSQLExpr(pCmd, pLeft, pQueryInfo, pList, type);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
} else {
- int32_t ret = validateSQLExpr(pCmd, pLeft, pQueryInfo, pList, type);
+ int32_t ret = validateSQLExpr(pCmd, pLeft, pQueryInfo, pList, type, &uidLeft);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
@@ -3435,10 +3576,15 @@ static int32_t validateArithmeticSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryI
return ret;
}
} else {
- int32_t ret = validateSQLExpr(pCmd, pRight, pQueryInfo, pList, type);
+ int32_t ret = validateSQLExpr(pCmd, pRight, pQueryInfo, pList, type, &uidRight);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
+
+ // the expression not from the same table, return error
+ if (uidLeft != uidRight && uidLeft != 0 && uidRight != 0) {
+ return TSDB_CODE_TSC_INVALID_SQL;
+ }
}
return TSDB_CODE_SUCCESS;
@@ -3806,9 +3952,6 @@ static void doExtractExprForSTable(SSqlCmd* pCmd, tSQLExpr** pExpr, SQueryInfo*
return;
}
- SStrToken t = {0};
- extractTableNameFromToken(&pLeft->colInfo, &t);
-
*pOut = *pExpr;
(*pExpr) = NULL;
@@ -3900,7 +4043,7 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
int32_t ret = setObjFullName(idBuf, account, &dbToken, &t, &xlen);
if (ret != TSDB_CODE_SUCCESS) {
taosStringBuilderDestroy(&sb1);
- taosTFree(segments);
+ tfree(segments);
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg);
return ret;
@@ -3913,7 +4056,7 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
pQueryInfo->tagCond.tbnameCond.cond = strdup(str);
taosStringBuilderDestroy(&sb1);
- taosTFree(segments);
+ tfree(segments);
return TSDB_CODE_SUCCESS;
}
@@ -4043,7 +4186,7 @@ static void cleanQueryExpr(SCondExpr* pCondExpr) {
static void doAddJoinTagsColumnsIntoTagList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondExpr* pCondExpr) {
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
if (QUERY_IS_JOIN_QUERY(pQueryInfo->type) && UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
- SColumnIndex index = {0};
+ SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (getColumnIndexByName(pCmd, &pCondExpr->pJoinExpr->pLeft->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
tscError("%p: invalid column name (left)", pQueryInfo);
@@ -4309,8 +4452,8 @@ int32_t tsRewriteFieldNameIfNecessary(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
}
int32_t parseFillClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySQL) {
- tVariantList* pFillToken = pQuerySQL->fillType;
- tVariantListItem* pItem = &pFillToken->a[0];
+ SArray* pFillToken = pQuerySQL->fillType;
+ tVariantListItem* pItem = taosArrayGet(pFillToken, 0);
const int32_t START_INTERPO_COL_IDX = 1;
@@ -4322,7 +4465,7 @@ int32_t parseFillClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuery
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- size_t size = tscSqlExprNumOfExprs(pQueryInfo);
+ size_t size = tscNumOfFields(pQueryInfo);
if (pQueryInfo->fillVal == NULL) {
pQueryInfo->fillVal = calloc(size, sizeof(int64_t));
@@ -4336,12 +4479,8 @@ int32_t parseFillClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuery
} else if (strncasecmp(pItem->pVar.pz, "null", 4) == 0 && pItem->pVar.nLen == 4) {
pQueryInfo->fillType = TSDB_FILL_NULL;
for (int32_t i = START_INTERPO_COL_IDX; i < size; ++i) {
- TAOS_FIELD* pFields = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
- if (pFields->type == TSDB_DATA_TYPE_BINARY || pFields->type == TSDB_DATA_TYPE_NCHAR) {
- setVardataNull((char*) &pQueryInfo->fillVal[i], pFields->type);
- } else {
- setNull((char*)&pQueryInfo->fillVal[i], pFields->type, pFields->bytes);
- };
+ TAOS_FIELD* pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
+ setNull((char*)&pQueryInfo->fillVal[i], pField->type, pField->bytes);
}
} else if (strncasecmp(pItem->pVar.pz, "prev", 4) == 0 && pItem->pVar.nLen == 4) {
pQueryInfo->fillType = TSDB_FILL_PREV;
@@ -4350,12 +4489,13 @@ int32_t parseFillClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuery
} else if (strncasecmp(pItem->pVar.pz, "value", 5) == 0 && pItem->pVar.nLen == 5) {
pQueryInfo->fillType = TSDB_FILL_SET_VALUE;
- if (pFillToken->nExpr == 1) {
+ size_t num = taosArrayGetSize(pFillToken);
+ if (num == 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
int32_t startPos = 1;
- int32_t numOfFillVal = pFillToken->nExpr - 1;
+ int32_t numOfFillVal = (int32_t)(num - 1);
/* for point interpolation query, we do not have the timestamp column */
if (tscIsPointInterpQuery(pQueryInfo)) {
@@ -4365,35 +4505,36 @@ int32_t parseFillClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuery
numOfFillVal = (int32_t)size;
}
} else {
- numOfFillVal = (pFillToken->nExpr > (int32_t)size) ? (int32_t)size : pFillToken->nExpr;
+ numOfFillVal = (int16_t)((num > (int32_t)size) ? (int32_t)size : num);
}
int32_t j = 1;
for (int32_t i = startPos; i < numOfFillVal; ++i, ++j) {
- TAOS_FIELD* pFields = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
+ TAOS_FIELD* pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
- if (pFields->type == TSDB_DATA_TYPE_BINARY || pFields->type == TSDB_DATA_TYPE_NCHAR) {
- setVardataNull((char*) &pQueryInfo->fillVal[i], pFields->type);
+ if (pField->type == TSDB_DATA_TYPE_BINARY || pField->type == TSDB_DATA_TYPE_NCHAR) {
+ setVardataNull((char*) &pQueryInfo->fillVal[i], pField->type);
continue;
}
- int32_t ret = tVariantDump(&pFillToken->a[j].pVar, (char*)&pQueryInfo->fillVal[i], pFields->type, true);
+ tVariant* p = taosArrayGet(pFillToken, j);
+ int32_t ret = tVariantDump(p, (char*)&pQueryInfo->fillVal[i], pField->type, true);
if (ret != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg);
}
}
- if ((pFillToken->nExpr < size) || ((pFillToken->nExpr - 1 < size) && (tscIsPointInterpQuery(pQueryInfo)))) {
- tVariantListItem* lastItem = &pFillToken->a[pFillToken->nExpr - 1];
+ if ((num < size) || ((num - 1 < size) && (tscIsPointInterpQuery(pQueryInfo)))) {
+ tVariantListItem* lastItem = taosArrayGetLast(pFillToken);
for (int32_t i = numOfFillVal; i < size; ++i) {
- TAOS_FIELD* pFields = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
+ TAOS_FIELD* pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
- if (pFields->type == TSDB_DATA_TYPE_BINARY || pFields->type == TSDB_DATA_TYPE_NCHAR) {
- setVardataNull((char*) &pQueryInfo->fillVal[i], pFields->type);
+ if (pField->type == TSDB_DATA_TYPE_BINARY || pField->type == TSDB_DATA_TYPE_NCHAR) {
+ setVardataNull((char*) &pQueryInfo->fillVal[i], pField->type);
} else {
- tVariantDump(&lastItem->pVar, (char*)&pQueryInfo->fillVal[i], pFields->type, true);
+ tVariantDump(&lastItem->pVar, (char*)&pQueryInfo->fillVal[i], pField->type, true);
}
}
}
@@ -4424,8 +4565,8 @@ static void setDefaultOrderInfo(SQueryInfo* pQueryInfo) {
int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql, SSchema* pSchema) {
const char* msg0 = "only support order by primary timestamp";
const char* msg1 = "invalid column name";
- const char* msg2 = "only support order by primary timestamp and queried column";
- const char* msg3 = "only support order by primary timestamp and first tag in groupby clause";
+ const char* msg2 = "only support order by primary timestamp or queried column";
+ const char* msg3 = "only support order by primary timestamp or first tag in groupby clause";
setDefaultOrderInfo(pQueryInfo);
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
@@ -4434,7 +4575,7 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
return TSDB_CODE_SUCCESS;
}
- tVariantList* pSortorder = pQuerySql->pSortOrder;
+ SArray* pSortorder = pQuerySql->pSortOrder;
/*
* for table query, there is only one or none order option is allowed, which is the
@@ -4442,18 +4583,19 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
*
* for super table query, the order option must be less than 3.
*/
+ size_t size = taosArrayGetSize(pSortorder);
if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) {
- if (pSortorder->nExpr > 1) {
+ if (size > 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg0);
}
} else {
- if (pSortorder->nExpr > 2) {
+ if (size > 2) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
}
// handle the first part of order by
- tVariant* pVar = &pSortorder->a[0].pVar;
+ tVariant* pVar = taosArrayGet(pSortorder, 0);
// e.g., order by 1 asc, return directly with out further check.
if (pVar->nType >= TSDB_DATA_TYPE_TINYINT && pVar->nType <= TSDB_DATA_TYPE_BIGINT) {
@@ -4461,7 +4603,7 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
}
SStrToken columnName = {pVar->nLen, pVar->nType, pVar->pz};
- SColumnIndex index = {0};
+ SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { // super table query
if (getColumnIndexByName(pCmd, &columnName, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
@@ -4496,10 +4638,13 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
assert(!(orderByTags && orderByTS));
}
- if (pSortorder->nExpr == 1) {
+ size_t s = taosArrayGetSize(pSortorder);
+ if (s == 1) {
if (orderByTags) {
pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
- pQueryInfo->groupbyExpr.orderType = pQuerySql->pSortOrder->a[0].sortOrder;
+
+ tVariantListItem* p1 = taosArrayGet(pQuerySql->pSortOrder, 0);
+ pQueryInfo->groupbyExpr.orderType = p1->sortOrder;
} else if (isTopBottomQuery(pQueryInfo)) {
/* order of top/bottom query in interval is not valid */
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, 0);
@@ -4510,11 +4655,14 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- pQueryInfo->order.order = pQuerySql->pSortOrder->a[0].sortOrder;
+ tVariantListItem* p1 = taosArrayGet(pQuerySql->pSortOrder, 0);
+ pQueryInfo->order.order = p1->sortOrder;
pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId;
return TSDB_CODE_SUCCESS;
} else {
- pQueryInfo->order.order = pSortorder->a[0].sortOrder;
+ tVariantListItem* p1 = taosArrayGet(pQuerySql->pSortOrder, 0);
+
+ pQueryInfo->order.order = p1->sortOrder;
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
// orderby ts query on super table
@@ -4524,16 +4672,18 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
}
}
- if (pSortorder->nExpr == 2) {
+ if (s == 2) {
+ tVariantListItem *pItem = taosArrayGet(pQuerySql->pSortOrder, 0);
if (orderByTags) {
pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
- pQueryInfo->groupbyExpr.orderType = pQuerySql->pSortOrder->a[0].sortOrder;
+ pQueryInfo->groupbyExpr.orderType = pItem->sortOrder;
} else {
- pQueryInfo->order.order = pSortorder->a[0].sortOrder;
+ pQueryInfo->order.order = pItem->sortOrder;
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
}
- tVariant* pVar2 = &pSortorder->a[1].pVar;
+ pItem = taosArrayGet(pQuerySql->pSortOrder, 1);
+ tVariant* pVar2 = &pItem->pVar;
SStrToken cname = {pVar2->nLen, pVar2->nType, pVar2->pz};
if (getColumnIndexByName(pCmd, &cname, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
@@ -4542,7 +4692,8 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
if (index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
} else {
- pQueryInfo->order.order = pSortorder->a[1].sortOrder;
+ tVariantListItem* p1 = taosArrayGet(pSortorder, 1);
+ pQueryInfo->order.order = p1->sortOrder;
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
}
}
@@ -4566,12 +4717,14 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- pQueryInfo->order.order = pQuerySql->pSortOrder->a[0].sortOrder;
+ tVariantListItem* pItem = taosArrayGet(pQuerySql->pSortOrder, 0);
+ pQueryInfo->order.order = pItem->sortOrder;
pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId;
return TSDB_CODE_SUCCESS;
}
- pQueryInfo->order.order = pQuerySql->pSortOrder->a[0].sortOrder;
+ tVariantListItem* pItem = taosArrayGet(pQuerySql->pSortOrder, 0);
+ pQueryInfo->order.order = pItem->sortOrder;
}
return TSDB_CODE_SUCCESS;
@@ -4639,27 +4792,28 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
}
if (pAlterSQL->type == TSDB_ALTER_TABLE_ADD_TAG_COLUMN) {
- tFieldList* pFieldList = pAlterSQL->pAddColumns;
- if (pFieldList->nField > 1) {
+ SArray* pFieldList = pAlterSQL->pAddColumns;
+ if (taosArrayGetSize(pFieldList) > 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
- if (!validateOneTags(pCmd, &pFieldList->p[0])) {
+ TAOS_FIELD* p = taosArrayGet(pFieldList, 0);
+ if (!validateOneTags(pCmd, p)) {
return TSDB_CODE_TSC_INVALID_SQL;
}
- tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &pFieldList->p[0]);
+ tscFieldInfoAppend(&pQueryInfo->fieldsInfo, p);
} else if (pAlterSQL->type == TSDB_ALTER_TABLE_DROP_TAG_COLUMN) {
if (tscGetNumOfTags(pTableMeta) == 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7);
}
// numOfTags == 1
- if (pAlterSQL->varList->nExpr > 1) {
+ if (taosArrayGetSize(pAlterSQL->varList) > 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg8);
}
- tVariantListItem* pItem = &pAlterSQL->varList->a[0];
+ tVariantListItem* pItem = taosArrayGet(pAlterSQL->varList, 0);
if (pItem->pVar.nLen >= TSDB_COL_NAME_LEN) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg9);
}
@@ -4684,13 +4838,13 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
TAOS_FIELD f = tscCreateField(TSDB_DATA_TYPE_INT, name1, tDataTypeDesc[TSDB_DATA_TYPE_INT].nSize);
tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
} else if (pAlterSQL->type == TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN) {
- tVariantList* pVarList = pAlterSQL->varList;
- if (pVarList->nExpr > 2) {
+ SArray* pVarList = pAlterSQL->varList;
+ if (taosArrayGetSize(pVarList) > 2) {
return TSDB_CODE_TSC_INVALID_SQL;
}
- tVariantListItem* pSrcItem = &pAlterSQL->varList->a[0];
- tVariantListItem* pDstItem = &pAlterSQL->varList->a[1];
+ tVariantListItem* pSrcItem = taosArrayGet(pAlterSQL->varList, 0);
+ tVariantListItem* pDstItem = taosArrayGet(pAlterSQL->varList, 1);
if (pSrcItem->pVar.nLen >= TSDB_COL_NAME_LEN || pDstItem->pVar.nLen >= TSDB_COL_NAME_LEN) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg9);
@@ -4713,13 +4867,17 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg19);
}
+ tVariantListItem* pItem = taosArrayGet(pVarList, 0);
+
char name[TSDB_COL_NAME_LEN] = {0};
- strncpy(name, pVarList->a[0].pVar.pz, pVarList->a[0].pVar.nLen);
+ strncpy(name, pItem->pVar.pz, pItem->pVar.nLen);
TAOS_FIELD f = tscCreateField(TSDB_DATA_TYPE_INT, name, tDataTypeDesc[TSDB_DATA_TYPE_INT].nSize);
tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
+ pItem = taosArrayGet(pVarList, 1);
memset(name, 0, tListLen(name));
- strncpy(name, pVarList->a[1].pVar.pz, pVarList->a[1].pVar.nLen);
+
+ strncpy(name, pItem->pVar.pz, pItem->pVar.nLen);
f = tscCreateField(TSDB_DATA_TYPE_INT, name, tDataTypeDesc[TSDB_DATA_TYPE_INT].nSize);
tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
} else if (pAlterSQL->type == TSDB_ALTER_TABLE_UPDATE_TAG_VAL) {
@@ -4727,12 +4885,12 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
// the following is used to handle tags value for table created according to super table
pCmd->command = TSDB_SQL_UPDATE_TAGS_VAL;
- tVariantList* pVarList = pAlterSQL->varList;
- tVariant* pTagName = &pVarList->a[0].pVar;
+ SArray* pVarList = pAlterSQL->varList;
+ tVariantListItem* item = taosArrayGet(pVarList, 0);
int16_t numOfTags = tscGetNumOfTags(pTableMeta);
SColumnIndex columnIndex = COLUMN_INDEX_INITIALIZER;
- SStrToken name = {.type = TK_STRING, .z = pTagName->pz, .n = pTagName->nLen};
+ SStrToken name = {.type = TK_STRING, .z = item->pVar.pz, .n = item->pVar.nLen};
if (getColumnIndexByName(pCmd, &name, pQueryInfo, &columnIndex) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
@@ -4741,8 +4899,9 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg12);
}
+ tVariantListItem* pItem = taosArrayGet(pVarList, 1);
SSchema* pTagsSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, columnIndex.columnIndex);
- if (tVariantDump(&pVarList->a[1].pVar, pAlterSQL->tagData.data, pTagsSchema->type, true) != TSDB_CODE_SUCCESS) {
+ if (tVariantDump(&pItem->pVar, pAlterSQL->tagData.data, pTagsSchema->type, true) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg13);
}
@@ -4787,7 +4946,8 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
}
// copy the tag value to msg body
- tVariantDump(&pVarList->a[1].pVar, pUpdateMsg->data + schemaLen, pTagsSchema->type, true);
+ pItem = taosArrayGet(pVarList, 1);
+ tVariantDump(&pItem->pVar, pUpdateMsg->data + schemaLen, pTagsSchema->type, true);
int32_t len = 0;
if (pTagsSchema->type != TSDB_DATA_TYPE_BINARY && pTagsSchema->type != TSDB_DATA_TYPE_NCHAR) {
@@ -4802,27 +4962,29 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
pUpdateMsg->head.contLen = htonl(total);
} else if (pAlterSQL->type == TSDB_ALTER_TABLE_ADD_COLUMN) {
- tFieldList* pFieldList = pAlterSQL->pAddColumns;
- if (pFieldList->nField > 1) {
+ SArray* pFieldList = pAlterSQL->pAddColumns;
+ if (taosArrayGetSize(pFieldList) > 1) {
const char* msg = "only support add one column";
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg);
}
- if (!validateOneColumn(pCmd, &pFieldList->p[0])) {
+ TAOS_FIELD* p = taosArrayGet(pFieldList, 0);
+ if (!validateOneColumn(pCmd, p)) {
return TSDB_CODE_TSC_INVALID_SQL;
}
- tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &pFieldList->p[0]);
+ tscFieldInfoAppend(&pQueryInfo->fieldsInfo, p);
} else if (pAlterSQL->type == TSDB_ALTER_TABLE_DROP_COLUMN) {
if (tscGetNumOfColumns(pTableMeta) == TSDB_MIN_COLUMNS) { //
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg15);
}
- if (pAlterSQL->varList->nExpr > 1) {
+ size_t size = taosArrayGetSize(pAlterSQL->varList);
+ if (size > 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg16);
}
- tVariantListItem* pItem = &pAlterSQL->varList->a[0];
+ tVariantListItem* pItem = taosArrayGet(pAlterSQL->varList, 0);
SColumnIndex columnIndex = COLUMN_INDEX_INITIALIZER;
SStrToken name = {.type = TK_STRING, .z = pItem->pVar.pz, .n = pItem->pVar.nLen};
@@ -5186,28 +5348,35 @@ int32_t parseLimitClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t clauseIn
return TSDB_CODE_SUCCESS;
}
-static int32_t setKeepOption(SSqlCmd* pCmd, SCMCreateDbMsg* pMsg, SCreateDBInfo* pCreateDb) {
+static int32_t setKeepOption(SSqlCmd* pCmd, SCreateDbMsg* pMsg, SCreateDBInfo* pCreateDb) {
const char* msg = "invalid number of options";
pMsg->daysToKeep = htonl(-1);
pMsg->daysToKeep1 = htonl(-1);
pMsg->daysToKeep2 = htonl(-1);
- tVariantList* pKeep = pCreateDb->keep;
+ SArray* pKeep = pCreateDb->keep;
if (pKeep != NULL) {
- switch (pKeep->nExpr) {
- case 1:
- pMsg->daysToKeep = htonl((int32_t)pKeep->a[0].pVar.i64Key);
+ size_t s = taosArrayGetSize(pKeep);
+ tVariantListItem* p0 = taosArrayGet(pKeep, 0);
+ switch (s) {
+ case 1: {
+ pMsg->daysToKeep = htonl((int32_t)p0->pVar.i64Key);
+ }
break;
case 2: {
- pMsg->daysToKeep = htonl((int32_t)pKeep->a[0].pVar.i64Key);
- pMsg->daysToKeep1 = htonl((int32_t)pKeep->a[1].pVar.i64Key);
+ tVariantListItem* p1 = taosArrayGet(pKeep, 1);
+ pMsg->daysToKeep = htonl((int32_t)p0->pVar.i64Key);
+ pMsg->daysToKeep1 = htonl((int32_t)p1->pVar.i64Key);
break;
}
case 3: {
- pMsg->daysToKeep = htonl((int32_t)pKeep->a[0].pVar.i64Key);
- pMsg->daysToKeep1 = htonl((int32_t)pKeep->a[1].pVar.i64Key);
- pMsg->daysToKeep2 = htonl((int32_t)pKeep->a[2].pVar.i64Key);
+ tVariantListItem* p1 = taosArrayGet(pKeep, 1);
+ tVariantListItem* p2 = taosArrayGet(pKeep, 2);
+
+ pMsg->daysToKeep = htonl((int32_t)p0->pVar.i64Key);
+ pMsg->daysToKeep1 = htonl((int32_t)p1->pVar.i64Key);
+ pMsg->daysToKeep2 = htonl((int32_t)p2->pVar.i64Key);
break;
}
default: { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg); }
@@ -5217,7 +5386,7 @@ static int32_t setKeepOption(SSqlCmd* pCmd, SCMCreateDbMsg* pMsg, SCreateDBInfo*
return TSDB_CODE_SUCCESS;
}
-static int32_t setTimePrecision(SSqlCmd* pCmd, SCMCreateDbMsg* pMsg, SCreateDBInfo* pCreateDbInfo) {
+static int32_t setTimePrecision(SSqlCmd* pCmd, SCreateDbMsg* pMsg, SCreateDBInfo* pCreateDbInfo) {
const char* msg = "invalid time precision";
pMsg->precision = TSDB_TIME_PRECISION_MILLI; // millisecond by default
@@ -5241,7 +5410,7 @@ static int32_t setTimePrecision(SSqlCmd* pCmd, SCMCreateDbMsg* pMsg, SCreateDBIn
return TSDB_CODE_SUCCESS;
}
-static void setCreateDBOption(SCMCreateDbMsg* pMsg, SCreateDBInfo* pCreateDb) {
+static void setCreateDBOption(SCreateDbMsg* pMsg, SCreateDBInfo* pCreateDb) {
pMsg->maxTables = htonl(-1); // max tables can not be set anymore
pMsg->cacheBlockSize = htonl(pCreateDb->cacheBlockSize);
pMsg->totalBlocks = htonl(pCreateDb->numOfBlocks);
@@ -5255,10 +5424,11 @@ static void setCreateDBOption(SCMCreateDbMsg* pMsg, SCreateDBInfo* pCreateDb) {
pMsg->replications = pCreateDb->replica;
pMsg->quorum = pCreateDb->quorum;
pMsg->ignoreExist = pCreateDb->ignoreExists;
+ pMsg->update = pCreateDb->update;
}
int32_t parseCreateDBOptions(SSqlCmd* pCmd, SCreateDBInfo* pCreateDbSql) {
- SCMCreateDbMsg* pMsg = (SCMCreateDbMsg*)(pCmd->payload);
+ SCreateDbMsg* pMsg = (SCreateDbMsg *)(pCmd->payload);
setCreateDBOption(pMsg, pCreateDbSql);
if (setKeepOption(pCmd, pMsg, pCreateDbSql) != TSDB_CODE_SUCCESS) {
@@ -5281,21 +5451,27 @@ void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t subClau
if (pParentQueryInfo->groupbyExpr.numOfGroupCols > 0) {
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, subClauseIndex);
+ SSqlExpr* pExpr = NULL;
+
size_t size = taosArrayGetSize(pQueryInfo->exprList);
-
- SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, (int32_t)size - 1);
+ if (size > 0) {
+ pExpr = tscSqlExprGet(pQueryInfo, (int32_t)size - 1);
+ }
- if (pExpr->functionId != TSDB_FUNC_TAG) {
- STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, tableIndex);
- int16_t columnInfo = tscGetJoinTagColIdByUid(&pQueryInfo->tagCond, pTableMetaInfo->pTableMeta->id.uid);
- SColumnIndex index = {.tableIndex = 0, .columnIndex = columnInfo};
- SSchema* pSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);
+ if (pExpr == NULL || pExpr->functionId != TSDB_FUNC_TAG) {
+ STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pParentQueryInfo, tableIndex);
- int16_t type = pSchema[index.columnIndex].type;
- int16_t bytes = pSchema[index.columnIndex].bytes;
- char* name = pSchema[index.columnIndex].name;
-
- pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TAG, &index, type, bytes, bytes, true);
+ int16_t colId = tscGetJoinTagColIdByUid(&pQueryInfo->tagCond, pTableMetaInfo->pTableMeta->id.uid);
+
+ SSchema* pTagSchema = tscGetColumnSchemaById(pTableMetaInfo->pTableMeta, colId);
+ int16_t colIndex = tscGetTagColIndexById(pTableMetaInfo->pTableMeta, colId);
+ SColumnIndex index = {.tableIndex = 0, .columnIndex = colIndex};
+
+ char* name = pTagSchema->name;
+ int16_t type = pTagSchema->type;
+ int16_t bytes = pTagSchema->bytes;
+
+ pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TAG, &index, type, bytes, getNewResColId(pQueryInfo), bytes, true);
pExpr->colInfo.flag = TSDB_COL_TAG;
// NOTE: tag column does not add to source column list
@@ -5332,7 +5508,9 @@ void doAddGroupColumnForSubquery(SQueryInfo* pQueryInfo, int32_t tagIndex) {
tscAddSpecialColumnForSelect(pQueryInfo, (int32_t)size, TSDB_FUNC_PRJ, &colIndex, pSchema, TSDB_COL_NORMAL);
- SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, (int32_t)size);
+ int32_t numOfFields = tscNumOfFields(pQueryInfo);
+ SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, numOfFields - 1);
+
doLimitOutputNormalColOfGroupby(pInfo->pSqlExpr);
pInfo->visible = false;
}
@@ -5598,7 +5776,7 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo
if (TSDB_COL_IS_TAG(pColIndex->flag)) {
SColumnIndex index = {.tableIndex = pQueryInfo->groupbyExpr.tableIndex, .columnIndex = colIndex};
- SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TAG, &index, type, bytes, bytes, true);
+ SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TAG, &index, type, bytes, getNewResColId(pQueryInfo), bytes, true);
memset(pExpr->aliasName, 0, sizeof(pExpr->aliasName));
tstrncpy(pExpr->aliasName, name, sizeof(pExpr->aliasName));
@@ -5761,7 +5939,7 @@ int32_t doLocalQueryProcess(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ
SColumnIndex ind = {0};
SSqlExpr* pExpr1 = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TAG_DUMMY, &ind, TSDB_DATA_TYPE_INT,
- tDataTypeDesc[TSDB_DATA_TYPE_INT].nSize, tDataTypeDesc[TSDB_DATA_TYPE_INT].nSize, false);
+ tDataTypeDesc[TSDB_DATA_TYPE_INT].nSize, getNewResColId(pQueryInfo), tDataTypeDesc[TSDB_DATA_TYPE_INT].nSize, false);
const char* name = (pExprList->a[0].aliasName != NULL)? pExprList->a[0].aliasName:functionsInfo[index].name;
tstrncpy(pExpr1->aliasName, name, tListLen(pExpr1->aliasName));
@@ -5770,7 +5948,7 @@ int32_t doLocalQueryProcess(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ
}
// can only perform the parameters based on the macro definitation
-int32_t tscCheckCreateDbParams(SSqlCmd* pCmd, SCMCreateDbMsg* pCreate) {
+int32_t tscCheckCreateDbParams(SSqlCmd* pCmd, SCreateDbMsg* pCreate) {
char msg[512] = {0};
if (pCreate->walLevel != -1 && (pCreate->walLevel < TSDB_MIN_WAL_LEVEL || pCreate->walLevel > TSDB_MAX_WAL_LEVEL)) {
@@ -5887,8 +6065,8 @@ int32_t doCheckForCreateTable(SSqlObj* pSql, int32_t subClauseIndex, SSqlInfo* p
SCreateTableSQL* pCreateTable = pInfo->pCreateTableInfo;
- tFieldList* pFieldList = pCreateTable->colInfo.pColumns;
- tFieldList* pTagList = pCreateTable->colInfo.pTagColumns;
+ SArray* pFieldList = pCreateTable->colInfo.pColumns;
+ SArray* pTagList = pCreateTable->colInfo.pTagColumns;
assert(pFieldList != NULL);
@@ -5910,18 +6088,23 @@ int32_t doCheckForCreateTable(SSqlObj* pSql, int32_t subClauseIndex, SSqlInfo* p
}
int32_t col = 0;
- for (; col < pFieldList->nField; ++col) {
- tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &pFieldList->p[col]);
+ size_t numOfFields = taosArrayGetSize(pFieldList);
+
+ for (; col < numOfFields; ++col) {
+ TAOS_FIELD* p = taosArrayGet(pFieldList, col);
+ tscFieldInfoAppend(&pQueryInfo->fieldsInfo, p);
}
- pCmd->numOfCols = (int16_t)pFieldList->nField;
+ pCmd->numOfCols = (int16_t)numOfFields;
if (pTagList != NULL) { // create super table[optional]
- for (int32_t i = 0; i < pTagList->nField; ++i) {
- tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &pTagList->p[i]);
+ size_t numOfTags = taosArrayGetSize(pTagList);
+ for (int32_t i = 0; i < numOfTags; ++i) {
+ TAOS_FIELD* p = taosArrayGet(pTagList, i);
+ tscFieldInfoAppend(&pQueryInfo->fieldsInfo, p);
}
- pCmd->count = pTagList->nField;
+ pCmd->count =(int32_t) numOfTags;
}
return TSDB_CODE_SUCCESS;
@@ -5962,14 +6145,15 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
// get meter meta from mnode
tstrncpy(pCreateTable->usingInfo.tagdata.name, pStableMeterMetaInfo->name, sizeof(pCreateTable->usingInfo.tagdata.name));
- tVariantList* pList = pInfo->pCreateTableInfo->usingInfo.pTagVals;
+ SArray* pList = pInfo->pCreateTableInfo->usingInfo.pTagVals;
code = tscGetTableMeta(pSql, pStableMeterMetaInfo);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
- if (tscGetNumOfTags(pStableMeterMetaInfo->pTableMeta) != pList->nExpr) {
+ size_t size = taosArrayGetSize(pList);
+ if (tscGetNumOfTags(pStableMeterMetaInfo->pTableMeta) != size) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
@@ -5983,18 +6167,19 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
}
int32_t ret = TSDB_CODE_SUCCESS;
- for (int32_t i = 0; i < pList->nExpr; ++i) {
+ for (int32_t i = 0; i < size; ++i) {
SSchema* pSchema = &pTagSchema[i];
-
+ tVariantListItem* pItem = taosArrayGet(pList, i);
+
char tagVal[TSDB_MAX_TAGS_LEN];
if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) {
- if (pList->a[i].pVar.nLen > pSchema->bytes) {
+ if (pItem->pVar.nLen > pSchema->bytes) {
tdDestroyKVRowBuilder(&kvRowBuilder);
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
}
- ret = tVariantDump(&(pList->a[i].pVar), tagVal, pSchema->type, true);
+ ret = tVariantDump(&(pItem->pVar), tagVal, pSchema->type, true);
// check again after the convert since it may be converted from binary to nchar.
if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) {
@@ -6061,13 +6246,13 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
- tVariantList* pSrcMeterName = pInfo->pCreateTableInfo->pSelect->from;
- if (pSrcMeterName == NULL || pSrcMeterName->nExpr == 0) {
+ SArray* pSrcMeterName = pInfo->pCreateTableInfo->pSelect->from;
+ if (pSrcMeterName == NULL || taosArrayGetSize(pSrcMeterName) == 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
- tVariant* pVar = &pSrcMeterName->a[0].pVar;
- SStrToken srcToken = {.z = pVar->pz, .n = pVar->nLen, .type = TK_STRING};
+ tVariantListItem* p1 = taosArrayGet(pSrcMeterName, 0);
+ SStrToken srcToken = {.z = p1->pVar.pz, .n = p1->pVar.nLen, .type = TK_STRING};
if (tscValidateName(&srcToken) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
@@ -6094,7 +6279,7 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
}
// set interval value
- if (parseIntervalClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
+ if (parseIntervalClause(pSql, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
} else {
if ((pQueryInfo->interval.interval > 0) &&
@@ -6132,7 +6317,7 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
- tVariantListItem* pItem = &pQuerySql->fillType->a[0];
+ tVariantListItem* pItem = taosArrayGet(pQuerySql->fillType, 0);
if (pItem->pVar.nType == TSDB_DATA_TYPE_BINARY) {
if (!((strncmp(pItem->pVar.pz, "none", 4) == 0 && pItem->pVar.nLen == 4) ||
(strncmp(pItem->pVar.pz, "null", 4) == 0 && pItem->pVar.nLen == 4))) {
@@ -6147,7 +6332,7 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
}
int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
- assert(pQuerySql != NULL && (pQuerySql->from == NULL || pQuerySql->from->nExpr > 0));
+ assert(pQuerySql != NULL && (pQuerySql->from == NULL || taosArrayGetSize(pQuerySql->from) > 0));
const char* msg0 = "invalid table name";
const char* msg2 = "point interpolation query needs timestamp";
@@ -6189,19 +6374,21 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
return doLocalQueryProcess(pCmd, pQueryInfo, pQuerySql);
}
- if (pQuerySql->from->nExpr > TSDB_MAX_JOIN_TABLE_NUM * 2) {
+ size_t fromSize = taosArrayGetSize(pQuerySql->from);
+ if (fromSize > TSDB_MAX_JOIN_TABLE_NUM * 2) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7);
}
pQueryInfo->command = TSDB_SQL_SELECT;
- if (pQuerySql->from->nExpr > 4) {
+ if (fromSize > 4) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg10);
}
// set all query tables, which are maybe more than one.
- for (int32_t i = 0; i < pQuerySql->from->nExpr; ) {
- tVariant* pTableItem = &pQuerySql->from->a[i].pVar;
+ for (int32_t i = 0; i < fromSize; ) {
+ tVariantListItem* item = taosArrayGet(pQuerySql->from, i);
+ tVariant* pTableItem = &item->pVar;
if (pTableItem->nType != TSDB_DATA_TYPE_BINARY) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg0);
@@ -6226,21 +6413,21 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
return code;
}
- tVariant* pTableItem1 = &pQuerySql->from->a[i + 1].pVar;
- if (pTableItem1->nType != TSDB_DATA_TYPE_BINARY) {
+ tVariantListItem* p1 = taosArrayGet(pQuerySql->from, i + 1);
+ if (p1->pVar.nType != TSDB_DATA_TYPE_BINARY) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg11);
}
- SStrToken aliasName = {.z = pTableItem1->pz, .n = pTableItem1->nLen, .type = TK_STRING};
+ SStrToken aliasName = {.z = p1->pVar.pz, .n = p1->pVar.nLen, .type = TK_STRING};
if (tscValidateName(&aliasName) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg11);
}
// has no table alias name
- if (memcmp(pTableItem->pz, pTableItem1->pz, pTableItem1->nLen) == 0) {
+ if (memcmp(pTableItem->pz, p1->pVar.pz, p1->pVar.nLen) == 0) {
extractTableName(pTableMetaInfo1->name, pTableMetaInfo1->aliasName);
} else {
- tstrncpy(pTableMetaInfo1->aliasName, pTableItem1->pz, sizeof(pTableMetaInfo1->aliasName));
+ tstrncpy(pTableMetaInfo1->aliasName, p1->pVar.pz, sizeof(pTableMetaInfo1->aliasName));
}
code = tscGetTableMeta(pSql, pTableMetaInfo1);
@@ -6251,7 +6438,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
i += 2;
}
- assert(pQueryInfo->numOfTables == pQuerySql->from->nExpr / 2);
+ assert(pQueryInfo->numOfTables == taosArrayGetSize(pQuerySql->from) / 2);
bool isSTable = false;
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
@@ -6285,12 +6472,12 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
pQueryInfo->window.ekey = pQueryInfo->window.ekey / 1000;
}
} else { // set the time rang
- if (pQuerySql->from->nExpr > 2) { // it is a join query, no wher clause is not allowed.
+ if (taosArrayGetSize(pQuerySql->from) > 2) { // it is a join query, no wher clause is not allowed.
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), "condition missing for join query ");
}
}
- int32_t joinQuery = (pQuerySql->from != NULL && pQuerySql->from->nExpr > 2);
+ int32_t joinQuery = (pQuerySql->from != NULL && taosArrayGetSize(pQuerySql->from) > 2);
if (parseSelectClause(pCmd, index, pQuerySql->pSelection, isSTable, joinQuery) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
@@ -6302,7 +6489,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
}
// set interval value
- if (parseIntervalClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
+ if (parseIntervalClause(pSql, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
} else {
if ((pQueryInfo->interval.interval > 0) &&
@@ -6424,6 +6611,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS
if (strcmp((*pExpr)->pSchema->name, p1->aliasName) == 0) {
(*pExpr)->pSchema->type = (uint8_t)p1->resType;
(*pExpr)->pSchema->bytes = p1->resBytes;
+ (*pExpr)->pSchema->colId = p1->resColId;
if (uid != NULL) {
*uid = p1->uid;
@@ -6433,7 +6621,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS
}
}
} else if (pSqlExpr->nSQLOptr == TK_ID) { // column name, normal column arithmetic expression
- SColumnIndex index = {0};
+ SColumnIndex index = COLUMN_INDEX_INITIALIZER;
int32_t ret = getColumnIndexByName(pCmd, &pSqlExpr->colInfo, pQueryInfo, &index);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
@@ -6473,7 +6661,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS
(*pExpr)->_node.pRight = pRight;
SStrToken t = {.type = pSqlExpr->nSQLOptr};
- (*pExpr)->_node.optr = getBinaryExprOptr(&t);
+ (*pExpr)->_node.optr = convertOptr(&t);
assert((*pExpr)->_node.optr != 0);
diff --git a/src/client/src/tscSchemaUtil.c b/src/client/src/tscSchemaUtil.c
index dfd707344c5ab3ec42b49859937f604fa477fe10..fcc93ffadc4f7dc62b79fffe245947799a770b40 100644
--- a/src/client/src/tscSchemaUtil.c
+++ b/src/client/src/tscSchemaUtil.c
@@ -118,7 +118,7 @@ SSchema* tscGetTableColumnSchema(const STableMeta* pTableMeta, int32_t colIndex)
}
// TODO for large number of columns, employ the binary search method
-SSchema* tscGetTableColumnSchemaById(STableMeta* pTableMeta, int16_t colId) {
+SSchema* tscGetColumnSchemaById(STableMeta* pTableMeta, int16_t colId) {
STableComInfo tinfo = tscGetTableInfo(pTableMeta);
for(int32_t i = 0; i < tinfo.numOfColumns + tinfo.numOfTags; ++i) {
@@ -130,17 +130,7 @@ SSchema* tscGetTableColumnSchemaById(STableMeta* pTableMeta, int16_t colId) {
return NULL;
}
-struct SSchema tscGetTbnameColumnSchema() {
- struct SSchema s = {
- .colId = TSDB_TBNAME_COLUMN_INDEX,
- .type = TSDB_DATA_TYPE_BINARY,
- .bytes = TSDB_TABLE_NAME_LEN
- };
-
- strcpy(s.name, TSQL_TBNAME_L);
- return s;
-}
-static void tscInitCorVgroupInfo(SCMCorVgroupInfo *corVgroupInfo, SCMVgroupInfo *vgroupInfo) {
+static void tscInitCorVgroupInfo(SCorVgroupInfo *corVgroupInfo, SVgroupInfo *vgroupInfo) {
corVgroupInfo->version = 0;
corVgroupInfo->inUse = 0;
corVgroupInfo->numOfEps = vgroupInfo->numOfEps;
@@ -166,7 +156,7 @@ STableMeta* tscCreateTableMetaFromMsg(STableMetaMsg* pTableMetaMsg, size_t* size
pTableMeta->id.tid = pTableMetaMsg->tid;
pTableMeta->id.uid = pTableMetaMsg->uid;
- SCMVgroupInfo* pVgroupInfo = &pTableMeta->vgroupInfo;
+ SVgroupInfo* pVgroupInfo = &pTableMeta->vgroupInfo;
pVgroupInfo->numOfEps = pTableMetaMsg->vgroup.numOfEps;
pVgroupInfo->vgId = pTableMetaMsg->vgroup.vgId;
@@ -177,7 +167,7 @@ STableMeta* tscCreateTableMetaFromMsg(STableMetaMsg* pTableMetaMsg, size_t* size
pVgroupInfo->epAddr[i].port = pEpMsg->port;
}
- tscInitCorVgroupInfo(&pTableMeta->corVgroupInfo, &pTableMeta->vgroupInfo);
+ tscInitCorVgroupInfo(&pTableMeta->corVgroupInfo, pVgroupInfo);
pTableMeta->sversion = pTableMetaMsg->sversion;
pTableMeta->tversion = pTableMetaMsg->tversion;
@@ -197,28 +187,6 @@ STableMeta* tscCreateTableMetaFromMsg(STableMetaMsg* pTableMetaMsg, size_t* size
return pTableMeta;
}
-/**
- * the TableMeta data format in memory is as follows:
- *
- * +--------------------+
- * |STableMeta Body data| sizeof(STableMeta)
- * +--------------------+
- * |Schema data | numOfTotalColumns * sizeof(SSchema)
- * +--------------------+
- * |Tags data | tag_col_1.bytes + tag_col_2.bytes + ....
- * +--------------------+
- *
- * @param pTableMeta
- * @return
- */
-char* tsGetTagsValue(STableMeta* pTableMeta) {
- int32_t offset = 0;
-// int32_t numOfTotalCols = pTableMeta->numOfColumns + pTableMeta->numOfTags;
-// uint32_t offset = sizeof(STableMeta) + numOfTotalCols * sizeof(SSchema);
-
- return ((char*)pTableMeta + offset);
-}
-
// todo refactor
UNUSED_FUNC static FORCE_INLINE char* skipSegments(char* input, char delim, int32_t num) {
for (int32_t i = 0; i < num; ++i) {
diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c
index a0841fa2344682facb4a6dc8666716e38a31ea1d..cbc5604a279fdb4fd0eab8e9cdb902e3c42a4832 100644
--- a/src/client/src/tscServer.c
+++ b/src/client/src/tscServer.c
@@ -48,7 +48,7 @@ static int32_t getWaitingTimeInterval(int32_t count) {
return initial * (2<<(count - 2));
}
-static void tscSetDnodeEpSet(SSqlObj* pSql, SCMVgroupInfo* pVgroupInfo) {
+static void tscSetDnodeEpSet(SSqlObj* pSql, SVgroupInfo* pVgroupInfo) {
assert(pSql != NULL && pVgroupInfo != NULL && pVgroupInfo->numOfEps > 0);
SRpcEpSet* pEpSet = &pSql->epSet;
@@ -100,7 +100,7 @@ void tscUpdateMgmtEpSet(SRpcEpSet *pEpSet) {
tscMgmtEpSet.epSet = *pEpSet;
taosCorEndWrite(&tscMgmtEpSet.version);
}
-static void tscDumpEpSetFromVgroupInfo(SCMCorVgroupInfo *pVgroupInfo, SRpcEpSet *pEpSet) {
+static void tscDumpEpSetFromVgroupInfo(SCorVgroupInfo *pVgroupInfo, SRpcEpSet *pEpSet) {
if (pVgroupInfo == NULL) { return;}
taosCorBeginRead(&pVgroupInfo->version);
int8_t inUse = pVgroupInfo->inUse;
@@ -117,14 +117,14 @@ static void tscUpdateVgroupInfo(SSqlObj *pObj, SRpcEpSet *pEpSet) {
SSqlCmd *pCmd = &pObj->cmd;
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
if (pTableMetaInfo == NULL || pTableMetaInfo->pTableMeta == NULL) { return;}
- SCMCorVgroupInfo *pVgroupInfo = &pTableMetaInfo->pTableMeta->corVgroupInfo;
+ SCorVgroupInfo *pVgroupInfo = &pTableMetaInfo->pTableMeta->corVgroupInfo;
taosCorBeginWrite(&pVgroupInfo->version);
tscDebug("before: Endpoint in use: %d", pVgroupInfo->inUse);
pVgroupInfo->inUse = pEpSet->inUse;
pVgroupInfo->numOfEps = pEpSet->numOfEps;
for (int32_t i = 0; i < pVgroupInfo->numOfEps; i++) {
- taosTFree(pVgroupInfo->epAddr[i].fqdn);
+ tfree(pVgroupInfo->epAddr[i].fqdn);
pVgroupInfo->epAddr[i].fqdn = strndup(pEpSet->fqdn[i], tListLen(pEpSet->fqdn[i]));
pVgroupInfo->epAddr[i].port = pEpSet->port[i];
}
@@ -150,7 +150,7 @@ void tscProcessHeartBeatRsp(void *param, TAOS_RES *tres, int code) {
if (pObj == NULL) return;
if (pObj != pObj->signature) {
- tscError("heart beat msg, pObj:%p, signature:%p invalid", pObj, pObj->signature);
+ tscError("heartbeat msg, pObj:%p, signature:%p invalid", pObj, pObj->signature);
return;
}
@@ -158,12 +158,12 @@ void tscProcessHeartBeatRsp(void *param, TAOS_RES *tres, int code) {
SSqlRes *pRes = &pSql->res;
if (code == 0) {
- SCMHeartBeatRsp *pRsp = (SCMHeartBeatRsp *)pRes->pRsp;
- SRpcEpSet * epSet = &pRsp->epSet;
+ SHeartBeatRsp *pRsp = (SHeartBeatRsp *)pRes->pRsp;
+ SRpcEpSet * epSet = &pRsp->epSet;
if (epSet->numOfEps > 0) {
tscEpSetHtons(epSet);
tscUpdateMgmtEpSet(epSet);
- }
+ }
pSql->pTscObj->connId = htonl(pRsp->connId);
@@ -175,44 +175,44 @@ void tscProcessHeartBeatRsp(void *param, TAOS_RES *tres, int code) {
if (pRsp->streamId) tscKillStream(pObj, htonl(pRsp->streamId));
}
} else {
- tscDebug("heartbeat failed, code:%s", tstrerror(code));
+ tscDebug("%p heartbeat failed, code:%s", pObj->pHb, tstrerror(code));
}
if (pObj->pHb != NULL) {
int32_t waitingDuring = tsShellActivityTimer * 500;
- tscDebug("%p start heartbeat in %dms", pSql, waitingDuring);
+ tscDebug("%p send heartbeat in %dms", pSql, waitingDuring);
- taosTmrReset(tscProcessActivityTimer, waitingDuring, pObj, tscTmr, &pObj->pTimer);
+ taosTmrReset(tscProcessActivityTimer, waitingDuring, (void *)pObj->rid, tscTmr, &pObj->pTimer);
} else {
tscDebug("%p start to close tscObj:%p, not send heartbeat again", pSql, pObj);
}
}
void tscProcessActivityTimer(void *handle, void *tmrId) {
- STscObj *pObj = (STscObj *)handle;
- if (pObj == NULL || pObj->signature != pObj) {
- return;
- }
+ int64_t rid = (int64_t) handle;
+ STscObj *pObj = taosAcquireRef(tscRefId, rid);
+ if (pObj == NULL) return;
SSqlObj* pHB = pObj->pHb;
- if (pObj->pTimer != tmrId || pHB == NULL) {
- return;
- }
void** p = taosCacheAcquireByKey(tscObjCache, &pHB, sizeof(TSDB_CACHE_PTR_TYPE));
if (p == NULL) {
tscWarn("%p HB object has been released already", pHB);
+ taosReleaseRef(tscRefId, pObj->rid);
return;
}
assert(*pHB->self == pHB);
+ pHB->retry = 0;
int32_t code = tscProcessSql(pHB);
taosCacheRelease(tscObjCache, (void**) &p, false);
if (code != TSDB_CODE_SUCCESS) {
tscError("%p failed to sent HB to server, reason:%s", pHB, tstrerror(code));
}
+
+ taosReleaseRef(tscRefId, rid);
}
int tscSendMsgToServer(SSqlObj *pSql) {
@@ -237,15 +237,11 @@ int tscSendMsgToServer(SSqlObj *pSql) {
.pCont = pMsg,
.contLen = pSql->cmd.payloadLen,
.ahandle = pSql,
- .handle = &pSql->pRpcCtx,
+ .handle = NULL,
.code = 0
};
- // NOTE: the rpc context should be acquired before sending data to server.
- // Otherwise, the pSql object may have been released already during the response function, which is
- // processMsgFromServer function. In the meanwhile, the assignment of the rpc context to sql object will absolutely
- // cause crash.
- rpcSendRequest(pObj->pDnodeConn, &pSql->epSet, &rpcMsg);
+ rpcSendRequest(pObj->pDnodeConn, &pSql->epSet, &rpcMsg, &pSql->rpcRid);
return TSDB_CODE_SUCCESS;
}
@@ -265,7 +261,7 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
SSqlCmd *pCmd = &pSql->cmd;
assert(*pSql->self == pSql);
- pSql->pRpcCtx = NULL;
+ pSql->rpcRid = -1;
if (pObj->signature != pObj) {
tscDebug("%p DB connection is closed, cmd:%d pObj:%p signature:%p", pSql, pCmd->command, pObj, pObj->signature);
@@ -361,7 +357,7 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
memcpy(pRes->pRsp, rpcMsg->pCont, pRes->rspLen);
}
} else {
- pRes->pRsp = NULL;
+ tfree(pRes->pRsp);
}
/*
@@ -481,14 +477,25 @@ int tscBuildFetchMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
int32_t vgIndex = pTableMetaInfo->vgroupIndex;
-
- SVgroupsInfo* pVgroupInfo = pTableMetaInfo->vgroupList;
- assert(pVgroupInfo->vgroups[vgIndex].vgId > 0 && vgIndex < pTableMetaInfo->vgroupList->numOfVgroups);
+ if (pTableMetaInfo->pVgroupTables == NULL) {
+ SVgroupsInfo *pVgroupInfo = pTableMetaInfo->vgroupList;
+ assert(pVgroupInfo->vgroups[vgIndex].vgId > 0 && vgIndex < pTableMetaInfo->vgroupList->numOfVgroups);
+
+ pRetrieveMsg->header.vgId = htonl(pVgroupInfo->vgroups[vgIndex].vgId);
+ tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d", pSql, pVgroupInfo->vgroups[vgIndex].vgId, vgIndex);
+ } else {
+ int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables);
+ assert(vgIndex >= 0 && vgIndex < numOfVgroups);
+
+ SVgroupTableInfo* pTableIdList = taosArrayGet(pTableMetaInfo->pVgroupTables, vgIndex);
- pRetrieveMsg->header.vgId = htonl(pVgroupInfo->vgroups[vgIndex].vgId);
+ pRetrieveMsg->header.vgId = htonl(pTableIdList->vgInfo.vgId);
+ tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d", pSql, pTableIdList->vgInfo.vgId, vgIndex);
+ }
} else {
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
pRetrieveMsg->header.vgId = htonl(pTableMeta->vgroupInfo.vgId);
+ tscDebug("%p build fetch msg from only one vgroup, vgId:%d", pSql, pTableMeta->vgroupInfo.vgId);
}
pSql->cmd.payloadLen = sizeof(SRetrieveTableMsg);
@@ -538,11 +545,28 @@ static int32_t tscEstimateQueryMsgSize(SSqlCmd *pCmd, int32_t clauseIndex) {
SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, clauseIndex);
int32_t srcColListSize = (int32_t)(taosArrayGetSize(pQueryInfo->colList) * sizeof(SColumnInfo));
-
- size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo);
- int32_t exprSize = (int32_t)(sizeof(SSqlFuncMsg) * numOfExprs);
-
- return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + exprSize + 4096;
+
+ size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo);
+ int32_t exprSize = (int32_t)(sizeof(SSqlFuncMsg) * numOfExprs * 2);
+
+ int32_t tsBufSize = (pQueryInfo->tsBuf != NULL) ? pQueryInfo->tsBuf->fileSize : 0;
+
+ int32_t tableSerialize = 0;
+ STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+ if (pTableMetaInfo->pVgroupTables != NULL) {
+ size_t numOfGroups = taosArrayGetSize(pTableMetaInfo->pVgroupTables);
+
+ int32_t totalTables = 0;
+ for (int32_t i = 0; i < numOfGroups; ++i) {
+ SVgroupTableInfo *pTableInfo = taosArrayGet(pTableMetaInfo->pVgroupTables, i);
+ totalTables += (int32_t) taosArrayGetSize(pTableInfo->itemList);
+ }
+
+ tableSerialize = totalTables * sizeof(STableIdInfo);
+ }
+
+ return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + exprSize + tsBufSize +
+ tableSerialize + 4096;
}
static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char *pMsg) {
@@ -552,7 +576,7 @@ static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char
STableMeta * pTableMeta = pTableMetaInfo->pTableMeta;
if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || pTableMetaInfo->pVgroupTables == NULL) {
- SCMVgroupInfo* pVgroupInfo = NULL;
+ SVgroupInfo* pVgroupInfo = NULL;
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
int32_t index = pTableMetaInfo->vgroupIndex;
assert(index >= 0);
@@ -662,19 +686,19 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
pQueryMsg->limit = htobe64(pQueryInfo->limit.limit);
pQueryMsg->offset = htobe64(pQueryInfo->limit.offset);
pQueryMsg->numOfCols = htons((int16_t)taosArrayGetSize(pQueryInfo->colList));
- pQueryMsg->interval.interval = htobe64(pQueryInfo->interval.interval);
- pQueryMsg->interval.sliding = htobe64(pQueryInfo->interval.sliding);
+ pQueryMsg->interval.interval = htobe64(pQueryInfo->interval.interval);
+ pQueryMsg->interval.sliding = htobe64(pQueryInfo->interval.sliding);
pQueryMsg->interval.offset = htobe64(pQueryInfo->interval.offset);
pQueryMsg->interval.intervalUnit = pQueryInfo->interval.intervalUnit;
- pQueryMsg->interval.slidingUnit = pQueryInfo->interval.slidingUnit;
- pQueryMsg->interval.offsetUnit = pQueryInfo->interval.offsetUnit;
+ pQueryMsg->interval.slidingUnit = pQueryInfo->interval.slidingUnit;
+ pQueryMsg->interval.offsetUnit = pQueryInfo->interval.offsetUnit;
pQueryMsg->numOfGroupCols = htons(pQueryInfo->groupbyExpr.numOfGroupCols);
pQueryMsg->numOfTags = htonl(numOfTags);
pQueryMsg->tagNameRelType = htons(pQueryInfo->tagCond.relType);
pQueryMsg->queryType = htonl(pQueryInfo->type);
size_t numOfOutput = tscSqlExprNumOfExprs(pQueryInfo);
- pQueryMsg->numOfOutput = htons((int16_t)numOfOutput);
+ pQueryMsg->numOfOutput = htons((int16_t)numOfOutput); // this is the stage one output column number
// set column list ids
size_t numOfCols = taosArrayGetSize(pQueryInfo->colList);
@@ -736,12 +760,15 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
return TSDB_CODE_TSC_INVALID_SQL;
}
+ assert(pExpr->resColId < 0);
+
pSqlFuncExpr->colInfo.colId = htons(pExpr->colInfo.colId);
pSqlFuncExpr->colInfo.colIndex = htons(pExpr->colInfo.colIndex);
pSqlFuncExpr->colInfo.flag = htons(pExpr->colInfo.flag);
pSqlFuncExpr->functionId = htons(pExpr->functionId);
pSqlFuncExpr->numOfParams = htons(pExpr->numOfParams);
+ pSqlFuncExpr->resColId = htons(pExpr->resColId);
pMsg += sizeof(SSqlFuncMsg);
for (int32_t j = 0; j < pExpr->numOfParams; ++j) {
@@ -759,7 +786,74 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
pSqlFuncExpr = (SSqlFuncMsg *)pMsg;
}
-
+
+ size_t output = tscNumOfFields(pQueryInfo);
+
+ if (tscIsSecondStageQuery(pQueryInfo)) {
+ pQueryMsg->secondStageOutput = htonl((int32_t) output);
+
+ SSqlFuncMsg *pSqlFuncExpr1 = (SSqlFuncMsg *)pMsg;
+
+ for (int32_t i = 0; i < output; ++i) {
+ SInternalField* pField = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i);
+ SSqlExpr *pExpr = pField->pSqlExpr;
+ if (pExpr != NULL) {
+ if (!tscValidateColumnId(pTableMetaInfo, pExpr->colInfo.colId, pExpr->numOfParams)) {
+ tscError("%p table schema is not matched with parsed sql", pSql);
+ return TSDB_CODE_TSC_INVALID_SQL;
+ }
+
+ pSqlFuncExpr1->colInfo.colId = htons(pExpr->colInfo.colId);
+ pSqlFuncExpr1->colInfo.colIndex = htons(pExpr->colInfo.colIndex);
+ pSqlFuncExpr1->colInfo.flag = htons(pExpr->colInfo.flag);
+
+ pSqlFuncExpr1->functionId = htons(pExpr->functionId);
+ pSqlFuncExpr1->numOfParams = htons(pExpr->numOfParams);
+ pMsg += sizeof(SSqlFuncMsg);
+
+ for (int32_t j = 0; j < pExpr->numOfParams; ++j) {
+ // todo add log
+ pSqlFuncExpr1->arg[j].argType = htons((uint16_t)pExpr->param[j].nType);
+ pSqlFuncExpr1->arg[j].argBytes = htons(pExpr->param[j].nLen);
+
+ if (pExpr->param[j].nType == TSDB_DATA_TYPE_BINARY) {
+ memcpy(pMsg, pExpr->param[j].pz, pExpr->param[j].nLen);
+ pMsg += pExpr->param[j].nLen;
+ } else {
+ pSqlFuncExpr1->arg[j].argValue.i64 = htobe64(pExpr->param[j].i64Key);
+ }
+ }
+
+ pSqlFuncExpr1 = (SSqlFuncMsg *)pMsg;
+ } else {
+ assert(pField->pArithExprInfo != NULL);
+ SExprInfo* pExprInfo = pField->pArithExprInfo;
+
+ pSqlFuncExpr1->colInfo.colId = htons(pExprInfo->base.colInfo.colId);
+ pSqlFuncExpr1->functionId = htons(pExprInfo->base.functionId);
+ pSqlFuncExpr1->numOfParams = htons(pExprInfo->base.numOfParams);
+ pMsg += sizeof(SSqlFuncMsg);
+
+ for (int32_t j = 0; j < pExprInfo->base.numOfParams; ++j) {
+ // todo add log
+ pSqlFuncExpr1->arg[j].argType = htons((uint16_t)pExprInfo->base.arg[j].argType);
+ pSqlFuncExpr1->arg[j].argBytes = htons(pExprInfo->base.arg[j].argBytes);
+
+ if (pExprInfo->base.arg[j].argType == TSDB_DATA_TYPE_BINARY) {
+ memcpy(pMsg, pExprInfo->base.arg[j].argValue.pz, pExprInfo->base.arg[j].argBytes);
+ pMsg += pExprInfo->base.arg[j].argBytes;
+ } else {
+ pSqlFuncExpr1->arg[j].argValue.i64 = htobe64(pExprInfo->base.arg[j].argValue.i64);
+ }
+ }
+
+ pSqlFuncExpr1 = (SSqlFuncMsg *)pMsg;
+ }
+ }
+ } else {
+ pQueryMsg->secondStageOutput = 0;
+ }
+
// serialize the table info (sid, uid, tags)
pMsg = doSerializeTableInfo(pQueryMsg, pSql, pMsg);
@@ -786,7 +880,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
}
if (pQueryInfo->fillType != TSDB_FILL_NONE) {
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
+ for (int32_t i = 0; i < tscSqlExprNumOfExprs(pQueryInfo); ++i) {
*((int64_t *)pMsg) = htobe64(pQueryInfo->fillVal[i]);
pMsg += sizeof(pQueryInfo->fillVal[0]);
}
@@ -846,41 +940,25 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
// compressed ts block
pQueryMsg->tsOffset = htonl((int32_t)(pMsg - pCmd->payload));
- int32_t tsLen = 0;
- int32_t numOfBlocks = 0;
if (pQueryInfo->tsBuf != NULL) {
- STSVnodeBlockInfo *pBlockInfo = tsBufGetVnodeBlockInfo(pQueryInfo->tsBuf, pTableMetaInfo->vgroupIndex);
- assert(QUERY_IS_JOIN_QUERY(pQueryInfo->type) && pBlockInfo != NULL); // this query should not be sent
-
- // todo refactor
- if (fseek(pQueryInfo->tsBuf->f, pBlockInfo->offset, SEEK_SET) != 0) {
- int code = TAOS_SYSTEM_ERROR(ferror(pQueryInfo->tsBuf->f));
- tscError("%p: fseek failed: %s", pSql, tstrerror(code));
- return code;
- }
-
- size_t s = fread(pMsg, 1, pBlockInfo->compLen, pQueryInfo->tsBuf->f);
- if (s != pBlockInfo->compLen) {
- int code = TAOS_SYSTEM_ERROR(ferror(pQueryInfo->tsBuf->f));
- tscError("%p: fread didn't return expected data: %s", pSql, tstrerror(code));
+ // note: here used the index instead of actual vnode id.
+ int32_t vnodeIndex = pTableMetaInfo->vgroupIndex;
+ int32_t code = dumpFileBlockByGroupId(pQueryInfo->tsBuf, vnodeIndex, pMsg, &pQueryMsg->tsLen, &pQueryMsg->tsNumOfBlocks);
+ if (code != TSDB_CODE_SUCCESS) {
return code;
}
- pMsg += pBlockInfo->compLen;
- tsLen = pBlockInfo->compLen;
- numOfBlocks = pBlockInfo->numOfBlocks;
- }
+ pMsg += pQueryMsg->tsLen;
- pQueryMsg->tsLen = htonl(tsLen);
- pQueryMsg->tsNumOfBlocks = htonl(numOfBlocks);
- if (pQueryInfo->tsBuf != NULL) {
pQueryMsg->tsOrder = htonl(pQueryInfo->tsBuf->tsOrder);
+ pQueryMsg->tsLen = htonl(pQueryMsg->tsLen);
+ pQueryMsg->tsNumOfBlocks = htonl(pQueryMsg->tsNumOfBlocks);
}
int32_t msgLen = (int32_t)(pMsg - pCmd->payload);
- tscDebug("%p msg built success,len:%d bytes", pSql, msgLen);
+ tscDebug("%p msg built success, len:%d bytes", pSql, msgLen);
pCmd->payloadLen = msgLen;
pSql->cmd.msgType = TSDB_MSG_TYPE_QUERY;
@@ -892,10 +970,10 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int32_t tscBuildCreateDbMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
- pCmd->payloadLen = sizeof(SCMCreateDbMsg);
+ pCmd->payloadLen = sizeof(SCreateDbMsg);
pCmd->msgType = TSDB_MSG_TYPE_CM_CREATE_DB;
- SCMCreateDbMsg *pCreateDbMsg = (SCMCreateDbMsg*)pCmd->payload;
+ SCreateDbMsg *pCreateDbMsg = (SCreateDbMsg *)pCmd->payload;
assert(pCmd->numOfClause == 1);
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
@@ -906,13 +984,13 @@ int32_t tscBuildCreateDbMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int32_t tscBuildCreateDnodeMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
- pCmd->payloadLen = sizeof(SCMCreateDnodeMsg);
+ pCmd->payloadLen = sizeof(SCreateDnodeMsg);
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, pCmd->payloadLen)) {
tscError("%p failed to malloc for query msg", pSql);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- SCMCreateDnodeMsg *pCreate = (SCMCreateDnodeMsg *)pCmd->payload;
+ SCreateDnodeMsg *pCreate = (SCreateDnodeMsg *)pCmd->payload;
strncpy(pCreate->ep, pInfo->pDCLInfo->a[0].z, pInfo->pDCLInfo->a[0].n);
pCmd->msgType = TSDB_MSG_TYPE_CM_CREATE_DNODE;
@@ -922,13 +1000,13 @@ int32_t tscBuildCreateDnodeMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int32_t tscBuildAcctMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
- pCmd->payloadLen = sizeof(SCMCreateAcctMsg);
+ pCmd->payloadLen = sizeof(SCreateAcctMsg);
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, pCmd->payloadLen)) {
tscError("%p failed to malloc for query msg", pSql);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- SCMCreateAcctMsg *pAlterMsg = (SCMCreateAcctMsg *)pCmd->payload;
+ SCreateAcctMsg *pAlterMsg = (SCreateAcctMsg *)pCmd->payload;
SStrToken *pName = &pInfo->pDCLInfo->user.user;
SStrToken *pPwd = &pInfo->pDCLInfo->user.passwd;
@@ -967,14 +1045,14 @@ int32_t tscBuildAcctMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int32_t tscBuildUserMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
- pCmd->payloadLen = sizeof(SCMCreateUserMsg);
+ pCmd->payloadLen = sizeof(SCreateUserMsg);
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, pCmd->payloadLen)) {
tscError("%p failed to malloc for query msg", pSql);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- SCMCreateUserMsg *pAlterMsg = (SCMCreateUserMsg*)pCmd->payload;
+ SCreateUserMsg *pAlterMsg = (SCreateUserMsg *)pCmd->payload;
SUserInfo *pUser = &pInfo->pDCLInfo->user;
strncpy(pAlterMsg->user, pUser->user.z, pUser->user.n);
@@ -999,21 +1077,21 @@ int32_t tscBuildUserMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int32_t tscBuildCfgDnodeMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
- pCmd->payloadLen = sizeof(SCMCfgDnodeMsg);
+ pCmd->payloadLen = sizeof(SCfgDnodeMsg);
pCmd->msgType = TSDB_MSG_TYPE_CM_CONFIG_DNODE;
return TSDB_CODE_SUCCESS;
}
int32_t tscBuildDropDbMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
- pCmd->payloadLen = sizeof(SCMDropDbMsg);
+ pCmd->payloadLen = sizeof(SDropDbMsg);
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, pCmd->payloadLen)) {
tscError("%p failed to malloc for query msg", pSql);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- SCMDropDbMsg *pDropDbMsg = (SCMDropDbMsg*)pCmd->payload;
+ SDropDbMsg *pDropDbMsg = (SDropDbMsg*)pCmd->payload;
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
tstrncpy(pDropDbMsg->db, pTableMetaInfo->name, sizeof(pDropDbMsg->db));
@@ -1043,13 +1121,13 @@ int32_t tscBuildDropTableMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int32_t tscBuildDropDnodeMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
- pCmd->payloadLen = sizeof(SCMDropDnodeMsg);
+ pCmd->payloadLen = sizeof(SDropDnodeMsg);
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, pCmd->payloadLen)) {
tscError("%p failed to malloc for query msg", pSql);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- SCMDropDnodeMsg *pDrop = (SCMDropDnodeMsg *)pCmd->payload;
+ SDropDnodeMsg * pDrop = (SDropDnodeMsg *)pCmd->payload;
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
tstrncpy(pDrop->ep, pTableMetaInfo->name, sizeof(pDrop->ep));
pCmd->msgType = TSDB_MSG_TYPE_CM_DROP_DNODE;
@@ -1059,7 +1137,7 @@ int32_t tscBuildDropDnodeMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int32_t tscBuildDropUserMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
- pCmd->payloadLen = sizeof(SCMDropUserMsg);
+ pCmd->payloadLen = sizeof(SDropUserMsg);
pCmd->msgType = TSDB_MSG_TYPE_CM_DROP_USER;
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, pCmd->payloadLen)) {
@@ -1067,7 +1145,7 @@ int32_t tscBuildDropUserMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- SCMDropUserMsg *pDropMsg = (SCMDropUserMsg*)pCmd->payload;
+ SDropUserMsg * pDropMsg = (SDropUserMsg *)pCmd->payload;
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
tstrncpy(pDropMsg->user, pTableMetaInfo->name, sizeof(pDropMsg->user));
@@ -1076,7 +1154,7 @@ int32_t tscBuildDropUserMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int32_t tscBuildDropAcctMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
- pCmd->payloadLen = sizeof(SCMDropUserMsg);
+ pCmd->payloadLen = sizeof(SDropUserMsg);
pCmd->msgType = TSDB_MSG_TYPE_CM_DROP_ACCT;
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, pCmd->payloadLen)) {
@@ -1084,7 +1162,7 @@ int32_t tscBuildDropAcctMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- SCMDropUserMsg *pDropMsg = (SCMDropUserMsg*)pCmd->payload;
+ SDropUserMsg * pDropMsg = (SDropUserMsg *)pCmd->payload;
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
tstrncpy(pDropMsg->user, pTableMetaInfo->name, sizeof(pDropMsg->user));
@@ -1093,14 +1171,14 @@ int32_t tscBuildDropAcctMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int32_t tscBuildUseDbMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
- pCmd->payloadLen = sizeof(SCMUseDbMsg);
+ pCmd->payloadLen = sizeof(SUseDbMsg);
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, pCmd->payloadLen)) {
tscError("%p failed to malloc for query msg", pSql);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- SCMUseDbMsg *pUseDbMsg = (SCMUseDbMsg*)pCmd->payload;
+ SUseDbMsg *pUseDbMsg = (SUseDbMsg *)pCmd->payload;
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
strcpy(pUseDbMsg->db, pTableMetaInfo->name);
pCmd->msgType = TSDB_MSG_TYPE_CM_USE_DB;
@@ -1112,14 +1190,14 @@ int32_t tscBuildShowMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
STscObj *pObj = pSql->pTscObj;
SSqlCmd *pCmd = &pSql->cmd;
pCmd->msgType = TSDB_MSG_TYPE_CM_SHOW;
- pCmd->payloadLen = sizeof(SCMShowMsg) + 100;
+ pCmd->payloadLen = sizeof(SShowMsg) + 100;
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, pCmd->payloadLen)) {
tscError("%p failed to malloc for query msg", pSql);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- SCMShowMsg *pShowMsg = (SCMShowMsg*)pCmd->payload;
+ SShowMsg *pShowMsg = (SShowMsg *)pCmd->payload;
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
size_t nameLen = strlen(pTableMetaInfo->name);
@@ -1146,13 +1224,13 @@ int32_t tscBuildShowMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
pShowMsg->payloadLen = htons(pEpAddr->n);
}
- pCmd->payloadLen = sizeof(SCMShowMsg) + pShowMsg->payloadLen;
+ pCmd->payloadLen = sizeof(SShowMsg) + pShowMsg->payloadLen;
return TSDB_CODE_SUCCESS;
}
int32_t tscBuildKillMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
- pCmd->payloadLen = sizeof(SCMKillQueryMsg);
+ pCmd->payloadLen = sizeof(SKillQueryMsg);
switch (pCmd->command) {
case TSDB_SQL_KILL_QUERY:
@@ -1264,8 +1342,7 @@ int tscBuildCreateTableMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int tscEstimateAlterTableMsgLength(SSqlCmd *pCmd) {
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
- return minMsgSize() + sizeof(SCMAlterTableMsg) + sizeof(SSchema) * tscNumOfFields(pQueryInfo) +
- TSDB_EXTRA_PAYLOAD_SIZE;
+ return minMsgSize() + sizeof(SAlterTableMsg) + sizeof(SSchema) * tscNumOfFields(pQueryInfo) + TSDB_EXTRA_PAYLOAD_SIZE;
}
int tscBuildAlterTableMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
@@ -1284,7 +1361,7 @@ int tscBuildAlterTableMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- SCMAlterTableMsg *pAlterTableMsg = (SCMAlterTableMsg *)pCmd->payload;
+ SAlterTableMsg *pAlterTableMsg = (SAlterTableMsg *)pCmd->payload;
tscGetDBInfoFromTableFullName(pTableMetaInfo->name, pAlterTableMsg->db);
strcpy(pAlterTableMsg->tableId, pTableMetaInfo->name);
@@ -1333,10 +1410,10 @@ int tscBuildUpdateTagMsg(SSqlObj* pSql, SSqlInfo *pInfo) {
int tscAlterDbMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
- pCmd->payloadLen = sizeof(SCMAlterDbMsg);
+ pCmd->payloadLen = sizeof(SAlterDbMsg);
pCmd->msgType = TSDB_MSG_TYPE_CM_ALTER_DB;
- SCMAlterDbMsg *pAlterDbMsg = (SCMAlterDbMsg*)pCmd->payload;
+ SAlterDbMsg *pAlterDbMsg = (SAlterDbMsg* )pCmd->payload;
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
tstrncpy(pAlterDbMsg->db, pTableMetaInfo->name, sizeof(pAlterDbMsg->db));
@@ -1361,19 +1438,6 @@ int tscBuildRetrieveFromMgmtMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
return TSDB_CODE_SUCCESS;
}
-static int tscSetResultPointer(SQueryInfo *pQueryInfo, SSqlRes *pRes) {
- if (tscCreateResPointerInfo(pRes, pQueryInfo) != TSDB_CODE_SUCCESS) {
- return pRes->code;
- }
-
- for (int i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
- int16_t offset = tscFieldInfoGetOffset(pQueryInfo, i);
- pRes->tsrow[i] = (unsigned char*)((char*) pRes->data + offset * pRes->numOfRows);
- }
-
- return 0;
-}
-
/*
* this function can only be called once.
* by using pRes->rspType to denote its status
@@ -1384,15 +1448,18 @@ static int tscLocalResultCommonBuilder(SSqlObj *pSql, int32_t numOfRes) {
SSqlRes *pRes = &pSql->res;
SSqlCmd *pCmd = &pSql->cmd;
- SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
-
pRes->code = TSDB_CODE_SUCCESS;
if (pRes->rspType == 0) {
pRes->numOfRows = numOfRes;
pRes->row = 0;
pRes->rspType = 1;
- tscSetResultPointer(pQueryInfo, pRes);
+ SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+ if (tscCreateResPointerInfo(pRes, pQueryInfo) != TSDB_CODE_SUCCESS) {
+ return pRes->code;
+ }
+
+ tscSetResRawPtr(pRes, pQueryInfo);
} else {
tscResetForNextRetrieve(pRes);
}
@@ -1436,10 +1503,11 @@ int tscProcessRetrieveLocalMergeRsp(SSqlObj *pSql) {
}
pRes->code = tscDoLocalMerge(pSql);
- SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
if (pRes->code == TSDB_CODE_SUCCESS && pRes->numOfRows > 0) {
+ SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
tscCreateResPointerInfo(pRes, pQueryInfo);
+ tscSetResRawPtr(pRes, pQueryInfo);
}
pRes->row = 0;
@@ -1461,14 +1529,14 @@ int tscBuildConnectMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
STscObj *pObj = pSql->pTscObj;
SSqlCmd *pCmd = &pSql->cmd;
pCmd->msgType = TSDB_MSG_TYPE_CM_CONNECT;
- pCmd->payloadLen = sizeof(SCMConnectMsg);
+ pCmd->payloadLen = sizeof(SConnectMsg);
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, pCmd->payloadLen)) {
tscError("%p failed to malloc for query msg", pSql);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- SCMConnectMsg *pConnect = (SCMConnectMsg*)pCmd->payload;
+ SConnectMsg *pConnect = (SConnectMsg*)pCmd->payload;
// TODO refactor full_name
char *db; // ugly code to move the space
@@ -1490,11 +1558,11 @@ int tscBuildTableMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
- SCMTableInfoMsg* pInfoMsg = (SCMTableInfoMsg *)pCmd->payload;
+ STableInfoMsg *pInfoMsg = (STableInfoMsg *)pCmd->payload;
strcpy(pInfoMsg->tableId, pTableMetaInfo->name);
pInfoMsg->createFlag = htons(pSql->cmd.autoCreated ? 1 : 0);
- char* pMsg = (char*)pInfoMsg + sizeof(SCMTableInfoMsg);
+ char *pMsg = (char *)pInfoMsg + sizeof(STableInfoMsg);
size_t len = htonl(pCmd->tagData.dataLen);
if (pSql->cmd.autoCreated) {
@@ -1513,7 +1581,7 @@ int tscBuildTableMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
/**
* multi table meta req pkg format:
- * | SMgmtHead | SCMMultiTableInfoMsg | tableId0 | tableId1 | tableId2 | ......
+ * | SMgmtHead | SMultiTableInfoMsg | tableId0 | tableId1 | tableId2 | ......
* no used 4B
**/
int tscBuildMultiMeterMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
@@ -1531,16 +1599,16 @@ int tscBuildMultiMeterMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SMgmtHead *pMgmt = (SMgmtHead *)(pCmd->payload + tsRpcHeadSize);
memset(pMgmt->db, 0, TSDB_TABLE_FNAME_LEN); // server don't need the db
- SCMMultiTableInfoMsg *pInfoMsg = (SCMMultiTableInfoMsg *)(pCmd->payload + tsRpcHeadSize + sizeof(SMgmtHead));
+ SMultiTableInfoMsg *pInfoMsg = (SMultiTableInfoMsg *)(pCmd->payload + tsRpcHeadSize + sizeof(SMgmtHead));
pInfoMsg->numOfTables = htonl((int32_t)pCmd->count);
if (pCmd->payloadLen > 0) {
memcpy(pInfoMsg->tableIds, tmpData, pCmd->payloadLen);
}
- taosTFree(tmpData);
+ tfree(tmpData);
- pCmd->payloadLen += sizeof(SMgmtHead) + sizeof(SCMMultiTableInfoMsg);
+ pCmd->payloadLen += sizeof(SMgmtHead) + sizeof(SMultiTableInfoMsg);
pCmd->msgType = TSDB_MSG_TYPE_CM_TABLES_META;
assert(pCmd->payloadLen + minMsgSize() <= pCmd->allocSize);
@@ -1585,12 +1653,12 @@ int tscBuildSTableVgroupMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
char* pMsg = pCmd->payload;
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
-
- SCMSTableVgroupMsg *pStableVgroupMsg = (SCMSTableVgroupMsg *) pMsg;
+
+ SSTableVgroupMsg *pStableVgroupMsg = (SSTableVgroupMsg *)pMsg;
pStableVgroupMsg->numOfTables = htonl(pQueryInfo->numOfTables);
- pMsg += sizeof(SCMSTableVgroupMsg);
-
- for(int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
+ pMsg += sizeof(SSTableVgroupMsg);
+
+ for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, i);
size_t size = sizeof(pTableMetaInfo->name);
tstrncpy(pMsg, pTableMetaInfo->name, size);
@@ -1623,14 +1691,17 @@ int tscBuildHeartBeatMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
numOfStreams++;
}
- int size = numOfQueries * sizeof(SQueryDesc) + numOfStreams * sizeof(SStreamDesc) + sizeof(SCMHeartBeatMsg) + 100;
+ int size = numOfQueries * sizeof(SQueryDesc) + numOfStreams * sizeof(SStreamDesc) + sizeof(SHeartBeatMsg) + 100;
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, size)) {
pthread_mutex_unlock(&pObj->mutex);
- tscError("%p failed to malloc for heartbeat msg", pSql);
+ tscError("%p failed to create heartbeat msg", pSql);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- SCMHeartBeatMsg *pHeartbeat = (SCMHeartBeatMsg *)pCmd->payload;
+ // TODO the expired hb and client can not be identified by server till now.
+ SHeartBeatMsg *pHeartbeat = (SHeartBeatMsg *)pCmd->payload;
+ tstrncpy(pHeartbeat->clientVer, version, tListLen(pHeartbeat->clientVer));
+
pHeartbeat->numOfQueries = numOfQueries;
pHeartbeat->numOfStreams = numOfStreams;
@@ -1704,8 +1775,7 @@ int tscProcessTableMetaRsp(SSqlObj *pSql) {
pTableMetaInfo->pTableMeta = (STableMeta *) taosCachePut(tscMetaCache, pTableMetaInfo->name,
strlen(pTableMetaInfo->name), pTableMeta, size, tsTableMetaKeepTimer * 1000);
-
- // todo handle out of memory case
+
if (pTableMetaInfo->pTableMeta == NULL) {
free(pTableMeta);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
@@ -1719,7 +1789,7 @@ int tscProcessTableMetaRsp(SSqlObj *pSql) {
/**
* multi table meta rsp pkg format:
- * | STaosRsp | ieType | SCMMultiTableInfoMsg | SMeterMeta0 | SSchema0 | SMeterMeta1 | SSchema1 | SMeterMeta2 | SSchema2
+ * | STaosRsp | ieType | SMultiTableInfoMsg | SMeterMeta0 | SSchema0 | SMeterMeta1 | SSchema1 | SMeterMeta2 | SSchema2
* |...... 1B 1B 4B
**/
int tscProcessMultiMeterMetaRsp(SSqlObj *pSql) {
@@ -1736,9 +1806,9 @@ int tscProcessMultiMeterMetaRsp(SSqlObj *pSql) {
rsp++;
- SCMMultiTableInfoMsg *pInfo = (SCMMultiTableInfoMsg *)rsp;
+ SMultiTableInfoMsg *pInfo = (SMultiTableInfoMsg *)rsp;
totalNum = htonl(pInfo->numOfTables);
- rsp += sizeof(SCMMultiTableInfoMsg);
+ rsp += sizeof(SMultiTableInfoMsg);
for (i = 0; i < totalNum; i++) {
SMultiTableMeta *pMultiMeta = (SMultiTableMeta *)rsp;
@@ -1830,10 +1900,10 @@ int tscProcessSTableVgroupRsp(SSqlObj *pSql) {
SSqlRes* pRes = &pSql->res;
// NOTE: the order of several table must be preserved.
- SCMSTableVgroupRspMsg *pStableVgroup = (SCMSTableVgroupRspMsg *)pRes->pRsp;
+ SSTableVgroupRspMsg *pStableVgroup = (SSTableVgroupRspMsg *)pRes->pRsp;
pStableVgroup->numOfTables = htonl(pStableVgroup->numOfTables);
- char* pMsg = pRes->pRsp + sizeof(SCMSTableVgroupRspMsg);
-
+ char *pMsg = pRes->pRsp + sizeof(SSTableVgroupRspMsg);
+
// master sqlObj locates in param
SSqlObj* parent = pSql->param;
assert(parent != NULL);
@@ -1845,18 +1915,18 @@ int tscProcessSTableVgroupRsp(SSqlObj *pSql) {
SVgroupsMsg * pVgroupMsg = (SVgroupsMsg *) pMsg;
pVgroupMsg->numOfVgroups = htonl(pVgroupMsg->numOfVgroups);
- size_t size = sizeof(SCMVgroupMsg) * pVgroupMsg->numOfVgroups + sizeof(SVgroupsMsg);
+ size_t size = sizeof(SVgroupMsg) * pVgroupMsg->numOfVgroups + sizeof(SVgroupsMsg);
- size_t vgroupsz = sizeof(SCMVgroupInfo) * pVgroupMsg->numOfVgroups + sizeof(SVgroupsInfo);
+ size_t vgroupsz = sizeof(SVgroupInfo) * pVgroupMsg->numOfVgroups + sizeof(SVgroupsInfo);
pInfo->vgroupList = calloc(1, vgroupsz);
assert(pInfo->vgroupList != NULL);
pInfo->vgroupList->numOfVgroups = pVgroupMsg->numOfVgroups;
for (int32_t j = 0; j < pInfo->vgroupList->numOfVgroups; ++j) {
//just init, no need to lock
- SCMVgroupInfo *pVgroups = &pInfo->vgroupList->vgroups[j];
+ SVgroupInfo *pVgroups = &pInfo->vgroupList->vgroups[j];
- SCMVgroupMsg *vmsg = &pVgroupMsg->vgroups[j];
+ SVgroupMsg *vmsg = &pVgroupMsg->vgroups[j];
pVgroups->vgId = htonl(vmsg->vgId);
pVgroups->numOfEps = vmsg->numOfEps;
@@ -1878,10 +1948,10 @@ int tscProcessSTableVgroupRsp(SSqlObj *pSql) {
* current process do not use the cache at all
*/
int tscProcessShowRsp(SSqlObj *pSql) {
- STableMetaMsg * pMetaMsg;
- SCMShowRsp *pShow;
- SSchema * pSchema;
- char key[20];
+ STableMetaMsg *pMetaMsg;
+ SShowRsp * pShow;
+ SSchema * pSchema;
+ char key[20];
SSqlRes *pRes = &pSql->res;
SSqlCmd *pCmd = &pSql->cmd;
@@ -1890,7 +1960,7 @@ int tscProcessShowRsp(SSqlObj *pSql) {
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
- pShow = (SCMShowRsp *)pRes->pRsp;
+ pShow = (SShowRsp *)pRes->pRsp;
pShow->qhandle = htobe64(pShow->qhandle);
pRes->qhandle = pShow->qhandle;
@@ -1937,13 +2007,13 @@ int tscProcessShowRsp(SSqlObj *pSql) {
SInternalField* pInfo = tscFieldInfoAppend(pFieldInfo, &f);
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index,
- pTableSchema[i].type, pTableSchema[i].bytes, pTableSchema[i].bytes, false);
+ pTableSchema[i].type, pTableSchema[i].bytes, getNewResColId(pQueryInfo), pTableSchema[i].bytes, false);
}
pCmd->numOfCols = pQueryInfo->fieldsInfo.numOfOutput;
tscFieldInfoUpdateOffset(pQueryInfo);
- taosTFree(pTableMeta);
+ tfree(pTableMeta);
return 0;
}
@@ -1968,7 +2038,7 @@ static void createHBObj(STscObj* pObj) {
pSql->cmd.command = pQueryInfo->command;
if (TSDB_CODE_SUCCESS != tscAllocPayload(&(pSql->cmd), TSDB_DEFAULT_PAYLOAD_SIZE)) {
- taosTFree(pSql);
+ tfree(pSql);
return;
}
@@ -1983,11 +2053,12 @@ static void createHBObj(STscObj* pObj) {
}
int tscProcessConnectRsp(SSqlObj *pSql) {
- char temp[TSDB_TABLE_FNAME_LEN * 2];
STscObj *pObj = pSql->pTscObj;
SSqlRes *pRes = &pSql->res;
- SCMConnectRsp *pConnect = (SCMConnectRsp *)pRes->pRsp;
+ char temp[TSDB_TABLE_FNAME_LEN * 2] = {0};
+
+ SConnectRsp *pConnect = (SConnectRsp *)pRes->pRsp;
tstrncpy(pObj->acctId, pConnect->acctId, sizeof(pObj->acctId)); // copy acctId from response
int32_t len = sprintf(temp, "%s%s%s", pObj->acctId, TS_PATH_DELIMITER, pObj->db);
@@ -2005,7 +2076,9 @@ int tscProcessConnectRsp(SSqlObj *pSql) {
pObj->connId = htonl(pConnect->connId);
createHBObj(pObj);
- taosTmrReset(tscProcessActivityTimer, tsShellActivityTimer * 500, pObj, tscTmr, &pObj->pTimer);
+
+ //launch a timer to send heartbeat to maintain the connection and send status to mnode
+ taosTmrReset(tscProcessActivityTimer, tsShellActivityTimer * 500, (void *)pObj->rid, tscTmr, &pObj->pTimer);
return 0;
}
@@ -2114,7 +2187,16 @@ int tscProcessRetrieveRspFromNode(SSqlObj *pSql) {
if (tscCreateResPointerInfo(pRes, pQueryInfo) != TSDB_CODE_SUCCESS) {
return pRes->code;
}
-
+
+ STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+ if (pCmd->command == TSDB_SQL_RETRIEVE) {
+ tscSetResRawPtr(pRes, pQueryInfo);
+ } else if ((UTIL_TABLE_IS_CHILD_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) && !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_SUBQUERY)) {
+ tscSetResRawPtr(pRes, pQueryInfo);
+ } else if (tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0) && !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_QUERY) && !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_SEC_STAGE)) {
+ tscSetResRawPtr(pRes, pQueryInfo);
+ }
+
if (pSql->pSubscription != NULL) {
int32_t numOfCols = pQueryInfo->fieldsInfo.numOfOutput;
@@ -2136,7 +2218,7 @@ int tscProcessRetrieveRspFromNode(SSqlObj *pSql) {
}
pRes->row = 0;
- tscDebug("%p numOfRows:%" PRId64 ", offset:%" PRId64 ", complete:%d", pSql, pRes->numOfRows, pRes->offset, pRes->completed);
+ tscDebug("%p numOfRows:%d, offset:%" PRId64 ", complete:%d", pSql, pRes->numOfRows, pRes->offset, pRes->completed);
return 0;
}
@@ -2271,7 +2353,7 @@ int tscGetSTableVgroupInfo(SSqlObj *pSql, int32_t clauseIndex) {
for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
STableMetaInfo *pMInfo = tscGetMetaInfo(pQueryInfo, i);
STableMeta *pTableMeta = taosCacheAcquireByData(tscMetaCache, pMInfo->pTableMeta);
- tscAddTableMetaInfo(pNewQueryInfo, pMInfo->name, pTableMeta, NULL, pMInfo->tagColList);
+ tscAddTableMetaInfo(pNewQueryInfo, pMInfo->name, pTableMeta, NULL, pMInfo->tagColList, pMInfo->pVgroupTables);
}
if ((code = tscAllocPayload(&pNew->cmd, TSDB_DEFAULT_PAYLOAD_SIZE)) != TSDB_CODE_SUCCESS) {
diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c
index 8cac9b3398a0bc4569b52acc7858bbc1e50de542..de0177647234d0b63fa21a3b0fe2ec5763f40da3 100644
--- a/src/client/src/tscSql.c
+++ b/src/client/src/tscSql.c
@@ -28,7 +28,6 @@
#include "tutil.h"
#include "ttimer.h"
#include "tscProfile.h"
-#include "ttimer.h"
static bool validImpl(const char* str, size_t maxsize) {
if (str == NULL) {
@@ -161,6 +160,7 @@ static SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pa
registerSqlObj(pSql);
tsInsertHeadSize = sizeof(SMsgDesc) + sizeof(SSubmitMsg);
+ pObj->rid = taosAddRef(tscRefId, pObj);
return pSql;
}
@@ -278,9 +278,9 @@ void taos_close(TAOS *taos) {
SSqlObj* pHb = pObj->pHb;
if (pHb != NULL && atomic_val_compare_exchange_ptr(&pObj->pHb, pHb, 0) == pHb) {
- if (pHb->pRpcCtx != NULL) { // wait for rsp from dnode
- rpcCancelRequest(pHb->pRpcCtx);
- pHb->pRpcCtx = NULL;
+ if (pHb->rpcRid > 0) { // wait for rsp from dnode
+ rpcCancelRequest(pHb->rpcRid);
+ pHb->rpcRid = -1;
}
tscDebug("%p HB is freed", pHb);
@@ -296,7 +296,8 @@ void taos_close(TAOS *taos) {
}
tscDebug("%p all sqlObj are freed, free tscObj and close dnodeConn:%p", pObj, pObj->pDnodeConn);
- tscCloseTscObj(pObj);
+
+ taosRemoveRef(tscRefId, pObj->rid);
}
void waitForQueryRsp(void *param, TAOS_RES *tres, int code) {
@@ -320,7 +321,7 @@ TAOS_RES* taos_query_c(TAOS *taos, const char *sqlstr, uint32_t sqlLen, TAOS_RES
if (sqlLen > (uint32_t)tsMaxSQLStringLen) {
tscError("sql string exceeds max length:%d", tsMaxSQLStringLen);
- terrno = TSDB_CODE_TSC_INVALID_SQL;
+ terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT;
return NULL;
}
@@ -393,7 +394,7 @@ int taos_affected_rows(TAOS_RES *tres) {
SSqlObj* pSql = (SSqlObj*) tres;
if (pSql == NULL || pSql->signature != pSql) return 0;
- return (int)(pSql->res.numOfRows);
+ return pSql->res.numOfRows;
}
TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
@@ -419,7 +420,16 @@ TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
for(int32_t i = 0; i < pFieldInfo->numOfOutput; ++i) {
SInternalField* pField = tscFieldInfoGetInternalField(pFieldInfo, i);
if (pField->visible) {
- f[j++] = pField->field;
+ f[j] = pField->field;
+
+ // revise the length for binary and nchar fields
+ if (f[j].type == TSDB_DATA_TYPE_BINARY) {
+ f[j].bytes -= VARSTR_HEADER_SIZE;
+ } else if (f[j].type == TSDB_DATA_TYPE_NCHAR) {
+ f[j].bytes = (f[j].bytes - VARSTR_HEADER_SIZE)/TSDB_NCHAR_SIZE;
+ }
+
+ j += 1;
}
}
@@ -442,50 +452,30 @@ int taos_retrieve(TAOS_RES *res) {
if (pCmd->command < TSDB_SQL_LOCAL) {
pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
}
- tscProcessSql(pSql);
- return (int)pRes->numOfRows;
+ tscProcessSql(pSql);
+ return pRes->numOfRows;
}
-int taos_fetch_block_impl(TAOS_RES *res, TAOS_ROW *rows) {
- SSqlObj *pSql = (SSqlObj *)res;
- SSqlCmd *pCmd = &pSql->cmd;
+static bool needToFetchNewBlock(SSqlObj* pSql) {
SSqlRes *pRes = &pSql->res;
+ SSqlCmd *pCmd = &pSql->cmd;
- if (pRes->qhandle == 0 || pSql->signature != pSql) {
- *rows = NULL;
- return 0;
- }
-
- // Retrieve new block
- tscResetForNextRetrieve(pRes);
- if (pCmd->command < TSDB_SQL_LOCAL) {
- pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
- }
-
- tscProcessSql(pSql);
- if (pRes->numOfRows == 0) {
- *rows = NULL;
- return 0;
- }
-
- // secondary merge has handle this situation
- if (pCmd->command != TSDB_SQL_RETRIEVE_LOCALMERGE) {
- pRes->numOfClauseTotal += pRes->numOfRows;
- }
-
- SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
- if (pQueryInfo == NULL)
- return 0;
-
- assert(0);
- for (int i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
- tscGetResultColumnChr(pRes, &pQueryInfo->fieldsInfo, i);
- }
-
- *rows = pRes->tsrow;
-
- return (int)((pQueryInfo->order.order == TSDB_ORDER_DESC) ? pRes->numOfRows : -pRes->numOfRows);
+ return (pRes->completed != true || hasMoreVnodesToTry(pSql) || hasMoreClauseToTry(pSql)) &&
+ (pCmd->command == TSDB_SQL_RETRIEVE ||
+ pCmd->command == TSDB_SQL_RETRIEVE_LOCALMERGE ||
+ pCmd->command == TSDB_SQL_TABLE_JOIN_RETRIEVE ||
+ pCmd->command == TSDB_SQL_FETCH ||
+ pCmd->command == TSDB_SQL_SHOW ||
+ pCmd->command == TSDB_SQL_SHOW_CREATE_TABLE ||
+ pCmd->command == TSDB_SQL_SHOW_CREATE_DATABASE ||
+ pCmd->command == TSDB_SQL_SELECT ||
+ pCmd->command == TSDB_SQL_DESCRIBE_TABLE ||
+ pCmd->command == TSDB_SQL_SERV_STATUS ||
+ pCmd->command == TSDB_SQL_CURRENT_DB ||
+ pCmd->command == TSDB_SQL_SERV_VERSION ||
+ pCmd->command == TSDB_SQL_CLI_VERSION ||
+ pCmd->command == TSDB_SQL_CURRENT_USER);
}
TAOS_ROW taos_fetch_row(TAOS_RES *res) {
@@ -508,77 +498,50 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) {
// set the sql object owner
tscSetSqlOwner(pSql);
- // current data set are exhausted, fetch more data from node
- if (pRes->row >= pRes->numOfRows && (pRes->completed != true || hasMoreVnodesToTry(pSql) || hasMoreClauseToTry(pSql)) &&
- (pCmd->command == TSDB_SQL_RETRIEVE ||
- pCmd->command == TSDB_SQL_RETRIEVE_LOCALMERGE ||
- pCmd->command == TSDB_SQL_TABLE_JOIN_RETRIEVE ||
- pCmd->command == TSDB_SQL_FETCH ||
- pCmd->command == TSDB_SQL_SHOW ||
- pCmd->command == TSDB_SQL_SHOW_CREATE_TABLE ||
- pCmd->command == TSDB_SQL_SHOW_CREATE_DATABASE ||
- pCmd->command == TSDB_SQL_SELECT ||
- pCmd->command == TSDB_SQL_DESCRIBE_TABLE ||
- pCmd->command == TSDB_SQL_SERV_STATUS ||
- pCmd->command == TSDB_SQL_CURRENT_DB ||
- pCmd->command == TSDB_SQL_SERV_VERSION ||
- pCmd->command == TSDB_SQL_CLI_VERSION ||
- pCmd->command == TSDB_SQL_CURRENT_USER )) {
+ // current data set are exhausted, fetch more result from node
+ if (pRes->row >= pRes->numOfRows && needToFetchNewBlock(pSql)) {
taos_fetch_rows_a(res, waitForRetrieveRsp, pSql->pTscObj);
tsem_wait(&pSql->rspSem);
}
- void* data = doSetResultRowData(pSql, true);
+ void* data = doSetResultRowData(pSql);
tscClearSqlOwner(pSql);
return data;
}
int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
-#if 0
SSqlObj *pSql = (SSqlObj *)res;
- SSqlCmd *pCmd = &pSql->cmd;
- SSqlRes *pRes = &pSql->res;
-
- int nRows = 0;
-
if (pSql == NULL || pSql->signature != pSql) {
terrno = TSDB_CODE_TSC_DISCONNECTED;
- *rows = NULL;
return 0;
}
- // projection query on metric, pipeline retrieve data from vnode list,
- // instead of two-stage mergednodeProcessMsgFromShell free qhandle
- nRows = taos_fetch_block_impl(res, rows);
-
- // current subclause is completed, try the next subclause
- while (rows == NULL && pCmd->clauseIndex < pCmd->numOfClause - 1) {
- SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
-
- pSql->cmd.command = pQueryInfo->command;
- pCmd->clauseIndex++;
-
- pRes->numOfTotal += pRes->numOfClauseTotal;
- pRes->numOfClauseTotal = 0;
- pRes->rspType = 0;
+ SSqlCmd *pCmd = &pSql->cmd;
+ SSqlRes *pRes = &pSql->res;
- pSql->subState.numOfSub = 0;
- taosTFree(pSql->pSubs);
+ if (pRes->qhandle == 0 ||
+ pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED ||
+ pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
+ pCmd->command == TSDB_SQL_INSERT) {
+ return 0;
+ }
- assert(pSql->fp == NULL);
+ tscResetForNextRetrieve(pRes);
- tscDebug("%p try data in the next subclause:%d, total subclause:%d", pSql, pCmd->clauseIndex, pCmd->numOfClause);
- tscProcessSql(pSql);
+ // set the sql object owner
+ tscSetSqlOwner(pSql);
- nRows = taos_fetch_block_impl(res, rows);
+ // current data set are exhausted, fetch more data from node
+ if (needToFetchNewBlock(pSql)) {
+ taos_fetch_rows_a(res, waitForRetrieveRsp, pSql->pTscObj);
+ tsem_wait(&pSql->rspSem);
}
- return nRows;
-#endif
+ *rows = pRes->urow;
- (*rows) = taos_fetch_row(res);
- return ((*rows) != NULL)? 1:0;
+ tscClearSqlOwner(pSql);
+ return pRes->numOfRows;
}
int taos_select_db(TAOS *taos, const char *db) {
@@ -599,7 +562,7 @@ int taos_select_db(TAOS *taos, const char *db) {
}
// send free message to vnode to free qhandle and corresponding resources in vnode
-static UNUSED_FUNC bool tscKillQueryInDnode(SSqlObj* pSql) {
+static bool tscKillQueryInDnode(SSqlObj* pSql) {
SSqlCmd* pCmd = &pSql->cmd;
SSqlRes* pRes = &pSql->res;
@@ -746,9 +709,9 @@ static void tscKillSTableQuery(SSqlObj *pSql) {
assert(pSubObj->self == (SSqlObj**) p);
pSubObj->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
- if (pSubObj->pRpcCtx != NULL) {
- rpcCancelRequest(pSubObj->pRpcCtx);
- pSubObj->pRpcCtx = NULL;
+ if (pSubObj->rpcRid > 0) {
+ rpcCancelRequest(pSubObj->rpcRid);
+ pSubObj->rpcRid = -1;
}
tscQueueAsyncRes(pSubObj);
@@ -773,7 +736,7 @@ void taos_stop_query(TAOS_RES *res) {
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
if (tscIsTwoStageSTableQuery(pQueryInfo, 0)) {
- assert(pSql->pRpcCtx == NULL);
+ assert(pSql->rpcRid <= 0);
tscKillSTableQuery(pSql);
} else {
if (pSql->cmd.command < TSDB_SQL_LOCAL) {
@@ -782,9 +745,9 @@ void taos_stop_query(TAOS_RES *res) {
* reset and freed in the processMsgFromServer function, and causes the invalid
* write problem for rpcCancelRequest.
*/
- if (pSql->pRpcCtx != NULL) {
- rpcCancelRequest(pSql->pRpcCtx);
- pSql->pRpcCtx = NULL;
+ if (pSql->rpcRid > 0) {
+ rpcCancelRequest(pSql->rpcRid);
+ pSql->rpcRid = -1;
}
tscQueueAsyncRes(pSql);
@@ -794,6 +757,25 @@ void taos_stop_query(TAOS_RES *res) {
tscDebug("%p query is cancelled", res);
}
+bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) {
+ SSqlObj *pSql = (SSqlObj *)res;
+ if (pSql == NULL || pSql->signature != pSql) {
+ return true;
+ }
+
+ SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
+ if (pQueryInfo == NULL) {
+ return true;
+ }
+
+ SInternalField* pInfo = (SInternalField*)TARRAY_GET_ELEM(pQueryInfo->fieldsInfo.internalField, col);
+ if (col < 0 || col >= tscNumOfFields(pQueryInfo) || row < 0 || row > pSql->res.numOfRows) {
+ return true;
+ }
+
+ return isNull(((char*) pSql->res.urow[col]) + row * pInfo->field.bytes, pInfo->field.type);
+}
+
int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
int len = 0;
for (int i = 0; i < num_fields; ++i) {
@@ -891,18 +873,16 @@ int taos_validate_sql(TAOS *taos, const char *sql) {
int32_t sqlLen = (int32_t)strlen(sql);
if (sqlLen > tsMaxSQLStringLen) {
tscError("%p sql too long", pSql);
- pRes->code = TSDB_CODE_TSC_INVALID_SQL;
- taosTFree(pSql);
- return pRes->code;
+ tfree(pSql);
+ return TSDB_CODE_TSC_EXCEED_SQL_LIMIT;
}
pSql->sqlstr = realloc(pSql->sqlstr, sqlLen + 1);
if (pSql->sqlstr == NULL) {
- pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
tscError("%p failed to malloc sql string buffer", pSql);
tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(pSql), pObj);
- taosTFree(pSql);
- return pRes->code;
+ tfree(pSql);
+ return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
strtolower(pSql->sqlstr, sql);
diff --git a/src/client/src/tscStream.c b/src/client/src/tscStream.c
index 0f67911bbea992503979e5de019e4e10d3bf3c14..68c3bcae165050863cc4bf9c92a1510581531c3a 100644
--- a/src/client/src/tscStream.c
+++ b/src/client/src/tscStream.c
@@ -273,7 +273,7 @@ static void tscProcessStreamRetrieveResult(void *param, TAOS_RES *res, int numOf
taosCacheRelease(tscMetaCache, (void**)&(pTableMetaInfo->pTableMeta), false);
tscFreeSqlResult(pSql);
- taosTFree(pSql->pSubs);
+ tfree(pSql->pSubs);
pSql->subState.numOfSub = 0;
pTableMetaInfo->vgroupList = tscVgroupInfoClear(pTableMetaInfo->vgroupList);
tscSetNextLaunchTimer(pStream, pSql);
@@ -617,6 +617,6 @@ void taos_close_stream(TAOS_STREAM *handle) {
pStream->pSql = NULL;
taos_free_result(pSql);
- taosTFree(pStream);
+ tfree(pStream);
}
}
diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c
index 6b615c3a9b14f97f57013f476b60acc0db53db53..6ebbeeef411f8922662e7045027cf55410cbf89d 100644
--- a/src/client/src/tscSubquery.c
+++ b/src/client/src/tscSubquery.c
@@ -23,7 +23,6 @@
#include "tscSubquery.h"
#include "tschemautil.h"
#include "tsclient.h"
-#include "tscSubquery.h"
typedef struct SInsertSupporter {
SSqlObj* pSql;
@@ -33,11 +32,26 @@ typedef struct SInsertSupporter {
static void freeJoinSubqueryObj(SSqlObj* pSql);
static bool tscHasRemainDataInSubqueryResultSet(SSqlObj *pSql);
-static bool tsCompare(int32_t order, int64_t left, int64_t right) {
+static int32_t tsCompare(int32_t order, int64_t left, int64_t right) {
+ if (left == right) {
+ return 0;
+ }
+
if (order == TSDB_ORDER_ASC) {
- return left < right;
+ return left < right? -1:1;
} else {
- return left > right;
+ return left > right? -1:1;
+ }
+}
+
+static void skipRemainValue(STSBuf* pTSBuf, tVariant* tag1) {
+ while (tsBufNextPos(pTSBuf)) {
+ STSElem el1 = tsBufGetElem(pTSBuf);
+
+ int32_t res = tVariantCompare(el1.tag, tag1);
+ if (res != 0) { // it is a record with new tag
+ return;
+ }
}
}
@@ -52,13 +66,15 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJ
SLimitVal* pLimit = &pQueryInfo->limit;
int32_t order = pQueryInfo->order.order;
-
+
SQueryInfo* pSubQueryInfo1 = tscGetQueryInfoDetail(&pSql->pSubs[0]->cmd, 0);
SQueryInfo* pSubQueryInfo2 = tscGetQueryInfoDetail(&pSql->pSubs[1]->cmd, 0);
-
+
pSubQueryInfo1->tsBuf = output1;
pSubQueryInfo2->tsBuf = output2;
+ TSKEY st = taosGetTimestampUs();
+
// no result generated, return directly
if (pSupporter1->pTSBuf == NULL || pSupporter2->pTSBuf == NULL) {
tscDebug("%p at least one ts-comp is empty, 0 for secondary query after ts blocks intersecting", pSql);
@@ -87,58 +103,74 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJ
int64_t numOfInput1 = 1;
int64_t numOfInput2 = 1;
- while (1) {
- STSElem elem1 = tsBufGetElem(pSupporter1->pTSBuf);
- STSElem elem2 = tsBufGetElem(pSupporter2->pTSBuf);
+ while(1) {
+ STSElem elem = tsBufGetElem(pSupporter1->pTSBuf);
-#ifdef _DEBUG_VIEW
- tscInfo("%" PRId64 ", tags:%"PRId64" \t %" PRId64 ", tags:%"PRId64, elem1.ts, elem1.tag.i64Key, elem2.ts, elem2.tag.i64Key);
-#endif
+ // no data in pSupporter1 anymore, jump out of loop
+ if (!tsBufIsValidElem(&elem)) {
+ break;
+ }
- int32_t res = tVariantCompare(&elem1.tag, &elem2.tag);
- if (res == -1 || (res == 0 && tsCompare(order, elem1.ts, elem2.ts))) {
- if (!tsBufNextPos(pSupporter1->pTSBuf)) {
- break;
- }
+ // find the data in supporter2 with the same tag value
+ STSElem e2 = tsBufFindElemStartPosByTag(pSupporter2->pTSBuf, elem.tag);
- numOfInput1++;
- } else if ((res > 0) || (res == 0 && tsCompare(order, elem2.ts, elem1.ts))) {
- if (!tsBufNextPos(pSupporter2->pTSBuf)) {
- break;
- }
+ /**
+ * there are elements in pSupporter2 with the same tag, continue
+ */
+ tVariant tag1 = {0};
+ tVariantAssign(&tag1, elem.tag);
- numOfInput2++;
- } else {
- /*
- * in case of stable query, limit/offset is not applied here. the limit/offset is applied to the
- * final results which is acquired after the secondry merge of in the client.
- */
- if (pLimit->offset == 0 || pQueryInfo->interval.interval > 0 || QUERY_IS_STABLE_QUERY(pQueryInfo->type)) {
- if (win->skey > elem1.ts) {
- win->skey = elem1.ts;
+ if (tsBufIsValidElem(&e2)) {
+ while (1) {
+ STSElem elem1 = tsBufGetElem(pSupporter1->pTSBuf);
+ STSElem elem2 = tsBufGetElem(pSupporter2->pTSBuf);
+
+ // data with current are exhausted
+ if (!tsBufIsValidElem(&elem1) || tVariantCompare(elem1.tag, &tag1) != 0) {
+ break;
}
-
- if (win->ekey < elem1.ts) {
- win->ekey = elem1.ts;
+
+ if (!tsBufIsValidElem(&elem2) || tVariantCompare(elem2.tag, &tag1) != 0) { // ignore all records with the same tag
+ skipRemainValue(pSupporter1->pTSBuf, &tag1);
+ break;
}
-
- tsBufAppend(output1, elem1.vnode, &elem1.tag, (const char*)&elem1.ts, sizeof(elem1.ts));
- tsBufAppend(output2, elem2.vnode, &elem2.tag, (const char*)&elem2.ts, sizeof(elem2.ts));
- } else {
- pLimit->offset -= 1;
- }
- if (!tsBufNextPos(pSupporter1->pTSBuf)) {
- break;
- }
+ /*
+ * in case of stable query, limit/offset is not applied here. the limit/offset is applied to the
+ * final results which is acquired after the secondary merge of in the client.
+ */
+ int32_t re = tsCompare(order, elem1.ts, elem2.ts);
+ if (re < 0) {
+ tsBufNextPos(pSupporter1->pTSBuf);
+ numOfInput1++;
+ } else if (re > 0) {
+ tsBufNextPos(pSupporter2->pTSBuf);
+ numOfInput2++;
+ } else {
+ if (pLimit->offset == 0 || pQueryInfo->interval.interval > 0 || QUERY_IS_STABLE_QUERY(pQueryInfo->type)) {
+ if (win->skey > elem1.ts) {
+ win->skey = elem1.ts;
+ }
+
+ if (win->ekey < elem1.ts) {
+ win->ekey = elem1.ts;
+ }
+
+ tsBufAppend(output1, elem1.id, elem1.tag, (const char*)&elem1.ts, sizeof(elem1.ts));
+ tsBufAppend(output2, elem2.id, elem2.tag, (const char*)&elem2.ts, sizeof(elem2.ts));
+ } else {
+ pLimit->offset -= 1;//offset apply to projection?
+ }
- numOfInput1++;
+ tsBufNextPos(pSupporter1->pTSBuf);
+ numOfInput1++;
- if (!tsBufNextPos(pSupporter2->pTSBuf)) {
- break;
+ tsBufNextPos(pSupporter2->pTSBuf);
+ numOfInput2++;
+ }
}
-
- numOfInput2++;
+ } else { // no data in pSupporter2, ignore current data in pSupporter2
+ skipRemainValue(pSupporter1->pTSBuf, &tag1);
}
}
@@ -158,9 +190,11 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJ
tsBufDestroy(pSupporter1->pTSBuf);
tsBufDestroy(pSupporter2->pTSBuf);
- tscDebug("%p input1:%" PRId64 ", input2:%" PRId64 ", final:%" PRId64 " for secondary query after ts blocks "
- "intersecting, skey:%" PRId64 ", ekey:%" PRId64, pSql, numOfInput1, numOfInput2, output1->numOfTotal,
- win->skey, win->ekey);
+ TSKEY et = taosGetTimestampUs();
+ tscDebug("%p input1:%" PRId64 ", input2:%" PRId64 ", final:%" PRId64 " in %d vnodes for secondary query after ts blocks "
+ "intersecting, skey:%" PRId64 ", ekey:%" PRId64 ", numOfVnode:%d, elapsed time:%" PRId64 " us",
+ pSql, numOfInput1, numOfInput2, output1->numOfTotal, output1->numOfGroups, win->skey, win->ekey,
+ tsBufGetNumOfGroup(output1), et - st);
return output1->numOfTotal;
}
@@ -216,7 +250,12 @@ static void tscDestroyJoinSupporter(SJoinSupporter* pSupporter) {
pSupporter->f = NULL;
}
- taosTFree(pSupporter->pIdTagList);
+ if (pSupporter->pVgroupTables != NULL) {
+ taosArrayDestroy(pSupporter->pVgroupTables);
+ pSupporter->pVgroupTables = NULL;
+ }
+
+ tfree(pSupporter->pIdTagList);
tscTagCondRelease(&pSupporter->tagCond);
free(pSupporter);
}
@@ -240,6 +279,68 @@ static UNUSED_FUNC bool needSecondaryQuery(SQueryInfo* pQueryInfo) {
return false;
}
+static void filterVgroupTables(SQueryInfo* pQueryInfo, SArray* pVgroupTables) {
+ int32_t num = 0;
+ int32_t* list = NULL;
+ tsBufGetGroupIdList(pQueryInfo->tsBuf, &num, &list);
+
+ // The virtual node, of which all tables are disqualified after the timestamp intersection,
+ // is removed to avoid next stage query.
+ // TODO: If tables from some vnodes are not qualified for next stage query, discard them.
+ for (int32_t k = 0; k < taosArrayGetSize(pVgroupTables);) {
+ SVgroupTableInfo* p = taosArrayGet(pVgroupTables, k);
+
+ bool found = false;
+ for (int32_t f = 0; f < num; ++f) {
+ if (p->vgInfo.vgId == list[f]) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ tscRemoveVgroupTableGroup(pVgroupTables, k);
+ } else {
+ k++;
+ }
+ }
+
+ assert(taosArrayGetSize(pVgroupTables) > 0);
+ TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_MULTITABLE_QUERY);
+
+ tfree(list);
+}
+
+static SArray* buildVgroupTableByResult(SQueryInfo* pQueryInfo, SArray* pVgroupTables) {
+ int32_t num = 0;
+ int32_t* list = NULL;
+ tsBufGetGroupIdList(pQueryInfo->tsBuf, &num, &list);
+
+ size_t numOfGroups = taosArrayGetSize(pVgroupTables);
+
+ SArray* pNew = taosArrayInit(num, sizeof(SVgroupTableInfo));
+
+ SVgroupTableInfo info;
+ for (int32_t i = 0; i < num; ++i) {
+ int32_t vnodeId = list[i];
+
+ for (int32_t j = 0; j < numOfGroups; ++j) {
+ SVgroupTableInfo* p1 = taosArrayGet(pVgroupTables, j);
+ if (p1->vgInfo.vgId == vnodeId) {
+ tscVgroupTableCopy(&info, p1);
+ break;
+ }
+ }
+
+ taosArrayPush(pNew, &info);
+ }
+
+ tfree(list);
+ TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_MULTITABLE_QUERY);
+
+ return pNew;
+}
+
/*
* launch secondary stage query to fetch the result that contains timestamp in set
*/
@@ -305,7 +406,6 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) {
// set the second stage sub query for join process
TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_SEC_STAGE);
-
memcpy(&pQueryInfo->interval, &pSupporter->interval, sizeof(pQueryInfo->interval));
tscTagCondCopy(&pQueryInfo->tagCond, &pSupporter->tagCond);
@@ -313,24 +413,27 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) {
pQueryInfo->colList = pSupporter->colList;
pQueryInfo->exprList = pSupporter->exprList;
pQueryInfo->fieldsInfo = pSupporter->fieldsInfo;
+ pQueryInfo->groupbyExpr = pSupporter->groupInfo;
+
+ assert(pNew->subState.numOfSub == 0 && pNew->cmd.numOfClause == 1 && pQueryInfo->numOfTables == 1);
+
+ tscFieldInfoUpdateOffset(pQueryInfo);
+
+ STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+ pTableMetaInfo->pVgroupTables = pSupporter->pVgroupTables;
pSupporter->exprList = NULL;
pSupporter->colList = NULL;
+ pSupporter->pVgroupTables = NULL;
memset(&pSupporter->fieldsInfo, 0, sizeof(SFieldInfo));
-
- SQueryInfo *pNewQueryInfo = tscGetQueryInfoDetail(&pNew->cmd, 0);
- assert(pNew->subState.numOfSub == 0 && pNew->cmd.numOfClause == 1 && pNewQueryInfo->numOfTables == 1);
-
- tscFieldInfoUpdateOffset(pNewQueryInfo);
-
- STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pNewQueryInfo, 0);
-
+ memset(&pSupporter->groupInfo, 0, sizeof(SSqlGroupbyExpr));
+
/*
* When handling the projection query, the offset value will be modified for table-table join, which is changed
* during the timestamp intersection.
*/
pSupporter->limit = pQueryInfo->limit;
- pNewQueryInfo->limit = pSupporter->limit;
+ pQueryInfo->limit = pSupporter->limit;
SColumnIndex index = {.tableIndex = 0, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX};
SSchema* s = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, 0);
@@ -345,7 +448,7 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) {
tscAddSpecialColumnForSelect(pQueryInfo, 0, functionId, &index, s, TSDB_COL_NORMAL);
tscPrintSelectClause(pNew, 0);
- tscFieldInfoUpdateOffset(pNewQueryInfo);
+ tscFieldInfoUpdateOffset(pQueryInfo);
pExpr = tscSqlExprGet(pQueryInfo, 0);
}
@@ -356,14 +459,25 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) {
int16_t colId = tscGetJoinTagColIdByUid(&pQueryInfo->tagCond, pTableMetaInfo->pTableMeta->id.uid);
// set the tag column id for executor to extract correct tag value
- pExpr->param[0].i64Key = colId;
+ pExpr->param[0] = (tVariant) {.i64Key = colId, .nType = TSDB_DATA_TYPE_BIGINT, .nLen = sizeof(int64_t)};
pExpr->numOfParams = 1;
}
- size_t numOfCols = taosArrayGetSize(pNewQueryInfo->colList);
+ if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
+ assert(pTableMetaInfo->pVgroupTables != NULL);
+ if (tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
+ SArray* p = buildVgroupTableByResult(pQueryInfo, pTableMetaInfo->pVgroupTables);
+ tscFreeVgroupTableInfo(pTableMetaInfo->pVgroupTables);
+ pTableMetaInfo->pVgroupTables = p;
+ } else {
+ filterVgroupTables(pQueryInfo, pTableMetaInfo->pVgroupTables);
+ }
+ }
+
+ size_t numOfCols = taosArrayGetSize(pQueryInfo->colList);
tscDebug("%p subquery:%p tableIndex:%d, vgroupIndex:%d, type:%d, exprInfo:%" PRIzu ", colList:%" PRIzu ", fieldsInfo:%d, name:%s",
- pSql, pNew, 0, pTableMetaInfo->vgroupIndex, pNewQueryInfo->type, taosArrayGetSize(pNewQueryInfo->exprList),
- numOfCols, pNewQueryInfo->fieldsInfo.numOfOutput, pTableMetaInfo->name);
+ pSql, pNew, 0, pTableMetaInfo->vgroupIndex, pQueryInfo->type, taosArrayGetSize(pQueryInfo->exprList),
+ numOfCols, pQueryInfo->fieldsInfo.numOfOutput, pTableMetaInfo->name);
}
//prepare the subqueries object failed, abort
@@ -409,7 +523,7 @@ static void quitAllSubquery(SSqlObj* pSqlObj, SJoinSupporter* pSupporter) {
assert(pSqlObj->subState.numOfRemain > 0);
if (atomic_sub_fetch_32(&pSqlObj->subState.numOfRemain, 1) <= 0) {
- tscError("%p all subquery return and query failed, global code:%d", pSqlObj, pSqlObj->res.code);
+ tscError("%p all subquery return and query failed, global code:%s", pSqlObj, tstrerror(pSqlObj->res.code));
freeJoinSubqueryObj(pSqlObj);
}
}
@@ -418,20 +532,40 @@ static void quitAllSubquery(SSqlObj* pSqlObj, SJoinSupporter* pSupporter) {
static void updateQueryTimeRange(SQueryInfo* pQueryInfo, STimeWindow* win) {
assert(pQueryInfo->window.skey <= win->skey && pQueryInfo->window.ekey >= win->ekey);
pQueryInfo->window = *win;
+
+
}
-int32_t tscCompareTidTags(const void* p1, const void* p2) {
- const STidTags* t1 = (const STidTags*) varDataVal(p1);
- const STidTags* t2 = (const STidTags*) varDataVal(p2);
+int32_t tidTagsCompar(const void* p1, const void* p2) {
+ const STidTags* t1 = (const STidTags*) (p1);
+ const STidTags* t2 = (const STidTags*) (p2);
if (t1->vgId != t2->vgId) {
return (t1->vgId > t2->vgId) ? 1 : -1;
}
- if (t1->tid != t2->tid) {
- return (t1->tid > t2->tid) ? 1 : -1;
+ tstr* tag1 = (tstr*) t1->tag;
+ tstr* tag2 = (tstr*) t2->tag;
+
+ if (tag1->len != tag2->len) {
+ return (tag1->len > tag2->len)? 1: -1;
+ }
+
+ return strncmp(tag1->data, tag2->data, tag1->len);
+}
+
+int32_t tagValCompar(const void* p1, const void* p2) {
+ const STidTags* t1 = (const STidTags*) varDataVal(p1);
+ const STidTags* t2 = (const STidTags*) varDataVal(p2);
+
+ tstr* tag1 = (tstr*) t1->tag;
+ tstr* tag2 = (tstr*) t2->tag;
+
+ if (tag1->len != tag2->len) {
+ return (tag1->len > tag2->len)? 1: -1;
}
- return 0;
+
+ return memcmp(tag1->data, tag2->data, tag1->len);
}
void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArray* tables) {
@@ -449,7 +583,7 @@ void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArr
SVgroupTableInfo info = {{0}};
for (int32_t m = 0; m < pvg->numOfVgroups; ++m) {
if (tt->vgId == pvg->vgroups[m].vgId) {
- tscSCMVgroupInfoCopy(&info.vgInfo, &pvg->vgroups[m]);
+ tscSVgroupInfoCopy(&info.vgInfo, &pvg->vgroups[m]);
break;
}
}
@@ -457,27 +591,40 @@ void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArr
vgTables = taosArrayInit(4, sizeof(STableIdInfo));
info.itemList = vgTables;
+
+ if (taosArrayGetSize(result) > 0) {
+ SVgroupTableInfo* prevGroup = taosArrayGet(result, taosArrayGetSize(result) - 1);
+ tscDebug("%p vgId:%d, tables:%"PRIzu, pSql, prevGroup->vgInfo.vgId, taosArrayGetSize(prevGroup->itemList));
+ }
+
taosArrayPush(result, &info);
}
- tscDebug("%p tid:%d, uid:%"PRIu64",vgId:%d added for vnode query", pSql, tt->tid, tt->uid, tt->vgId)
STableIdInfo item = {.uid = tt->uid, .tid = tt->tid, .key = INT64_MIN};
taosArrayPush(vgTables, &item);
+
+ tscTrace("%p tid:%d, uid:%"PRIu64",vgId:%d added", pSql, tt->tid, tt->uid, tt->vgId);
prev = tt;
}
pTableMetaInfo->pVgroupTables = result;
pTableMetaInfo->vgroupIndex = 0;
+
+ if (taosArrayGetSize(result) > 0) {
+ SVgroupTableInfo* g = taosArrayGet(result, taosArrayGetSize(result) - 1);
+ tscDebug("%p vgId:%d, tables:%"PRIzu, pSql, g->vgInfo.vgId, taosArrayGetSize(g->itemList));
+ }
}
static void issueTSCompQuery(SSqlObj* pSql, SJoinSupporter* pSupporter, SSqlObj* pParent) {
SSqlCmd* pCmd = &pSql->cmd;
tscClearSubqueryInfo(pCmd);
tscFreeSqlResult(pSql);
-
+
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
+ assert(pQueryInfo->numOfTables == 1);
+
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
-
tscInitQueryInfo(pQueryInfo);
TSDB_QUERY_CLEAR_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY);
@@ -524,13 +671,7 @@ static void issueTSCompQuery(SSqlObj* pSql, SJoinSupporter* pSupporter, SSqlObj*
tscProcessSql(pSql);
}
-static bool checkForDuplicateTagVal(SQueryInfo* pQueryInfo, SJoinSupporter* p1, SSqlObj* pPSqlObj) {
- STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
-
- SSchema* pSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);// todo: tags mismatch, tags not completed
- SColumn *pCol = taosArrayGetP(pTableMetaInfo->tagColList, 0);
- SSchema *pColSchema = &pSchema[pCol->colIndex.columnIndex];
-
+static bool checkForDuplicateTagVal(SSchema* pColSchema, SJoinSupporter* p1, SSqlObj* pPSqlObj) {
for(int32_t i = 1; i < p1->num; ++i) {
STidTags* prev = (STidTags*) varDataVal(p1->pIdTagList + (i - 1) * p1->tagSize);
STidTags* p = (STidTags*) varDataVal(p1->pIdTagList + i * p1->tagSize);
@@ -547,24 +688,26 @@ static bool checkForDuplicateTagVal(SQueryInfo* pQueryInfo, SJoinSupporter* p1,
}
static int32_t getIntersectionOfTableTuple(SQueryInfo* pQueryInfo, SSqlObj* pParentSql, SArray** s1, SArray** s2) {
- tscDebug("%p all subqueries retrieve complete, do tags match", pParentSql);
-
SJoinSupporter* p1 = pParentSql->pSubs[0]->param;
SJoinSupporter* p2 = pParentSql->pSubs[1]->param;
- qsort(p1->pIdTagList, p1->num, p1->tagSize, tscCompareTidTags);
- qsort(p2->pIdTagList, p2->num, p2->tagSize, tscCompareTidTags);
+ tscDebug("%p all subquery retrieve complete, do tags match, %d, %d", pParentSql, p1->num, p2->num);
+
+ // sort according to the tag value
+ qsort(p1->pIdTagList, p1->num, p1->tagSize, tagValCompar);
+ qsort(p2->pIdTagList, p2->num, p2->tagSize, tagValCompar);
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
int16_t tagColId = tscGetJoinTagColIdByUid(&pQueryInfo->tagCond, pTableMetaInfo->pTableMeta->id.uid);
- SSchema* pColSchema = tscGetTableColumnSchemaById(pTableMetaInfo->pTableMeta, tagColId);
+ SSchema* pColSchema = tscGetColumnSchemaById(pTableMetaInfo->pTableMeta, tagColId);
// int16_t for padding
- *s1 = taosArrayInit(p1->num, p1->tagSize - sizeof(int16_t));
- *s2 = taosArrayInit(p2->num, p2->tagSize - sizeof(int16_t));
+ int32_t size = p1->tagSize - sizeof(int16_t);
+ *s1 = taosArrayInit(p1->num, size);
+ *s2 = taosArrayInit(p2->num, size);
- if (!(checkForDuplicateTagVal(pQueryInfo, p1, pParentSql) && checkForDuplicateTagVal(pQueryInfo, p2, pParentSql))) {
+ if (!(checkForDuplicateTagVal(pColSchema, p1, pParentSql) && checkForDuplicateTagVal(pColSchema, p2, pParentSql))) {
return TSDB_CODE_QRY_DUP_JOIN_KEY;
}
@@ -590,6 +733,27 @@ static int32_t getIntersectionOfTableTuple(SQueryInfo* pQueryInfo, SSqlObj* pPar
}
}
+ // reorganize the tid-tag value according to both the vgroup id and tag values
+ // sort according to the tag value
+ size_t t1 = taosArrayGetSize(*s1);
+ size_t t2 = taosArrayGetSize(*s2);
+
+ qsort((*s1)->pData, t1, size, tidTagsCompar);
+ qsort((*s2)->pData, t2, size, tidTagsCompar);
+
+#if 0
+ for(int32_t k = 0; k < t1; ++k) {
+ STidTags* p = (*s1)->pData + size * k;
+ printf("%d, tag:%s\n", p->vgId, ((tstr*)(p->tag))->data);
+ }
+
+ for(int32_t k = 0; k < t1; ++k) {
+ STidTags* p = (*s2)->pData + size * k;
+ printf("%d, tag:%s\n", p->vgId, ((tstr*)(p->tag))->data);
+ }
+#endif
+
+ tscDebug("%p tags match complete, result: %"PRIzu", %"PRIzu, pParentSql, t1, t2);
return TSDB_CODE_SUCCESS;
}
@@ -689,11 +853,15 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
}
if (taosArrayGetSize(s1) == 0 || taosArrayGetSize(s2) == 0) { // no results,return.
+ assert(pParentSql->fp != tscJoinQueryCallback);
+
tscDebug("%p tag intersect does not generated qualified tables for join, free all sub SqlObj and quit", pParentSql);
freeJoinSubqueryObj(pParentSql);
// set no result command
pParentSql->cmd.command = TSDB_SQL_RETRIEVE_EMPTY_RESULT;
+ assert(pParentSql->fp != tscJoinQueryCallback);
+
(*pParentSql->fp)(pParentSql->param, pParentSql, 0);
} else {
// proceed to for ts_comp query
@@ -708,6 +876,12 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
STableMetaInfo* pTableMetaInfo2 = tscGetMetaInfo(pQueryInfo2, 0);
tscBuildVgroupTableInfo(pParentSql, pTableMetaInfo2, s2);
+ SSqlObj* psub1 = pParentSql->pSubs[0];
+ ((SJoinSupporter*)psub1->param)->pVgroupTables = tscVgroupTableInfoClone(pTableMetaInfo1->pVgroupTables);
+
+ SSqlObj* psub2 = pParentSql->pSubs[1];
+ ((SJoinSupporter*)psub2->param)->pVgroupTables = tscVgroupTableInfoClone(pTableMetaInfo2->pVgroupTables);
+
pParentSql->subState.numOfSub = 2;
pParentSql->subState.numOfRemain = pParentSql->subState.numOfSub;
@@ -766,9 +940,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
pSupporter->pTSBuf = pBuf;
} else {
assert(pQueryInfo->numOfTables == 1); // for subquery, only one
- STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
-
- tsBufMerge(pSupporter->pTSBuf, pBuf, pTableMetaInfo->vgroupIndex);
+ tsBufMerge(pSupporter->pTSBuf, pBuf);
tsBufDestroy(pBuf);
}
@@ -776,7 +948,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
if (!pRes->completed) {
taosGetTmpfilePath("ts-join", pSupporter->path);
pSupporter->f = fopen(pSupporter->path, "w");
- pRes->row = (int32_t)pRes->numOfRows;
+ pRes->row = pRes->numOfRows;
taos_fetch_rows_a(tres, tsCompRetrieveCallback, param);
return;
@@ -802,7 +974,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
// TODO check for failure
pSupporter->f = fopen(pSupporter->path, "w");
- pRes->row = (int32_t)pRes->numOfRows;
+ pRes->row = pRes->numOfRows;
// set the callback function
pSql->fp = tscJoinQueryCallback;
@@ -835,6 +1007,8 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
// launch the query the retrieve actual results from vnode along with the filtered timestamp
SQueryInfo* pPQueryInfo = tscGetQueryInfoDetail(&pParentSql->cmd, pParentSql->cmd.clauseIndex);
updateQueryTimeRange(pPQueryInfo, &win);
+
+ //update the vgroup that involved in real data query
tscLaunchRealSubqueries(pParentSql);
}
@@ -868,20 +1042,28 @@ static void joinRetrieveFinalResCallback(void* param, TAOS_RES* tres, int numOfR
assert(pQueryInfo->numOfTables == 1);
// for projection query, need to try next vnode if current vnode is exhausted
- if ((++pTableMetaInfo->vgroupIndex) < pTableMetaInfo->vgroupList->numOfVgroups) {
- pState->numOfRemain = 1;
- pState->numOfSub = 1;
+ int32_t numOfVgroups = 0; // TODO refactor
+ if (pTableMetaInfo->pVgroupTables != NULL) {
+ numOfVgroups = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables);
+ } else {
+ numOfVgroups = pTableMetaInfo->vgroupList->numOfVgroups;
+ }
+ if ((++pTableMetaInfo->vgroupIndex) < numOfVgroups) {
+ tscDebug("%p no result in current vnode anymore, try next vnode, vgIndex:%d", pSql, pTableMetaInfo->vgroupIndex);
pSql->cmd.command = TSDB_SQL_SELECT;
pSql->fp = tscJoinQueryCallback;
- tscProcessSql(pSql);
+ tscProcessSql(pSql);
return;
+ } else {
+ tscDebug("%p no result in current subquery anymore", pSql);
}
}
- if (atomic_sub_fetch_32(&pParentSql->subState.numOfRemain, 1) > 0) {
- tscDebug("%p sub:%p completed, remain:%d, total:%d", pParentSql, tres, pParentSql->subState.numOfRemain, pState->numOfSub);
+ assert(pState->numOfRemain > 0);
+ if (atomic_sub_fetch_32(&pState->numOfRemain, 1) > 0) {
+ tscDebug("%p sub:%p completed, remain:%d, total:%d", pParentSql, tres, pState->numOfRemain, pState->numOfSub);
return;
}
@@ -893,62 +1075,66 @@ static void joinRetrieveFinalResCallback(void* param, TAOS_RES* tres, int numOfR
}
// update the records for each subquery in parent sql object.
+ bool stableQuery = tscIsTwoStageSTableQuery(pQueryInfo, 0);
for (int32_t i = 0; i < pState->numOfSub; ++i) {
if (pParentSql->pSubs[i] == NULL) {
+ tscDebug("%p %p sub:%d not retrieve data", pParentSql, NULL, i);
continue;
}
SSqlRes* pRes1 = &pParentSql->pSubs[i]->res;
- pRes1->numOfClauseTotal += pRes1->numOfRows;
- }
- // data has retrieved to client, build the join results
- tscBuildResFromSubqueries(pParentSql);
-}
-
-static SJoinSupporter* tscUpdateSubqueryStatus(SSqlObj* pSql, int32_t numOfFetch) {
- int32_t notInvolved = 0;
- SJoinSupporter* pSupporter = NULL;
- SSubqueryState* pState = &pSql->subState;
-
- for(int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
- if (pSql->pSubs[i] == NULL) {
- notInvolved++;
+ if (pRes1->row > 0 && pRes1->numOfRows > 0) {
+ tscDebug("%p sub:%p index:%d numOfRows:%d total:%"PRId64 " (not retrieve)", pParentSql, pParentSql->pSubs[i], i,
+ pRes1->numOfRows, pRes1->numOfTotal);
+ assert(pRes1->row < pRes1->numOfRows);
} else {
- pSupporter = (SJoinSupporter*)pSql->pSubs[i]->param;
+ if (!stableQuery) {
+ pRes1->numOfClauseTotal += pRes1->numOfRows;
+ }
+
+ tscDebug("%p sub:%p index:%d numOfRows:%d total:%"PRId64, pParentSql, pParentSql->pSubs[i], i,
+ pRes1->numOfRows, pRes1->numOfTotal);
}
}
-
- pState->numOfRemain = numOfFetch;
- return pSupporter;
+
+ // data has retrieved to client, build the join results
+ tscBuildResFromSubqueries(pParentSql);
}
-void tscFetchDatablockFromSubquery(SSqlObj* pSql) {
+void tscFetchDatablockForSubquery(SSqlObj* pSql) {
assert(pSql->subState.numOfSub >= 1);
int32_t numOfFetch = 0;
- bool hasData = true;
+ bool hasData = true;
+ bool reachLimit = false;
+
+ // if the subquery is NULL, it does not involved in the final result generation
for (int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
- // if the subquery is NULL, it does not involved in the final result generation
SSqlObj* pSub = pSql->pSubs[i];
if (pSub == NULL) {
continue;
}
-
+
SSqlRes *pRes = &pSub->res;
+
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSub->cmd, 0);
if (!tscHasReachLimitation(pQueryInfo, pRes)) {
if (pRes->row >= pRes->numOfRows) {
+ // no data left in current result buffer
hasData = false;
+ // The current query is completed for the active vnode, try next vnode if exists
+ // If it is completed, no need to fetch anymore.
if (!pRes->completed) {
numOfFetch++;
}
}
} else { // has reach the limitation, no data anymore
if (pRes->row >= pRes->numOfRows) {
- hasData = false;
+ reachLimit = true;
+ hasData = false;
break;
}
}
@@ -958,29 +1144,113 @@ void tscFetchDatablockFromSubquery(SSqlObj* pSql) {
if (hasData) {
tscBuildResFromSubqueries(pSql);
return;
- } else if (numOfFetch <= 0) {
+ }
+
+ // If at least one subquery is completed in current vnode, try the next vnode in case of multi-vnode
+ // super table projection query.
+ if (reachLimit) {
pSql->res.completed = true;
freeJoinSubqueryObj(pSql);
-
+
if (pSql->res.code == TSDB_CODE_SUCCESS) {
(*pSql->fp)(pSql->param, pSql, 0);
} else {
tscQueueAsyncRes(pSql);
}
-
+
+ return;
+ }
+
+ if (numOfFetch <= 0) {
+ bool tryNextVnode = false;
+
+ bool orderedPrjQuery = false;
+ for(int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
+ SSqlObj* pSub = pSql->pSubs[i];
+ if (pSub == NULL) {
+ continue;
+ }
+
+ SQueryInfo* p = tscGetQueryInfoDetail(&pSub->cmd, 0);
+ orderedPrjQuery = tscNonOrderedProjectionQueryOnSTable(p, 0);
+ if (orderedPrjQuery) {
+ break;
+ }
+ }
+
+ // get the number of subquery that need to retrieve the next vnode.
+ if (orderedPrjQuery) {
+ for (int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
+ SSqlObj* pSub = pSql->pSubs[i];
+ if (pSub != NULL && pSub->res.row >= pSub->res.numOfRows && pSub->res.completed) {
+ pSql->subState.numOfRemain++;
+ }
+ }
+ }
+
+ for (int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
+ SSqlObj* pSub = pSql->pSubs[i];
+ if (pSub == NULL) {
+ continue;
+ }
+
+ SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSub->cmd, 0);
+
+ if (tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0) && pSub->res.row >= pSub->res.numOfRows &&
+ pSub->res.completed) {
+ STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+ assert(pQueryInfo->numOfTables == 1);
+
+ // for projection query, need to try next vnode if current vnode is exhausted
+ int32_t numOfVgroups = 0; // TODO refactor
+ if (pTableMetaInfo->pVgroupTables != NULL) {
+ numOfVgroups = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables);
+ } else {
+ numOfVgroups = pTableMetaInfo->vgroupList->numOfVgroups;
+ }
+
+ if ((++pTableMetaInfo->vgroupIndex) < numOfVgroups) {
+ tscDebug("%p no result in current vnode anymore, try next vnode, vgIndex:%d", pSub,
+ pTableMetaInfo->vgroupIndex);
+ pSub->cmd.command = TSDB_SQL_SELECT;
+ pSub->fp = tscJoinQueryCallback;
+
+ tscProcessSql(pSub);
+ tryNextVnode = true;
+ } else {
+ tscDebug("%p no result in current subquery anymore", pSub);
+ }
+ }
+ }
+
+ if (tryNextVnode) {
+ return;
+ }
+
+ pSql->res.completed = true;
+ freeJoinSubqueryObj(pSql);
+
+ if (pSql->res.code == TSDB_CODE_SUCCESS) {
+ (*pSql->fp)(pSql->param, pSql, 0);
+ } else {
+ tscQueueAsyncRes(pSql);
+ }
+
return;
}
// TODO multi-vnode retrieve for projection query with limitation has bugs, since the global limiation is not handled
+ // retrieve data from current vnode.
tscDebug("%p retrieve data from %d subqueries", pSql, numOfFetch);
- SJoinSupporter* pSupporter = tscUpdateSubqueryStatus(pSql, numOfFetch);
-
+ SJoinSupporter* pSupporter = NULL;
+ pSql->subState.numOfRemain = numOfFetch;
+
for (int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
SSqlObj* pSql1 = pSql->pSubs[i];
if (pSql1 == NULL) {
continue;
}
-
+
SSqlRes* pRes1 = &pSql1->res;
SSqlCmd* pCmd1 = &pSql1->cmd;
@@ -1013,7 +1283,6 @@ void tscSetupOutputColumnIndex(SSqlObj* pSql) {
SSqlCmd* pCmd = &pSql->cmd;
SSqlRes* pRes = &pSql->res;
- tscDebug("%p all subquery response, retrieve data for subclause:%d", pSql, pCmd->clauseIndex);
// the column transfer support struct has been built
if (pRes->pColumnIndex != NULL) {
@@ -1109,21 +1378,23 @@ void tscJoinQueryCallback(void* param, TAOS_RES* tres, int code) {
return;
}
- // wait for the other subqueries response from vnode
- if (atomic_sub_fetch_32(&pParentSql->subState.numOfRemain, 1) > 0) {
- return;
+
+ STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+
+ // In case of consequence query from other vnode, do not wait for other query response here.
+ if (!(pTableMetaInfo->vgroupIndex > 0 && tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0))) {
+ if (atomic_sub_fetch_32(&pParentSql->subState.numOfRemain, 1) > 0) {
+ return;
+ }
}
tscSetupOutputColumnIndex(pParentSql);
- STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
/**
* if the query is a continue query (vgroupIndex > 0 for projection query) for next vnode, do the retrieval of
* data instead of returning to its invoker
*/
if (pTableMetaInfo->vgroupIndex > 0 && tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
- pParentSql->subState.numOfRemain = pParentSql->subState.numOfSub; // reset the record value
-
pSql->fp = joinRetrieveFinalResCallback; // continue retrieve data
pSql->cmd.command = TSDB_SQL_FETCH;
tscProcessSql(pSql);
@@ -1192,6 +1463,9 @@ int32_t tscCreateJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
+ pSupporter->groupInfo = pNewQueryInfo->groupbyExpr;
+ memset(&pNewQueryInfo->groupbyExpr, 0, sizeof(SSqlGroupbyExpr));
+
pNew->cmd.numOfCols = 0;
pNewQueryInfo->interval.interval = 0;
pSupporter->limit = pNewQueryInfo->limit;
@@ -1212,17 +1486,9 @@ int32_t tscCreateJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter
assert(pTagCond->joinInfo.hasJoin);
int32_t tagColId = tscGetJoinTagColIdByUid(pTagCond, pTableMetaInfo->pTableMeta->id.uid);
- SSchema* s = tscGetTableColumnSchemaById(pTableMetaInfo->pTableMeta, tagColId);
-
- // get the tag colId column index
- int32_t numOfTags = tscGetNumOfTags(pTableMetaInfo->pTableMeta);
- SSchema* pSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);
- for(int32_t i = 0; i < numOfTags; ++i) {
- if (pSchema[i].colId == tagColId) {
- colIndex.columnIndex = i;
- break;
- }
- }
+ SSchema* s = tscGetColumnSchemaById(pTableMetaInfo->pTableMeta, tagColId);
+
+ colIndex.columnIndex = tscGetTagColIndexById(pTableMetaInfo->pTableMeta, tagColId);
int16_t bytes = 0;
int16_t type = 0;
@@ -1303,6 +1569,7 @@ void tscHandleMasterJoinQuery(SSqlObj* pSql) {
tscDebug("%p start subquery, total:%d", pSql, pQueryInfo->numOfTables);
for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
+
SJoinSupporter *pSupporter = tscCreateJoinSupporter(pSql, i);
if (pSupporter == NULL) { // failed to create support struct, abort current query
@@ -1357,8 +1624,8 @@ static void doCleanupSubqueries(SSqlObj *pSql, int32_t numOfSubs) {
SRetrieveSupport* pSupport = pSub->param;
- taosTFree(pSupport->localBuffer);
- taosTFree(pSupport);
+ tfree(pSupport->localBuffer);
+ tfree(pSupport);
taos_free_result(pSub);
}
@@ -1375,9 +1642,10 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
}
tExtMemBuffer ** pMemoryBuf = NULL;
- tOrderDescriptor *pDesc = NULL;
- SColumnModel * pModel = NULL;
-
+ tOrderDescriptor *pDesc = NULL;
+ SColumnModel *pModel = NULL;
+ SColumnModel *pFinalModel = NULL;
+
pRes->qhandle = 0x1; // hack the qhandle check
const uint32_t nBufferSize = (1u << 16); // 64KB
@@ -1386,14 +1654,20 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
SSubqueryState *pState = &pSql->subState;
- pState->numOfSub = pTableMetaInfo->vgroupList->numOfVgroups;
+ pState->numOfSub = 0;
+ if (pTableMetaInfo->pVgroupTables == NULL) {
+ pState->numOfSub = pTableMetaInfo->vgroupList->numOfVgroups;
+ } else {
+ pState->numOfSub = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables);
+ }
+
assert(pState->numOfSub > 0);
- int32_t ret = tscLocalReducerEnvCreate(pSql, &pMemoryBuf, &pDesc, &pModel, nBufferSize);
+ int32_t ret = tscLocalReducerEnvCreate(pSql, &pMemoryBuf, &pDesc, &pModel, &pFinalModel, nBufferSize);
if (ret != 0) {
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
tscQueueAsyncRes(pSql);
- taosTFree(pMemoryBuf);
+ tfree(pMemoryBuf);
return ret;
}
@@ -1402,9 +1676,9 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
tscDebug("%p retrieved query data from %d vnode(s)", pSql, pState->numOfSub);
if (pSql->pSubs == NULL) {
- taosTFree(pSql->pSubs);
+ tfree(pSql->pSubs);
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
- tscLocalReducerEnvDestroy(pMemoryBuf, pDesc, pModel, pState->numOfSub);
+ tscLocalReducerEnvDestroy(pMemoryBuf, pDesc, pModel, pFinalModel,pState->numOfSub);
tscQueueAsyncRes(pSql);
return ret;
@@ -1427,19 +1701,20 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
trs->localBuffer = (tFilePage *)calloc(1, nBufferSize + sizeof(tFilePage));
if (trs->localBuffer == NULL) {
tscError("%p failed to malloc buffer for local buffer, orderOfSub:%d, reason:%s", pSql, i, strerror(errno));
- taosTFree(trs);
+ tfree(trs);
break;
}
trs->subqueryIndex = i;
trs->pParentSql = pSql;
trs->pFinalColModel = pModel;
-
+ trs->pFFColModel = pFinalModel;
+
SSqlObj *pNew = tscCreateSTableSubquery(pSql, trs, NULL);
if (pNew == NULL) {
tscError("%p failed to malloc buffer for subObj, orderOfSub:%d, reason:%s", pSql, i, strerror(errno));
- taosTFree(trs->localBuffer);
- taosTFree(trs);
+ tfree(trs->localBuffer);
+ tfree(trs);
break;
}
@@ -1457,13 +1732,13 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
tscError("%p failed to prepare subquery structure and launch subqueries", pSql);
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
- tscLocalReducerEnvDestroy(pMemoryBuf, pDesc, pModel, pState->numOfSub);
+ tscLocalReducerEnvDestroy(pMemoryBuf, pDesc, pModel, pFinalModel, pState->numOfSub);
doCleanupSubqueries(pSql, i);
return pRes->code; // free all allocated resource
}
if (pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED) {
- tscLocalReducerEnvDestroy(pMemoryBuf, pDesc, pModel, pState->numOfSub);
+ tscLocalReducerEnvDestroy(pMemoryBuf, pDesc, pModel, pFinalModel, pState->numOfSub);
doCleanupSubqueries(pSql, i);
return pRes->code;
}
@@ -1489,12 +1764,8 @@ static void tscFreeRetrieveSup(SSqlObj *pSql) {
}
tscDebug("%p start to free subquery supp obj:%p", pSql, trsupport);
-// int32_t index = trsupport->subqueryIndex;
-// SSqlObj *pParentSql = trsupport->pParentSql;
-
-// assert(pSql == pParentSql->pSubs[index]);
- taosTFree(trsupport->localBuffer);
- taosTFree(trsupport);
+ tfree(trsupport->localBuffer);
+ tfree(trsupport);
}
static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfRows);
@@ -1518,8 +1789,8 @@ static int32_t tscReissueSubquery(SRetrieveSupport *trsupport, SSqlObj *pSql, in
SSqlObj *pParentSql = trsupport->pParentSql;
int32_t subqueryIndex = trsupport->subqueryIndex;
- STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, 0, 0);
- SCMVgroupInfo* pVgroup = &pTableMetaInfo->vgroupList->vgroups[0];
+ STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, 0, 0);
+ SVgroupInfo* pVgroup = &pTableMetaInfo->vgroupList->vgroups[0];
tExtMemBufferClear(trsupport->pExtMemBuffer[subqueryIndex]);
@@ -1607,7 +1878,7 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO
tstrerror(pParentSql->res.code));
// release allocated resource
- tscLocalReducerEnvDestroy(trsupport->pExtMemBuffer, trsupport->pOrderDescriptor, trsupport->pFinalColModel,
+ tscLocalReducerEnvDestroy(trsupport->pExtMemBuffer, trsupport->pOrderDescriptor, trsupport->pFinalColModel, trsupport->pFFColModel,
pState->numOfSub);
tscFreeRetrieveSup(pSql);
@@ -1683,7 +1954,7 @@ static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* p
SQueryInfo *pPQueryInfo = tscGetQueryInfoDetail(&pParentSql->cmd, 0);
tscClearInterpInfo(pPQueryInfo);
- tscCreateLocalReducer(trsupport->pExtMemBuffer, pState->numOfSub, pDesc, trsupport->pFinalColModel, pParentSql);
+ tscCreateLocalReducer(trsupport->pExtMemBuffer, pState->numOfSub, pDesc, trsupport->pFinalColModel, trsupport->pFFColModel, pParentSql);
tscDebug("%p build loser tree completed", pParentSql);
pParentSql->res.precision = pSql->res.precision;
@@ -1721,7 +1992,7 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR
assert(pState->numOfRemain <= pState->numOfSub && pState->numOfRemain >= 0);
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, 0, 0);
- SCMVgroupInfo *pVgroup = &pTableMetaInfo->vgroupList->vgroups[0];
+ SVgroupInfo *pVgroup = &pTableMetaInfo->vgroupList->vgroups[0];
if (pParentSql->res.code != TSDB_CODE_SUCCESS) {
trsupport->numOfRetry = MAX_NUM_OF_SUBQUERY_RETRY;
@@ -1761,7 +2032,7 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR
assert(pRes->numOfRows == numOfRows);
int64_t num = atomic_add_fetch_64(&pState->numOfRetrievedRows, numOfRows);
- tscDebug("%p sub:%p retrieve numOfRows:%" PRId64 " totalNumOfRows:%" PRIu64 " from ep:%s, orderOfSub:%d", pParentSql, pSql,
+ tscDebug("%p sub:%p retrieve numOfRows:%d totalNumOfRows:%" PRIu64 " from ep:%s, orderOfSub:%d", pParentSql, pSql,
pRes->numOfRows, pState->numOfRetrievedRows, pSql->epSet.fqdn[pSql->epSet.inUse], idx);
if (num > tsMaxNumOfOrderedResults && tscIsProjectionQueryOnSTable(pQueryInfo, 0)) {
@@ -1788,7 +2059,7 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR
}
int32_t ret = saveToBuffer(trsupport->pExtMemBuffer[idx], pDesc, trsupport->localBuffer, pRes->data,
- (int32_t)pRes->numOfRows, pQueryInfo->groupbyExpr.orderType);
+ pRes->numOfRows, pQueryInfo->groupbyExpr.orderType);
if (ret != 0) { // set no disk space error info, and abort retry
tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_NO_DISKSPACE);
} else if (pRes->completed) {
@@ -1832,7 +2103,7 @@ void tscRetrieveDataRes(void *param, TAOS_RES *tres, int code) {
assert(pSql->cmd.numOfClause == 1 && pQueryInfo->numOfTables == 1);
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, 0, 0);
- SCMVgroupInfo* pVgroup = &pTableMetaInfo->vgroupList->vgroups[trsupport->subqueryIndex];
+ SVgroupInfo* pVgroup = &pTableMetaInfo->vgroupList->vgroups[trsupport->subqueryIndex];
// stable query killed or other subquery failed, all query stopped
if (pParentSql->res.code != TSDB_CODE_SUCCESS) {
@@ -1894,13 +2165,13 @@ static void multiVnodeInsertFinalize(void* param, TAOS_RES* tres, int numOfRows)
pParentObj->res.code = pSql->res.code;
}
- taosTFree(pSupporter);
+ tfree(pSupporter);
if (atomic_sub_fetch_32(&pParentObj->subState.numOfRemain, 1) > 0) {
return;
}
- tscDebug("%p Async insertion completed, total inserted:%" PRId64, pParentObj, pParentObj->res.numOfRows);
+ tscDebug("%p Async insertion completed, total inserted:%d", pParentObj, pParentObj->res.numOfRows);
// restore user defined fp
pParentObj->fp = pParentObj->fetchFp;
@@ -2017,7 +2288,7 @@ static char* getResultBlockPosition(SSqlCmd* pCmd, SSqlRes* pRes, int32_t column
assert(pInfo->pSqlExpr != NULL);
*bytes = pInfo->pSqlExpr->resBytes;
- char* pData = pRes->data + pInfo->pSqlExpr->offset * pRes->numOfRows;
+ char* pData = pRes->data + pInfo->pSqlExpr->offset * pRes->numOfRows + pRes->row * (*bytes);
return pData;
}
@@ -2029,21 +2300,24 @@ static void doBuildResFromSubqueries(SSqlObj* pSql) {
int32_t numOfRes = INT32_MAX;
for (int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
- if (pSql->pSubs[i] == NULL) {
+ SSqlObj* pSub = pSql->pSubs[i];
+ if (pSub == NULL) {
continue;
}
- numOfRes = (int32_t)(MIN(numOfRes, pSql->pSubs[i]->res.numOfRows));
+ int32_t remain = (int32_t)(pSub->res.numOfRows - pSub->res.row);
+ numOfRes = (int32_t)(MIN(numOfRes, remain));
}
- if (numOfRes == 0) {
+ if (numOfRes == 0) { // no result any more, free all subquery objects
+ freeJoinSubqueryObj(pSql);
return;
}
- int32_t totalSize = tscGetResRowLength(pQueryInfo->exprList);
+ int32_t rowSize = tscGetResRowLength(pQueryInfo->exprList);
- assert(numOfRes * totalSize > 0);
- char* tmp = realloc(pRes->pRsp, numOfRes * totalSize);
+ assert(numOfRes * rowSize > 0);
+ char* tmp = realloc(pRes->pRsp, numOfRes * rowSize + sizeof(tFilePage));
if (tmp == NULL) {
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
return;
@@ -2051,26 +2325,49 @@ static void doBuildResFromSubqueries(SSqlObj* pSql) {
pRes->pRsp = tmp;
}
- pRes->data = pRes->pRsp;
+ tFilePage* pFilePage = (tFilePage*) pRes->pRsp;
+ pFilePage->num = numOfRes;
+ pRes->data = pFilePage->data;
char* data = pRes->data;
+
int16_t bytes = 0;
size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo);
for(int32_t i = 0; i < numOfExprs; ++i) {
SColumnIndex* pIndex = &pRes->pColumnIndex[i];
- SSqlRes *pRes1 = &pSql->pSubs[pIndex->tableIndex]->res;
- SSqlCmd *pCmd1 = &pSql->pSubs[pIndex->tableIndex]->cmd;
+ SSqlRes* pRes1 = &pSql->pSubs[pIndex->tableIndex]->res;
+ SSqlCmd* pCmd1 = &pSql->pSubs[pIndex->tableIndex]->cmd;
char* pData = getResultBlockPosition(pCmd1, pRes1, pIndex->columnIndex, &bytes);
memcpy(data, pData, bytes * numOfRes);
data += bytes * numOfRes;
- pRes1->row = numOfRes;
+ }
+
+ for(int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
+ SSqlObj* pSub = pSql->pSubs[i];
+ if (pSub == NULL) {
+ continue;
+ }
+
+ pSub->res.row += numOfRes;
+ assert(pSub->res.row <= pSub->res.numOfRows);
}
pRes->numOfRows = numOfRes;
pRes->numOfClauseTotal += numOfRes;
+
+ int32_t finalRowSize = 0;
+ for(int32_t i = 0; i < tscNumOfFields(pQueryInfo); ++i) {
+ TAOS_FIELD* pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
+ finalRowSize += pField->bytes;
+ }
+
+ doArithmeticCalculate(pQueryInfo, pFilePage, rowSize, finalRowSize);
+
+ pRes->data = pFilePage->data;
+ tscSetResRawPtr(pRes, pQueryInfo);
}
void tscBuildResFromSubqueries(SSqlObj *pSql) {
@@ -2083,11 +2380,12 @@ void tscBuildResFromSubqueries(SSqlObj *pSql) {
if (pRes->tsrow == NULL) {
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex);
+ pRes->numOfCols = (int16_t) tscSqlExprNumOfExprs(pQueryInfo);
- size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo);
- pRes->tsrow = calloc(numOfExprs, POINTER_BYTES);
- pRes->buffer = calloc(numOfExprs, POINTER_BYTES);
- pRes->length = calloc(numOfExprs, sizeof(int32_t));
+ pRes->tsrow = calloc(pRes->numOfCols, POINTER_BYTES);
+ pRes->urow = calloc(pRes->numOfCols, POINTER_BYTES);
+ pRes->buffer = calloc(pRes->numOfCols, POINTER_BYTES);
+ pRes->length = calloc(pRes->numOfCols, sizeof(int32_t));
if (pRes->tsrow == NULL || pRes->buffer == NULL || pRes->length == NULL) {
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
@@ -2107,7 +2405,7 @@ void tscBuildResFromSubqueries(SSqlObj *pSql) {
}
}
-static void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pField) {
+static UNUSED_FUNC void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pField) {
SSqlRes *pRes = &pSql->res;
if (pRes->tsrow[columnIndex] != NULL && pField->type == TSDB_DATA_TYPE_NCHAR) {
@@ -2131,7 +2429,7 @@ static void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pF
}
}
-static char *getArithemicInputSrc(void *param, const char *name, int32_t colId) {
+char *getArithmeticInputSrc(void *param, const char *name, int32_t colId) {
SArithmeticSupport *pSupport = (SArithmeticSupport *) param;
int32_t index = -1;
@@ -2149,13 +2447,13 @@ static char *getArithemicInputSrc(void *param, const char *name, int32_t colId)
return pSupport->data[index] + pSupport->offset * pExpr->resBytes;
}
-TAOS_ROW doSetResultRowData(SSqlObj *pSql, bool finalResult) {
+TAOS_ROW doSetResultRowData(SSqlObj *pSql) {
SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res;
assert(pRes->row >= 0 && pRes->row <= pRes->numOfRows);
if (pRes->row >= pRes->numOfRows) { // all the results has returned to invoker
- taosTFree(pRes->tsrow);
+ tfree(pRes->tsrow);
return pRes->tsrow;
}
@@ -2163,47 +2461,19 @@ TAOS_ROW doSetResultRowData(SSqlObj *pSql, bool finalResult) {
size_t size = tscNumOfFields(pQueryInfo);
for (int i = 0; i < size; ++i) {
- SInternalField* pSup = TARRAY_GET_ELEM(pQueryInfo->fieldsInfo.internalField, i);
- if (pSup->pSqlExpr != NULL) {
- tscGetResultColumnChr(pRes, &pQueryInfo->fieldsInfo, i);
- }
+ SInternalField* pInfo = (SInternalField*)TARRAY_GET_ELEM(pQueryInfo->fieldsInfo.internalField, i);
- // primary key column cannot be null in interval query, no need to check
- if (i == 0 && pQueryInfo->interval.interval > 0) {
- continue;
- }
+ int32_t type = pInfo->field.type;
+ int32_t bytes = pInfo->field.bytes;
- TAOS_FIELD *pField = TARRAY_GET_ELEM(pQueryInfo->fieldsInfo.internalField, i);
- if (pRes->tsrow[i] != NULL && pField->type == TSDB_DATA_TYPE_NCHAR) {
- transferNcharData(pSql, i, pField);
+ if (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR) {
+ pRes->tsrow[i] = isNull(pRes->urow[i], type) ? NULL : pRes->urow[i];
+ } else {
+ pRes->tsrow[i] = isNull(pRes->urow[i], type) ? NULL : varDataVal(pRes->urow[i]);
+ pRes->length[i] = varDataLen(pRes->urow[i]);
}
- // calculate the result from several other columns
- if (pSup->pArithExprInfo != NULL) {
- if (pRes->pArithSup == NULL) {
- pRes->pArithSup = (SArithmeticSupport*)calloc(1, sizeof(SArithmeticSupport));
- }
-
- pRes->pArithSup->offset = 0;
- pRes->pArithSup->pArithExpr = pSup->pArithExprInfo;
- pRes->pArithSup->numOfCols = (int32_t)tscSqlExprNumOfExprs(pQueryInfo);
- pRes->pArithSup->exprList = pQueryInfo->exprList;
- pRes->pArithSup->data = calloc(pRes->pArithSup->numOfCols, POINTER_BYTES);
-
- if (pRes->buffer[i] == NULL) {
- TAOS_FIELD* field = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
- pRes->buffer[i] = malloc(field->bytes);
- }
-
- for(int32_t k = 0; k < pRes->pArithSup->numOfCols; ++k) {
- SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, k);
- pRes->pArithSup->data[k] = (pRes->data + pRes->numOfRows* pExpr->offset) + pRes->row*pExpr->resBytes;
- }
-
- tExprTreeCalcTraverse(pRes->pArithSup->pArithExpr->pExpr, 1, pRes->buffer[i], pRes->pArithSup,
- TSDB_ORDER_ASC, getArithemicInputSrc);
- pRes->tsrow[i] = (unsigned char*)pRes->buffer[i];
- }
+ ((char**) pRes->urow)[i] += bytes;
}
pRes->row++; // index increase one-step
diff --git a/src/client/src/tscSystem.c b/src/client/src/tscSystem.c
index 47c2d35a75cba4787e00c645e2f242ae24788df7..9e9a00550a4497ae11cbdffe48991c2fd7b742d6 100644
--- a/src/client/src/tscSystem.c
+++ b/src/client/src/tscSystem.c
@@ -36,6 +36,7 @@ void * tscTmr;
void * tscQhandle;
void * tscCheckDiskUsageTmr;
int tsInsertHeadSize;
+int tscRefId = -1;
int tscNumOfThreads;
@@ -79,7 +80,7 @@ int32_t tscInitRpc(const char *user, const char *secretEncrypt, void **pDnodeCon
void taos_init_imp(void) {
- char temp[128];
+ char temp[128] = {0};
errno = TSDB_CODE_SUCCESS;
srand(taosGetTimestampSec());
@@ -103,8 +104,8 @@ void taos_init_imp(void) {
taosReadGlobalCfg();
taosCheckGlobalCfg();
- taosPrintGlobalCfg();
+ rpcInit();
tscDebug("starting to initialize TAOS client ...");
tscDebug("Local End Point is:%s", tsLocalEp);
}
@@ -146,29 +147,45 @@ void taos_init_imp(void) {
tscObjCache = taosCacheInit(TSDB_CACHE_PTR_KEY, refreshTime / 2, false, tscFreeRegisteredSqlObj, "sqlObj");
}
+ tscRefId = taosOpenRef(200, tscCloseTscObj);
+
+ // in other language APIs, taos_cleanup is not available yet.
+ // So, to make sure taos_cleanup will be invoked to clean up the allocated
+ // resource to suppress the valgrind warning.
+ atexit(taos_cleanup);
tscDebug("client is initialized successfully");
}
void taos_init() { pthread_once(&tscinit, taos_init_imp); }
-void taos_cleanup() {
- if (tscMetaCache != NULL) {
- taosCacheCleanup(tscMetaCache);
- tscMetaCache = NULL;
+// this function may be called by user or system, or by both simultaneously.
+void taos_cleanup(void) {
+ tscDebug("start to cleanup client environment");
- taosCacheCleanup(tscObjCache);
- tscObjCache = NULL;
+ void* m = tscMetaCache;
+ if (m != NULL && atomic_val_compare_exchange_ptr(&tscMetaCache, m, 0) == m) {
+ taosCacheCleanup(m);
}
-
- if (tscQhandle != NULL) {
- taosCleanUpScheduler(tscQhandle);
- tscQhandle = NULL;
+
+ m = tscObjCache;
+ if (m != NULL && atomic_val_compare_exchange_ptr(&tscObjCache, m, 0) == m) {
+ taosCacheCleanup(m);
+ }
+
+ m = tscQhandle;
+ if (m != NULL && atomic_val_compare_exchange_ptr(&tscQhandle, m, 0) == m) {
+ taosCleanUpScheduler(m);
}
+ taosCloseRef(tscRefId);
taosCleanupKeywordsTable();
taosCloseLog();
-
- taosTmrCleanUp(tscTmr);
+ if (tscEmbedded == 0) rpcCleanup();
+
+ m = tscTmr;
+ if (m != NULL && atomic_val_compare_exchange_ptr(&tscTmr, m, 0) == m) {
+ taosTmrCleanUp(m);
+ }
}
static int taos_options_imp(TSDB_OPTION option, const char *pStr) {
diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c
index b60bf958a84bcefd8fb14970923f4af1074b7a6f..7a82bcaaab63603d136ae79f28b1625c90944779 100644
--- a/src/client/src/tscUtil.c
+++ b/src/client/src/tscUtil.c
@@ -71,7 +71,8 @@ void tsSetSTableQueryCond(STagCond* pTagCond, uint64_t uid, SBufferWriter* bw) {
}
bool tscQueryTags(SQueryInfo* pQueryInfo) {
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
+ int32_t numOfCols = (int32_t) tscSqlExprNumOfExprs(pQueryInfo);
+ for (int32_t i = 0; i < numOfCols; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
int32_t functId = pExpr->functionId;
@@ -201,13 +202,9 @@ bool tscIsProjectionQuery(SQueryInfo* pQueryInfo) {
bool tscIsPointInterpQuery(SQueryInfo* pQueryInfo) {
size_t size = tscSqlExprNumOfExprs(pQueryInfo);
-
for (int32_t i = 0; i < size; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
assert(pExpr != NULL);
-// if (pExpr == NULL) {
-// return false;
-// }
int32_t functionId = pExpr->functionId;
if (functionId == TSDB_FUNC_TAG) {
@@ -222,6 +219,22 @@ bool tscIsPointInterpQuery(SQueryInfo* pQueryInfo) {
return true;
}
+bool tscIsSecondStageQuery(SQueryInfo* pQueryInfo) {
+ if (tscIsProjectionQuery(pQueryInfo)) {
+ return false;
+ }
+
+ size_t numOfOutput = tscNumOfFields(pQueryInfo);
+ for(int32_t i = 0; i < numOfOutput; ++i) {
+ SExprInfo* pExprInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i)->pArithExprInfo;
+ if (pExprInfo != NULL) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool tscIsTWAQuery(SQueryInfo* pQueryInfo) {
size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo);
for (int32_t i = 0; i < numOfExprs; ++i) {
@@ -245,21 +258,25 @@ void tscClearInterpInfo(SQueryInfo* pQueryInfo) {
}
pQueryInfo->fillType = TSDB_FILL_NONE;
- taosTFree(pQueryInfo->fillVal);
+ tfree(pQueryInfo->fillVal);
}
int32_t tscCreateResPointerInfo(SSqlRes* pRes, SQueryInfo* pQueryInfo) {
if (pRes->tsrow == NULL) {
- int32_t numOfOutput = pQueryInfo->fieldsInfo.numOfOutput;
- pRes->numOfCols = numOfOutput;
+ pRes->numOfCols = pQueryInfo->fieldsInfo.numOfOutput;
- pRes->tsrow = calloc(numOfOutput, POINTER_BYTES);
- pRes->length = calloc(numOfOutput, sizeof(int32_t));
- pRes->buffer = calloc(numOfOutput, POINTER_BYTES);
+ pRes->tsrow = calloc(pRes->numOfCols, POINTER_BYTES);
+ pRes->urow = calloc(pRes->numOfCols, POINTER_BYTES);
+ pRes->length = calloc(pRes->numOfCols, sizeof(int32_t));
+ pRes->buffer = calloc(pRes->numOfCols, POINTER_BYTES);
// not enough memory
- if (pRes->tsrow == NULL || (pRes->buffer == NULL && pRes->numOfCols > 0)) {
- taosTFree(pRes->tsrow);
+ if (pRes->tsrow == NULL || pRes->urow == NULL || pRes->length == NULL || (pRes->buffer == NULL && pRes->numOfCols > 0)) {
+ tfree(pRes->tsrow);
+ tfree(pRes->urow);
+ tfree(pRes->length);
+ tfree(pRes->buffer);
+
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
return pRes->code;
}
@@ -268,27 +285,93 @@ int32_t tscCreateResPointerInfo(SSqlRes* pRes, SQueryInfo* pQueryInfo) {
return TSDB_CODE_SUCCESS;
}
+void tscSetResRawPtr(SSqlRes* pRes, SQueryInfo* pQueryInfo) {
+ assert(pRes->numOfCols > 0);
+
+ int32_t offset = 0;
+
+ for (int32_t i = 0; i < pRes->numOfCols; ++i) {
+ SInternalField* pInfo = (SInternalField*)TARRAY_GET_ELEM(pQueryInfo->fieldsInfo.internalField, i);
+
+ pRes->urow[i] = pRes->data + offset * pRes->numOfRows;
+ pRes->length[i] = pInfo->field.bytes;
+
+ offset += pInfo->field.bytes;
+
+ // generated the user-defined column result
+ if (pInfo->pSqlExpr != NULL && TSDB_COL_IS_UD_COL(pInfo->pSqlExpr->colInfo.flag)) {
+ if (pInfo->pSqlExpr->param[1].nType == TSDB_DATA_TYPE_NULL) {
+ setNullN(pRes->urow[i], pInfo->field.type, pInfo->field.bytes, (int32_t) pRes->numOfRows);
+ } else {
+ if (pInfo->field.type == TSDB_DATA_TYPE_NCHAR || pInfo->field.type == TSDB_DATA_TYPE_BINARY) {
+ assert(pInfo->pSqlExpr->param[1].nLen <= pInfo->field.bytes);
+
+ for (int32_t k = 0; k < pRes->numOfRows; ++k) {
+ char* p = ((char**)pRes->urow)[i] + k * pInfo->field.bytes;
+
+ memcpy(varDataVal(p), pInfo->pSqlExpr->param[1].pz, pInfo->pSqlExpr->param[1].nLen);
+ varDataSetLen(p, pInfo->pSqlExpr->param[1].nLen);
+ }
+ } else {
+ for (int32_t k = 0; k < pRes->numOfRows; ++k) {
+ char* p = ((char**)pRes->urow)[i] + k * pInfo->field.bytes;
+ memcpy(p, &pInfo->pSqlExpr->param[1].i64Key, pInfo->field.bytes);
+ }
+ }
+ }
+
+ } else if (pInfo->field.type == TSDB_DATA_TYPE_NCHAR) {
+ // convert unicode to native code in a temporary buffer extra one byte for terminated symbol
+ pRes->buffer[i] = realloc(pRes->buffer[i], pInfo->field.bytes * pRes->numOfRows);
+
+ // string terminated char for binary data
+ memset(pRes->buffer[i], 0, pInfo->field.bytes * pRes->numOfRows);
+
+ char* p = pRes->urow[i];
+ for (int32_t k = 0; k < pRes->numOfRows; ++k) {
+ char* dst = pRes->buffer[i] + k * pInfo->field.bytes;
+
+ if (isNull(p, TSDB_DATA_TYPE_NCHAR)) {
+ memcpy(dst, p, varDataTLen(p));
+ } else {
+ int32_t length = taosUcs4ToMbs(varDataVal(p), varDataLen(p), varDataVal(dst));
+ varDataSetLen(dst, length);
+
+ if (length == 0) {
+ tscError("charset:%s to %s. val:%s convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)p);
+ }
+ }
+
+ p += pInfo->field.bytes;
+ }
+
+ memcpy(pRes->urow[i], pRes->buffer[i], pInfo->field.bytes * pRes->numOfRows);
+ }
+ }
+}
+
static void tscDestroyResPointerInfo(SSqlRes* pRes) {
if (pRes->buffer != NULL) { // free all buffers containing the multibyte string
for (int i = 0; i < pRes->numOfCols; i++) {
- taosTFree(pRes->buffer[i]);
+ tfree(pRes->buffer[i]);
}
pRes->numOfCols = 0;
}
- taosTFree(pRes->pRsp);
+ tfree(pRes->pRsp);
- taosTFree(pRes->tsrow);
- taosTFree(pRes->length);
- taosTFree(pRes->buffer);
+ tfree(pRes->tsrow);
+ tfree(pRes->length);
+ tfree(pRes->buffer);
+ tfree(pRes->urow);
- taosTFree(pRes->pGroupRec);
- taosTFree(pRes->pColumnIndex);
+ tfree(pRes->pGroupRec);
+ tfree(pRes->pColumnIndex);
if (pRes->pArithSup != NULL) {
- taosTFree(pRes->pArithSup->data);
- taosTFree(pRes->pArithSup);
+ tfree(pRes->pArithSup->data);
+ tfree(pRes->pArithSup);
}
pRes->data = NULL; // pRes->data points to the buffer of pRsp, no need to free
@@ -305,11 +388,11 @@ static void tscFreeQueryInfo(SSqlCmd* pCmd, bool removeFromCache) {
freeQueryInfoImpl(pQueryInfo);
clearAllTableMetaInfo(pQueryInfo, (const char*)addr, removeFromCache);
- taosTFree(pQueryInfo);
+ tfree(pQueryInfo);
}
pCmd->numOfClause = 0;
- taosTFree(pCmd->pQueryInfo);
+ tfree(pCmd->pQueryInfo);
}
void tscResetSqlCmdObj(SSqlCmd* pCmd, bool removeFromCache) {
@@ -338,34 +421,6 @@ void tscFreeSqlResult(SSqlObj* pSql) {
memset(&pSql->res, 0, sizeof(SSqlRes));
}
-void tscPartiallyFreeSqlObj(SSqlObj* pSql) {
- if (pSql == NULL || pSql->signature != pSql) {
- return;
- }
-
- SSqlCmd* pCmd = &pSql->cmd;
- int32_t cmd = pCmd->command;
- if (cmd < TSDB_SQL_INSERT || cmd == TSDB_SQL_RETRIEVE_LOCALMERGE || cmd == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
- cmd == TSDB_SQL_TABLE_JOIN_RETRIEVE) {
- tscRemoveFromSqlList(pSql);
- }
-
- // pSql->sqlstr will be used by tscBuildQueryStreamDesc
-// if (pObj->signature == pObj) {
- //pthread_mutex_lock(&pObj->mutex);
- taosTFree(pSql->sqlstr);
- //pthread_mutex_unlock(&pObj->mutex);
-// }
-
- tscFreeSqlResult(pSql);
-
- taosTFree(pSql->pSubs);
- pSql->subState.numOfSub = 0;
- pSql->self = 0;
-
- tscResetSqlCmdObj(pCmd, false);
-}
-
static void tscFreeSubobj(SSqlObj* pSql) {
if (pSql->subState.numOfSub == 0) {
return;
@@ -404,7 +459,7 @@ void tscFreeRegisteredSqlObj(void *pSql) {
tscDebug("%p free sqlObj completed, tscObj:%p ref:%d", *p, pTscObj, ref);
if (ref == 0) {
tscDebug("%p all sqlObj freed, free tscObj:%p", *p, pTscObj);
- tscCloseTscObj(pTscObj);
+ taosRemoveRef(tscRefId, pTscObj->rid);
}
}
@@ -415,14 +470,14 @@ void tscFreeTableMetaHelper(void *pTableMeta) {
assert(numOfEps >= 0 && numOfEps <= TSDB_MAX_REPLICA);
for(int32_t i = 0; i < numOfEps; ++i) {
- taosTFree(p->vgroupInfo.epAddr[i].fqdn);
+ tfree(p->vgroupInfo.epAddr[i].fqdn);
}
int32_t numOfEps1 = p->corVgroupInfo.numOfEps;
assert(numOfEps1 >= 0 && numOfEps1 <= TSDB_MAX_REPLICA);
for(int32_t i = 0; i < numOfEps1; ++i) {
- taosTFree(p->corVgroupInfo.epAddr[i].fqdn);
+ tfree(p->corVgroupInfo.epAddr[i].fqdn);
}
}
@@ -434,22 +489,32 @@ void tscFreeSqlObj(SSqlObj* pSql) {
tscDebug("%p start to free sqlObj", pSql);
pSql->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
+
tscFreeSubobj(pSql);
- tscPartiallyFreeSqlObj(pSql);
+ SSqlCmd* pCmd = &pSql->cmd;
+ int32_t cmd = pCmd->command;
+ if (cmd < TSDB_SQL_INSERT || cmd == TSDB_SQL_RETRIEVE_LOCALMERGE || cmd == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
+ cmd == TSDB_SQL_TABLE_JOIN_RETRIEVE) {
+ tscRemoveFromSqlList(pSql);
+ }
pSql->signature = NULL;
pSql->fp = NULL;
-
- SSqlCmd* pCmd = &pSql->cmd;
+ tfree(pSql->sqlstr);
+
+ tfree(pSql->pSubs);
+ pSql->subState.numOfSub = 0;
+ pSql->self = 0;
+
+ tscFreeSqlResult(pSql);
+ tscResetSqlCmdObj(pCmd, false);
memset(pCmd->payload, 0, (size_t)pCmd->allocSize);
- taosTFree(pCmd->payload);
+ tfree(pCmd->payload);
pCmd->allocSize = 0;
- taosTFree(pSql->sqlstr);
tsem_destroy(&pSql->rspSem);
-
free(pSql);
}
@@ -458,15 +523,15 @@ void tscDestroyDataBlock(STableDataBlocks* pDataBlock) {
return;
}
- taosTFree(pDataBlock->pData);
- taosTFree(pDataBlock->params);
+ tfree(pDataBlock->pData);
+ tfree(pDataBlock->params);
// free the refcount for metermeta
if (pDataBlock->pTableMeta != NULL) {
taosCacheRelease(tscMetaCache, (void**)&(pDataBlock->pTableMeta), false);
}
- taosTFree(pDataBlock);
+ tfree(pDataBlock);
}
SParamInfo* tscAddParamToDataBlock(STableDataBlocks* pDataBlock, char type, uint8_t timePrec, int16_t bytes,
@@ -741,7 +806,7 @@ int32_t tscMergeTableDataBlocks(SSqlObj* pSql, SArray* pTableDataBlockList) {
taosHashCleanup(pVnodeDataBlockHashList);
tscDestroyBlockArrayList(pVnodeDataBlockList);
- taosTFree(dataBuf->pData);
+ tfree(dataBuf->pData);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
@@ -786,8 +851,8 @@ int32_t tscMergeTableDataBlocks(SSqlObj* pSql, SArray* pTableDataBlockList) {
}
// TODO: all subqueries should be freed correctly before close this connection.
-void tscCloseTscObj(STscObj* pObj) {
- assert(pObj != NULL);
+void tscCloseTscObj(void *param) {
+ STscObj *pObj = param;
pObj->signature = NULL;
taosTmrStopA(&(pObj->pTimer));
@@ -801,7 +866,7 @@ void tscCloseTscObj(STscObj* pObj) {
pthread_mutex_destroy(&pObj->mutex);
tscDebug("%p DB connection is closed, dnodeConn:%p", pObj, p);
- taosTFree(pObj);
+ tfree(pObj);
}
bool tscIsInsertData(char* sqlstr) {
@@ -876,28 +941,11 @@ void tscFieldInfoUpdateOffset(SQueryInfo* pQueryInfo) {
SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, 0);
pExpr->offset = 0;
-
- for (int32_t i = 1; i < numOfExprs; ++i) {
- SSqlExpr* prev = taosArrayGetP(pQueryInfo->exprList, i - 1);
- SSqlExpr* p = taosArrayGetP(pQueryInfo->exprList, i);
-
- p->offset = prev->offset + prev->resBytes;
- }
-}
-void tscFieldInfoUpdateOffsetForInterResult(SQueryInfo* pQueryInfo) {
- if (tscSqlExprNumOfExprs(pQueryInfo) == 0) {
- return;
- }
-
- SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, 0);
- pExpr->offset = 0;
-
- size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo);
for (int32_t i = 1; i < numOfExprs; ++i) {
SSqlExpr* prev = taosArrayGetP(pQueryInfo->exprList, i - 1);
SSqlExpr* p = taosArrayGetP(pQueryInfo->exprList, i);
-
+
p->offset = prev->offset + prev->resBytes;
}
}
@@ -965,18 +1013,26 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo) {
if (pInfo->pArithExprInfo != NULL) {
tExprTreeDestroy(&pInfo->pArithExprInfo->pExpr, NULL);
- taosTFree(pInfo->pArithExprInfo);
+
+ SSqlFuncMsg* pFuncMsg = &pInfo->pArithExprInfo->base;
+ for(int32_t j = 0; j < pFuncMsg->numOfParams; ++j) {
+ if (pFuncMsg->arg[j].argType == TSDB_DATA_TYPE_BINARY) {
+ tfree(pFuncMsg->arg[j].argValue.pz);
+ }
+ }
+
+ tfree(pInfo->pArithExprInfo);
}
}
taosArrayDestroy(pFieldInfo->internalField);
- taosTFree(pFieldInfo->final);
+ tfree(pFieldInfo->final);
memset(pFieldInfo, 0, sizeof(SFieldInfo));
}
static SSqlExpr* doBuildSqlExpr(SQueryInfo* pQueryInfo, int16_t functionId, SColumnIndex* pColIndex, int16_t type,
- int16_t size, int16_t interSize, int32_t colType) {
+ int16_t size, int16_t resColId, int16_t interSize, int32_t colType) {
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, pColIndex->tableIndex);
SSqlExpr* pExpr = calloc(1, sizeof(SSqlExpr));
@@ -1009,8 +1065,9 @@ static SSqlExpr* doBuildSqlExpr(SQueryInfo* pQueryInfo, int16_t functionId, SCol
pExpr->resType = type;
pExpr->resBytes = size;
+ pExpr->resColId = resColId;
pExpr->interBytes = interSize;
-
+
if (pTableMetaInfo->pTableMeta) {
pExpr->uid = pTableMetaInfo->pTableMeta->id.uid;
}
@@ -1019,20 +1076,20 @@ static SSqlExpr* doBuildSqlExpr(SQueryInfo* pQueryInfo, int16_t functionId, SCol
}
SSqlExpr* tscSqlExprInsert(SQueryInfo* pQueryInfo, int32_t index, int16_t functionId, SColumnIndex* pColIndex, int16_t type,
- int16_t size, int16_t interSize, bool isTagCol) {
+ int16_t size, int16_t resColId, int16_t interSize, bool isTagCol) {
int32_t num = (int32_t)taosArrayGetSize(pQueryInfo->exprList);
if (index == num) {
- return tscSqlExprAppend(pQueryInfo, functionId, pColIndex, type, size, interSize, isTagCol);
+ return tscSqlExprAppend(pQueryInfo, functionId, pColIndex, type, size, resColId, interSize, isTagCol);
}
- SSqlExpr* pExpr = doBuildSqlExpr(pQueryInfo, functionId, pColIndex, type, size, interSize, isTagCol);
+ SSqlExpr* pExpr = doBuildSqlExpr(pQueryInfo, functionId, pColIndex, type, size, resColId, interSize, isTagCol);
taosArrayInsert(pQueryInfo->exprList, index, &pExpr);
return pExpr;
}
SSqlExpr* tscSqlExprAppend(SQueryInfo* pQueryInfo, int16_t functionId, SColumnIndex* pColIndex, int16_t type,
- int16_t size, int16_t interSize, bool isTagCol) {
- SSqlExpr* pExpr = doBuildSqlExpr(pQueryInfo, functionId, pColIndex, type, size, interSize, isTagCol);
+ int16_t size, int16_t resColId, int16_t interSize, bool isTagCol) {
+ SSqlExpr* pExpr = doBuildSqlExpr(pQueryInfo, functionId, pColIndex, type, size, resColId, interSize, isTagCol);
taosArrayPush(pQueryInfo->exprList, &pExpr);
return pExpr;
}
@@ -1060,16 +1117,14 @@ size_t tscSqlExprNumOfExprs(SQueryInfo* pQueryInfo) {
return taosArrayGetSize(pQueryInfo->exprList);
}
-void addExprParams(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes, int16_t tableIndex) {
- if (pExpr == NULL || argument == NULL || bytes == 0) {
- return;
- }
+void addExprParams(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes) {
+ assert (pExpr != NULL || argument != NULL || bytes != 0);
// set parameter value
// transfer to tVariant from byte data/no ascii data
tVariantCreateFromBinary(&pExpr->param[pExpr->numOfParams], argument, bytes, type);
-
pExpr->numOfParams += 1;
+
assert(pExpr->numOfParams <= 3);
}
@@ -1086,7 +1141,7 @@ void* sqlExprDestroy(SSqlExpr* pExpr) {
tVariantDestroy(&pExpr->param[i]);
}
- taosTFree(pExpr);
+ tfree(pExpr);
return NULL;
}
@@ -1121,6 +1176,8 @@ int32_t tscSqlExprCopy(SArray* dst, const SArray* src, uint64_t uid, bool deepco
}
*p1 = *pExpr;
+ memset(p1->param, 0, sizeof(tVariant) * tListLen(p1->param));
+
for (int32_t j = 0; j < pExpr->numOfParams; ++j) {
tVariantAssign(&p1->param[j], &pExpr->param[j]);
}
@@ -1184,11 +1241,11 @@ SColumn* tscColumnListInsert(SArray* pColumnList, SColumnIndex* pColIndex) {
static void destroyFilterInfo(SColumnFilterInfo* pFilterInfo, int32_t numOfFilters) {
for(int32_t i = 0; i < numOfFilters; ++i) {
if (pFilterInfo[i].filterstr) {
- taosTFree(pFilterInfo[i].pz);
+ tfree(pFilterInfo[i].pz);
}
}
- taosTFree(pFilterInfo);
+ tfree(pFilterInfo);
}
SColumn* tscColumnClone(const SColumn* src) {
@@ -1254,8 +1311,7 @@ void tscColumnListDestroy(SArray* pColumnList) {
*
*/
static int32_t validateQuoteToken(SStrToken* pToken) {
- strdequote(pToken->z);
- pToken->n = (uint32_t)strtrim(pToken->z);
+ tscDequoteAndTrimToken(pToken);
int32_t k = tSQLGetToken(pToken->z, &pToken->type);
@@ -1270,8 +1326,6 @@ static int32_t validateQuoteToken(SStrToken* pToken) {
}
void tscDequoteAndTrimToken(SStrToken* pToken) {
- assert(pToken->type == TK_STRING);
-
uint32_t first = 0, last = pToken->n;
// trim leading spaces
@@ -1383,7 +1437,8 @@ int32_t tscValidateName(SStrToken* pToken) {
} else {
pStr[firstPartLen] = TS_PATH_DELIMITER[0];
memmove(&pStr[firstPartLen + 1], pToken->z, pToken->n);
- pStr[firstPartLen + sizeof(TS_PATH_DELIMITER[0]) + pToken->n] = 0;
+ uint32_t offset = (uint32_t)(pToken->z - (pStr + firstPartLen + 1));
+ memset(pToken->z + pToken->n - offset, ' ', offset);
}
pToken->n += (firstPartLen + sizeof(TS_PATH_DELIMITER[0]));
pToken->z = pStr;
@@ -1476,7 +1531,7 @@ void tscTagCondRelease(STagCond* pTagCond) {
size_t s = taosArrayGetSize(pTagCond->pCond);
for (int32_t i = 0; i < s; ++i) {
SCond* p = taosArrayGet(pTagCond->pCond, i);
- taosTFree(p->cond);
+ tfree(p->cond);
}
taosArrayDestroy(pTagCond->pCond);
@@ -1622,6 +1677,7 @@ void tscInitQueryInfo(SQueryInfo* pQueryInfo) {
pQueryInfo->exprList = taosArrayInit(4, POINTER_BYTES);
pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES);
pQueryInfo->udColumnId = TSDB_UD_COLUMN_INDEX;
+ pQueryInfo->resColumnId= -1000;
}
int32_t tscAddSubqueryInfo(SSqlCmd* pCmd) {
@@ -1663,11 +1719,12 @@ static void freeQueryInfoImpl(SQueryInfo* pQueryInfo) {
if (pQueryInfo->groupbyExpr.columnInfo != NULL) {
taosArrayDestroy(pQueryInfo->groupbyExpr.columnInfo);
pQueryInfo->groupbyExpr.columnInfo = NULL;
+ pQueryInfo->groupbyExpr.numOfGroupCols = 0;
}
pQueryInfo->tsBuf = tsBufDestroy(pQueryInfo->tsBuf);
- taosTFree(pQueryInfo->fillVal);
+ tfree(pQueryInfo->fillVal);
}
void tscClearSubqueryInfo(SSqlCmd* pCmd) {
@@ -1678,23 +1735,71 @@ void tscClearSubqueryInfo(SSqlCmd* pCmd) {
}
void tscFreeVgroupTableInfo(SArray* pVgroupTables) {
- if (pVgroupTables != NULL) {
- size_t num = taosArrayGetSize(pVgroupTables);
- for (size_t i = 0; i < num; i++) {
- SVgroupTableInfo* pInfo = taosArrayGet(pVgroupTables, i);
+ if (pVgroupTables == NULL) {
+ return;
+ }
- for(int32_t j = 0; j < pInfo->vgInfo.numOfEps; ++j) {
- taosTFree(pInfo->vgInfo.epAddr[j].fqdn);
- }
+ size_t num = taosArrayGetSize(pVgroupTables);
+ for (size_t i = 0; i < num; i++) {
+ SVgroupTableInfo* pInfo = taosArrayGet(pVgroupTables, i);
- taosArrayDestroy(pInfo->itemList);
+ for(int32_t j = 0; j < pInfo->vgInfo.numOfEps; ++j) {
+ tfree(pInfo->vgInfo.epAddr[j].fqdn);
}
- taosArrayDestroy(pVgroupTables);
+
+ taosArrayDestroy(pInfo->itemList);
+ }
+
+ taosArrayDestroy(pVgroupTables);
+}
+
+void tscRemoveVgroupTableGroup(SArray* pVgroupTable, int32_t index) {
+ assert(pVgroupTable != NULL && index >= 0);
+
+ size_t size = taosArrayGetSize(pVgroupTable);
+ assert(size > index);
+
+ SVgroupTableInfo* pInfo = taosArrayGet(pVgroupTable, index);
+ for(int32_t j = 0; j < pInfo->vgInfo.numOfEps; ++j) {
+ tfree(pInfo->vgInfo.epAddr[j].fqdn);
+ }
+
+ taosArrayDestroy(pInfo->itemList);
+ taosArrayRemove(pVgroupTable, index);
+}
+
+void tscVgroupTableCopy(SVgroupTableInfo* info, SVgroupTableInfo* pInfo) {
+ memset(info, 0, sizeof(SVgroupTableInfo));
+
+ info->vgInfo = pInfo->vgInfo;
+ for(int32_t j = 0; j < pInfo->vgInfo.numOfEps; ++j) {
+ info->vgInfo.epAddr[j].fqdn = strdup(pInfo->vgInfo.epAddr[j].fqdn);
+ }
+
+ info->itemList = taosArrayClone(pInfo->itemList);
+}
+
+SArray* tscVgroupTableInfoClone(SArray* pVgroupTables) {
+ if (pVgroupTables == NULL) {
+ return NULL;
}
+
+ size_t num = taosArrayGetSize(pVgroupTables);
+ SArray* pa = taosArrayInit(num, sizeof(SVgroupTableInfo));
+
+ SVgroupTableInfo info;
+ for (size_t i = 0; i < num; i++) {
+ SVgroupTableInfo* pInfo = taosArrayGet(pVgroupTables, i);
+ tscVgroupTableCopy(&info, pInfo);
+
+ taosArrayPush(pa, &info);
+ }
+
+ return pa;
}
void clearAllTableMetaInfo(SQueryInfo* pQueryInfo, const char* address, bool removeFromCache) {
- tscDebug("%p deref the table meta in cache, numOfTables:%d", address, pQueryInfo->numOfTables);
+ tscDebug("%p unref %d tables in the tableMeta cache", address, pQueryInfo->numOfTables);
for(int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, i);
@@ -1704,11 +1809,11 @@ void clearAllTableMetaInfo(SQueryInfo* pQueryInfo, const char* address, bool rem
free(pTableMetaInfo);
}
- taosTFree(pQueryInfo->pTableMetaInfo);
+ tfree(pQueryInfo->pTableMetaInfo);
}
STableMetaInfo* tscAddTableMetaInfo(SQueryInfo* pQueryInfo, const char* name, STableMeta* pTableMeta,
- SVgroupsInfo* vgroupList, SArray* pTagCols) {
+ SVgroupsInfo* vgroupList, SArray* pTagCols, SArray* pVgroupTables) {
void* pAlloc = realloc(pQueryInfo->pTableMetaInfo, (pQueryInfo->numOfTables + 1) * POINTER_BYTES);
if (pAlloc == NULL) {
terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
@@ -1734,6 +1839,7 @@ STableMetaInfo* tscAddTableMetaInfo(SQueryInfo* pQueryInfo, const char* name, ST
pTableMetaInfo->vgroupList = tscVgroupInfoClone(vgroupList);
}
+ // TODO handle malloc failure
pTableMetaInfo->tagColList = taosArrayInit(4, POINTER_BYTES);
if (pTableMetaInfo->tagColList == NULL) {
return NULL;
@@ -1742,13 +1848,15 @@ STableMetaInfo* tscAddTableMetaInfo(SQueryInfo* pQueryInfo, const char* name, ST
if (pTagCols != NULL) {
tscColumnListCopy(pTableMetaInfo->tagColList, pTagCols, -1);
}
+
+ pTableMetaInfo->pVgroupTables = tscVgroupTableInfoClone(pVgroupTables);
pQueryInfo->numOfTables += 1;
return pTableMetaInfo;
}
STableMetaInfo* tscAddEmptyMetaInfo(SQueryInfo* pQueryInfo) {
- return tscAddTableMetaInfo(pQueryInfo, NULL, NULL, NULL, NULL);
+ return tscAddTableMetaInfo(pQueryInfo, NULL, NULL, NULL, NULL, NULL);
}
void tscClearTableMetaInfo(STableMetaInfo* pTableMetaInfo, bool removeFromCache) {
@@ -1822,7 +1930,7 @@ SSqlObj* createSimpleSubObj(SSqlObj* pSql, void (*fp)(), void* param, int32_t cm
assert(pSql->cmd.clauseIndex == 0);
STableMetaInfo* pMasterTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, pSql->cmd.clauseIndex, 0);
- tscAddTableMetaInfo(pQueryInfo, pMasterTableMetaInfo->name, NULL, NULL, NULL);
+ tscAddTableMetaInfo(pQueryInfo, pMasterTableMetaInfo->name, NULL, NULL, NULL, NULL);
registerSqlObj(pNew);
return pNew;
@@ -1987,14 +2095,16 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
STableMeta* pTableMeta = taosCacheAcquireByData(tscMetaCache, pTableMetaInfo->pTableMeta); // get by name may failed due to the cache cleanup
assert(pTableMeta != NULL);
- pFinalInfo = tscAddTableMetaInfo(pNewQueryInfo, name, pTableMeta, pTableMetaInfo->vgroupList, pTableMetaInfo->tagColList);
+ pFinalInfo = tscAddTableMetaInfo(pNewQueryInfo, name, pTableMeta, pTableMetaInfo->vgroupList,
+ pTableMetaInfo->tagColList, pTableMetaInfo->pVgroupTables);
} else { // transfer the ownership of pTableMeta to the newly create sql object.
STableMetaInfo* pPrevInfo = tscGetTableMetaInfoFromCmd(&pPrevSql->cmd, pPrevSql->cmd.clauseIndex, 0);
STableMeta* pPrevTableMeta = taosCacheTransfer(tscMetaCache, (void**)&pPrevInfo->pTableMeta);
SVgroupsInfo* pVgroupsInfo = pPrevInfo->vgroupList;
- pFinalInfo = tscAddTableMetaInfo(pNewQueryInfo, name, pPrevTableMeta, pVgroupsInfo, pTableMetaInfo->tagColList);
+ pFinalInfo = tscAddTableMetaInfo(pNewQueryInfo, name, pPrevTableMeta, pVgroupsInfo, pTableMetaInfo->tagColList,
+ pTableMetaInfo->pVgroupTables);
}
if (pFinalInfo->pTableMeta == NULL) {
@@ -2106,6 +2216,21 @@ int16_t tscGetJoinTagColIdByUid(STagCond* pTagCond, uint64_t uid) {
}
}
+int16_t tscGetTagColIndexById(STableMeta* pTableMeta, int16_t colId) {
+ int32_t numOfTags = tscGetNumOfTags(pTableMeta);
+
+ SSchema* pSchema = tscGetTableTagSchema(pTableMeta);
+ for(int32_t i = 0; i < numOfTags; ++i) {
+ if (pSchema[i].colId == colId) {
+ return i;
+ }
+ }
+
+ // can not reach here
+ assert(0);
+ return INT16_MIN;
+}
+
bool tscIsUpdateQuery(SSqlObj* pSql) {
if (pSql == NULL || pSql->signature != pSql) {
terrno = TSDB_CODE_TSC_DISCONNECTED;
@@ -2283,7 +2408,7 @@ void tscTryQueryNextClause(SSqlObj* pSql, __async_cb_func_t fp) {
pRes->numOfTotal = num;
- taosTFree(pSql->pSubs);
+ tfree(pSql->pSubs);
pSql->subState.numOfSub = 0;
pSql->fp = fp;
@@ -2375,7 +2500,7 @@ SVgroupsInfo* tscVgroupInfoClone(SVgroupsInfo *vgroupList) {
return NULL;
}
- size_t size = sizeof(SVgroupsInfo) + sizeof(SCMVgroupInfo) * vgroupList->numOfVgroups;
+ size_t size = sizeof(SVgroupsInfo) + sizeof(SVgroupInfo) * vgroupList->numOfVgroups;
SVgroupsInfo* pNew = calloc(1, size);
if (pNew == NULL) {
return NULL;
@@ -2384,9 +2509,9 @@ SVgroupsInfo* tscVgroupInfoClone(SVgroupsInfo *vgroupList) {
pNew->numOfVgroups = vgroupList->numOfVgroups;
for(int32_t i = 0; i < vgroupList->numOfVgroups; ++i) {
- SCMVgroupInfo* pNewVInfo = &pNew->vgroups[i];
+ SVgroupInfo* pNewVInfo = &pNew->vgroups[i];
- SCMVgroupInfo* pvInfo = &vgroupList->vgroups[i];
+ SVgroupInfo* pvInfo = &vgroupList->vgroups[i];
pNewVInfo->vgId = pvInfo->vgId;
pNewVInfo->numOfEps = pvInfo->numOfEps;
@@ -2405,21 +2530,22 @@ void* tscVgroupInfoClear(SVgroupsInfo *vgroupList) {
}
for(int32_t i = 0; i < vgroupList->numOfVgroups; ++i) {
- SCMVgroupInfo* pVgroupInfo = &vgroupList->vgroups[i];
+ SVgroupInfo* pVgroupInfo = &vgroupList->vgroups[i];
for(int32_t j = 0; j < pVgroupInfo->numOfEps; ++j) {
- taosTFree(pVgroupInfo->epAddr[j].fqdn);
+ tfree(pVgroupInfo->epAddr[j].fqdn);
}
}
- taosTFree(vgroupList);
+ tfree(vgroupList);
return NULL;
}
-void tscSCMVgroupInfoCopy(SCMVgroupInfo* dst, const SCMVgroupInfo* src) {
+void tscSVgroupInfoCopy(SVgroupInfo* dst, const SVgroupInfo* src) {
dst->vgId = src->vgId;
dst->numOfEps = src->numOfEps;
for(int32_t i = 0; i < dst->numOfEps; ++i) {
+ tfree(dst->epAddr[i].fqdn);
dst->epAddr[i].port = src->epAddr[i].port;
dst->epAddr[i].fqdn = strdup(src->epAddr[i].fqdn);
}
diff --git a/src/common/inc/tdataformat.h b/src/common/inc/tdataformat.h
index cc4afeb3f850785ffb18a972961668f91061c6a4..8d4949d9b4364fd1e8c70cbb883aa56468724108 100644
--- a/src/common/inc/tdataformat.h
+++ b/src/common/inc/tdataformat.h
@@ -80,7 +80,7 @@ typedef struct {
#define schemaFLen(s) ((s)->flen)
#define schemaVLen(s) ((s)->vlen)
#define schemaColAt(s, i) ((s)->columns + i)
-#define tdFreeSchema(s) taosTFree((s))
+#define tdFreeSchema(s) tfree((s))
STSchema *tdDupSchema(STSchema *pSchema);
int tdEncodeSchema(void **buf, STSchema *pSchema);
@@ -119,6 +119,33 @@ void tdResetTSchemaBuilder(STSchemaBuilder *pBuilder, int32_t version);
int tdAddColToSchema(STSchemaBuilder *pBuilder, int8_t type, int16_t colId, int16_t bytes);
STSchema *tdGetSchemaFromBuilder(STSchemaBuilder *pBuilder);
+// ----------------- Semantic timestamp key definition
+typedef uint64_t TKEY;
+
+#define TKEY_INVALID UINT64_MAX
+#define TKEY_NULL TKEY_INVALID
+#define TKEY_NEGATIVE_FLAG (((TKEY)1) << 63)
+#define TKEY_DELETE_FLAG (((TKEY)1) << 62)
+#define TKEY_VALUE_FILTER (~(TKEY_NEGATIVE_FLAG | TKEY_DELETE_FLAG))
+
+#define TKEY_IS_NEGATIVE(tkey) (((tkey)&TKEY_NEGATIVE_FLAG) != 0)
+#define TKEY_IS_DELETED(tkey) (((tkey)&TKEY_DELETE_FLAG) != 0)
+#define tdSetTKEYDeleted(tkey) ((tkey) | TKEY_DELETE_FLAG)
+#define tdGetTKEY(key) (((TKEY)ABS(key)) | (TKEY_NEGATIVE_FLAG & (TKEY)(key)))
+#define tdGetKey(tkey) (((TSKEY)((tkey)&TKEY_VALUE_FILTER)) * (TKEY_IS_NEGATIVE(tkey) ? -1 : 1))
+
+static FORCE_INLINE int tkeyComparFn(const void *tkey1, const void *tkey2) {
+ TSKEY key1 = tdGetKey(*(TKEY *)tkey1);
+ TSKEY key2 = tdGetKey(*(TKEY *)tkey2);
+
+ if (key1 < key2) {
+ return -1;
+ } else if (key1 > key2) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
// ----------------- Data row structure
/* A data row, the format is like below:
@@ -129,6 +156,8 @@ STSchema *tdGetSchemaFromBuilder(STSchemaBuilder *pBuilder);
* +----------+----------+---------------------------------+---------------------------------+
* | len | sversion | First part | Second part |
* +----------+----------+---------------------------------+---------------------------------+
+ *
+ * NOTE: timestamp in this row structure is TKEY instead of TSKEY
*/
typedef void *SDataRow;
@@ -137,11 +166,13 @@ typedef void *SDataRow;
#define dataRowLen(r) (*(uint16_t *)(r))
#define dataRowVersion(r) *(int16_t *)POINTER_SHIFT(r, sizeof(int16_t))
#define dataRowTuple(r) POINTER_SHIFT(r, TD_DATA_ROW_HEAD_SIZE)
-#define dataRowKey(r) (*(TSKEY *)(dataRowTuple(r)))
+#define dataRowTKey(r) (*(TKEY *)(dataRowTuple(r)))
+#define dataRowKey(r) tdGetKey(dataRowTKey(r))
#define dataRowSetLen(r, l) (dataRowLen(r) = (l))
#define dataRowSetVersion(r, v) (dataRowVersion(r) = (v))
#define dataRowCpy(dst, r) memcpy((dst), (r), dataRowLen(r))
#define dataRowMaxBytesFromSchema(s) (schemaTLen(s) + TD_DATA_ROW_HEAD_SIZE)
+#define dataRowDeleted(r) TKEY_IS_DELETED(dataRowTKey(r))
SDataRow tdNewDataRowFromSchema(STSchema *pSchema);
void tdFreeDataRow(SDataRow row);
@@ -154,16 +185,18 @@ static FORCE_INLINE int tdAppendColVal(SDataRow row, void *value, int8_t type, i
int32_t toffset = offset + TD_DATA_ROW_HEAD_SIZE;
char * ptr = (char *)POINTER_SHIFT(row, dataRowLen(row));
- switch (type) {
- case TSDB_DATA_TYPE_BINARY:
- case TSDB_DATA_TYPE_NCHAR:
- *(VarDataOffsetT *)POINTER_SHIFT(row, toffset) = dataRowLen(row);
- memcpy(ptr, value, varDataTLen(value));
- dataRowLen(row) += varDataTLen(value);
- break;
- default:
+ if (IS_VAR_DATA_TYPE(type)) {
+ *(VarDataOffsetT *)POINTER_SHIFT(row, toffset) = dataRowLen(row);
+ memcpy(ptr, value, varDataTLen(value));
+ dataRowLen(row) += varDataTLen(value);
+ } else {
+ if (offset == 0) {
+ ASSERT(type == TSDB_DATA_TYPE_TIMESTAMP);
+ TKEY tvalue = tdGetTKEY(*(TSKEY *)value);
+ memcpy(POINTER_SHIFT(row, toffset), (void *)(&tvalue), TYPE_BYTES[type]);
+ } else {
memcpy(POINTER_SHIFT(row, toffset), value, TYPE_BYTES[type]);
- break;
+ }
}
return 0;
@@ -171,12 +204,10 @@ static FORCE_INLINE int tdAppendColVal(SDataRow row, void *value, int8_t type, i
// NOTE: offset here including the header size
static FORCE_INLINE void *tdGetRowDataOfCol(SDataRow row, int8_t type, int32_t offset) {
- switch (type) {
- case TSDB_DATA_TYPE_BINARY:
- case TSDB_DATA_TYPE_NCHAR:
- return POINTER_SHIFT(row, *(VarDataOffsetT *)POINTER_SHIFT(row, offset));
- default:
- return POINTER_SHIFT(row, offset);
+ if (IS_VAR_DATA_TYPE(type)) {
+ return POINTER_SHIFT(row, *(VarDataOffsetT *)POINTER_SHIFT(row, offset));
+ } else {
+ return POINTER_SHIFT(row, offset);
}
}
@@ -196,7 +227,6 @@ static FORCE_INLINE void dataColReset(SDataCol *pDataCol) { pDataCol->len = 0; }
void dataColInit(SDataCol *pDataCol, STColumn *pCol, void **pBuf, int maxPoints);
void dataColAppendVal(SDataCol *pCol, void *value, int numOfRows, int maxPoints);
-void dataColPopPoints(SDataCol *pCol, int pointsToPop, int numOfRows);
void dataColSetOffset(SDataCol *pCol, int nEle);
bool isNEleNull(SDataCol *pCol, int nEle);
@@ -204,28 +234,20 @@ void dataColSetNEleNull(SDataCol *pCol, int nEle, int maxPoints);
// Get the data pointer from a column-wised data
static FORCE_INLINE void *tdGetColDataOfRow(SDataCol *pCol, int row) {
- switch (pCol->type) {
- case TSDB_DATA_TYPE_BINARY:
- case TSDB_DATA_TYPE_NCHAR:
- return POINTER_SHIFT(pCol->pData, pCol->dataOff[row]);
- break;
-
- default:
- return POINTER_SHIFT(pCol->pData, TYPE_BYTES[pCol->type] * row);
- break;
+ if (IS_VAR_DATA_TYPE(pCol->type)) {
+ return POINTER_SHIFT(pCol->pData, pCol->dataOff[row]);
+ } else {
+ return POINTER_SHIFT(pCol->pData, TYPE_BYTES[pCol->type] * row);
}
}
static FORCE_INLINE int32_t dataColGetNEleLen(SDataCol *pDataCol, int rows) {
ASSERT(rows > 0);
- switch (pDataCol->type) {
- case TSDB_DATA_TYPE_BINARY:
- case TSDB_DATA_TYPE_NCHAR:
- return pDataCol->dataOff[rows - 1] + varDataTLen(tdGetColDataOfRow(pDataCol, rows - 1));
- break;
- default:
- return TYPE_BYTES[pDataCol->type] * rows;
+ if (IS_VAR_DATA_TYPE(pDataCol->type)) {
+ return pDataCol->dataOff[rows - 1] + varDataTLen(tdGetColDataOfRow(pDataCol, rows - 1));
+ } else {
+ return TYPE_BYTES[pDataCol->type] * rows;
}
}
@@ -243,9 +265,14 @@ typedef struct {
} SDataCols;
#define keyCol(pCols) (&((pCols)->cols[0])) // Key column
-#define dataColsKeyAt(pCols, idx) ((TSKEY *)(keyCol(pCols)->pData))[(idx)]
-#define dataColsKeyFirst(pCols) dataColsKeyAt(pCols, 0)
-#define dataColsKeyLast(pCols) ((pCols->numOfRows == 0) ? 0 : dataColsKeyAt(pCols, (pCols)->numOfRows - 1))
+#define dataColsTKeyAt(pCols, idx) ((TKEY *)(keyCol(pCols)->pData))[(idx)]
+#define dataColsKeyAt(pCols, idx) tdGetKey(dataColsTKeyAt(pCols, idx))
+#define dataColsTKeyFirst(pCols) (((pCols)->numOfRows == 0) ? TKEY_INVALID : dataColsTKeyAt(pCols, 0))
+#define dataColsKeyFirst(pCols) (((pCols)->numOfRows == 0) ? TSDB_DATA_TIMESTAMP_NULL : dataColsKeyAt(pCols, 0))
+#define dataColsTKeyLast(pCols) \
+ (((pCols)->numOfRows == 0) ? TKEY_INVALID : dataColsTKeyAt(pCols, (pCols)->numOfRows - 1))
+#define dataColsKeyLast(pCols) \
+ (((pCols)->numOfRows == 0) ? TSDB_DATA_TIMESTAMP_NULL : dataColsKeyAt(pCols, (pCols)->numOfRows - 1))
SDataCols *tdNewDataCols(int maxRowSize, int maxCols, int maxRows);
void tdResetDataCols(SDataCols *pCols);
@@ -253,10 +280,7 @@ int tdInitDataCols(SDataCols *pCols, STSchema *pSchema);
SDataCols *tdDupDataCols(SDataCols *pCols, bool keepData);
void tdFreeDataCols(SDataCols *pCols);
void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols *pCols);
-void tdPopDataColsPoints(SDataCols *pCols, int pointsToPop); //!!!!
int tdMergeDataCols(SDataCols *target, SDataCols *src, int rowsToMerge);
-void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limit1, SDataCols *src2, int *iter2,
- int limit2, int tRows);
// ----------------- K-V data row structure
/*
@@ -284,7 +308,7 @@ typedef struct {
#define kvRowCpy(dst, r) memcpy((dst), (r), kvRowLen(r))
#define kvRowColVal(r, colIdx) POINTER_SHIFT(kvRowValues(r), (colIdx)->offset)
#define kvRowColIdxAt(r, i) (kvRowColIdx(r) + (i))
-#define kvRowFree(r) taosTFree(r)
+#define kvRowFree(r) tfree(r)
#define kvRowEnd(r) POINTER_SHIFT(r, kvRowLen(r))
SKVRow tdKVRowDup(SKVRow row);
diff --git a/src/common/inc/tglobal.h b/src/common/inc/tglobal.h
index 515115c323294a67318b5eb1dd17660e651d09f8..4087f638a95b063fcf6081db2556758643ef1c9a 100644
--- a/src/common/inc/tglobal.h
+++ b/src/common/inc/tglobal.h
@@ -44,13 +44,18 @@ extern int32_t tsMaxShellConns;
extern int32_t tsShellActivityTimer;
extern uint32_t tsMaxTmrCtrl;
extern float tsNumOfThreadsPerCore;
-extern float tsRatioOfQueryThreads;
+extern int32_t tsNumOfCommitThreads;
+extern float tsRatioOfQueryThreads; // todo remove it
extern int8_t tsDaylight;
extern char tsTimezone[];
extern char tsLocale[];
-extern char tsCharset[]; // default encode string
+extern char tsCharset[]; // default encode string
extern int32_t tsEnableCoreFile;
extern int32_t tsCompressMsgSize;
+extern char tsTempDir[];
+
+//query buffer management
+extern int32_t tsQueryBufferSize; // maximum allowed usage buffer for each data node during query processing
// client
extern int32_t tsTableMetaKeepTimer;
@@ -84,6 +89,7 @@ extern int16_t tsWAL;
extern int32_t tsFsyncPeriod;
extern int32_t tsReplications;
extern int32_t tsQuorum;
+extern int32_t tsUpdate;
// balance
extern int32_t tsEnableBalance;
@@ -180,13 +186,13 @@ extern int32_t debugFlag;
#define NEEDTO_COMPRESSS_MSG(size) (tsCompressMsgSize != -1 && (size) > tsCompressMsgSize)
-void taosInitGlobalCfg();
-bool taosCheckGlobalCfg();
-void taosSetAllDebugFlag();
-bool taosCfgDynamicOptions(char *msg);
-int taosGetFqdnPortFromEp(const char *ep, char *fqdn, uint16_t *port);
-bool taosCheckBalanceCfgOptions(const char *option, int32_t *vnodeId, int32_t *dnodeId);
-
+void taosInitGlobalCfg();
+int32_t taosCheckGlobalCfg();
+void taosSetAllDebugFlag();
+bool taosCfgDynamicOptions(char *msg);
+int taosGetFqdnPortFromEp(const char *ep, char *fqdn, uint16_t *port);
+bool taosCheckBalanceCfgOptions(const char *option, int32_t *vnodeId, int32_t *dnodeId);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/common/inc/tname.h b/src/common/inc/tname.h
index 6b73d98b81fa8cbcce8d322f566d8b6709396f1c..6c48ca72f3b5ea010c662faa09211afd40152615 100644
--- a/src/common/inc/tname.h
+++ b/src/common/inc/tname.h
@@ -35,6 +35,6 @@ bool tscValidateTableNameLength(size_t len);
SColumnFilterInfo* tscFilterInfoClone(const SColumnFilterInfo* src, int32_t numOfFilters);
-// int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, int64_t intervalTime, char timeUnit, int16_t precision);
+SSchema tscGetTbnameColumnSchema();
#endif // TDENGINE_NAME_H
diff --git a/src/common/src/tdataformat.c b/src/common/src/tdataformat.c
index 28289b051e4ef32e1b1e22847df584238857002b..f21205479396ba606a1212f30350df2e0b3f59b5 100644
--- a/src/common/src/tdataformat.c
+++ b/src/common/src/tdataformat.c
@@ -18,6 +18,9 @@
#include "tcoding.h"
#include "wchar.h"
+static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limit1, SDataCols *src2, int *iter2,
+ int limit2, int tRows);
+
/**
* Duplicate the schema and return a new object
*/
@@ -94,7 +97,7 @@ int tdInitTSchemaBuilder(STSchemaBuilder *pBuilder, int32_t version) {
void tdDestroyTSchemaBuilder(STSchemaBuilder *pBuilder) {
if (pBuilder) {
- taosTFree(pBuilder->columns);
+ tfree(pBuilder->columns);
}
}
@@ -202,7 +205,7 @@ void dataColInit(SDataCol *pDataCol, STColumn *pCol, void **pBuf, int maxPoints)
pDataCol->offset = colOffset(pCol) + TD_DATA_ROW_HEAD_SIZE;
pDataCol->len = 0;
- if (pDataCol->type == TSDB_DATA_TYPE_BINARY || pDataCol->type == TSDB_DATA_TYPE_NCHAR) {
+ if (IS_VAR_DATA_TYPE(pDataCol->type)) {
pDataCol->dataOff = (VarDataOffsetT *)(*pBuf);
pDataCol->pData = POINTER_SHIFT(*pBuf, sizeof(VarDataOffsetT) * maxPoints);
pDataCol->spaceSize = pDataCol->bytes * maxPoints;
@@ -215,60 +218,29 @@ void dataColInit(SDataCol *pDataCol, STColumn *pCol, void **pBuf, int maxPoints)
}
}
+// value from timestamp should be TKEY here instead of TSKEY
void dataColAppendVal(SDataCol *pCol, void *value, int numOfRows, int maxPoints) {
ASSERT(pCol != NULL && value != NULL);
- switch (pCol->type) {
- case TSDB_DATA_TYPE_BINARY:
- case TSDB_DATA_TYPE_NCHAR:
- // set offset
- pCol->dataOff[numOfRows] = pCol->len;
- // Copy data
- memcpy(POINTER_SHIFT(pCol->pData, pCol->len), value, varDataTLen(value));
- // Update the length
- pCol->len += varDataTLen(value);
- break;
- default:
- ASSERT(pCol->len == TYPE_BYTES[pCol->type] * numOfRows);
- memcpy(POINTER_SHIFT(pCol->pData, pCol->len), value, pCol->bytes);
- pCol->len += pCol->bytes;
- break;
- }
-}
-
-void dataColPopPoints(SDataCol *pCol, int pointsToPop, int numOfRows) {
- int pointsLeft = numOfRows - pointsToPop;
-
- ASSERT(pointsLeft > 0);
-
- if (pCol->type == TSDB_DATA_TYPE_BINARY || pCol->type == TSDB_DATA_TYPE_NCHAR) {
- ASSERT(pCol->len > 0);
- VarDataOffsetT toffset = pCol->dataOff[pointsToPop];
- pCol->len = pCol->len - toffset;
- ASSERT(pCol->len > 0);
- memmove(pCol->pData, POINTER_SHIFT(pCol->pData, toffset), pCol->len);
- dataColSetOffset(pCol, pointsLeft);
+ if (IS_VAR_DATA_TYPE(pCol->type)) {
+ // set offset
+ pCol->dataOff[numOfRows] = pCol->len;
+ // Copy data
+ memcpy(POINTER_SHIFT(pCol->pData, pCol->len), value, varDataTLen(value));
+ // Update the length
+ pCol->len += varDataTLen(value);
} else {
ASSERT(pCol->len == TYPE_BYTES[pCol->type] * numOfRows);
- pCol->len = TYPE_BYTES[pCol->type] * pointsLeft;
- memmove(pCol->pData, POINTER_SHIFT(pCol->pData, TYPE_BYTES[pCol->type] * pointsToPop), pCol->len);
+ memcpy(POINTER_SHIFT(pCol->pData, pCol->len), value, pCol->bytes);
+ pCol->len += pCol->bytes;
}
}
bool isNEleNull(SDataCol *pCol, int nEle) {
- switch (pCol->type) {
- case TSDB_DATA_TYPE_BINARY:
- case TSDB_DATA_TYPE_NCHAR:
- for (int i = 0; i < nEle; i++) {
- if (!isNull(tdGetColDataOfRow(pCol, i), pCol->type)) return false;
- }
- return true;
- default:
- for (int i = 0; i < nEle; i++) {
- if (!isNull(tdGetColDataOfRow(pCol, i), pCol->type)) return false;
- }
- return true;
+ for (int i = 0; i < nEle; i++) {
+ if (!isNull(tdGetColDataOfRow(pCol, i), pCol->type)) return false;
}
+ return true;
}
void dataColSetNullAt(SDataCol *pCol, int index) {
@@ -367,8 +339,8 @@ int tdInitDataCols(SDataCols *pCols, STSchema *pSchema) {
void tdFreeDataCols(SDataCols *pCols) {
if (pCols) {
- taosTFree(pCols->buf);
- taosTFree(pCols->cols);
+ tfree(pCols->buf);
+ tfree(pCols->cols);
free(pCols);
}
}
@@ -390,7 +362,7 @@ SDataCols *tdDupDataCols(SDataCols *pDataCols, bool keepData) {
pRet->cols[i].spaceSize = pDataCols->cols[i].spaceSize;
pRet->cols[i].pData = (void *)((char *)pRet->buf + ((char *)(pDataCols->cols[i].pData) - (char *)(pDataCols->buf)));
- if (pRet->cols[i].type == TSDB_DATA_TYPE_BINARY || pRet->cols[i].type == TSDB_DATA_TYPE_NCHAR) {
+ if (IS_VAR_DATA_TYPE(pRet->cols[i].type)) {
ASSERT(pDataCols->cols[i].dataOff != NULL);
pRet->cols[i].dataOff =
(int32_t *)((char *)pRet->buf + ((char *)(pDataCols->cols[i].dataOff) - (char *)(pDataCols->buf)));
@@ -400,7 +372,7 @@ SDataCols *tdDupDataCols(SDataCols *pDataCols, bool keepData) {
pRet->cols[i].len = pDataCols->cols[i].len;
if (pDataCols->cols[i].len > 0) {
memcpy(pRet->cols[i].pData, pDataCols->cols[i].pData, pDataCols->cols[i].len);
- if (pRet->cols[i].type == TSDB_DATA_TYPE_BINARY || pRet->cols[i].type == TSDB_DATA_TYPE_NCHAR) {
+ if (IS_VAR_DATA_TYPE(pRet->cols[i].type)) {
memcpy(pRet->cols[i].dataOff, pDataCols->cols[i].dataOff, sizeof(VarDataOffsetT) * pDataCols->maxPoints);
}
}
@@ -420,58 +392,54 @@ void tdResetDataCols(SDataCols *pCols) {
}
void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols *pCols) {
- ASSERT(dataColsKeyLast(pCols) < dataRowKey(row));
+ ASSERT(pCols->numOfRows == 0 || dataColsKeyLast(pCols) < dataRowKey(row));
int rcol = 0;
int dcol = 0;
- while (dcol < pCols->numOfCols) {
- SDataCol *pDataCol = &(pCols->cols[dcol]);
- if (rcol >= schemaNCols(pSchema)) {
- dataColSetNullAt(pDataCol, pCols->numOfRows);
- dcol++;
- continue;
+ if (dataRowDeleted(row)) {
+ for (; dcol < pCols->numOfCols; dcol++) {
+ SDataCol *pDataCol = &(pCols->cols[dcol]);
+ if (dcol == 0) {
+ dataColAppendVal(pDataCol, dataRowTuple(row), pCols->numOfRows, pCols->maxPoints);
+ } else {
+ dataColSetNullAt(pDataCol, pCols->numOfRows);
+ }
}
+ } else {
+ while (dcol < pCols->numOfCols) {
+ SDataCol *pDataCol = &(pCols->cols[dcol]);
+ if (rcol >= schemaNCols(pSchema)) {
+ dataColSetNullAt(pDataCol, pCols->numOfRows);
+ dcol++;
+ continue;
+ }
- STColumn *pRowCol = schemaColAt(pSchema, rcol);
- if (pRowCol->colId == pDataCol->colId) {
- void *value = tdGetRowDataOfCol(row, pRowCol->type, pRowCol->offset+TD_DATA_ROW_HEAD_SIZE);
- dataColAppendVal(pDataCol, value, pCols->numOfRows, pCols->maxPoints);
- dcol++;
- rcol++;
- } else if (pRowCol->colId < pDataCol->colId) {
- rcol++;
- } else {
- dataColSetNullAt(pDataCol, pCols->numOfRows);
- dcol++;
+ STColumn *pRowCol = schemaColAt(pSchema, rcol);
+ if (pRowCol->colId == pDataCol->colId) {
+ void *value = tdGetRowDataOfCol(row, pRowCol->type, pRowCol->offset + TD_DATA_ROW_HEAD_SIZE);
+ dataColAppendVal(pDataCol, value, pCols->numOfRows, pCols->maxPoints);
+ dcol++;
+ rcol++;
+ } else if (pRowCol->colId < pDataCol->colId) {
+ rcol++;
+ } else {
+ dataColSetNullAt(pDataCol, pCols->numOfRows);
+ dcol++;
+ }
}
}
pCols->numOfRows++;
}
-// Pop pointsToPop points from the SDataCols
-void tdPopDataColsPoints(SDataCols *pCols, int pointsToPop) {
- int pointsLeft = pCols->numOfRows - pointsToPop;
- if (pointsLeft <= 0) {
- tdResetDataCols(pCols);
- return;
- }
-
- for (int iCol = 0; iCol < pCols->numOfCols; iCol++) {
- SDataCol *pCol = pCols->cols + iCol;
- dataColPopPoints(pCol, pointsToPop, pCols->numOfRows);
- }
- pCols->numOfRows = pointsLeft;
-}
-
int tdMergeDataCols(SDataCols *target, SDataCols *source, int rowsToMerge) {
ASSERT(rowsToMerge > 0 && rowsToMerge <= source->numOfRows);
- ASSERT(target->numOfRows + rowsToMerge <= target->maxPoints);
ASSERT(target->numOfCols == source->numOfCols);
SDataCols *pTarget = NULL;
if (dataColsKeyLast(target) < dataColsKeyFirst(source)) { // No overlap
+ ASSERT(target->numOfRows + rowsToMerge <= target->maxPoints);
for (int i = 0; i < rowsToMerge; i++) {
for (int j = 0; j < source->numOfCols; j++) {
if (source->cols[j].len > 0) {
@@ -499,17 +467,23 @@ _err:
return -1;
}
-void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limit1, SDataCols *src2, int *iter2, int limit2, int tRows) {
+// src2 data has more priority than src1
+static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limit1, SDataCols *src2, int *iter2,
+ int limit2, int tRows) {
tdResetDataCols(target);
ASSERT(limit1 <= src1->numOfRows && limit2 <= src2->numOfRows);
while (target->numOfRows < tRows) {
if (*iter1 >= limit1 && *iter2 >= limit2) break;
- TSKEY key1 = (*iter1 >= limit1) ? INT64_MAX : ((TSKEY *)(src1->cols[0].pData))[*iter1];
- TSKEY key2 = (*iter2 >= limit2) ? INT64_MAX : ((TSKEY *)(src2->cols[0].pData))[*iter2];
+ TSKEY key1 = (*iter1 >= limit1) ? INT64_MAX : dataColsKeyAt(src1, *iter1);
+ TKEY tkey1 = (*iter1 >= limit1) ? TKEY_NULL : dataColsTKeyAt(src1, *iter1);
+ TSKEY key2 = (*iter2 >= limit2) ? INT64_MAX : dataColsKeyAt(src2, *iter2);
+ TKEY tkey2 = (*iter2 >= limit2) ? TKEY_NULL : dataColsTKeyAt(src2, *iter2);
- if (key1 <= key2) {
+ ASSERT(tkey1 == TKEY_NULL || (!TKEY_IS_DELETED(tkey1)));
+
+ if (key1 < key2) {
for (int i = 0; i < src1->numOfCols; i++) {
ASSERT(target->cols[i].type == src1->cols[i].type);
if (src1->cols[i].len > 0) {
@@ -520,19 +494,23 @@ void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limi
target->numOfRows++;
(*iter1)++;
- if (key1 == key2) (*iter2)++;
- } else {
- for (int i = 0; i < src2->numOfCols; i++) {
- ASSERT(target->cols[i].type == src2->cols[i].type);
- if (src2->cols[i].len > 0) {
- dataColAppendVal(&(target->cols[i]), tdGetColDataOfRow(src2->cols + i, *iter2), target->numOfRows,
- target->maxPoints);
+ } else if (key1 >= key2) {
+ if ((key1 > key2) || (key1 == key2 && !TKEY_IS_DELETED(tkey2))) {
+ for (int i = 0; i < src2->numOfCols; i++) {
+ ASSERT(target->cols[i].type == src2->cols[i].type);
+ if (src2->cols[i].len > 0) {
+ dataColAppendVal(&(target->cols[i]), tdGetColDataOfRow(src2->cols + i, *iter2), target->numOfRows,
+ target->maxPoints);
+ }
}
+ target->numOfRows++;
}
- target->numOfRows++;
(*iter2)++;
+ if (key1 == key2) (*iter1)++;
}
+
+ ASSERT(target->numOfRows <= target->maxPoints);
}
}
@@ -691,8 +669,8 @@ int tdInitKVRowBuilder(SKVRowBuilder *pBuilder) {
}
void tdDestroyKVRowBuilder(SKVRowBuilder *pBuilder) {
- taosTFree(pBuilder->pColIdx);
- taosTFree(pBuilder->buf);
+ tfree(pBuilder->pColIdx);
+ tfree(pBuilder->buf);
}
void tdResetKVRowBuilder(SKVRowBuilder *pBuilder) {
diff --git a/src/common/src/tglobal.c b/src/common/src/tglobal.c
index c24ba490ba7f4cb25ba032b0404790d68540c826..4495c3d9288a5df0b8944aa444625c143b5c7670 100644
--- a/src/common/src/tglobal.c
+++ b/src/common/src/tglobal.c
@@ -45,19 +45,21 @@ int32_t tsEnableTelemetryReporting = 1;
char tsEmail[TSDB_FQDN_LEN] = {0};
// common
-int32_t tsRpcTimer = 1000;
-int32_t tsRpcMaxTime = 600; // seconds;
-int32_t tsMaxShellConns = 5000;
+int32_t tsRpcTimer = 1000;
+int32_t tsRpcMaxTime = 600; // seconds;
+int32_t tsMaxShellConns = 5000;
int32_t tsMaxConnections = 5000;
-int32_t tsShellActivityTimer = 3; // second
-float tsNumOfThreadsPerCore = 1.0;
-float tsRatioOfQueryThreads = 0.5;
-int8_t tsDaylight = 0;
+int32_t tsShellActivityTimer = 3; // second
+float tsNumOfThreadsPerCore = 1.0f;
+int32_t tsNumOfCommitThreads = 1;
+float tsRatioOfQueryThreads = 0.5f;
+int8_t tsDaylight = 0;
char tsTimezone[TSDB_TIMEZONE_LEN] = {0};
char tsLocale[TSDB_LOCALE_LEN] = {0};
char tsCharset[TSDB_LOCALE_LEN] = {0}; // default encode string
int32_t tsEnableCoreFile = 0;
int32_t tsMaxBinaryDisplayWidth = 30;
+char tsTempDir[TSDB_FILENAME_LEN] = "/tmp/";
/*
* denote if the server needs to compress response message at the application layer to client, including query rsp,
@@ -99,6 +101,12 @@ float tsStreamComputDelayRatio = 0.1f;
int32_t tsProjectExecInterval = 10000; // every 10sec, the projection will be executed once
int64_t tsMaxRetentWindow = 24 * 3600L; // maximum time window tolerance
+// the maximum allowed query buffer size during query processing for each data node.
+// -1 no limit (default)
+// 0 no query allowed, queries are disabled
+// positive value (in MB)
+int32_t tsQueryBufferSize = -1;
+
// db parameters
int32_t tsCacheBlockSize = TSDB_DEFAULT_CACHE_BLOCK_SIZE;
int32_t tsBlocksPerVnode = TSDB_DEFAULT_TOTAL_BLOCKS;
@@ -113,6 +121,7 @@ int16_t tsWAL = TSDB_DEFAULT_WAL_LEVEL;
int32_t tsFsyncPeriod = TSDB_DEFAULT_FSYNC_PERIOD;
int32_t tsReplications = TSDB_DEFAULT_DB_REPLICA_OPTION;
int32_t tsQuorum = TSDB_DEFAULT_DB_QUORUM_OPTION;
+int32_t tsUpdate = TSDB_DEFAULT_DB_UPDATE_OPTION;
int32_t tsMaxVgroupsPerDb = 0;
int32_t tsMinTablePerVnode = TSDB_TABLES_STEP;
int32_t tsMaxTablePerVnode = TSDB_DEFAULT_TABLES;
@@ -210,6 +219,8 @@ int32_t (*monitorStartSystemFp)() = NULL;
void (*monitorStopSystemFp)() = NULL;
void (*monitorExecuteSQLFp)(char *sql) = NULL;
+char *qtypeStr[] = {"rpc", "fwd", "wal", "cq", "query"};
+
static pthread_once_t tsInitGlobalCfgOnce = PTHREAD_ONCE_INIT;
void taosSetAllDebugFlag() {
@@ -416,6 +427,16 @@ static void doInitGlobalConfig(void) {
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
+ cfg.option = "numOfCommitThreads";
+ cfg.ptr = &tsNumOfCommitThreads;
+ cfg.valType = TAOS_CFG_VTYPE_INT32;
+ cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG;
+ cfg.minValue = 1;
+ cfg.maxValue = 100;
+ cfg.ptrLength = 0;
+ cfg.unitType = TAOS_CFG_UTYPE_NONE;
+ taosInitConfigOption(cfg);
+
cfg.option = "ratioOfQueryThreads";
cfg.ptr = &tsRatioOfQueryThreads;
cfg.valType = TAOS_CFG_VTYPE_FLOAT;
@@ -676,7 +697,7 @@ static void doInitGlobalConfig(void) {
cfg.minValue = TSDB_MIN_CACHE_BLOCK_SIZE;
cfg.maxValue = TSDB_MAX_CACHE_BLOCK_SIZE;
cfg.ptrLength = 0;
- cfg.unitType = TAOS_CFG_UTYPE_Mb;
+ cfg.unitType = TAOS_CFG_UTYPE_MB;
taosInitConfigOption(cfg);
cfg.option = "blocks";
@@ -779,6 +800,16 @@ static void doInitGlobalConfig(void) {
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
+ cfg.option = "update";
+ cfg.ptr = &tsUpdate;
+ cfg.valType = TAOS_CFG_VTYPE_INT32;
+ cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_SHOW;
+ cfg.minValue = TSDB_MIN_DB_UPDATE;
+ cfg.maxValue = TSDB_MAX_DB_UPDATE;
+ cfg.ptrLength = 0;
+ cfg.unitType = TAOS_CFG_UTYPE_NONE;
+ taosInitConfigOption(cfg);
+
cfg.option = "mqttHostName";
cfg.ptr = tsMqttHostName;
cfg.valType = TAOS_CFG_VTYPE_STRING;
@@ -839,6 +870,16 @@ static void doInitGlobalConfig(void) {
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
+ cfg.option = "queryBufferSize";
+ cfg.ptr = &tsQueryBufferSize;
+ cfg.valType = TAOS_CFG_VTYPE_INT32;
+ cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_SHOW;
+ cfg.minValue = -1;
+ cfg.maxValue = 500000000000.0f;
+ cfg.ptrLength = 0;
+ cfg.unitType = TAOS_CFG_UTYPE_BYTE;
+ taosInitConfigOption(cfg);
+
// locale & charset
cfg.option = "timezone";
cfg.ptr = tsTimezone;
@@ -1294,13 +1335,23 @@ static void doInitGlobalConfig(void) {
cfg.ptrLength = 0;
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
+
+ cfg.option = "tempDir";
+ cfg.ptr = tsTempDir;
+ cfg.valType = TAOS_CFG_VTYPE_STRING;
+ cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_CLIENT;
+ cfg.minValue = 0;
+ cfg.maxValue = 0;
+ cfg.ptrLength = tListLen(tsTempDir);
+ cfg.unitType = TAOS_CFG_UTYPE_NONE;
+ taosInitConfigOption(cfg);
}
void taosInitGlobalCfg() {
pthread_once(&tsInitGlobalCfgOnce, doInitGlobalConfig);
}
-bool taosCheckGlobalCfg() {
+int32_t taosCheckGlobalCfg() {
char fqdn[TSDB_FQDN_LEN];
uint16_t port;
@@ -1359,7 +1410,9 @@ bool taosCheckGlobalCfg() {
tsSyncPort = tsServerPort + TSDB_PORT_SYNC;
tsHttpPort = tsServerPort + TSDB_PORT_HTTP;
- return true;
+ taosPrintGlobalCfg();
+
+ return 0;
}
int taosGetFqdnPortFromEp(const char *ep, char *fqdn, uint16_t *port) {
diff --git a/src/common/src/tname.c b/src/common/src/tname.c
index 8879e9e7979be5b019b3048389105faa86ac9225..bea8c52ef21ea607bee5379ace879ef936ff60bb 100644
--- a/src/common/src/tname.c
+++ b/src/common/src/tname.c
@@ -188,3 +188,14 @@ void extractTableNameFromToken(SStrToken* pToken, SStrToken* pTable) {
pToken->z = r;
}
}
+
+SSchema tscGetTbnameColumnSchema() {
+ struct SSchema s = {
+ .colId = TSDB_TBNAME_COLUMN_INDEX,
+ .type = TSDB_DATA_TYPE_BINARY,
+ .bytes = TSDB_TABLE_NAME_LEN
+ };
+
+ strcpy(s.name, TSQL_TBNAME_L);
+ return s;
+}
\ No newline at end of file
diff --git a/src/common/src/ttypes.c b/src/common/src/ttypes.c
index 50554ce08e3fb659c1a5915c4c50b09f950324b4..f28481977f41bf550205d2669c6f90a016d2b7c4 100644
--- a/src/common/src/ttypes.c
+++ b/src/common/src/ttypes.c
@@ -355,32 +355,6 @@ bool isValidDataType(int32_t type) {
return type >= TSDB_DATA_TYPE_NULL && type <= TSDB_DATA_TYPE_NCHAR;
}
-//bool isNull(const char *val, int32_t type) {
-// switch (type) {
-// case TSDB_DATA_TYPE_BOOL:
-// return *(uint8_t *)val == TSDB_DATA_BOOL_NULL;
-// case TSDB_DATA_TYPE_TINYINT:
-// return *(uint8_t *)val == TSDB_DATA_TINYINT_NULL;
-// case TSDB_DATA_TYPE_SMALLINT:
-// return *(uint16_t *)val == TSDB_DATA_SMALLINT_NULL;
-// case TSDB_DATA_TYPE_INT:
-// return *(uint32_t *)val == TSDB_DATA_INT_NULL;
-// case TSDB_DATA_TYPE_BIGINT:
-// case TSDB_DATA_TYPE_TIMESTAMP:
-// return *(uint64_t *)val == TSDB_DATA_BIGINT_NULL;
-// case TSDB_DATA_TYPE_FLOAT:
-// return *(uint32_t *)val == TSDB_DATA_FLOAT_NULL;
-// case TSDB_DATA_TYPE_DOUBLE:
-// return *(uint64_t *)val == TSDB_DATA_DOUBLE_NULL;
-// case TSDB_DATA_TYPE_NCHAR:
-// return *(uint32_t*) varDataVal(val) == TSDB_DATA_NCHAR_NULL;
-// case TSDB_DATA_TYPE_BINARY:
-// return *(uint8_t *) varDataVal(val) == TSDB_DATA_BINARY_NULL;
-// default:
-// return false;
-// };
-//}
-
void setVardataNull(char* val, int32_t type) {
if (type == TSDB_DATA_TYPE_BINARY) {
varDataSetLen(val, sizeof(int8_t));
@@ -433,14 +407,10 @@ void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems) {
*(uint64_t *)(val + i * tDataTypeDesc[type].nSize) = TSDB_DATA_DOUBLE_NULL;
}
break;
- case TSDB_DATA_TYPE_NCHAR: // todo : without length?
- for (int32_t i = 0; i < numOfElems; ++i) {
- *(uint32_t *)(val + i * bytes) = TSDB_DATA_NCHAR_NULL;
- }
- break;
+ case TSDB_DATA_TYPE_NCHAR:
case TSDB_DATA_TYPE_BINARY:
for (int32_t i = 0; i < numOfElems; ++i) {
- *(uint8_t *)(val + i * bytes) = TSDB_DATA_BINARY_NULL;
+ setVardataNull(val + i * bytes, type);
}
break;
default: {
diff --git a/src/common/src/tvariant.c b/src/common/src/tvariant.c
index 005def6dc597361436b03c15535840af2bd3461e..6dd065382265cb09e26f8d1b6f86c4b5b3f5110b 100644
--- a/src/common/src/tvariant.c
+++ b/src/common/src/tvariant.c
@@ -108,7 +108,7 @@ void tVariantCreateFromBinary(tVariant *pVar, const char *pz, size_t len, uint32
break;
}
case TSDB_DATA_TYPE_BINARY: { // todo refactor, extract a method
- pVar->pz = calloc(len, sizeof(char));
+ pVar->pz = calloc(len + 1, sizeof(char));
memcpy(pVar->pz, pz, len);
pVar->nLen = (int32_t)len;
break;
@@ -125,7 +125,7 @@ void tVariantDestroy(tVariant *pVar) {
if (pVar == NULL) return;
if (pVar->nType == TSDB_DATA_TYPE_BINARY || pVar->nType == TSDB_DATA_TYPE_NCHAR) {
- taosTFree(pVar->pz);
+ tfree(pVar->pz);
pVar->nLen = 0;
}
@@ -144,21 +144,24 @@ void tVariantDestroy(tVariant *pVar) {
void tVariantAssign(tVariant *pDst, const tVariant *pSrc) {
if (pSrc == NULL || pDst == NULL) return;
- *pDst = *pSrc;
-
+ pDst->nType = pSrc->nType;
if (pSrc->nType == TSDB_DATA_TYPE_BINARY || pSrc->nType == TSDB_DATA_TYPE_NCHAR) {
- int32_t len = pSrc->nLen + 1;
- if (pSrc->nType == TSDB_DATA_TYPE_NCHAR) {
- len = len * TSDB_NCHAR_SIZE;
- }
-
- pDst->pz = calloc(1, len);
- memcpy(pDst->pz, pSrc->pz, len);
+ int32_t len = pSrc->nLen + TSDB_NCHAR_SIZE;
+ char* p = realloc(pDst->pz, len);
+ assert(p);
+
+ memset(p, 0, len);
+ pDst->pz = p;
+
+ memcpy(pDst->pz, pSrc->pz, pSrc->nLen);
+ pDst->nLen = pSrc->nLen;
return;
+
}
- // this is only for string array
- if (pSrc->nType == TSDB_DATA_TYPE_ARRAY) {
+ if (pSrc->nType >= TSDB_DATA_TYPE_BOOL && pSrc->nType <= TSDB_DATA_TYPE_DOUBLE) {
+ pDst->i64Key = pSrc->i64Key;
+ } else if (pSrc->nType == TSDB_DATA_TYPE_ARRAY) { // this is only for string array
size_t num = taosArrayGetSize(pSrc->arr);
pDst->arr = taosArrayInit(num, sizeof(char*));
for(size_t i = 0; i < num; i++) {
@@ -166,8 +169,6 @@ void tVariantAssign(tVariant *pDst, const tVariant *pSrc) {
char* n = strdup(p);
taosArrayPush(pDst->arr, &n);
}
-
- return;
}
pDst->nLen = tDataTypeDesc[pDst->nType].nSize;
diff --git a/src/connector/C#/TDengineDriver.cs b/src/connector/C#/TDengineDriver.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b6f143e1813d60c1ac4ae8356efdca4929c51345
--- /dev/null
+++ b/src/connector/C#/TDengineDriver.cs
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace TDengineDriver
+{
+ enum TDengineDataType {
+ TSDB_DATA_TYPE_NULL = 0, // 1 bytes
+ TSDB_DATA_TYPE_BOOL = 1, // 1 bytes
+ TSDB_DATA_TYPE_TINYINT = 2, // 1 bytes
+ TSDB_DATA_TYPE_SMALLINT = 3, // 2 bytes
+ TSDB_DATA_TYPE_INT = 4, // 4 bytes
+ TSDB_DATA_TYPE_BIGINT = 5, // 8 bytes
+ TSDB_DATA_TYPE_FLOAT = 6, // 4 bytes
+ TSDB_DATA_TYPE_DOUBLE = 7, // 8 bytes
+ TSDB_DATA_TYPE_BINARY = 8, // string
+ TSDB_DATA_TYPE_TIMESTAMP = 9,// 8 bytes
+ TSDB_DATA_TYPE_NCHAR = 10 // unicode string
+ }
+
+ enum TDengineInitOption
+ {
+ TSDB_OPTION_LOCALE = 0,
+ TSDB_OPTION_CHARSET = 1,
+ TSDB_OPTION_TIMEZONE = 2,
+ TDDB_OPTION_CONFIGDIR = 3,
+ TDDB_OPTION_SHELL_ACTIVITY_TIMER = 4
+ }
+
+ class TDengineMeta
+ {
+ public string name;
+ public short size;
+ public byte type;
+ public string TypeName()
+ {
+ switch ((TDengineDataType)type)
+ {
+ case TDengineDataType.TSDB_DATA_TYPE_BOOL:
+ return "BOOLEAN";
+ case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
+ return "BYTE";
+ case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
+ return "SHORT";
+ case TDengineDataType.TSDB_DATA_TYPE_INT:
+ return "INT";
+ case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
+ return "LONG";
+ case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
+ return "FLOAT";
+ case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
+ return "DOUBLE";
+ case TDengineDataType.TSDB_DATA_TYPE_BINARY:
+ return "STRING";
+ case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
+ return "TIMESTAMP";
+ case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
+ return "NCHAR";
+ default:
+ return "undefine";
+ }
+ }
+ }
+
+ class TDengine
+ {
+ public const int TSDB_CODE_SUCCESS = 0;
+
+ [DllImport("taos.dll", EntryPoint = "taos_init", CallingConvention = CallingConvention.Cdecl)]
+ static extern public void Init();
+
+ [DllImport("taos.dll", EntryPoint = "taos_cleanup", CallingConvention = CallingConvention.Cdecl)]
+ static extern public void Cleanup();
+
+ [DllImport("taos.dll", EntryPoint = "taos_options", CallingConvention = CallingConvention.Cdecl)]
+ static extern public void Options(int option, string value);
+
+ [DllImport("taos.dll", EntryPoint = "taos_connect", CallingConvention = CallingConvention.Cdecl)]
+ static extern public IntPtr Connect(string ip, string user, string password, string db, short port);
+
+ [DllImport("taos.dll", EntryPoint = "taos_errstr", CallingConvention = CallingConvention.Cdecl)]
+ static extern private IntPtr taos_errstr(IntPtr res);
+ static public string Error(IntPtr res)
+ {
+ IntPtr errPtr = taos_errstr(res);
+ return Marshal.PtrToStringAnsi(errPtr);
+ }
+
+ [DllImport("taos.dll", EntryPoint = "taos_errno", CallingConvention = CallingConvention.Cdecl)]
+ static extern public int ErrorNo(IntPtr res);
+
+ [DllImport("taos.dll", EntryPoint = "taos_query", CallingConvention = CallingConvention.Cdecl)]
+ static extern public IntPtr Query(IntPtr conn, string sqlstr);
+
+ [DllImport("taos.dll", EntryPoint = "taos_affected_rows", CallingConvention = CallingConvention.Cdecl)]
+ static extern public int AffectRows(IntPtr res);
+
+ [DllImport("taos.dll", EntryPoint = "taos_field_count", CallingConvention = CallingConvention.Cdecl)]
+ static extern public int FieldCount(IntPtr res);
+
+ [DllImport("taos.dll", EntryPoint = "taos_fetch_fields", CallingConvention = CallingConvention.Cdecl)]
+ static extern private IntPtr taos_fetch_fields(IntPtr res);
+ static public List FetchFields(IntPtr res)
+ {
+ const int fieldSize = 68;
+
+ List metas = new List();
+ if (res == IntPtr.Zero)
+ {
+ return metas;
+ }
+
+ int fieldCount = FieldCount(res);
+ IntPtr fieldsPtr = taos_fetch_fields(res);
+
+ for (int i = 0; i < fieldCount; ++i)
+ {
+ int offset = i * fieldSize;
+
+ TDengineMeta meta = new TDengineMeta();
+ meta.name = Marshal.PtrToStringAnsi(fieldsPtr + offset);
+ meta.type = Marshal.ReadByte(fieldsPtr + offset + 65);
+ meta.size = Marshal.ReadInt16(fieldsPtr + offset + 66);
+ metas.Add(meta);
+ }
+
+ return metas;
+ }
+
+ [DllImport("taos.dll", EntryPoint = "taos_fetch_row", CallingConvention = CallingConvention.Cdecl)]
+ static extern public IntPtr FetchRows(IntPtr res);
+
+ [DllImport("taos.dll", EntryPoint = "taos_free_result", CallingConvention = CallingConvention.Cdecl)]
+ static extern public IntPtr FreeResult(IntPtr res);
+
+ [DllImport("taos.dll", EntryPoint = "taos_close", CallingConvention = CallingConvention.Cdecl)]
+ static extern public int Close(IntPtr taos);
+ }
+}
\ No newline at end of file
diff --git a/src/connector/go b/src/connector/go
index 8d7bf743852897110cbdcc7c4322cd7a74d4167b..050667e5b4d0eafa5387e4283e713559b421203f 160000
--- a/src/connector/go
+++ b/src/connector/go
@@ -1 +1 @@
-Subproject commit 8d7bf743852897110cbdcc7c4322cd7a74d4167b
+Subproject commit 050667e5b4d0eafa5387e4283e713559b421203f
diff --git a/src/connector/grafanaplugin b/src/connector/grafanaplugin
index d598db167eb256fe67409b7bb3d0eb7fffc3ff8c..ec77d9049a719dabfd1a7c1122a209e201861944 160000
--- a/src/connector/grafanaplugin
+++ b/src/connector/grafanaplugin
@@ -1 +1 @@
-Subproject commit d598db167eb256fe67409b7bb3d0eb7fffc3ff8c
+Subproject commit ec77d9049a719dabfd1a7c1122a209e201861944
diff --git a/src/connector/hivemq-tdengine-extension b/src/connector/hivemq-tdengine-extension
new file mode 160000
index 0000000000000000000000000000000000000000..b62a26ecc164a310104df57691691b237e091c89
--- /dev/null
+++ b/src/connector/hivemq-tdengine-extension
@@ -0,0 +1 @@
+Subproject commit b62a26ecc164a310104df57691691b237e091c89
diff --git a/src/connector/jdbc/deploy-pom.xml b/src/connector/jdbc/deploy-pom.xml
index 3f6ebeff03f538e4963540e015c7fd4b310acc42..51db837c7b1149bfc5dca6d69a953ceb6b3eb898 100755
--- a/src/connector/jdbc/deploy-pom.xml
+++ b/src/connector/jdbc/deploy-pom.xml
@@ -5,14 +5,13 @@
com.taosdata.jdbc
taos-jdbcdriver
- 2.0.6
+ 2.0.10
jar
JDBCDriver
https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc
TDengine JDBC Driver
-
GNU AFFERO GENERAL PUBLIC LICENSE Version 3
diff --git a/src/connector/jdbc/pom.xml b/src/connector/jdbc/pom.xml
index 3b62f66d2ec88002d2f749166fb00bff670617ee..e7124a0599fa80baabba84700eb097bde3e57287 100755
--- a/src/connector/jdbc/pom.xml
+++ b/src/connector/jdbc/pom.xml
@@ -56,6 +56,23 @@
test
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.8
+
+
+ org.apache.commons
+ commons-lang3
+ 3.9
+
+
+ com.alibaba
+ fastjson
+ 1.2.58
+
+
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractTaosDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractTaosDriver.java
new file mode 100644
index 0000000000000000000000000000000000000000..f864788bfffc8bdfefb0b91ec645a10ae8eec843
--- /dev/null
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractTaosDriver.java
@@ -0,0 +1,161 @@
+package com.taosdata.jdbc;
+
+import java.io.*;
+import java.sql.Driver;
+import java.sql.DriverPropertyInfo;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+public abstract class AbstractTaosDriver implements Driver {
+
+ private static final String TAOS_CFG_FILENAME = "taos.cfg";
+
+ /**
+ * @param cfgDirPath
+ * @return return the config dir
+ **/
+ protected File loadConfigDir(String cfgDirPath) {
+ if (cfgDirPath == null)
+ return loadDefaultConfigDir();
+ File cfgDir = new File(cfgDirPath);
+ if (!cfgDir.exists())
+ return loadDefaultConfigDir();
+ return cfgDir;
+ }
+
+ /**
+ * @return search the default config dir, if the config dir is not exist will return null
+ */
+ protected File loadDefaultConfigDir() {
+ File cfgDir;
+ File cfgDir_linux = new File("/etc/taos");
+ cfgDir = cfgDir_linux.exists() ? cfgDir_linux : null;
+ File cfgDir_windows = new File("C:\\TDengine\\cfg");
+ cfgDir = (cfgDir == null && cfgDir_windows.exists()) ? cfgDir_windows : cfgDir;
+ return cfgDir;
+ }
+
+ protected List loadConfigEndpoints(File cfgFile) {
+ List endpoints = new ArrayList<>();
+ try (BufferedReader reader = new BufferedReader(new FileReader(cfgFile))) {
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ if (line.trim().startsWith("firstEp") || line.trim().startsWith("secondEp")) {
+ endpoints.add(line.substring(line.indexOf('p') + 1).trim());
+ }
+ if (endpoints.size() > 1)
+ break;
+ }
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return endpoints;
+ }
+
+ protected void loadTaosConfig(Properties info) {
+ if ((info.getProperty(TSDBDriver.PROPERTY_KEY_HOST) == null ||
+ info.getProperty(TSDBDriver.PROPERTY_KEY_HOST).isEmpty()) && (
+ info.getProperty(TSDBDriver.PROPERTY_KEY_PORT) == null ||
+ info.getProperty(TSDBDriver.PROPERTY_KEY_PORT).isEmpty())) {
+ File cfgDir = loadConfigDir(info.getProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR));
+ File cfgFile = cfgDir.listFiles((dir, name) -> TAOS_CFG_FILENAME.equalsIgnoreCase(name))[0];
+ List endpoints = loadConfigEndpoints(cfgFile);
+ if (!endpoints.isEmpty()) {
+ info.setProperty(TSDBDriver.PROPERTY_KEY_HOST, endpoints.get(0).split(":")[0]);
+ info.setProperty(TSDBDriver.PROPERTY_KEY_PORT, endpoints.get(0).split(":")[1]);
+ }
+ }
+ }
+
+ protected DriverPropertyInfo[] getPropertyInfo(Properties info) {
+ DriverPropertyInfo hostProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_HOST, info.getProperty(TSDBDriver.PROPERTY_KEY_HOST));
+ hostProp.required = false;
+ hostProp.description = "Hostname";
+
+ DriverPropertyInfo portProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_PORT, info.getProperty(TSDBDriver.PROPERTY_KEY_PORT, TSDBConstants.DEFAULT_PORT));
+ portProp.required = false;
+ portProp.description = "Port";
+
+ DriverPropertyInfo dbProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_DBNAME, info.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME));
+ dbProp.required = false;
+ dbProp.description = "Database name";
+
+ DriverPropertyInfo userProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_USER, info.getProperty(TSDBDriver.PROPERTY_KEY_USER));
+ userProp.required = true;
+ userProp.description = "User";
+
+ DriverPropertyInfo passwordProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_PASSWORD, info.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD));
+ passwordProp.required = true;
+ passwordProp.description = "Password";
+
+ DriverPropertyInfo[] propertyInfo = new DriverPropertyInfo[5];
+ propertyInfo[0] = hostProp;
+ propertyInfo[1] = portProp;
+ propertyInfo[2] = dbProp;
+ propertyInfo[3] = userProp;
+ propertyInfo[4] = passwordProp;
+ return propertyInfo;
+ }
+
+ protected Properties parseURL(String url, Properties defaults) {
+ Properties urlProps = (defaults != null) ? defaults : new Properties();
+
+ // parse properties
+ int beginningOfSlashes = url.indexOf("//");
+ int index = url.indexOf("?");
+ if (index != -1) {
+ String paramString = url.substring(index + 1, url.length());
+ url = url.substring(0, index);
+ StringTokenizer queryParams = new StringTokenizer(paramString, "&");
+ while (queryParams.hasMoreElements()) {
+ String parameterValuePair = queryParams.nextToken();
+ int indexOfEqual = parameterValuePair.indexOf("=");
+ String parameter = null;
+ String value = null;
+ if (indexOfEqual != -1) {
+ parameter = parameterValuePair.substring(0, indexOfEqual);
+ if (indexOfEqual + 1 < parameterValuePair.length()) {
+ value = parameterValuePair.substring(indexOfEqual + 1);
+ }
+ }
+ if ((value != null && value.length() > 0) && (parameter != null && parameter.length() > 0)) {
+ urlProps.setProperty(parameter, value);
+ }
+ }
+ }
+
+ // parse Product Name
+ String dbProductName = url.substring(0, beginningOfSlashes);
+ dbProductName = dbProductName.substring(dbProductName.indexOf(":") + 1);
+ dbProductName = dbProductName.substring(0, dbProductName.indexOf(":"));
+ // parse dbname
+ url = url.substring(beginningOfSlashes + 2);
+ int indexOfSlash = url.indexOf("/");
+ if (indexOfSlash != -1) {
+ if (indexOfSlash + 1 < url.length()) {
+ urlProps.setProperty(TSDBDriver.PROPERTY_KEY_DBNAME, url.substring(indexOfSlash + 1));
+ }
+ url = url.substring(0, indexOfSlash);
+ }
+ // parse port
+ int indexOfColon = url.indexOf(":");
+ if (indexOfColon != -1) {
+ if (indexOfColon + 1 < url.length()) {
+ urlProps.setProperty(TSDBDriver.PROPERTY_KEY_PORT, url.substring(indexOfColon + 1));
+ }
+ url = url.substring(0, indexOfColon);
+ }
+ // parse host
+ if (url != null && url.length() > 0 && url.trim().length() > 0) {
+ urlProps.setProperty(TSDBDriver.PROPERTY_KEY_HOST, url);
+ }
+ return urlProps;
+ }
+
+
+
+}
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java
index 5c7f80c715c12d1d3831a4cfbfe5f4a326b569eb..633fdcd5ab7c9f077abbd725c2511bcc2251db44 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java
@@ -16,10 +16,10 @@ package com.taosdata.jdbc;
public class ColumnMetaData {
- int colType = 0;
- String colName = null;
- int colSize = -1;
- int colIndex = 0;
+ private int colType = 0;
+ private String colName = null;
+ private int colSize = -1;
+ private int colIndex = 0;
public int getColSize() {
return colSize;
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java
index ac0e4eb84aa0fbcc8162e68d94de00cb2f4e79f5..94abe3965507170a4b31e17ebb431ddcb4fa11f8 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java
@@ -14,7 +14,6 @@
*****************************************************************************/
package com.taosdata.jdbc;
-import java.io.*;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
@@ -35,11 +34,10 @@ import java.util.*;
import java.util.concurrent.Executor;
public class TSDBConnection implements Connection {
+ protected Properties props = null;
private TSDBJNIConnector connector = null;
- protected Properties props = null;
-
private String catalog = null;
private TSDBDatabaseMetaData dbMetaData = null;
@@ -47,16 +45,21 @@ public class TSDBConnection implements Connection {
private Properties clientInfoProps = new Properties();
private int timeoutMilliseconds = 0;
-
- private String tsCharSet = "";
+
+ private boolean batchFetch = false;
public TSDBConnection(Properties info, TSDBDatabaseMetaData meta) throws SQLException {
this.dbMetaData = meta;
-
connect(info.getProperty(TSDBDriver.PROPERTY_KEY_HOST),
Integer.parseInt(info.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "0")),
- info.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME), info.getProperty(TSDBDriver.PROPERTY_KEY_USER),
+ info.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME),
+ info.getProperty(TSDBDriver.PROPERTY_KEY_USER),
info.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD));
+
+ String batchLoad = info.getProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD);
+ if (batchLoad != null) {
+ this.batchFetch = Boolean.parseBoolean(batchLoad);
+ }
}
private void connect(String host, int port, String dbName, String user, String password) throws SQLException {
@@ -197,12 +200,14 @@ public class TSDBConnection implements Connection {
}
public SQLWarning getWarnings() throws SQLException {
- throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
+ //todo: implement getWarnings according to the warning messages returned from TDengine
+ return null;
+// throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public void clearWarnings() throws SQLException {
// left blank to support HikariCP connection
- //todo: implement getWarnings according to the warning messages returned from TDengine
+ //todo: implement clearWarnings according to the warning messages returned from TDengine
}
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
@@ -222,6 +227,14 @@ public class TSDBConnection implements Connection {
return this.prepareStatement(sql);
}
+
+ public Boolean getBatchFetch() {
+ return this.batchFetch;
+ }
+
+ public void setBatchFetch(Boolean batchFetch) {
+ this.batchFetch = batchFetch;
+ }
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDatabaseMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDatabaseMetaData.java
index c1d9d2af8e5a5c24dcfed6039e3ce06530b95276..f4dee67adf03a3474f582dbe662a8c5e988e3fab 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDatabaseMetaData.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDatabaseMetaData.java
@@ -96,7 +96,7 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
}
public int getDriverMajorVersion() {
- return 0;
+ return 2;
}
public int getDriverMinorVersion() {
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java
index 97d93fb0a18fa887465583bce1492c8305faaec5..06f88cebfaa8aa90cc81506a98374ec8076ad82e 100755
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java
@@ -14,13 +14,8 @@
*****************************************************************************/
package com.taosdata.jdbc;
-
-import java.io.*;
-
import java.sql.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
+import java.util.*;
import java.util.logging.Logger;
/**
@@ -42,78 +37,60 @@ import java.util.logging.Logger;
* register it with the DriverManager. This means that a user can load and
* register a driver by doing Class.forName("foo.bah.Driver")
*/
-public class TSDBDriver implements java.sql.Driver {
-
+public class TSDBDriver extends AbstractTaosDriver {
@Deprecated
private static final String URL_PREFIX1 = "jdbc:TSDB://";
private static final String URL_PREFIX = "jdbc:TAOS://";
- /**
- * Key used to retrieve the database value from the properties instance passed
- * to the driver.
- */
- public static final String PROPERTY_KEY_DBNAME = "dbname";
-
/**
* Key used to retrieve the host value from the properties instance passed to
* the driver.
*/
public static final String PROPERTY_KEY_HOST = "host";
- /**
- * Key used to retrieve the password value from the properties instance passed
- * to the driver.
- */
- public static final String PROPERTY_KEY_PASSWORD = "password";
-
/**
* Key used to retrieve the port number value from the properties instance
* passed to the driver.
*/
public static final String PROPERTY_KEY_PORT = "port";
-
+ /**
+ * Key used to retrieve the database value from the properties instance passed
+ * to the driver.
+ */
+ public static final String PROPERTY_KEY_DBNAME = "dbname";
/**
* Key used to retrieve the user value from the properties instance passed to
* the driver.
*/
public static final String PROPERTY_KEY_USER = "user";
-
-
+ /**
+ * Key used to retrieve the password value from the properties instance passed
+ * to the driver.
+ */
+ public static final String PROPERTY_KEY_PASSWORD = "password";
/**
* Key for the configuration file directory of TSDB client in properties instance
*/
public static final String PROPERTY_KEY_CONFIG_DIR = "cfgdir";
-
/**
* Key for the timezone used by the TSDB client in properties instance
*/
public static final String PROPERTY_KEY_TIME_ZONE = "timezone";
-
/**
* Key for the locale used by the TSDB client in properties instance
*/
public static final String PROPERTY_KEY_LOCALE = "locale";
-
-
/**
* Key for the char encoding used by the TSDB client in properties instance
*/
public static final String PROPERTY_KEY_CHARSET = "charset";
- public static final String PROPERTY_KEY_PROTOCOL = "protocol";
-
-
/**
- * Index for port coming out of parseHostPortPair().
+ * fetch data from native function in a batch model
*/
- public final static int PORT_NUMBER_INDEX = 1;
-
- /**
- * Index for host coming out of parseHostPortPair().
- */
- public final static int HOST_NAME_INDEX = 0;
-
+ public static final String PROPERTY_KEY_BATCH_LOAD = "batchfetch";
+
private TSDBDatabaseMetaData dbMetaData = null;
static {
@@ -124,74 +101,23 @@ public class TSDBDriver implements java.sql.Driver {
}
}
- private List loadConfigEndpoints(File cfgFile) {
- List endpoints = new ArrayList<>();
- try (BufferedReader reader = new BufferedReader(new FileReader(cfgFile))) {
- String line = null;
- while ((line = reader.readLine()) != null) {
- if (line.trim().startsWith("firstEp") || line.trim().startsWith("secondEp")) {
- endpoints.add(line.substring(line.indexOf('p') + 1).trim());
- }
- if (endpoints.size() > 1)
- break;
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return endpoints;
- }
-
- /**
- * @param cfgDirPath
- * @return return the config dir
- **/
- private File loadConfigDir(String cfgDirPath) {
- if (cfgDirPath == null)
- return loadDefaultConfigDir();
- File cfgDir = new File(cfgDirPath);
- if (!cfgDir.exists())
- return loadDefaultConfigDir();
- return cfgDir;
- }
-
- /**
- * @return search the default config dir, if the config dir is not exist will return null
- */
- private File loadDefaultConfigDir() {
- File cfgDir;
- File cfgDir_linux = new File("/etc/taos");
- cfgDir = cfgDir_linux.exists() ? cfgDir_linux : null;
- File cfgDir_windows = new File("C:\\TDengine\\cfg");
- cfgDir = (cfgDir == null && cfgDir_windows.exists()) ? cfgDir_windows : cfgDir;
- return cfgDir;
- }
-
public Connection connect(String url, Properties info) throws SQLException {
- if (url == null) {
+ if (url == null)
throw new SQLException(TSDBConstants.WrapErrMsg("url is not set!"));
- }
+
+ if (!acceptsURL(url))
+ return null;
Properties props = null;
if ((props = parseURL(url, info)) == null) {
return null;
}
-
//load taos.cfg start
- if (info.getProperty(TSDBDriver.PROPERTY_KEY_HOST) == null && info.getProperty(TSDBDriver.PROPERTY_KEY_PORT) == null) {
- File cfgDir = loadConfigDir(info.getProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR));
- File cfgFile = cfgDir.listFiles((dir, name) -> "taos.cfg".equalsIgnoreCase(name))[0];
- List endpoints = loadConfigEndpoints(cfgFile);
- if (!endpoints.isEmpty()) {
- info.setProperty(TSDBDriver.PROPERTY_KEY_HOST, endpoints.get(0).split(":")[0]);
- info.setProperty(TSDBDriver.PROPERTY_KEY_PORT, endpoints.get(0).split(":")[1]);
- }
- }
+ loadTaosConfig(info);
try {
- TSDBJNIConnector.init((String) props.get(PROPERTY_KEY_CONFIG_DIR), (String) props.get(PROPERTY_KEY_LOCALE), (String) props.get(PROPERTY_KEY_CHARSET),
- (String) props.get(PROPERTY_KEY_TIME_ZONE));
+ TSDBJNIConnector.init((String) props.get(PROPERTY_KEY_CONFIG_DIR), (String) props.get(PROPERTY_KEY_LOCALE),
+ (String) props.get(PROPERTY_KEY_CHARSET), (String) props.get(PROPERTY_KEY_TIME_ZONE));
Connection newConn = new TSDBConnection(props, this.dbMetaData);
return newConn;
} catch (SQLWarning sqlWarning) {
@@ -208,43 +134,15 @@ public class TSDBDriver implements java.sql.Driver {
}
/**
- * Parses hostPortPair in the form of [host][:port] into an array, with the
- * element of index HOST_NAME_INDEX being the host (or null if not specified),
- * and the element of index PORT_NUMBER_INDEX being the port (or null if not
- * specified).
- *
- * @param hostPortPair host and port in form of of [host][:port]
- * @return array containing host and port as Strings
- * @throws SQLException if a parse error occurs
+ * @param url the URL of the database
+ * @return true
if this driver understands the given URL;
+ * false
otherwise
+ * @throws SQLException if a database access error occurs or the url is {@code null}
*/
- protected static String[] parseHostPortPair(String hostPortPair) throws SQLException {
- String[] splitValues = new String[2];
-
- int portIndex = hostPortPair.indexOf(":");
-
- String hostname = null;
-
- if (portIndex != -1) {
- if ((portIndex + 1) < hostPortPair.length()) {
- String portAsString = hostPortPair.substring(portIndex + 1);
- hostname = hostPortPair.substring(0, portIndex);
-
- splitValues[HOST_NAME_INDEX] = hostname;
-
- splitValues[PORT_NUMBER_INDEX] = portAsString;
- } else {
- throw new SQLException(TSDBConstants.WrapErrMsg("port is not proper!"));
- }
- } else {
- splitValues[HOST_NAME_INDEX] = hostPortPair;
- splitValues[PORT_NUMBER_INDEX] = null;
- }
-
- return splitValues;
- }
-
public boolean acceptsURL(String url) throws SQLException {
- return (url != null && url.length() > 0 && url.trim().length() > 0) && url.startsWith(URL_PREFIX);
+ if (url == null)
+ throw new SQLException(TSDBConstants.WrapErrMsg("url is null"));
+ return (url != null && url.length() > 0 && url.trim().length() > 0) && (url.startsWith(URL_PREFIX) || url.startsWith(URL_PREFIX1));
}
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
@@ -252,133 +150,80 @@ public class TSDBDriver implements java.sql.Driver {
info = new Properties();
}
- if ((url != null) && (url.startsWith(URL_PREFIX) || url.startsWith(URL_PREFIX1))) {
+ if (acceptsURL(url)) {
info = parseURL(url, info);
}
- DriverPropertyInfo hostProp = new DriverPropertyInfo(PROPERTY_KEY_HOST, info.getProperty(PROPERTY_KEY_HOST));
- hostProp.required = true;
-
- DriverPropertyInfo portProp = new DriverPropertyInfo(PROPERTY_KEY_PORT, info.getProperty(PROPERTY_KEY_PORT, TSDBConstants.DEFAULT_PORT));
- portProp.required = false;
-
- DriverPropertyInfo dbProp = new DriverPropertyInfo(PROPERTY_KEY_DBNAME, info.getProperty(PROPERTY_KEY_DBNAME));
- dbProp.required = false;
- dbProp.description = "Database name";
-
- DriverPropertyInfo userProp = new DriverPropertyInfo(PROPERTY_KEY_USER, info.getProperty(PROPERTY_KEY_USER));
- userProp.required = true;
-
- DriverPropertyInfo passwordProp = new DriverPropertyInfo(PROPERTY_KEY_PASSWORD, info.getProperty(PROPERTY_KEY_PASSWORD));
- passwordProp.required = true;
-
- DriverPropertyInfo[] propertyInfo = new DriverPropertyInfo[5];
- propertyInfo[0] = hostProp;
- propertyInfo[1] = portProp;
- propertyInfo[2] = dbProp;
- propertyInfo[3] = userProp;
- propertyInfo[4] = passwordProp;
-
- return propertyInfo;
+ return getPropertyInfo(info);
}
/**
- * example: jdbc:TSDB://127.0.0.1:0/db?user=root&password=your_password
+ * example: jdbc:TAOS://127.0.0.1:0/db?user=root&password=your_password
*/
- public Properties parseURL(String url, Properties defaults) throws java.sql.SQLException {
+ @Override
+ public Properties parseURL(String url, Properties defaults) {
Properties urlProps = (defaults != null) ? defaults : new Properties();
- if (url == null) {
+ if (url == null || url.length() <= 0 || url.trim().length() <= 0)
return null;
- }
-
- if (!url.startsWith(URL_PREFIX) && !url.startsWith(URL_PREFIX1)) {
+ if (!url.startsWith(URL_PREFIX) && !url.startsWith(URL_PREFIX1))
return null;
- }
+ // parse properties
String urlForMeta = url;
-
- String dbProductName = url.substring(url.indexOf(":") + 1);
- dbProductName = dbProductName.substring(0, dbProductName.indexOf(":"));
int beginningOfSlashes = url.indexOf("//");
- url = url.substring(beginningOfSlashes + 2);
-
- String host = url.substring(0, url.indexOf(":"));
- url = url.substring(url.indexOf(":") + 1);
- urlProps.setProperty(PROPERTY_KEY_HOST, host);
-
- String port = url.substring(0, url.indexOf("/"));
- urlProps.setProperty(PROPERTY_KEY_PORT, port);
- url = url.substring(url.indexOf("/") + 1);
-
- if (url.indexOf("?") != -1) {
- String dbName = url.substring(0, url.indexOf("?"));
- urlProps.setProperty(PROPERTY_KEY_DBNAME, dbName);
- url = url.trim().substring(url.indexOf("?") + 1);
- } else {
- // without user & password so return
- if (!url.trim().isEmpty()) {
- String dbName = url.trim();
- urlProps.setProperty(PROPERTY_KEY_DBNAME, dbName);
+ int index = url.indexOf("?");
+ if (index != -1) {
+ String paramString = url.substring(index + 1, url.length());
+ url = url.substring(0, index);
+ StringTokenizer queryParams = new StringTokenizer(paramString, "&");
+ while (queryParams.hasMoreElements()) {
+ String oneToken = queryParams.nextToken();
+ String[] pair = oneToken.split("=");
+
+ if ((pair[0] != null && pair[0].trim().length() > 0) && (pair[1] != null && pair[1].trim().length() > 0)) {
+ urlProps.setProperty(pair[0].trim(), pair[1].trim());
+ }
}
- this.dbMetaData = new TSDBDatabaseMetaData(dbProductName, urlForMeta, urlProps.getProperty("user"));
- return urlProps;
}
-
- String user = "";
-
- if (url.indexOf("&") == -1) {
- String[] kvPair = url.trim().split("=");
- if (kvPair.length == 2) {
- setPropertyValue(urlProps, kvPair);
- return urlProps;
+
+ // parse Product Name
+ String dbProductName = url.substring(0, beginningOfSlashes);
+ dbProductName = dbProductName.substring(dbProductName.indexOf(":") + 1);
+ dbProductName = dbProductName.substring(0, dbProductName.indexOf(":"));
+
+ // parse database name
+ url = url.substring(beginningOfSlashes + 2);
+ int indexOfSlash = url.indexOf("/");
+ if (indexOfSlash != -1) {
+ if (indexOfSlash + 1 < url.length()) {
+ urlProps.setProperty(TSDBDriver.PROPERTY_KEY_DBNAME, url.substring(indexOfSlash + 1));
}
+ url = url.substring(0, indexOfSlash);
}
-
- String[] queryStrings = url.trim().split("&");
- for (String queryStr : queryStrings) {
- String[] kvPair = queryStr.trim().split("=");
- if (kvPair.length < 2) {
- continue;
+
+ // parse port
+ int indexOfColon = url.indexOf(":");
+ if (indexOfColon != -1) {
+ if (indexOfColon + 1 < url.length()) {
+ urlProps.setProperty(TSDBDriver.PROPERTY_KEY_PORT, url.substring(indexOfColon + 1));
}
- setPropertyValue(urlProps, kvPair);
+ url = url.substring(0, indexOfColon);
}
-
- user = urlProps.getProperty(PROPERTY_KEY_USER).toString();
- this.dbMetaData = new TSDBDatabaseMetaData(dbProductName, urlForMeta, user);
-
- return urlProps;
- }
-
- public void setPropertyValue(Properties property, String[] keyValuePair) {
- switch (keyValuePair[0].toLowerCase()) {
- case PROPERTY_KEY_USER:
- property.setProperty(PROPERTY_KEY_USER, keyValuePair[1]);
- break;
- case PROPERTY_KEY_PASSWORD:
- property.setProperty(PROPERTY_KEY_PASSWORD, keyValuePair[1]);
- break;
- case PROPERTY_KEY_TIME_ZONE:
- property.setProperty(PROPERTY_KEY_TIME_ZONE, keyValuePair[1]);
- break;
- case PROPERTY_KEY_LOCALE:
- property.setProperty(PROPERTY_KEY_LOCALE, keyValuePair[1]);
- break;
- case PROPERTY_KEY_CHARSET:
- property.setProperty(PROPERTY_KEY_CHARSET, keyValuePair[1]);
- break;
- case PROPERTY_KEY_CONFIG_DIR:
- property.setProperty(PROPERTY_KEY_CONFIG_DIR, keyValuePair[1]);
- break;
+
+ if (url != null && url.length() > 0 && url.trim().length() > 0) {
+ urlProps.setProperty(TSDBDriver.PROPERTY_KEY_HOST, url);
}
+
+ this.dbMetaData = new TSDBDatabaseMetaData(dbProductName, urlForMeta, urlProps.getProperty(TSDBDriver.PROPERTY_KEY_USER));
+ return urlProps;
}
-
public int getMajorVersion() {
- return 1;
+ return 2;
}
public int getMinorVersion() {
- return 1;
+ return 0;
}
public boolean jdbcCompliant() {
@@ -389,33 +234,4 @@ public class TSDBDriver implements java.sql.Driver {
return null;
}
- /**
- * Returns the host property
- *
- * @param props the java.util.Properties instance to retrieve the hostname from.
- * @return the host
- */
- public String host(Properties props) {
- return props.getProperty(PROPERTY_KEY_HOST, "localhost");
- }
-
- /**
- * Returns the port number property
- *
- * @param props the properties to get the port number from
- * @return the port number
- */
- public int port(Properties props) {
- return Integer.parseInt(props.getProperty(PROPERTY_KEY_PORT, TSDBConstants.DEFAULT_PORT));
- }
-
- /**
- * Returns the database property from props
- *
- * @param props the Properties to look for the database property.
- * @return the database name.
- */
- public String database(Properties props) {
- return props.getProperty(PROPERTY_KEY_DBNAME);
- }
}
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java
index 0cd185de50d858aec78b60acc4055c1ae99a4cb5..f918463439fba293171827001acf6930ab271b81 100755
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java
@@ -111,8 +111,8 @@ public class TSDBJNIConnector {
* @throws SQLException
*/
public long executeQuery(String sql) throws SQLException {
- // close previous result set if the user forgets to invoke the
- // free method to close previous result set.
+ // close previous result set if the user forgets to invoke the
+ // free method to close previous result set.
if (!this.isResultsetClosed) {
freeResultSet(taosResultSetPointer);
}
@@ -122,23 +122,23 @@ public class TSDBJNIConnector {
pSql = this.executeQueryImp(sql.getBytes(TaosGlobalConfig.getCharset()), this.taos);
} catch (Exception e) {
e.printStackTrace();
- this.freeResultSet(pSql);
+ this.freeResultSetImp(this.taos, pSql);
throw new SQLException(TSDBConstants.WrapErrMsg("Unsupported encoding"));
}
-
+
int code = this.getErrCode(pSql);
if (code != 0) {
affectedRows = -1;
String msg = this.getErrMsg(pSql);
-
- this.freeResultSet(pSql);
+
+ this.freeResultSetImp(this.taos, pSql);
throw new SQLException(TSDBConstants.WrapErrMsg(msg), "", code);
}
// Try retrieving result set for the executed SQL using the current connection pointer.
taosResultSetPointer = this.getResultSetImp(this.taos, pSql);
isResultsetClosed = (taosResultSetPointer == TSDBConstants.JNI_NULL_POINTER);
-
+
return pSql;
}
@@ -171,11 +171,11 @@ 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 ? true : false;
}
-
+
private native long isUpdateQueryImp(long connection, long pSql);
/**
@@ -191,7 +191,7 @@ public class TSDBJNIConnector {
res = this.freeResultSetImp(this.taos, result);
taosResultSetPointer = TSDBConstants.JNI_NULL_POINTER;
}
-
+
isResultsetClosed = true;
return res;
}
@@ -243,6 +243,11 @@ public class TSDBJNIConnector {
private native int fetchRowImp(long connection, long resultSet, TSDBResultSetRowData rowData);
+ public int fetchBlock(long resultSet, TSDBResultSetBlockData blockData) {
+ return this.fetchBlockImp(this.taos, resultSet, blockData);
+ }
+
+ private native int fetchBlockImp(long connection, long resultSet, TSDBResultSetBlockData blockData);
/**
* Execute close operation from C to release connection pointer by JNI
*
@@ -274,7 +279,7 @@ public class TSDBJNIConnector {
* Consume a subscription
*/
long consume(long subscription) {
- return this.consumeImp(subscription);
+ return this.consumeImp(subscription);
}
private native long consumeImp(long subscription);
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java
index 961633b8aec4ec433a56522e504fb35495ccfa78..84a3f58f4692a99737af7d93c5578fc7a5a09c27 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java
@@ -47,10 +47,14 @@ public class TSDBResultSet implements ResultSet {
private List columnMetaDataList = new ArrayList();
private TSDBResultSetRowData rowData;
+ private TSDBResultSetBlockData blockData;
+ private boolean batchFetch = false;
private boolean lastWasNull = false;
private final int COLUMN_INDEX_START_VALUE = 1;
+ private int rowIndex = 0;
+
public TSDBJNIConnector getJniConnector() {
return jniConnector;
}
@@ -67,6 +71,14 @@ public class TSDBResultSet implements ResultSet {
this.resultSetPointer = resultSetPointer;
}
+ public void setBatchFetch(boolean batchFetch) {
+ this.batchFetch = batchFetch;
+ }
+
+ public Boolean getBatchFetch() {
+ return this.batchFetch;
+ }
+
public List getColumnMetaDataList() {
return columnMetaDataList;
}
@@ -94,8 +106,8 @@ public class TSDBResultSet implements ResultSet {
public TSDBResultSet() {
}
- public TSDBResultSet(TSDBJNIConnector connecter, long resultSetPointer) throws SQLException {
- this.jniConnector = connecter;
+ public TSDBResultSet(TSDBJNIConnector connector, long resultSetPointer) throws SQLException {
+ this.jniConnector = connector;
this.resultSetPointer = resultSetPointer;
int code = this.jniConnector.getSchemaMetaData(this.resultSetPointer, this.columnMetaDataList);
if (code == TSDBConstants.JNI_CONNECTION_NULL) {
@@ -107,6 +119,7 @@ public class TSDBResultSet implements ResultSet {
}
this.rowData = new TSDBResultSetRowData(this.columnMetaDataList.size());
+ this.blockData = new TSDBResultSetBlockData(this.columnMetaDataList, this.columnMetaDataList.size());
}
public T unwrap(Class iface) throws SQLException {
@@ -118,21 +131,42 @@ public class TSDBResultSet implements ResultSet {
}
public boolean next() throws SQLException {
- if (rowData != null) {
- this.rowData.clear();
- }
+ if (this.getBatchFetch()) {
+ if (this.blockData.forward()) {
+ return true;
+ }
+
+ int code = this.jniConnector.fetchBlock(this.resultSetPointer, this.blockData);
+ this.blockData.reset();
+
+ if (code == TSDBConstants.JNI_CONNECTION_NULL) {
+ throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
+ } else if (code == TSDBConstants.JNI_RESULT_SET_NULL) {
+ throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL));
+ } else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) {
+ throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_NUM_OF_FIELDS_0));
+ } else if (code == TSDBConstants.JNI_FETCH_END) {
+ return false;
+ }
- int code = this.jniConnector.fetchRow(this.resultSetPointer, this.rowData);
- if (code == TSDBConstants.JNI_CONNECTION_NULL) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
- } else if (code == TSDBConstants.JNI_RESULT_SET_NULL) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL));
- } else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_NUM_OF_FIELDS_0));
- } else if (code == TSDBConstants.JNI_FETCH_END) {
- return false;
- } else {
return true;
+ } else {
+ if (rowData != null) {
+ this.rowData.clear();
+ }
+
+ int code = this.jniConnector.fetchRow(this.resultSetPointer, this.rowData);
+ if (code == TSDBConstants.JNI_CONNECTION_NULL) {
+ throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
+ } else if (code == TSDBConstants.JNI_RESULT_SET_NULL) {
+ throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL));
+ } else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) {
+ throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_NUM_OF_FIELDS_0));
+ } else if (code == TSDBConstants.JNI_FETCH_END) {
+ return false;
+ } else {
+ return true;
+ }
}
}
@@ -155,21 +189,30 @@ public class TSDBResultSet implements ResultSet {
String res = null;
int colIndex = getTrueColumnIndex(columnIndex);
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ if (!this.getBatchFetch()) {
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ }
+ return res;
+ } else {
+ return this.blockData.getString(colIndex);
}
- return res;
}
public boolean getBoolean(int columnIndex) throws SQLException {
boolean res = false;
int colIndex = getTrueColumnIndex(columnIndex);
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getBoolean(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ if (!this.getBatchFetch()) {
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getBoolean(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ }
+ } else {
+ return this.blockData.getBoolean(colIndex);
}
+
return res;
}
@@ -177,66 +220,91 @@ public class TSDBResultSet implements ResultSet {
byte res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = (byte) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ if (!this.getBatchFetch()) {
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = (byte) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ }
+ return res;
+ } else {
+ return (byte) this.blockData.getInt(colIndex);
}
- return res;
}
public short getShort(int columnIndex) throws SQLException {
short res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = (short) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ if (!this.getBatchFetch()) {
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = (short) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ }
+ return res;
+ } else {
+ return (short) this.blockData.getInt(colIndex);
}
- return res;
}
public int getInt(int columnIndex) throws SQLException {
int res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ if (!this.getBatchFetch()) {
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ }
+ return res;
+ } else {
+ return this.blockData.getInt(colIndex);
}
- return res;
+
}
public long getLong(int columnIndex) throws SQLException {
long res = 0l;
int colIndex = getTrueColumnIndex(columnIndex);
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ if (!this.getBatchFetch()) {
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ }
+ return res;
+ } else {
+ return this.blockData.getLong(colIndex);
}
- return res;
}
public float getFloat(int columnIndex) throws SQLException {
float res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getFloat(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ if (!this.getBatchFetch()) {
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getFloat(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ }
+ return res;
+ } else {
+ return (float) this.blockData.getDouble(colIndex);
}
- return res;
}
public double getDouble(int columnIndex) throws SQLException {
double res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getDouble(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ if (!this.getBatchFetch()) {
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getDouble(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ }
+ return res;
+ } else {
+ return this.blockData.getDouble(colIndex);
}
- return res;
}
/*
@@ -249,25 +317,11 @@ public class TSDBResultSet implements ResultSet {
*/
@Deprecated
public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
- BigDecimal res = null;
- int colIndex = getTrueColumnIndex(columnIndex);
-
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = new BigDecimal(this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType()));
- }
- return res;
+ return new BigDecimal(getLong(columnIndex));
}
public byte[] getBytes(int columnIndex) throws SQLException {
- byte[] res = null;
- int colIndex = getTrueColumnIndex(columnIndex);
-
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType()).getBytes();
- }
- return res;
+ return getString(columnIndex).getBytes();
}
public Date getDate(int columnIndex) throws SQLException {
@@ -284,11 +338,15 @@ public class TSDBResultSet implements ResultSet {
Timestamp res = null;
int colIndex = getTrueColumnIndex(columnIndex);
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getTimestamp(colIndex);
+ if (!this.getBatchFetch()) {
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getTimestamp(colIndex);
+ }
+ return res;
+ } else {
+ return this.blockData.getTimestamp(columnIndex);
}
- return res;
}
public InputStream getAsciiStream(int columnIndex) throws SQLException {
@@ -400,8 +458,12 @@ public class TSDBResultSet implements ResultSet {
public Object getObject(int columnIndex) throws SQLException {
int colIndex = getTrueColumnIndex(columnIndex);
- this.lastWasNull = this.rowData.wasNull(colIndex);
- return this.rowData.get(colIndex);
+ if (!this.getBatchFetch()) {
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ return this.rowData.get(colIndex);
+ } else {
+ return this.blockData.get(colIndex);
+ }
}
public Object getObject(String columnLabel) throws SQLException {
@@ -433,8 +495,12 @@ public class TSDBResultSet implements ResultSet {
public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
int colIndex = getTrueColumnIndex(columnIndex);
- this.lastWasNull = this.rowData.wasNull(colIndex);
- return new BigDecimal(this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType()));
+ if (!this.getBatchFetch()) {
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ return new BigDecimal(this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType()));
+ } else {
+ return new BigDecimal(this.blockData.getLong(colIndex));
+ }
}
public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java
new file mode 100644
index 0000000000000000000000000000000000000000..9352cf525350ff57525680f405d61c6b00c0cf55
--- /dev/null
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java
@@ -0,0 +1,497 @@
+/***************************************************************************
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+package com.taosdata.jdbc;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.LongBuffer;
+import java.nio.ShortBuffer;
+import java.sql.SQLDataException;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class TSDBResultSetBlockData {
+ private int numOfRows = 0;
+ private int rowIndex = 0;
+
+ private List columnMetaDataList;
+ private ArrayList