Merge branch 'develop' into feature/qrefactor

This commit is contained in:
Haojun Liao 2021-03-31 20:28:48 +08:00
commit 6530308140
114 changed files with 8354 additions and 2878 deletions

View File

@ -17,6 +17,7 @@ SET(TD_MQTT FALSE)
SET(TD_TSDB_PLUGINS FALSE) SET(TD_TSDB_PLUGINS FALSE)
SET(TD_STORAGE FALSE) SET(TD_STORAGE FALSE)
SET(TD_TOPIC FALSE) SET(TD_TOPIC FALSE)
SET(TD_MODULE FALSE)
SET(TD_COVER FALSE) SET(TD_COVER FALSE)
SET(TD_MEM_CHECK FALSE) SET(TD_MEM_CHECK FALSE)

23
Jenkinsfile vendored
View File

@ -6,6 +6,7 @@ node {
} }
def skipstage=0 def skipstage=0
def abortPreviousBuilds() { def abortPreviousBuilds() {
def currentJobName = env.JOB_NAME def currentJobName = env.JOB_NAME
def currentBuildNumber = env.BUILD_NUMBER.toInteger() def currentBuildNumber = env.BUILD_NUMBER.toInteger()
@ -33,18 +34,19 @@ def abort_previous(){
} }
def pre_test(){ def pre_test(){
sh ''' sh '''
sudo rmtaos || echo "taosd has not installed" sudo rmtaos || echo "taosd has not installed"
''' '''
sh ''' sh '''
killall -9 taosd ||echo "no taosd running"
killall -9 gdb || echo "no gdb running"
cd ${WKC} cd ${WKC}
git checkout develop git checkout develop
git reset --hard HEAD~10 >/dev/null git reset --hard HEAD~10 >/dev/null
git pull >/dev/null git pull >/dev/null
git fetch origin +refs/pull/${CHANGE_ID}/merge git fetch origin +refs/pull/${CHANGE_ID}/merge
git checkout -qf FETCH_HEAD git checkout -qf FETCH_HEAD
git --no-pager diff --name-only FETCH_HEAD $(git merge-base FETCH_HEAD develop)|grep -v -E '.*md|//src//connector|Jenkinsfile'
find ${WKC}/tests/pytest -name \'*\'.sql -exec rm -rf {} \\; find ${WKC}/tests/pytest -name \'*\'.sql -exec rm -rf {} \\;
cd ${WK} cd ${WK}
git reset --hard HEAD~10 git reset --hard HEAD~10
@ -79,6 +81,10 @@ pipeline {
changeRequest() changeRequest()
} }
steps { steps {
script{
abort_previous()
abortPreviousBuilds()
}
sh''' sh'''
cp -r ${WORKSPACE} ${WORKSPACE}.tes cp -r ${WORKSPACE} ${WORKSPACE}.tes
cd ${WORKSPACE}.tes cd ${WORKSPACE}.tes
@ -179,6 +185,14 @@ pipeline {
rm -rf /var/log/taos/* rm -rf /var/log/taos/*
./handle_crash_gen_val_log.sh ./handle_crash_gen_val_log.sh
''' '''
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh '''
cd ${WKC}/tests/pytest
rm -rf /var/lib/taos/*
rm -rf /var/log/taos/*
./handle_taosd_val_log.sh
'''
}
timeout(time: 45, unit: 'MINUTES'){ timeout(time: 45, unit: 'MINUTES'){
sh ''' sh '''
date date
@ -209,6 +223,11 @@ pipeline {
cd ${WKC}/tests cd ${WKC}/tests
./test-all.sh b3fq ./test-all.sh b3fq
date''' date'''
sh '''
date
cd ${WKC}/tests
./test-all.sh full example
date'''
} }
} }
} }

View File

@ -261,7 +261,13 @@ TDengine 的测试框架和所有测试例全部开源。
点击 [这里](tests/How-To-Run-Test-And-How-To-Add-New-Test-Case.md),了解如何运行测试例和添加新的测试例。 点击 [这里](tests/How-To-Run-Test-And-How-To-Add-New-Test-Case.md),了解如何运行测试例和添加新的测试例。
# 成为社区贡献者 # 成为社区贡献者
点击 [这里](https://www.taosdata.com/cn/contributor/),了解如何成为 TDengine 的贡献者。 点击 [这里](https://www.taosdata.com/cn/contributor/),了解如何成为 TDengine 的贡献者。
# 加入技术交流群 # 加入技术交流群
TDengine 官方社群「物联网大数据群」对外开放,欢迎您加入讨论。搜索微信号 "tdengine"加小T为好友即可入群。 TDengine 官方社群「物联网大数据群」对外开放,欢迎您加入讨论。搜索微信号 "tdengine"加小T为好友即可入群。
# [谁在使用TDengine](https://github.com/taosdata/TDengine/issues/2432)
欢迎所有 TDengine 用户及贡献者在 [这里](https://github.com/taosdata/TDengine/issues/2432) 分享您在当前工作中开发/使用 TDengine 的故事。

View File

@ -250,3 +250,6 @@ Please follow the [contribution guidelines](CONTRIBUTING.md) to contribute to th
Add WeChat “tdengine” to join the groupyou can communicate with other users. Add WeChat “tdengine” to join the groupyou can communicate with other users.
# [User List](https://github.com/taosdata/TDengine/issues/2432)
If you are using TDengine and feel it helps or you'd like to do some contributions, please add your company to [user list](https://github.com/taosdata/TDengine/issues/2432) and let us know your needs.

View File

@ -29,6 +29,10 @@ IF (TD_TOPIC)
ADD_DEFINITIONS(-D_TOPIC) ADD_DEFINITIONS(-D_TOPIC)
ENDIF () ENDIF ()
IF (TD_MODULE)
ADD_DEFINITIONS(-D_MODULE)
ENDIF ()
IF (TD_GODLL) IF (TD_GODLL)
ADD_DEFINITIONS(-D_TD_GO_DLL_) ADD_DEFINITIONS(-D_TD_GO_DLL_)
ENDIF () ENDIF ()

View File

@ -17,6 +17,14 @@ ELSEIF (${TOPIC} MATCHES "false")
MESSAGE(STATUS "Build without topic plugins") MESSAGE(STATUS "Build without topic plugins")
ENDIF () ENDIF ()
IF (${TD_MODULE} MATCHES "true")
SET(TD_MODULE TRUE)
MESSAGE(STATUS "Build with module plugins")
ELSEIF (${TOPIC} MATCHES "false")
SET(TD_MODULE FALSE)
MESSAGE(STATUS "Build without module plugins")
ENDIF ()
IF (${COVER} MATCHES "true") IF (${COVER} MATCHES "true")
SET(TD_COVER TRUE) SET(TD_COVER TRUE)
MESSAGE(STATUS "Build with test coverage") MESSAGE(STATUS "Build with test coverage")

View File

@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS)
#INSTALL(TARGETS taos RUNTIME DESTINATION driver) #INSTALL(TARGETS taos RUNTIME DESTINATION driver)
#INSTALL(TARGETS shell RUNTIME DESTINATION .) #INSTALL(TARGETS shell RUNTIME DESTINATION .)
IF (TD_MVN_INSTALLED) IF (TD_MVN_INSTALLED)
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.22-dist.jar DESTINATION connector/jdbc) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.24-dist.jar DESTINATION connector/jdbc)
ENDIF () ENDIF ()
ELSEIF (TD_DARWIN) ELSEIF (TD_DARWIN)
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh") SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")

View File

@ -120,7 +120,7 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台
* [TDengine性能对比测试工具](https://www.taosdata.com/blog/2020/01/18/1166.html) * [TDengine性能对比测试工具](https://www.taosdata.com/blog/2020/01/18/1166.html)
* [IDEA数据库管理工具可视化使用TDengine](https://www.taosdata.com/blog/2020/08/27/1767.html) * [IDEA数据库管理工具可视化使用TDengine](https://www.taosdata.com/blog/2020/08/27/1767.html)
* [基于eletron开发的跨平台TDengine图形化管理工具](https://github.com/skye0207/TDengineGUI) * [基于eletron开发的跨平台TDengine图形化管理工具](https://github.com/skye0207/TDengineGUI)
* [DataX支持TDengine的离线数据采集/同步工具](https://github.com/alibaba/DataX) * [DataX支持TDengine的离线数据采集/同步工具](https://github.com/wgzhao/DataX)(文档:[读取插件](https://github.com/wgzhao/DataX/blob/master/docs/src/main/sphinx/reader/tdenginereader.md)、[写入插件](https://github.com/wgzhao/DataX/blob/master/docs/src/main/sphinx/writer/tdenginewriter.md)
## TDengine与其他数据库的对比测试 ## TDengine与其他数据库的对比测试

View File

@ -179,7 +179,7 @@ taos> select avg(f1), max(f2), min(f3) from test.t10 interval(10s);
### TDengine服务器支持的平台列表 ### TDengine服务器支持的平台列表
| | **CentOS** **6/7/8** | **Ubuntu** **16/18/20** | **Other Linux** | **统信****UOS** | **银河****/****中标麒麟** | **凝思** **V60/V80** | | | **CentOS 6/7/8** | **Ubuntu 16/18/20** | **Other Linux** | **统信 UOS** | **银河/中标麒麟** | **凝思 V60/V80** |
| -------------- | --------------------- | ------------------------ | --------------- | --------------- | ------------------------- | --------------------- | | -------------- | --------------------- | ------------------------ | --------------- | --------------- | ------------------------- | --------------------- |
| X64 | ● | ● | | ○ | ● | ● | | X64 | ● | ● | | ○ | ● | ● |
| 树莓派 ARM32 | | ● | ● | | | | | 树莓派 ARM32 | | ● | ● | | | |
@ -203,7 +203,7 @@ taos> select avg(f1), max(f2), min(f3) from test.t10 interval(10s);
对照矩阵如下: 对照矩阵如下:
| **CPU** | **X64 64bit** | | | **X86 32bit** | **ARM64** | **ARM32** | **MIPS ** **龙芯** | **Alpha ** **申威** | **X64 ** **海光** | | **CPU** | **X64 64bit** | | | **X86 32bit** | **ARM64** | **ARM32** | **MIPS 龙芯** | **Alpha 申威** | **X64 海光** |
| ----------- | --------------- | --------- | --------- | --------------- | --------- | --------- | ------------------- | -------------------- | ------------------ | | ----------- | --------------- | --------- | --------- | --------------- | --------- | --------- | ------------------- | -------------------- | ------------------ |
| **OS** | **Linux** | **Win64** | **Win32** | **Win32** | **Linux** | **Linux** | **Linux** | **Linux** | **Linux** | | **OS** | **Linux** | **Win64** | **Win32** | **Win32** | **Linux** | **Linux** | **Linux** | **Linux** | **Linux** |
| **C/C++** | ● | ● | ● | ○ | ● | ● | ● | ● | ● | | **C/C++** | ● | ● | ● | ○ | ● | ● | ● | ● | ● |

View File

@ -1,27 +1,16 @@
# 高级功能 # 高级功能
## <a class="anchor" id="continuous-query"></a>连续查询(Continuous Query) ## <a class="anchor" id="continuous-query"></a>连续查询Continuous Query
连续查询是TDengine定期自动执行的查询采用滑动窗口的方式进行计算是一种简化的时间驱动的流式计算。 连续查询是TDengine定期自动执行的查询采用滑动窗口的方式进行计算是一种简化的时间驱动的流式计算。针对库中的表或超级表TDengine可提供定期自动执行的连续查询用户可让TDengine推送查询的结果也可以将结果再写回到TDengine中。每次执行的查询是一个时间窗口时间窗口随着时间流动向前滑动。在定义连续查询的时候需要指定时间窗口time window, 参数interval大小和每次前向增量时间forward sliding times, 参数sliding
针对库中的表或超级表TDengine可提供定期自动执行的连续查询
用户可让TDengine推送查询的结果也可以将结果再写回到TDengine中。
每次执行的查询是一个时间窗口,时间窗口随着时间流动向前滑动。
在定义连续查询的时候需要指定时间窗口time window, 参数interval大小和每次前向增量时间forward sliding times, 参数sliding
TDengine的连续查询采用时间驱动模式可以直接使用TAOS SQL进行定义不需要额外的操作。 TDengine的连续查询采用时间驱动模式可以直接使用TAOS SQL进行定义不需要额外的操作。使用连续查询可以方便快捷地按照时间窗口生成结果从而对原始采集数据进行降采样down sampling。用户通过TAOS SQL定义连续查询以后TDengine自动在最后的一个完整的时间周期末端拉起查询并将计算获得的结果推送给用户或者写回TDengine。
使用连续查询可以方便快捷地按照时间窗口生成结果从而对原始采集数据进行降采样down sampling
用户通过TAOS SQL定义连续查询以后TDengine自动在最后的一个完整的时间周期末端拉起查询
并将计算获得的结果推送给用户或者写回TDengine。
TDengine提供的连续查询与普通流计算中的时间窗口计算具有以下区别 TDengine提供的连续查询与普通流计算中的时间窗口计算具有以下区别
- 不同于流计算的实时反馈计算结果,连续查询只在时间窗口关闭以后才开始计算。 - 不同于流计算的实时反馈计算结果连续查询只在时间窗口关闭以后才开始计算。例如时间周期是1天那么当天的结果只会在23:59:59以后才会生成。
例如时间周期是1天那么当天的结果只会在23:59:59以后才会生成。 - 如果有历史记录写入到已经计算完成的时间区间连续查询并不会重新进行计算也不会重新将结果推送给用户。对于写回TDengine的模式也不会更新已经存在的计算结果。
- 如果有历史记录写入到已经计算完成的时间区间,连续查询并不会重新进行计算, - 使用连续查询推送结果的模式服务端并不缓存客户端计算状态也不提供Exactly-Once的语意保证。如果用户的应用端崩溃再次拉起的连续查询将只会从再次拉起的时间开始重新计算最近的一个完整的时间窗口。如果使用写回模式TDengine可确保数据写回的有效性和连续性。
也不会重新将结果推送给用户。对于写回TDengine的模式也不会更新已经存在的计算结果。
- 使用连续查询推送结果的模式服务端并不缓存客户端计算状态也不提供Exactly-Once的语意保证。
如果用户的应用端崩溃,再次拉起的连续查询将只会从再次拉起的时间开始重新计算最近的一个完整的时间窗口。
如果使用写回模式TDengine可确保数据写回的有效性和连续性。
### 使用连续查询 ### 使用连续查询
@ -40,23 +29,19 @@ create table D1002 using meters tags ("Beijing.Haidian", 2);
select avg(voltage) from meters interval(1m) sliding(30s); select avg(voltage) from meters interval(1m) sliding(30s);
``` ```
每次执行这条语句,都会重新计算所有数据。 每次执行这条语句,都会重新计算所有数据。 如果需要每隔30秒执行一次来增量计算最近一分钟的数据可以把上面的语句改进成下面的样子每次使用不同的 `startTime` 并定期执行:
如果需要每隔30秒执行一次来增量计算最近一分钟的数据
可以把上面的语句改进成下面的样子,每次使用不同的 `startTime` 并定期执行:
```sql ```sql
select avg(voltage) from meters where ts > {startTime} interval(1m) sliding(30s); select avg(voltage) from meters where ts > {startTime} interval(1m) sliding(30s);
``` ```
这样做没有问题但TDengine提供了更简单的方法 这样做没有问题但TDengine提供了更简单的方法只要在最初的查询语句前面加上 `create table {tableName} as ` 就可以了, 例如:
只要在最初的查询语句前面加上 `create table {tableName} as ` 就可以了, 例如:
```sql ```sql
create table avg_vol as select avg(voltage) from meters interval(1m) sliding(30s); create table avg_vol as select avg(voltage) from meters interval(1m) sliding(30s);
``` ```
会自动创建一个名为 `avg_vol` 的新表然后每隔30秒TDengine会增量执行 `as` 后面的 SQL 语句, 会自动创建一个名为 `avg_vol` 的新表然后每隔30秒TDengine会增量执行 `as` 后面的 SQL 语句,并将查询结果写入这个表中,用户程序后续只要从 `avg_vol` 中查询数据即可。 例如:
并将查询结果写入这个表中,用户程序后续只要从 `avg_vol` 中查询数据即可。 例如:
```mysql ```mysql
taos> select * from avg_vol; taos> select * from avg_vol;
@ -70,43 +55,27 @@ taos> select * from avg_vol;
需要注意查询时间窗口的最小值是10毫秒没有时间窗口范围的上限。 需要注意查询时间窗口的最小值是10毫秒没有时间窗口范围的上限。
此外TDengine还支持用户指定连续查询的起止时间。 此外TDengine还支持用户指定连续查询的起止时间。如果不输入开始时间连续查询将从第一条原始数据所在的时间窗口开始如果没有输入结束时间连续查询将永久运行如果用户指定了结束时间连续查询在系统时间达到指定的时间以后停止运行。比如使用下面的SQL创建的连续查询将运行一小时之后会自动停止。
如果不输入开始时间,连续查询将从第一条原始数据所在的时间窗口开始;
如果没有输入结束时间,连续查询将永久运行;
如果用户指定了结束时间,连续查询在系统时间达到指定的时间以后停止运行。
比如使用下面的SQL创建的连续查询将运行一小时之后会自动停止。
```mysql ```mysql
create table avg_vol as select avg(voltage) from meters where ts > now and ts <= now + 1h interval(1m) sliding(30s); create table avg_vol as select avg(voltage) from meters where ts > now and ts <= now + 1h interval(1m) sliding(30s);
``` ```
需要说明的是,上面例子中的 `now` 是指创建连续查询的时间,而不是查询执行的时间,否则,查询就无法自动停止了。 需要说明的是,上面例子中的 `now` 是指创建连续查询的时间而不是查询执行的时间否则查询就无法自动停止了。另外为了尽量避免原始数据延迟写入导致的问题TDengine中连续查询的计算有一定的延迟。也就是说一个时间窗口过去后TDengine并不会立即计算这个窗口的数据所以要稍等一会一般不会超过1分钟才能查到计算结果。
另外为了尽量避免原始数据延迟写入导致的问题TDengine中连续查询的计算有一定的延迟。
也就是说一个时间窗口过去后TDengine并不会立即计算这个窗口的数据
所以要稍等一会一般不会超过1分钟才能查到计算结果。
### 管理连续查询 ### 管理连续查询
用户可在控制台中通过 `show streams` 命令来查看系统中全部运行的连续查询, 用户可在控制台中通过 `show streams` 命令来查看系统中全部运行的连续查询,并可以通过 `kill stream` 命令杀掉对应的连续查询。后续版本会提供更细粒度和便捷的连续查询管理命令。
并可以通过 `kill stream` 命令杀掉对应的连续查询。
后续版本会提供更细粒度和便捷的连续查询管理命令。
## <a class="anchor" id="subscribe"></a>数据订阅(Publisher/Subscriber) ## <a class="anchor" id="subscribe"></a>数据订阅Publisher/Subscriber
基于数据天然的时间序列特性TDengine的数据写入insert与消息系统的数据发布pub逻辑上一致 基于数据天然的时间序列特性TDengine的数据写入insert与消息系统的数据发布pub逻辑上一致均可视为系统中插入一条带时间戳的新记录。同时TDengine在内部严格按照数据时间序列单调递增的方式保存数据。本质上来说TDengine中里每一张表均可视为一个标准的消息队列。
均可视为系统中插入一条带时间戳的新记录。
同时TDengine在内部严格按照数据时间序列单调递增的方式保存数据。
本质上来说TDengine中里每一张表均可视为一个标准的消息队列。
TDengine内嵌支持轻量级的消息订阅与推送服务。 TDengine内嵌支持轻量级的消息订阅与推送服务。使用系统提供的API用户可使用普通查询语句订阅数据库中的一张或多张表。订阅的逻辑和操作状态的维护均是由客户端完成客户端定时轮询服务器是否有新的记录到达有新的记录到达就会将结果反馈到客户。
使用系统提供的API用户可使用普通查询语句订阅数据库中的一张或多张表。
订阅的逻辑和操作状态的维护均是由客户端完成,客户端定时轮询服务器是否有新的记录到达,
有新的记录到达就会将结果反馈到客户。
TDengine的订阅与推送服务的状态是客户端维持TDengine服务器并不维持。 TDengine的订阅与推送服务的状态是客户端维持TDengine服务器并不维持。因此如果应用重启从哪个时间点开始获取最新数据由应用决定。
因此如果应用重启,从哪个时间点开始获取最新数据,由应用决定。
TDengine的API中与订阅相关的主要有以下三个 TDengine的API中与订阅相关的主要有以下三个
@ -116,12 +85,9 @@ taos_consume
taos_unsubscribe taos_unsubscribe
``` ```
这些API的文档请见 [C/C++ Connector](https://www.taosdata.com/cn/documentation/connector/) 这些API的文档请见 [C/C++ Connector](https://www.taosdata.com/cn/documentation/connector#c-cpp),下面仍以智能电表场景为例介绍一下它们的具体用法(超级表和子表结构请参考上一节“连续查询”),完整的示例代码可以在 [这里](https://github.com/taosdata/TDengine/blob/master/tests/examples/c/subscribe.c) 找到。
下面仍以智能电表场景为例介绍一下它们的具体用法(超级表和子表结构请参考上一节“连续查询”),
完整的示例代码可以在 [这里](https://github.com/taosdata/TDengine/blob/master/tests/examples/c/subscribe.c) 找到。
如果我们希望当某个电表的电流超过一定限制比如10A后能得到通知并进行一些处理 有两种方法: 如果我们希望当某个电表的电流超过一定限制比如10A后能得到通知并进行一些处理 有两种方法:一是分别对每张子表进行查询,每次查询后记录最后一条数据的时间戳,后续只查询这个时间戳之后的数据:
一是分别对每张子表进行查询,每次查询后记录最后一条数据的时间戳,后续只查询这个时间戳之后的数据:
```sql ```sql
select * from D1001 where ts > {last_timestamp1} and current > 10; select * from D1001 where ts > {last_timestamp1} and current > 10;
@ -129,8 +95,7 @@ select * from D1002 where ts > {last_timestamp2} and current > 10;
... ...
``` ```
这确实可行,但随着电表数量的增加,查询数量也会增加,客户端和服务端的性能都会受到影响, 这确实可行,但随着电表数量的增加,查询数量也会增加,客户端和服务端的性能都会受到影响,当电表数增长到一定的程度,系统就无法承受了。
当电表数增长到一定的程度,系统就无法承受了。
另一种方法是对超级表进行查询。这样,无论有多少电表,都只需一次查询: 另一种方法是对超级表进行查询。这样,无论有多少电表,都只需一次查询:
@ -138,12 +103,7 @@ select * from D1002 where ts > {last_timestamp2} and current > 10;
select * from meters where ts > {last_timestamp} and current > 10; select * from meters where ts > {last_timestamp} and current > 10;
``` ```
但是,如何选择 `last_timestamp` 就成了一个新的问题。 但是,如何选择 `last_timestamp` 就成了一个新的问题。因为一方面数据的产生时间也就是数据时间戳和数据入库的时间一般并不相同有时偏差还很大另一方面不同电表的数据到达TDengine的时间也会有差异。所以如果我们在查询中使用最慢的那台电表的数据的时间戳作为 `last_timestamp`,就可能重复读入其它电表的数据;如果使用最快的电表的时间戳,其它电表的数据就可能被漏掉。
因为,一方面数据的产生时间(也就是数据时间戳)和数据入库的时间一般并不相同,有时偏差还很大;
另一方面不同电表的数据到达TDengine的时间也会有差异。
所以,如果我们在查询中使用最慢的那台电表的数据的时间戳作为 `last_timestamp`
就可能重复读入其它电表的数据;
如果使用最快的电表的时间戳,其它电表的数据就可能被漏掉。
TDengine的订阅功能为上面这个问题提供了一个彻底的解决方案。 TDengine的订阅功能为上面这个问题提供了一个彻底的解决方案。
@ -160,47 +120,29 @@ if (async) {
} }
``` ```
TDengine中的订阅既可以是同步的也可以是异步的 TDengine中的订阅既可以是同步的也可以是异步的上面的代码会根据从命令行获取的参数`async`的值来决定使用哪种方式。这里,同步的意思是用户程序要直接调用`taos_consume`来拉取数据而异步则由API在内部的另一个线程中调用`taos_consume`,然后把拉取到的数据交给回调函数`subscribe_callback`去处理。
上面的代码会根据从命令行获取的参数`async`的值来决定使用哪种方式。
这里,同步的意思是用户程序要直接调用`taos_consume`来拉取数据,
而异步则由API在内部的另一个线程中调用`taos_consume`
然后把拉取到的数据交给回调函数`subscribe_callback`去处理。
参数`taos`是一个已经建立好的数据库连接,在同步模式下无特殊要求。 参数`taos`是一个已经建立好的数据库连接在同步模式下无特殊要求。但在异步模式下需要注意它不会被其它线程使用否则可能导致不可预计的错误因为回调函数在API的内部线程中被调用而TDengine的部分API不是线程安全的。
但在异步模式下,需要注意它不会被其它线程使用,否则可能导致不可预计的错误,
因为回调函数在API的内部线程中被调用而TDengine的部分API不是线程安全的。
参数`sql`是查询语句可以在其中使用where子句指定过滤条件。 参数`sql`是查询语句可以在其中使用where子句指定过滤条件。在我们的例子中如果只想订阅电流超过10A时的数据可以这样写
在我们的例子中如果只想订阅电流超过10A时的数据可以这样写
```sql ```sql
select * from meters where current > 10; select * from meters where current > 10;
``` ```
注意,这里没有指定起始时间,所以会读到所有时间的数据。 注意,这里没有指定起始时间,所以会读到所有时间的数据。如果只想从一天前的数据开始订阅,而不需要更早的历史数据,可以再加上一个时间条件:
如果只想从一天前的数据开始订阅,而不需要更早的历史数据,可以再加上一个时间条件:
```sql ```sql
select * from meters where ts > now - 1d and current > 10; select * from meters where ts > now - 1d and current > 10;
``` ```
订阅的`topic`实际上是它的名字因为订阅功能是在客户端API中实现的 订阅的`topic`实际上是它的名字因为订阅功能是在客户端API中实现的所以没必要保证它全局唯一但需要它在一台客户端机器上唯一。
所以没必要保证它全局唯一,但需要它在一台客户端机器上唯一。
如果名`topic`的订阅不存在,参数`restart`没有意义; 如果名`topic`的订阅不存在,参数`restart`没有意义;但如果用户程序创建这个订阅后退出,当它再次启动并重新使用这个`topic`时,`restart`就会被用于决定是从头开始读取数据,还是接续上次的位置进行读取。本例中,如果`restart`是 **true**(非零值),用户程序肯定会读到所有数据。但如果这个订阅之前就存在了,并且已经读取了一部分数据,且`restart`是 **false****0**),用户程序就不会读到之前已经读取的数据了。
但如果用户程序创建这个订阅后退出,当它再次启动并重新使用这个`topic`时,
`restart`就会被用于决定是从头开始读取数据,还是接续上次的位置进行读取。
本例中,如果`restart`是 **true**(非零值),用户程序肯定会读到所有数据。
但如果这个订阅之前就存在了,并且已经读取了一部分数据,
且`restart`是 **false****0**),用户程序就不会读到之前已经读取的数据了。
`taos_subscribe`的最后一个参数是以毫秒为单位的轮询周期。 `taos_subscribe`的最后一个参数是以毫秒为单位的轮询周期。在同步模式下,如果前后两次调用`taos_consume`的时间间隔小于此时间,`taos_consume`会阻塞,直到间隔超过此时间。异步模式下,这个时间是两次调用回调函数的最小时间间隔。
在同步模式下,如果前后两次调用`taos_consume`的时间间隔小于此时间,
`taos_consume`会阻塞,直到间隔超过此时间。
异步模式下,这个时间是两次调用回调函数的最小时间间隔。
`taos_subscribe`的倒数第二个参数用于用户程序向回调函数传递附加参数, `taos_subscribe`的倒数第二个参数用于用户程序向回调函数传递附加参数订阅API不对其做任何处理只原样传递给回调函数。此参数在同步模式下无意义。
订阅API不对其做任何处理只原样传递给回调函数。此参数在同步模式下无意义。
订阅创建以后,就可以消费其数据了,同步模式下,示例代码是下面的 else 部分: 订阅创建以后,就可以消费其数据了,同步模式下,示例代码是下面的 else 部分:
@ -219,9 +161,7 @@ if (async) {
} }
``` ```
这里是一个 **while** 循环,用户每按一次回车键就调用一次`taos_consume` 这里是一个 **while** 循环,用户每按一次回车键就调用一次`taos_consume`,而`taos_consume`的返回值是查询到的结果集,与`taos_use_result`完全相同,例子中使用这个结果集的代码是函数`print_result`
而`taos_consume`的返回值是查询到的结果集,与`taos_use_result`完全相同,
例子中使用这个结果集的代码是函数`print_result`
```c ```c
void print_result(TAOS_RES* res, int blockFetch) { void print_result(TAOS_RES* res, int blockFetch) {
@ -247,8 +187,7 @@ void print_result(TAOS_RES* res, int blockFetch) {
} }
``` ```
其中的 `taos_print_row` 用于处理订阅到数据,在我们的例子中,它会打印出所有符合条件的记录。 其中的 `taos_print_row` 用于处理订阅到数据,在我们的例子中,它会打印出所有符合条件的记录。而异步模式下,消费订阅到的数据则显得更为简单:
而异步模式下,消费订阅到的数据则显得更为简单:
```c ```c
void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) { void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
@ -262,11 +201,7 @@ void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
taos_unsubscribe(tsub, keep); taos_unsubscribe(tsub, keep);
``` ```
其第二个参数,用于决定是否在客户端保留订阅的进度信息。 其第二个参数,用于决定是否在客户端保留订阅的进度信息。如果这个参数是**false****0**),那无论下次调用`taos_subscribe`时的`restart`参数是什么,订阅都只能重新开始。另外,进度信息的保存位置是 *{DataDir}/subscribe/* 这个目录下,每个订阅有一个与其`topic`同名的文件,删掉某个文件,同样会导致下次创建其对应的订阅时只能重新开始。
如果这个参数是**false****0**),那无论下次调用`taos_subscribe`的时的`restart`参数是什么,
订阅都只能重新开始。
另外,进度信息的保存位置是 *{DataDir}/subscribe/* 这个目录下,
每个订阅有一个与其`topic`同名的文件,删掉某个文件,同样会导致下次创建其对应的订阅时只能重新开始。
代码介绍完毕,我们来看一下实际的运行效果。假设: 代码介绍完毕,我们来看一下实际的运行效果。假设:
@ -289,12 +224,11 @@ $ taos
> insert into D1001 values(now, 12, 220, 1); > insert into D1001 values(now, 12, 220, 1);
``` ```
这时因为电流超过了10A您应该可以看到示例程序将它输出到了屏幕上。 这时因为电流超过了10A您应该可以看到示例程序将它输出到了屏幕上。您可以继续插入一些数据观察示例程序的输出。
您可以继续插入一些数据观察示例程序的输出。
### Java 使用数据订阅功能 ### Java 使用数据订阅功能
订阅功能也提供了 Java 开发接口,相关说明请见 [Java Connector](https://www.taosdata.com/cn/documentation/connector/)。需要注意的是,目前 Java 接口没有提供异步订阅模式,但用户程序可以通过创建 `TimerTask` 等方式达到同样的效果。 订阅功能也提供了 Java 开发接口,相关说明请见 [Java Connector](https://www.taosdata.com/cn/documentation/connector/java#subscribe)。需要注意的是,目前 Java 接口没有提供异步订阅模式,但用户程序可以通过创建 `TimerTask` 等方式达到同样的效果。
下面以一个示例程序介绍其具体使用方法。它所完成的功能与前面介绍的 C 语言示例基本相同,也是订阅数据库中所有电流超过 10A 的记录。 下面以一个示例程序介绍其具体使用方法。它所完成的功能与前面介绍的 C 语言示例基本相同,也是订阅数据库中所有电流超过 10A 的记录。
@ -404,7 +338,7 @@ ts: 1597466400000 current: 12.4 voltage: 220 phase: 1 location: Beijing.Chaoyang
``` ```
## <a class="anchor" id="cache"></a>缓存(Cache) ## <a class="anchor" id="cache"></a>缓存Cache
TDengine采用时间驱动缓存管理策略First-In-First-OutFIFO又称为写驱动的缓存管理机制。这种策略有别于读驱动的数据缓存模式Least-Recent-UseLRU直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候将最早的数据批量写入磁盘。一般意义上来说对于物联网数据的使用用户最为关心最近产生的数据即当前状态。TDengine充分利用了这一特性将最近到达的当前状态数据保存在缓存中。 TDengine采用时间驱动缓存管理策略First-In-First-OutFIFO又称为写驱动的缓存管理机制。这种策略有别于读驱动的数据缓存模式Least-Recent-UseLRU直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候将最早的数据批量写入磁盘。一般意义上来说对于物联网数据的使用用户最为关心最近产生的数据即当前状态。TDengine充分利用了这一特性将最近到达的当前状态数据保存在缓存中。
@ -423,7 +357,7 @@ select last_row(voltage) from meters where location='Beijing.Chaoyang';
该SQL语句将获取所有位于北京朝阳区的电表最后记录的电压值。 该SQL语句将获取所有位于北京朝阳区的电表最后记录的电压值。
## <a class="anchor" id="alert"></a>报警监测(Alert) ## <a class="anchor" id="alert"></a>报警监测Alert
在 TDengine 的应用场景中,报警监测是一个常见需求,从概念上说,它要求程序从最近一段时间的数据中筛选出符合一定条件的数据,并基于这些数据根据定义好的公式计算出一个结果,当这个结果符合某个条件且持续一定时间后,以某种形式通知用户。 在 TDengine 的应用场景中,报警监测是一个常见需求,从概念上说,它要求程序从最近一段时间的数据中筛选出符合一定条件的数据,并基于这些数据根据定义好的公式计算出一个结果,当这个结果符合某个条件且持续一定时间后,以某种形式通知用户。

View File

@ -285,7 +285,7 @@ JDBC连接器可能报错的错误码包括3种JDBC driver本身的报错
* https://github.com/taosdata/TDengine/blob/develop/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java * https://github.com/taosdata/TDengine/blob/develop/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java
* https://github.com/taosdata/TDengine/blob/develop/src/inc/taoserror.h * https://github.com/taosdata/TDengine/blob/develop/src/inc/taoserror.h
### 订阅 ### <a class="anchor" id="subscribe"></a>订阅
#### 创建 #### 创建
@ -471,9 +471,11 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对
| BIGINT | java.lang.Long | | BIGINT | java.lang.Long |
| FLOAT | java.lang.Float | | FLOAT | java.lang.Float |
| DOUBLE | java.lang.Double | | DOUBLE | java.lang.Double |
| SMALLINT, TINYINT | java.lang.Short | | SMALLINT | java.lang.Short |
| TINYINT | java.lang.Byte |
| BOOL | java.lang.Boolean | | BOOL | java.lang.Boolean |
| BINARY, NCHAR | java.lang.String | | BINARY | byte array |
| NCHAR | java.lang.String |

View File

@ -113,6 +113,7 @@ taos>
- 任何已经加入集群在线的数据节点,都可以作为后续待加入节点的 firstEP。 - 任何已经加入集群在线的数据节点,都可以作为后续待加入节点的 firstEP。
- firstEp 这个参数仅仅在该数据节点首次加入集群时有作用,加入集群后,该数据节点会保存最新的 mnode 的 End Point 列表,不再依赖这个参数。 - firstEp 这个参数仅仅在该数据节点首次加入集群时有作用,加入集群后,该数据节点会保存最新的 mnode 的 End Point 列表,不再依赖这个参数。
- 接下来,配置文件中的 firstEp 参数就主要在客户端连接的时候使用了,例如 taos shell 如果不加参数,会默认连接由 firstEp 指定的节点。
- 两个没有配置 firstEp 参数的数据节点 dnode 启动后,会独立运行起来。这个时候,无法将其中一个数据节点加入到另外一个数据节点,形成集群。**无法将两个独立的集群合并成为新的集群**。 - 两个没有配置 firstEp 参数的数据节点 dnode 启动后,会独立运行起来。这个时候,无法将其中一个数据节点加入到另外一个数据节点,形成集群。**无法将两个独立的集群合并成为新的集群**。
## <a class="anchor" id="management"></a>数据节点管理 ## <a class="anchor" id="management"></a>数据节点管理

View File

@ -6,19 +6,27 @@
### 内存需求 ### 内存需求
每个 DB 可以创建固定数目的 vgroup默认与 CPU 核数相同,可通过 maxVgroupsPerDb 配置vgroup 中的每个副本会是一个 vnode每个 vnode 会占用固定大小的内存(大小与数据库的配置参数 blocks 和 cache 有关);每个 Table 会占用与标签总长度有关的内存;此外,系统会有一些固定的内存开销。因此,每个 DB 需要的系统内存可通过如下公式计算: 每个 Database 可以创建固定数目的 vgroup默认与 CPU 核数相同,可通过 maxVgroupsPerDb 配置vgroup 中的每个副本会是一个 vnode每个 vnode 会占用固定大小的内存(大小与数据库的配置参数 blocks 和 cache 有关);每个 Table 会占用与标签总长度有关的内存;此外,系统会有一些固定的内存开销。因此,每个 DB 需要的系统内存可通过如下公式计算:
``` ```
Memory Size = maxVgroupsPerDb * (blocks * cache + 10MB) + numOfTables * (tagSizePerTable + 0.5KB) Database Memory Size = maxVgroupsPerDb * (blocks * cache + 10MB) + numOfTables * (tagSizePerTable + 0.5KB)
``` ```
示例:假设是 4 核机器cache 是缺省大小 16M, blocks 是缺省值 6假设有 10 万张表,标签总长度是 256 字节则总的内存需求为4 \* (16 \* 6 + 10) + 100000 \* (0.25 + 0.5) / 1000 = 499M。 示例:假设是 4 核机器cache 是缺省大小 16M, blocks 是缺省值 6并且一个 DB 中有 10 万张表,标签总长度是 256 字节,则这个 DB 总的内存需求为4 \* (16 \* 6 + 10) + 100000 \* (0.25 + 0.5) / 1000 = 499M。
注意:从这个公式计算得到的内存容量,应理解为系统的“必要需求”,而不是“内存总数”。在实际运行的生产系统中,由于操作系统缓存、资源管理调度等方面的需要,内存规划应当在计算结果的基础上保留一定冗余,以维持系统状态和系统性能的稳定性。 在实际的系统运维中,我们通常会更关心 TDengine 服务进程taosd会占用的内存量。
```
taosd 内存总量 = vnode 内存 + mnode 内存 + 查询内存
```
实际运行的系统往往会根据数据特点的不同,将数据存放在不同的 DB 里。因此做规划时,也需要考虑。 其中:
1. “vnode 内存”指的是集群中所有的 Database 存储分摊到当前 taosd 节点上所占用的内存资源。可以按上文“Database Memory Size”计算公式估算每个 DB 的内存占用量进行加总,再按集群中总共的 TDengine 节点数做平均(如果设置为多副本,则还需要乘以对应的副本倍数)。
2. “mnode 内存”指的是集群中管理节点所占用的资源。如果一个 taosd 节点上分布有 mnode 管理节点则内存消耗还需要增加“0.2KB * 集群中数据表总数”。
3. “查询内存”指的是服务端处理查询请求时所需要占用的内存。单条查询语句至少会占用“0.2KB * 查询涉及的数据表总数”的内存量。
如果内存充裕,可以加大 Blocks 的配置,这样更多数据将保存在内存里,提高查询速度。 注意:以上内存估算方法,主要讲解了系统的“必须内存需求”,而不是“内存总数上限”。在实际运行的生产环境中,由于操作系统缓存、资源管理调度等方面的原因,内存规划应当在估算结果的基础上保留一定冗余,以维持系统状态和系统性能的稳定性。并且,生产环境通常会配置系统资源的监控工具,以便及时发现硬件资源的紧缺情况。
最后,如果内存充裕,可以考虑加大 Blocks 的配置,这样更多数据将保存在内存里,提高查询速度。
### CPU 需求 ### CPU 需求
@ -112,17 +120,17 @@ taosd -C
不同应用场景的数据往往具有不同的数据特征比如保留天数、副本数、采集频次、记录大小、采集点的数量、压缩等都可完全不同。为获得在存储上的最高效率TDengine提供如下存储相关的系统配置参数 不同应用场景的数据往往具有不同的数据特征比如保留天数、副本数、采集频次、记录大小、采集点的数量、压缩等都可完全不同。为获得在存储上的最高效率TDengine提供如下存储相关的系统配置参数
- days一个数据文件存储数据的时间跨度单位为天默认值10。 - days一个数据文件存储数据的时间跨度单位为天默认值10。
- keep数据库中数据保留的天数单位为天默认值3650。 - keep数据库中数据保留的天数单位为天默认值3650。(可通过 alter database 修改)
- minRows文件块中记录的最小条数单位为条默认值100。 - minRows文件块中记录的最小条数单位为条默认值100。
- maxRows文件块中记录的最大条数单位为条默认值4096。 - maxRows文件块中记录的最大条数单位为条默认值4096。
- comp文件压缩标志位0关闭1一阶段压缩2两阶段压缩。默认值2。 - comp文件压缩标志位0关闭1一阶段压缩2两阶段压缩。默认值2。(可通过 alter database 修改)
- walLevelWAL级别。1写wal但不执行fsync2写wal, 而且执行fsync。默认值1。 - walLevelWAL级别。1写wal但不执行fsync2写wal, 而且执行fsync。默认值1。
- fsync当wal设置为2时执行fsync的周期。设置为0表示每次写入立即执行fsync。单位为毫秒默认值3000。 - fsync当wal设置为2时执行fsync的周期。设置为0表示每次写入立即执行fsync。单位为毫秒默认值3000。
- cache内存块的大小单位为兆字节MB默认值16。 - cache内存块的大小单位为兆字节MB默认值16。
- blocks每个VNODETSDB中有多少cache大小的内存块。因此一个VNODE的用的内存大小粗略为cache * blocks。单位为块默认值4。 - blocks每个VNODETSDB中有多少cache大小的内存块。因此一个VNODE的用的内存大小粗略为cache * blocks。单位为块默认值4。(可通过 alter database 修改)
- replica副本个数取值范围1-3。单位为个默认值1 - replica副本个数取值范围1-3。单位为个默认值1。(可通过 alter database 修改)
- precision时间戳精度标识ms表示毫秒us表示微秒。默认值ms - precision时间戳精度标识ms表示毫秒us表示微秒。默认值ms
- cacheLast是否在内存中缓存子表 last_row0关闭1开启。默认值0。从 2.0.11 版本开始支持此参数) - cacheLast是否在内存中缓存子表 last_row0关闭1开启。默认值0。可通过 alter database 修改)(从 2.0.11 版本开始支持此参数)
对于一个应用场景可能有多种数据特征的数据并存最佳的设计是将具有相同数据特征的表放在一个库里这样一个应用有多个库而每个库可以配置不同的存储参数从而保证系统有最优的性能。TDengine允许应用在创建库时指定上述存储参数如果指定该参数就将覆盖对应的系统配置参数。举例有下述SQL 对于一个应用场景可能有多种数据特征的数据并存最佳的设计是将具有相同数据特征的表放在一个库里这样一个应用有多个库而每个库可以配置不同的存储参数从而保证系统有最优的性能。TDengine允许应用在创建库时指定上述存储参数如果指定该参数就将覆盖对应的系统配置参数。举例有下述SQL

View File

@ -156,3 +156,13 @@ ALTER LOCAL RESETLOG;
``` ```
其含义是,清空本机所有由客户端生成的日志文件。 其含义是,清空本机所有由客户端生成的日志文件。
## <a class="anchor" id="timezone"></a>18. 时间戳的时区信息是怎样处理的?
TDengine 中时间戳的时区总是由客户端进行处理,而与服务端无关。具体来说,客户端会对 SQL 语句中的时间戳进行时区转换,转为 UTC 时区(即 Unix 时间戳——Unix Timestamp再交由服务端进行写入和查询在读取数据时服务端也是采用 UTC 时区提供原始数据,客户端收到后再根据本地设置,把时间戳转换为本地系统所要求的时区进行显示。
客户端在处理时间戳字符串时,会采取如下逻辑:
1. 在未做特殊设置的情况下,客户端默认使用所在操作系统的时区设置。
2. 如果在 taos.cfg 中设置了 timezone 参数,则客户端会以这个配置文件中的设置为准。
3. 如果在 C/C++/Java/Python 等各种编程语言的 Connector Driver 中,在建立数据库连接时显式指定了 timezone那么会以这个指定的时区设置为准。例如 Java Connector 的 JDBC URL 中就有 timezone 参数。
4. 在书写 SQL 语句时,也可以直接使用 Unix 时间戳(例如 `1554984068000`)或带有时区的时间戳字符串,也即以 RFC 3339 格式(例如 `2013-04-12T15:52:01.123+08:00`)或 ISO-8601 格式(例如 `2013-04-12T15:52:01.123+0800`)来书写时间戳,此时这些时间戳的取值将不再受其他时区设置的影响。

View File

@ -29,6 +29,9 @@
# number of threads per CPU core # number of threads per CPU core
# numOfThreadsPerCore 1.0 # numOfThreadsPerCore 1.0
# number of threads to commit cache data
# numOfCommitThreads 4
# the proportion of total CPU cores available for query processing # the proportion of total CPU cores available for query processing
# 2.0: the query threads will be set to double of the CPU cores. # 2.0: the query threads will be set to double of the CPU cores.
# 1.0: all CPU cores are available for query processing [default]. # 1.0: all CPU cores are available for query processing [default].

View File

@ -83,6 +83,22 @@ typedef struct SJoinSupporter {
SArray* pVgroupTables; SArray* pVgroupTables;
} SJoinSupporter; } SJoinSupporter;
typedef struct SMergeCtx {
SJoinSupporter* p;
int32_t idx;
SArray* res;
int8_t compared;
}SMergeCtx;
typedef struct SMergeTsCtx {
SJoinSupporter* p;
STSBuf* res;
int64_t numOfInput;
int8_t compared;
}SMergeTsCtx;
typedef struct SVgroupTableInfo { typedef struct SVgroupTableInfo {
SVgroupInfo vgInfo; SVgroupInfo vgInfo;
SArray* itemList; //SArray<STableIdInfo> SArray* itemList; //SArray<STableIdInfo>
@ -183,6 +199,7 @@ int32_t tscSqlExprCopy(SArray* dst, const SArray* src, uint64_t uid, bool deep
void tscSqlExprInfoDestroy(SArray* pExprInfo); void tscSqlExprInfoDestroy(SArray* pExprInfo);
SColumn* tscColumnClone(const SColumn* src); SColumn* tscColumnClone(const SColumn* src);
bool tscColumnExists(SArray* pColumnList, SColumnIndex* pColIndex);
SColumn* tscColumnListInsert(SArray* pColList, SColumnIndex* colIndex); SColumn* tscColumnListInsert(SArray* pColList, SColumnIndex* colIndex);
SArray* tscColumnListClone(const SArray* src, int16_t tableIndex); SArray* tscColumnListClone(const SArray* src, int16_t tableIndex);
void tscColumnListDestroy(SArray* pColList); void tscColumnListDestroy(SArray* pColList);

View File

@ -142,15 +142,15 @@ typedef struct SCond {
} SCond; } SCond;
typedef struct SJoinNode { typedef struct SJoinNode {
char tableName[TSDB_TABLE_FNAME_LEN];
uint64_t uid; uint64_t uid;
int16_t tagColId; int16_t tagColId;
SArray* tsJoin;
SArray* tagJoin;
} SJoinNode; } SJoinNode;
typedef struct SJoinInfo { typedef struct SJoinInfo {
bool hasJoin; bool hasJoin;
SJoinNode left; SJoinNode* joinTables[TSDB_MAX_JOIN_TABLE_NUM];
SJoinNode right;
} SJoinInfo; } SJoinInfo;
typedef struct STagCond { typedef struct STagCond {
@ -439,6 +439,8 @@ void tscFreeSqlResult(SSqlObj *pSql);
* @param pObj * @param pObj
*/ */
void tscFreeSqlObj(SSqlObj *pSql); void tscFreeSqlObj(SSqlObj *pSql);
void tscFreeSubobj(SSqlObj* pSql);
void tscFreeRegisteredSqlObj(void *pSql); void tscFreeRegisteredSqlObj(void *pSql);
void tscCloseTscObj(void *pObj); void tscCloseTscObj(void *pObj);

View File

@ -977,12 +977,18 @@ int32_t parseSlidingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SStrToken* pSl
int32_t tscSetTableFullName(STableMetaInfo* pTableMetaInfo, SStrToken* pTableName, SSqlObj* pSql) { int32_t tscSetTableFullName(STableMetaInfo* pTableMetaInfo, SStrToken* pTableName, SSqlObj* pSql) {
const char* msg1 = "name too long"; const char* msg1 = "name too long";
const char* msg2 = "acctId too long"; const char* msg2 = "acctId too long";
const char* msg3 = "no acctId";
SSqlCmd* pCmd = &pSql->cmd; SSqlCmd* pCmd = &pSql->cmd;
int32_t code = TSDB_CODE_SUCCESS; int32_t code = TSDB_CODE_SUCCESS;
if (hasSpecifyDB(pTableName)) { // db has been specified in sql string so we ignore current db path if (hasSpecifyDB(pTableName)) { // db has been specified in sql string so we ignore current db path
code = tNameSetAcctId(&pTableMetaInfo->name, getAccountId(pSql)); char* acctId = getAccountId(pSql);
if (acctId == NULL || strlen(acctId) <= 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
code = tNameSetAcctId(&pTableMetaInfo->name, acctId);
if (code != 0) { if (code != 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
} }
@ -3353,23 +3359,25 @@ static int32_t getColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSq
} }
} }
static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) { static int32_t checkAndSetJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) {
const char* msg1 = "invalid join query condition"; int32_t code = 0;
const char* msg2 = "invalid table name in join query"; const char* msg1 = "timestamp required for join tables";
const char* msg3 = "type of join columns must be identical"; const char* msg3 = "type of join columns must be identical";
const char* msg4 = "invalid column name in join condition"; const char* msg4 = "invalid column name in join condition";
const char* msg5 = "only support one join tag for each table";
if (pExpr == NULL) { if (pExpr == NULL) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
if (!tSqlExprIsParentOfLeaf(pExpr)) { if (!tSqlExprIsParentOfLeaf(pExpr)) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); code = checkAndSetJoinCondInfo(pCmd, pQueryInfo, pExpr->pLeft);
if (code) {
return code;
} }
STagCond* pTagCond = &pQueryInfo->tagCond; return checkAndSetJoinCondInfo(pCmd, pQueryInfo, pExpr->pRight);
SJoinNode* pLeft = &pTagCond->joinInfo.left; }
SJoinNode* pRight = &pTagCond->joinInfo.right;
SColumnIndex index = COLUMN_INDEX_INITIALIZER; SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (getColumnIndexByName(pCmd, &pExpr->pLeft->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) { if (getColumnIndexByName(pCmd, &pExpr->pLeft->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
@ -3379,14 +3387,29 @@ static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr*
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
SSchema* pTagSchema1 = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex); SSchema* pTagSchema1 = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex);
pLeft->uid = pTableMetaInfo->pTableMeta->id.uid; assert(index.tableIndex >= 0 && index.tableIndex < TSDB_MAX_JOIN_TABLE_NUM);
pLeft->tagColId = pTagSchema1->colId;
int32_t code = tNameExtractFullName(&pTableMetaInfo->name, pLeft->tableName); SJoinNode **leftNode = &pQueryInfo->tagCond.joinInfo.joinTables[index.tableIndex];
if (code != TSDB_CODE_SUCCESS) { if (*leftNode == NULL) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
} }
(*leftNode)->uid = pTableMetaInfo->pTableMeta->id.uid;
(*leftNode)->tagColId = pTagSchema1->colId;
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
index.columnIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
if (!tscColumnExists(pTableMetaInfo->tagColList, &index)) {
tscColumnListInsert(pTableMetaInfo->tagColList, &index);
if (taosArrayGetSize(pTableMetaInfo->tagColList) > 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
}
}
int16_t leftIdx = index.tableIndex;
index = (SColumnIndex)COLUMN_INDEX_INITIALIZER; index = (SColumnIndex)COLUMN_INDEX_INITIALIZER;
if (getColumnIndexByName(pCmd, &pExpr->pRight->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) { if (getColumnIndexByName(pCmd, &pExpr->pRight->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
@ -3395,20 +3418,55 @@ static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr*
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
SSchema* pTagSchema2 = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex); SSchema* pTagSchema2 = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex);
pRight->uid = pTableMetaInfo->pTableMeta->id.uid; assert(index.tableIndex >= 0 && index.tableIndex < TSDB_MAX_JOIN_TABLE_NUM);
pRight->tagColId = pTagSchema2->colId;
code = tNameExtractFullName(&pTableMetaInfo->name, pRight->tableName); SJoinNode **rightNode = &pQueryInfo->tagCond.joinInfo.joinTables[index.tableIndex];
if (code != TSDB_CODE_SUCCESS) { if (*rightNode == NULL) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
} }
(*rightNode)->uid = pTableMetaInfo->pTableMeta->id.uid;
(*rightNode)->tagColId = pTagSchema2->colId;
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
index.columnIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
if (!tscColumnExists(pTableMetaInfo->tagColList, &index)) {
tscColumnListInsert(pTableMetaInfo->tagColList, &index);
if (taosArrayGetSize(pTableMetaInfo->tagColList) > 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
}
}
int16_t rightIdx = index.tableIndex;
if (pTagSchema1->type != pTagSchema2->type) { if (pTagSchema1->type != pTagSchema2->type) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
} }
pTagCond->joinInfo.hasJoin = true; if ((*leftNode)->tagJoin == NULL) {
(*leftNode)->tagJoin = taosArrayInit(2, sizeof(int16_t));
}
if ((*rightNode)->tagJoin == NULL) {
(*rightNode)->tagJoin = taosArrayInit(2, sizeof(int16_t));
}
taosArrayPush((*leftNode)->tagJoin, &rightIdx);
taosArrayPush((*rightNode)->tagJoin, &leftIdx);
pQueryInfo->tagCond.joinInfo.hasJoin = true;
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
}
static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) {
if (pExpr == NULL) {
return TSDB_CODE_SUCCESS;
}
return checkAndSetJoinCondInfo(pCmd, pQueryInfo, pExpr);
} }
static int32_t validateSQLExpr(SSqlCmd* pCmd, tSqlExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, static int32_t validateSQLExpr(SSqlCmd* pCmd, tSqlExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList,
@ -3674,7 +3732,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
const char* msg1 = "table query cannot use tags filter"; const char* msg1 = "table query cannot use tags filter";
const char* msg2 = "illegal column name"; const char* msg2 = "illegal column name";
const char* msg3 = "only one query time range allowed"; const char* msg3 = "only one query time range allowed";
const char* msg4 = "only one join condition allowed"; const char* msg4 = "too many join tables";
const char* msg5 = "not support ordinary column join"; const char* msg5 = "not support ordinary column join";
const char* msg6 = "only one query condition on tbname allowed"; const char* msg6 = "only one query condition on tbname allowed";
const char* msg7 = "only in/like allowed in filter table name"; const char* msg7 = "only in/like allowed in filter table name";
@ -3705,6 +3763,47 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_QUERY); TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_QUERY);
pCondExpr->tsJoin = true; pCondExpr->tsJoin = true;
assert(index.tableIndex >= 0 && index.tableIndex < TSDB_MAX_JOIN_TABLE_NUM);
SJoinNode **leftNode = &pQueryInfo->tagCond.joinInfo.joinTables[index.tableIndex];
if (*leftNode == NULL) {
*leftNode = calloc(1, sizeof(SJoinNode));
if (*leftNode == NULL) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
}
int16_t leftIdx = index.tableIndex;
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (getColumnIndexByName(pCmd, &pRight->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
if (index.tableIndex < 0 || index.tableIndex >= TSDB_MAX_JOIN_TABLE_NUM) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
}
SJoinNode **rightNode = &pQueryInfo->tagCond.joinInfo.joinTables[index.tableIndex];
if (*rightNode == NULL) {
*rightNode = calloc(1, sizeof(SJoinNode));
if (*rightNode == NULL) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
}
int16_t rightIdx = index.tableIndex;
if ((*leftNode)->tsJoin == NULL) {
(*leftNode)->tsJoin = taosArrayInit(2, sizeof(int16_t));
}
if ((*rightNode)->tsJoin == NULL) {
(*rightNode)->tsJoin = taosArrayInit(2, sizeof(int16_t));
}
taosArrayPush((*leftNode)->tsJoin, &rightIdx);
taosArrayPush((*rightNode)->tsJoin, &leftIdx);
/* /*
* to release expression, e.g., m1.ts = m2.ts, * to release expression, e.g., m1.ts = m2.ts,
* since this expression is used to set the join query type * since this expression is used to set the join query type
@ -3762,10 +3861,6 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
return TSDB_CODE_TSC_INVALID_SQL; return TSDB_CODE_TSC_INVALID_SQL;
} }
if (pCondExpr->pJoinExpr != NULL) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
}
pQueryInfo->type |= TSDB_QUERY_TYPE_JOIN_QUERY; pQueryInfo->type |= TSDB_QUERY_TYPE_JOIN_QUERY;
ret = setExprToCond(&pCondExpr->pJoinExpr, *pExpr, NULL, parentOptr, pQueryInfo->msg); ret = setExprToCond(&pCondExpr->pJoinExpr, *pExpr, NULL, parentOptr, pQueryInfo->msg);
*pExpr = NULL; *pExpr = NULL;
@ -3993,6 +4088,7 @@ static bool validateFilterExpr(SQueryInfo* pQueryInfo) {
static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) { static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) {
const char* msg0 = "invalid timestamp"; const char* msg0 = "invalid timestamp";
const char* msg1 = "only one time stamp window allowed"; const char* msg1 = "only one time stamp window allowed";
int32_t code = 0;
if (pExpr == NULL) { if (pExpr == NULL) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
@ -4003,7 +4099,10 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlE
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
} }
getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pLeft); code = getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pLeft);
if (code) {
return code;
}
return getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pRight); return getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pRight);
} else { } else {
@ -4085,6 +4184,7 @@ static void cleanQueryExpr(SCondExpr* pCondExpr) {
} }
} }
/*
static void doAddJoinTagsColumnsIntoTagList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondExpr* pCondExpr) { static void doAddJoinTagsColumnsIntoTagList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondExpr* pCondExpr) {
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
if (QUERY_IS_JOIN_QUERY(pQueryInfo->type) && UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { if (QUERY_IS_JOIN_QUERY(pQueryInfo->type) && UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
@ -4107,6 +4207,7 @@ static void doAddJoinTagsColumnsIntoTagList(SSqlCmd* pCmd, SQueryInfo* pQueryInf
tscColumnListInsert(pTableMetaInfo->tagColList, &index); tscColumnListInsert(pTableMetaInfo->tagColList, &index);
} }
} }
*/
static int32_t validateTagCondExpr(SSqlCmd* pCmd, tExprNode *p) { static int32_t validateTagCondExpr(SSqlCmd* pCmd, tExprNode *p) {
const char *msg1 = "invalid tag operator"; const char *msg1 = "invalid tag operator";
@ -4250,6 +4351,102 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE
return ret; return ret;
} }
int32_t validateJoinNodes(SQueryInfo* pQueryInfo, SSqlObj* pSql) {
const char* msg1 = "timestamp required for join tables";
const char* msg2 = "tag required for join stables";
for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
SJoinNode *node = pQueryInfo->tagCond.joinInfo.joinTables[i];
if (node == NULL || node->tsJoin == NULL || taosArrayGetSize(node->tsJoin) <= 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(&pSql->cmd), msg1);
}
}
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
SJoinNode *node = pQueryInfo->tagCond.joinInfo.joinTables[i];
if (node == NULL || node->tagJoin == NULL || taosArrayGetSize(node->tagJoin) <= 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(&pSql->cmd), msg2);
}
}
}
return TSDB_CODE_SUCCESS;
}
void mergeJoinNodesImpl(int8_t* r, int8_t* p, int16_t* tidx, SJoinNode** nodes, int32_t type) {
SJoinNode *node = nodes[*tidx];
SArray* arr = (type == 0) ? node->tsJoin : node->tagJoin;
size_t size = taosArrayGetSize(arr);
p[*tidx] = 1;
for (int32_t j = 0; j < size; j++) {
int16_t* idx = taosArrayGet(arr, j);
r[*idx] = 1;
if (p[*idx] == 0) {
mergeJoinNodesImpl(r, p, idx, nodes, type);
}
}
}
int32_t mergeJoinNodes(SQueryInfo* pQueryInfo, SSqlObj* pSql) {
const char* msg1 = "not all join tables have same timestamp";
const char* msg2 = "not all join tables have same tag";
int8_t r[TSDB_MAX_JOIN_TABLE_NUM] = {0};
int8_t p[TSDB_MAX_JOIN_TABLE_NUM] = {0};
for (int16_t i = 0; i < pQueryInfo->numOfTables; ++i) {
mergeJoinNodesImpl(r, p, &i, pQueryInfo->tagCond.joinInfo.joinTables, 0);
taosArrayClear(pQueryInfo->tagCond.joinInfo.joinTables[i]->tsJoin);
for (int32_t j = 0; j < TSDB_MAX_JOIN_TABLE_NUM; ++j) {
if (r[j]) {
taosArrayPush(pQueryInfo->tagCond.joinInfo.joinTables[i]->tsJoin, &j);
}
}
memset(r, 0, sizeof(r));
memset(p, 0, sizeof(p));
}
if (taosArrayGetSize(pQueryInfo->tagCond.joinInfo.joinTables[0]->tsJoin) != pQueryInfo->numOfTables) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(&pSql->cmd), msg1);
}
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
for (int16_t i = 0; i < pQueryInfo->numOfTables; ++i) {
mergeJoinNodesImpl(r, p, &i, pQueryInfo->tagCond.joinInfo.joinTables, 1);
taosArrayClear(pQueryInfo->tagCond.joinInfo.joinTables[i]->tagJoin);
for (int32_t j = 0; j < TSDB_MAX_JOIN_TABLE_NUM; ++j) {
if (r[j]) {
taosArrayPush(pQueryInfo->tagCond.joinInfo.joinTables[i]->tagJoin, &j);
}
}
memset(r, 0, sizeof(r));
memset(p, 0, sizeof(p));
}
if (taosArrayGetSize(pQueryInfo->tagCond.joinInfo.joinTables[0]->tagJoin) != pQueryInfo->numOfTables) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(&pSql->cmd), msg2);
}
}
return TSDB_CODE_SUCCESS;
}
int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql) { int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql) {
if (pExpr == NULL) { if (pExpr == NULL) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
@ -4295,17 +4492,17 @@ int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql
// 4. get the table name query condition // 4. get the table name query condition
if ((ret = getTablenameCond(&pSql->cmd, pQueryInfo, condExpr.pTableCond, &sb)) != TSDB_CODE_SUCCESS) { if ((ret = getTablenameCond(&pSql->cmd, pQueryInfo, condExpr.pTableCond, &sb)) != TSDB_CODE_SUCCESS) {
return ret; goto PARSE_WHERE_EXIT;
} }
// 5. other column query condition // 5. other column query condition
if ((ret = getColumnQueryCondInfo(&pSql->cmd, pQueryInfo, condExpr.pColumnCond, TK_AND)) != TSDB_CODE_SUCCESS) { if ((ret = getColumnQueryCondInfo(&pSql->cmd, pQueryInfo, condExpr.pColumnCond, TK_AND)) != TSDB_CODE_SUCCESS) {
return ret; goto PARSE_WHERE_EXIT;
} }
// 6. join condition // 6. join condition
if ((ret = getJoinCondInfo(&pSql->cmd, pQueryInfo, condExpr.pJoinExpr)) != TSDB_CODE_SUCCESS) { if ((ret = getJoinCondInfo(&pSql->cmd, pQueryInfo, condExpr.pJoinExpr)) != TSDB_CODE_SUCCESS) {
return ret; goto PARSE_WHERE_EXIT;
} }
// 7. query condition for table name // 7. query condition for table name
@ -4313,12 +4510,29 @@ int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql
ret = setTableCondForSTableQuery(&pSql->cmd, pQueryInfo, getAccountId(pSql), condExpr.pTableCond, condExpr.tableCondIndex, &sb); ret = setTableCondForSTableQuery(&pSql->cmd, pQueryInfo, getAccountId(pSql), condExpr.pTableCond, condExpr.tableCondIndex, &sb);
taosStringBuilderDestroy(&sb); taosStringBuilderDestroy(&sb);
if (ret) {
if (!validateFilterExpr(pQueryInfo)) { goto PARSE_WHERE_EXIT;
return invalidSqlErrMsg(tscGetErrorMsgPayload(&pSql->cmd), msg2);
} }
doAddJoinTagsColumnsIntoTagList(&pSql->cmd, pQueryInfo, &condExpr); if (!validateFilterExpr(pQueryInfo)) {
ret = invalidSqlErrMsg(tscGetErrorMsgPayload(&pSql->cmd), msg2);
goto PARSE_WHERE_EXIT;
}
//doAddJoinTagsColumnsIntoTagList(&pSql->cmd, pQueryInfo, &condExpr);
if (condExpr.tsJoin) {
ret = validateJoinNodes(pQueryInfo, pSql);
if (ret) {
goto PARSE_WHERE_EXIT;
}
ret = mergeJoinNodes(pQueryInfo, pSql);
if (ret) {
goto PARSE_WHERE_EXIT;
}
}
PARSE_WHERE_EXIT:
cleanQueryExpr(&condExpr); cleanQueryExpr(&condExpr);
return ret; return ret;
@ -6531,7 +6745,6 @@ int32_t doValidateSqlNode(SSqlObj* pSql, SQuerySqlNode* pQuerySqlNode, int32_t i
const char* msg1 = "point interpolation query needs timestamp"; const char* msg1 = "point interpolation query needs timestamp";
const char* msg2 = "fill only available for interval query"; const char* msg2 = "fill only available for interval query";
const char* msg3 = "start(end) time of query range required or time range too large"; const char* msg3 = "start(end) time of query range required or time range too large";
const char* msg4 = "illegal number of tables in from clause";
const char* msg5 = "too many columns in selection clause"; const char* msg5 = "too many columns in selection clause";
const char* msg6 = "too many tables in from clause"; const char* msg6 = "too many tables in from clause";
const char* msg7 = "invalid table alias name"; const char* msg7 = "invalid table alias name";
@ -6568,14 +6781,11 @@ int32_t doValidateSqlNode(SSqlObj* pSql, SQuerySqlNode* pQuerySqlNode, int32_t i
} }
size_t fromSize = taosArrayGetSize(pQuerySqlNode->from->tableList); size_t fromSize = taosArrayGetSize(pQuerySqlNode->from->tableList);
if (fromSize > TSDB_MAX_JOIN_TABLE_NUM) { if (fromSize > TSDB_MAX_JOIN_TABLE_NUM * 2) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
} }
pQueryInfo->command = TSDB_SQL_SELECT; pQueryInfo->command = TSDB_SQL_SELECT;
if (fromSize > 2) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
// set all query tables, which are maybe more than one. // set all query tables, which are maybe more than one.
for (int32_t i = 0; i < fromSize; ++i) { for (int32_t i = 0; i < fromSize; ++i) {

View File

@ -613,7 +613,7 @@ static int32_t tscEstimateQueryMsgSize(SSqlObj *pSql, int32_t clauseIndex) {
tableSerialize + sqlLen + 4096 + pQueryInfo->bufLen; tableSerialize + sqlLen + 4096 + pQueryInfo->bufLen;
} }
static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char *pMsg) { static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char *pMsg, int32_t *succeed) {
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, pSql->cmd.clauseIndex, 0); STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, pSql->cmd.clauseIndex, 0);
TSKEY dfltKey = htobe64(pQueryMsg->window.skey); TSKEY dfltKey = htobe64(pQueryMsg->window.skey);
@ -626,9 +626,14 @@ static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char
assert(index >= 0); assert(index >= 0);
SVgroupInfo* pVgroupInfo = NULL; SVgroupInfo* pVgroupInfo = NULL;
if (pTableMetaInfo->vgroupList->numOfVgroups > 0) { if (pTableMetaInfo->vgroupList && pTableMetaInfo->vgroupList->numOfVgroups > 0) {
assert(index < pTableMetaInfo->vgroupList->numOfVgroups); assert(index < pTableMetaInfo->vgroupList->numOfVgroups);
pVgroupInfo = &pTableMetaInfo->vgroupList->vgroups[index]; pVgroupInfo = &pTableMetaInfo->vgroupList->vgroups[index];
} else {
tscError("%p No vgroup info found", pSql);
*succeed = 0;
return pMsg;
} }
vgId = pVgroupInfo->vgId; vgId = pVgroupInfo->vgId;
@ -948,8 +953,13 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
pQueryMsg->secondStageOutput = 0; pQueryMsg->secondStageOutput = 0;
} }
int32_t succeed = 1;
// serialize the table info (sid, uid, tags) // serialize the table info (sid, uid, tags)
pMsg = doSerializeTableInfo(pQueryMsg, pSql, pMsg); pMsg = doSerializeTableInfo(pQueryMsg, pSql, pMsg, &succeed);
if (succeed == 0) {
return TSDB_CODE_TSC_APP_ERROR;
}
SSqlGroupbyExpr *pGroupbyExpr = &pQueryInfo->groupbyExpr; SSqlGroupbyExpr *pGroupbyExpr = &pQueryInfo->groupbyExpr;
if (pGroupbyExpr->numOfGroupCols > 0) { if (pGroupbyExpr->numOfGroupCols > 0) {
@ -2081,6 +2091,10 @@ int tscProcessSTableVgroupRsp(SSqlObj *pSql) {
assert(pInfo->vgroupList != NULL); assert(pInfo->vgroupList != NULL);
pInfo->vgroupList->numOfVgroups = pVgroupMsg->numOfVgroups; pInfo->vgroupList->numOfVgroups = pVgroupMsg->numOfVgroups;
if (pInfo->vgroupList->numOfVgroups <= 0) {
//tfree(pInfo->vgroupList);
tscError("%p empty vgroup info", pSql);
} else {
for (int32_t j = 0; j < pInfo->vgroupList->numOfVgroups; ++j) { for (int32_t j = 0; j < pInfo->vgroupList->numOfVgroups; ++j) {
//just init, no need to lock //just init, no need to lock
SVgroupInfo *pVgroups = &pInfo->vgroupList->vgroups[j]; SVgroupInfo *pVgroups = &pInfo->vgroupList->vgroups[j];
@ -2096,6 +2110,7 @@ int tscProcessSTableVgroupRsp(SSqlObj *pSql) {
pVgroups->epAddr[k].fqdn = strndup(vmsg->epAddr[k].fqdn, tListLen(vmsg->epAddr[k].fqdn)); pVgroups->epAddr[k].fqdn = strndup(vmsg->epAddr[k].fqdn, tListLen(vmsg->epAddr[k].fqdn));
} }
} }
}
pMsg += size; pMsg += size;
} }
@ -2632,7 +2647,6 @@ void tscInitMsgsFp() {
tscProcessMsgRsp[TSDB_SQL_SHOW_CREATE_TABLE] = tscProcessShowCreateRsp; tscProcessMsgRsp[TSDB_SQL_SHOW_CREATE_TABLE] = tscProcessShowCreateRsp;
tscProcessMsgRsp[TSDB_SQL_SHOW_CREATE_DATABASE] = tscProcessShowCreateRsp; tscProcessMsgRsp[TSDB_SQL_SHOW_CREATE_DATABASE] = tscProcessShowCreateRsp;
tscKeepConn[TSDB_SQL_SHOW] = 1; tscKeepConn[TSDB_SQL_SHOW] = 1;
tscKeepConn[TSDB_SQL_RETRIEVE] = 1; tscKeepConn[TSDB_SQL_RETRIEVE] = 1;
tscKeepConn[TSDB_SQL_SELECT] = 1; tscKeepConn[TSDB_SQL_SELECT] = 1;

View File

@ -299,6 +299,7 @@ static void tscProcessStreamRetrieveResult(void *param, TAOS_RES *res, int numOf
tfree(pTableMetaInfo->pTableMeta); tfree(pTableMetaInfo->pTableMeta);
tscFreeSqlResult(pSql); tscFreeSqlResult(pSql);
tscFreeSubobj(pSql);
tfree(pSql->pSubs); tfree(pSql->pSubs);
pSql->subState.numOfSub = 0; pSql->subState.numOfSub = 0;
pTableMetaInfo->vgroupList = tscVgroupInfoClear(pTableMetaInfo->vgroupList); pTableMetaInfo->vgroupList = tscVgroupInfoClear(pTableMetaInfo->vgroupList);

View File

@ -46,6 +46,13 @@ static int32_t tsCompare(int32_t order, int64_t left, int64_t right) {
} }
static void skipRemainValue(STSBuf* pTSBuf, tVariant* tag1) { static void skipRemainValue(STSBuf* pTSBuf, tVariant* tag1) {
STSElem el1 = tsBufGetElem(pTSBuf);
int32_t res = tVariantCompare(el1.tag, tag1);
if (res != 0) { // it is a record with new tag
return;
}
while (tsBufNextPos(pTSBuf)) { while (tsBufNextPos(pTSBuf)) {
STSElem el1 = tsBufGetElem(pTSBuf); STSElem el1 = tsBufGetElem(pTSBuf);
@ -118,123 +125,233 @@ static bool subAndCheckDone(SSqlObj *pSql, SSqlObj *pParentSql, int idx) {
static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJoinSupporter* pSupporter2, STimeWindow * win) { static int64_t doTSBlockIntersect(SSqlObj* pSql, STimeWindow * win) {
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex); SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex);
STSBuf* output1 = tsBufCreate(true, pQueryInfo->order.order);
STSBuf* output2 = tsBufCreate(true, pQueryInfo->order.order);
win->skey = INT64_MAX; win->skey = INT64_MAX;
win->ekey = INT64_MIN; win->ekey = INT64_MIN;
SLimitVal* pLimit = &pQueryInfo->limit; SLimitVal* pLimit = &pQueryInfo->limit;
int32_t order = pQueryInfo->order.order; int32_t order = pQueryInfo->order.order;
int32_t joinNum = pSql->subState.numOfSub;
SMergeTsCtx ctxlist[TSDB_MAX_JOIN_TABLE_NUM] = {{0}};
SMergeTsCtx* ctxStack[TSDB_MAX_JOIN_TABLE_NUM] = {0};
int32_t slot = 0;
size_t tableNum = 0;
int16_t* tableMIdx = 0;
int32_t equalNum = 0;
int32_t stackidx = 0;
SMergeTsCtx* ctx = NULL;
SMergeTsCtx* pctx = NULL;
SMergeTsCtx* mainCtx = NULL;
STSElem cur;
STSElem prev;
SArray* tsCond = NULL;
int32_t mergeDone = 0;
SQueryInfo* pSubQueryInfo1 = tscGetQueryInfoDetail(&pSql->pSubs[0]->cmd, 0); for (int32_t i = 0; i < joinNum; ++i) {
SQueryInfo* pSubQueryInfo2 = tscGetQueryInfoDetail(&pSql->pSubs[1]->cmd, 0); STSBuf* output = tsBufCreate(true, pQueryInfo->order.order);
SQueryInfo* pSubQueryInfo = tscGetQueryInfoDetail(&pSql->pSubs[i]->cmd, 0);
pSubQueryInfo1->tsBuf = output1; pSubQueryInfo->tsBuf = output;
pSubQueryInfo2->tsBuf = output2;
TSKEY st = taosGetTimestampUs(); SJoinSupporter* pSupporter = pSql->pSubs[i]->param;
// no result generated, return directly if (pSupporter->pTSBuf == NULL) {
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); tscDebug("%p at least one ts-comp is empty, 0 for secondary query after ts blocks intersecting", pSql);
return 0; return 0;
} }
tsBufResetPos(pSupporter1->pTSBuf); tsBufResetPos(pSupporter->pTSBuf);
tsBufResetPos(pSupporter2->pTSBuf);
if (!tsBufNextPos(pSupporter1->pTSBuf)) {
tsBufFlush(output1);
tsBufFlush(output2);
if (!tsBufNextPos(pSupporter->pTSBuf)) {
tscDebug("%p input1 is empty, 0 for secondary query after ts blocks intersecting", pSql); tscDebug("%p input1 is empty, 0 for secondary query after ts blocks intersecting", pSql);
return 0; return 0;
} }
if (!tsBufNextPos(pSupporter2->pTSBuf)) { tscDebug("%p sub:%p table idx:%d, input group number:%d", pSql, pSql->pSubs[i], i, pSupporter->pTSBuf->numOfGroups);
tsBufFlush(output1);
tsBufFlush(output2);
tscDebug("%p input2 is empty, 0 for secondary query after ts blocks intersecting", pSql); ctxlist[i].p = pSupporter;
return 0; ctxlist[i].res = output;
} }
int64_t numOfInput1 = 1; TSKEY st = taosGetTimestampUs();
int64_t numOfInput2 = 1;
for (int16_t tidx = 0; tidx < joinNum; tidx++) {
pctx = &ctxlist[tidx];
if (pctx->compared) {
continue;
}
assert(pctx->numOfInput == 0);
tsCond = pQueryInfo->tagCond.joinInfo.joinTables[tidx]->tsJoin;
tableNum = taosArrayGetSize(tsCond);
assert(tableNum >= 2);
for (int32_t i = 0; i < tableNum; ++i) {
tableMIdx = taosArrayGet(tsCond, i);
SMergeTsCtx* tctx = &ctxlist[*tableMIdx];
tctx->compared = 1;
}
tableMIdx = taosArrayGet(tsCond, 0);
pctx = &ctxlist[*tableMIdx];
mainCtx = pctx;
while (1) { while (1) {
STSElem elem = tsBufGetElem(pSupporter1->pTSBuf); pctx = mainCtx;
// no data in pSupporter1 anymore, jump out of loop prev = tsBufGetElem(pctx->p->pTSBuf);
if (!tsBufIsValidElem(&elem)) {
ctxStack[stackidx++] = pctx;
if (!tsBufIsValidElem(&prev)) {
break; break;
} }
tVariant tag = {0};
tVariantAssign(&tag, prev.tag);
int32_t skipped = 0;
for (int32_t i = 1; i < tableNum; ++i) {
SMergeTsCtx* tctx = &ctxlist[i];
// find the data in supporter2 with the same tag value // find the data in supporter2 with the same tag value
STSElem e2 = tsBufFindElemStartPosByTag(pSupporter2->pTSBuf, elem.tag); STSElem e2 = tsBufFindElemStartPosByTag(tctx->p->pTSBuf, &tag);
/** if (!tsBufIsValidElem(&e2)) {
* there are elements in pSupporter2 with the same tag, continue skipRemainValue(pctx->p->pTSBuf, &tag);
*/ skipped = 1;
tVariant tag1 = {0}; break;
tVariantAssign(&tag1, elem.tag); }
}
if (skipped) {
slot = 0;
stackidx = 0;
continue;
}
tableMIdx = taosArrayGet(tsCond, ++slot);
equalNum = 1;
if (tsBufIsValidElem(&e2)) {
while (1) { while (1) {
STSElem elem1 = tsBufGetElem(pSupporter1->pTSBuf); ctx = &ctxlist[*tableMIdx];
STSElem elem2 = tsBufGetElem(pSupporter2->pTSBuf);
prev = tsBufGetElem(pctx->p->pTSBuf);
cur = tsBufGetElem(ctx->p->pTSBuf);
// data with current are exhausted // data with current are exhausted
if (!tsBufIsValidElem(&elem1) || tVariantCompare(elem1.tag, &tag1) != 0) { if (!tsBufIsValidElem(&prev) || tVariantCompare(prev.tag, &tag) != 0) {
break; break;
} }
if (!tsBufIsValidElem(&elem2) || tVariantCompare(elem2.tag, &tag1) != 0) { // ignore all records with the same tag if (!tsBufIsValidElem(&cur) || tVariantCompare(cur.tag, &tag) != 0) { // ignore all records with the same tag
skipRemainValue(pSupporter1->pTSBuf, &tag1);
break; break;
} }
/* ctxStack[stackidx++] = ctx;
* 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 ret = tsCompare(order, prev.ts, cur.ts);
*/ if (ret == 0) {
int32_t re = tsCompare(order, elem1.ts, elem2.ts); if (++equalNum < tableNum) {
if (re < 0) { pctx = ctx;
tsBufNextPos(pSupporter1->pTSBuf);
numOfInput1++; if (++slot >= tableNum) {
} else if (re > 0) { slot = 0;
tsBufNextPos(pSupporter2->pTSBuf); }
numOfInput2++;
} else { tableMIdx = taosArrayGet(tsCond, slot);
continue;
}
assert(stackidx == tableNum);
if (pLimit->offset == 0 || pQueryInfo->interval.interval > 0 || QUERY_IS_STABLE_QUERY(pQueryInfo->type)) { if (pLimit->offset == 0 || pQueryInfo->interval.interval > 0 || QUERY_IS_STABLE_QUERY(pQueryInfo->type)) {
if (win->skey > elem1.ts) { if (win->skey > prev.ts) {
win->skey = elem1.ts; win->skey = prev.ts;
} }
if (win->ekey < elem1.ts) { if (win->ekey < prev.ts) {
win->ekey = elem1.ts; win->ekey = prev.ts;
} }
tsBufAppend(output1, elem1.id, elem1.tag, (const char*)&elem1.ts, sizeof(elem1.ts)); for (int32_t i = 0; i < stackidx; ++i) {
tsBufAppend(output2, elem2.id, elem2.tag, (const char*)&elem2.ts, sizeof(elem2.ts)); SMergeTsCtx* tctx = ctxStack[i];
prev = tsBufGetElem(tctx->p->pTSBuf);
tsBufAppend(tctx->res, prev.id, prev.tag, (const char*)&prev.ts, sizeof(prev.ts));
}
} else { } else {
pLimit->offset -= 1;//offset apply to projection? pLimit->offset -= 1;//offset apply to projection?
} }
tsBufNextPos(pSupporter1->pTSBuf); for (int32_t i = 0; i < stackidx; ++i) {
numOfInput1++; SMergeTsCtx* tctx = ctxStack[i];
tsBufNextPos(pSupporter2->pTSBuf); if (!tsBufNextPos(tctx->p->pTSBuf) && tctx == mainCtx) {
numOfInput2++; mergeDone = 1;
} }
tctx->numOfInput++;
} }
} else { // no data in pSupporter2, ignore current data in pSupporter2
skipRemainValue(pSupporter1->pTSBuf, &tag1); if (mergeDone) {
break;
} }
stackidx = 0;
equalNum = 1;
ctxStack[stackidx++] = pctx;
} else if (ret > 0) {
if (!tsBufNextPos(ctx->p->pTSBuf) && ctx == mainCtx) {
mergeDone = 1;
break;
}
ctx->numOfInput++;
stackidx--;
} else {
stackidx--;
for (int32_t i = 0; i < stackidx; ++i) {
SMergeTsCtx* tctx = ctxStack[i];
if (!tsBufNextPos(tctx->p->pTSBuf) && tctx == mainCtx) {
mergeDone = 1;
}
tctx->numOfInput++;
}
if (mergeDone) {
break;
}
stackidx = 0;
equalNum = 1;
ctxStack[stackidx++] = pctx;
}
}
if (mergeDone) {
break;
}
slot = 0;
stackidx = 0;
skipRemainValue(mainCtx->p->pTSBuf, &tag);
}
stackidx = 0;
slot = 0;
mergeDone = 0;
} }
/* /*
@ -242,28 +359,32 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJ
* 1. only one element * 1. only one element
* 2. only one element for each tag. * 2. only one element for each tag.
*/ */
if (output1->tsOrder == -1) { if (ctxlist[0].res->tsOrder == -1) {
output1->tsOrder = TSDB_ORDER_ASC; for (int32_t i = 0; i < joinNum; ++i) {
output2->tsOrder = TSDB_ORDER_ASC; ctxlist[i].res->tsOrder = TSDB_ORDER_ASC;
}
} }
tsBufFlush(output1); for (int32_t i = 0; i < joinNum; ++i) {
tsBufFlush(output2); tsBufFlush(ctxlist[i].res);
tsBufDestroy(pSupporter1->pTSBuf); tsBufDestroy(ctxlist[i].p->pTSBuf);
pSupporter1->pTSBuf = NULL; ctxlist[i].p->pTSBuf = NULL;
tsBufDestroy(pSupporter2->pTSBuf); }
pSupporter2->pTSBuf = NULL;
TSKEY et = taosGetTimestampUs(); 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; for (int32_t i = 0; i < joinNum; ++i) {
tscDebug("%p sub:%p tblidx:%d, input:%" PRId64 ", final:%" PRId64 " in %d vnodes for secondary query after ts blocks "
"intersecting, skey:%" PRId64 ", ekey:%" PRId64 ", numOfVnode:%d, elapsed time:%" PRId64 " us",
pSql, pSql->pSubs[i], i, ctxlist[i].numOfInput, ctxlist[i].res->numOfTotal, ctxlist[i].res->numOfGroups, win->skey, win->ekey,
tsBufGetNumOfGroup(ctxlist[i].res), et - st);
} }
return ctxlist[0].res->numOfTotal;
}
// todo handle failed to create sub query // todo handle failed to create sub query
SJoinSupporter* tscCreateJoinSupporter(SSqlObj* pSql, int32_t index) { SJoinSupporter* tscCreateJoinSupporter(SSqlObj* pSql, int32_t index) {
SJoinSupporter* pSupporter = calloc(1, sizeof(SJoinSupporter)); SJoinSupporter* pSupporter = calloc(1, sizeof(SJoinSupporter));
@ -768,76 +889,218 @@ static bool checkForDuplicateTagVal(SSchema* pColSchema, SJoinSupporter* p1, SSq
return true; return true;
} }
static int32_t getIntersectionOfTableTuple(SQueryInfo* pQueryInfo, SSqlObj* pParentSql, SArray** s1, SArray** s2) {
SJoinSupporter* p1 = pParentSql->pSubs[0]->param;
SJoinSupporter* p2 = pParentSql->pSubs[1]->param;
tscDebug("%p all subquery retrieve <tid, tags> 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);
static int32_t getIntersectionOfTableTuple(SQueryInfo* pQueryInfo, SSqlObj* pParentSql, SArray* resList) {
int16_t joinNum = pParentSql->subState.numOfSub;
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
int16_t tagColId = tscGetJoinTagColIdByUid(&pQueryInfo->tagCond, pTableMetaInfo->pTableMeta->id.uid); int16_t tagColId = tscGetJoinTagColIdByUid(&pQueryInfo->tagCond, pTableMetaInfo->pTableMeta->id.uid);
SJoinSupporter* p0 = pParentSql->pSubs[0]->param;
SMergeCtx ctxlist[TSDB_MAX_JOIN_TABLE_NUM] = {{0}};
SMergeCtx* ctxStack[TSDB_MAX_JOIN_TABLE_NUM] = {0};
// int16_t for padding
int32_t size = p0->tagSize - sizeof(int16_t);
SSchema* pColSchema = tscGetColumnSchemaById(pTableMetaInfo->pTableMeta, tagColId); SSchema* pColSchema = tscGetColumnSchemaById(pTableMetaInfo->pTableMeta, tagColId);
// int16_t for padding tscDebug("%p all subquery retrieve <tid, tags> complete, do tags match", pParentSql);
int32_t size = p1->tagSize - sizeof(int16_t);
*s1 = taosArrayInit(p1->num, size);
*s2 = taosArrayInit(p2->num, size);
if (!(checkForDuplicateTagVal(pColSchema, p1, pParentSql) && checkForDuplicateTagVal(pColSchema, p2, pParentSql))) { for (int32_t i = 0; i < joinNum; i++) {
SJoinSupporter* p = pParentSql->pSubs[i]->param;
ctxlist[i].p = p;
ctxlist[i].res = taosArrayInit(p->num, size);
tscDebug("Join %d - num:%d", i, p->num);
// sort according to the tag valu
qsort(p->pIdTagList, p->num, p->tagSize, tagValCompar);
if (!checkForDuplicateTagVal(pColSchema, p, pParentSql)) {
for (int32_t j = 0; j <= i; j++) {
taosArrayDestroy(ctxlist[j].res);
}
return TSDB_CODE_QRY_DUP_JOIN_KEY; return TSDB_CODE_QRY_DUP_JOIN_KEY;
} }
}
int32_t i = 0, j = 0; int32_t slot = 0;
while(i < p1->num && j < p2->num) { size_t tableNum = 0;
STidTags* pp1 = (STidTags*) varDataVal(p1->pIdTagList + i * p1->tagSize); int16_t* tableMIdx = 0;
STidTags* pp2 = (STidTags*) varDataVal(p2->pIdTagList + j * p2->tagSize); int32_t equalNum = 0;
assert(pp1->tid != 0 && pp2->tid != 0); int32_t stackidx = 0;
int32_t mergeDone = 0;
SMergeCtx* ctx = NULL;
SMergeCtx* pctx = NULL;
STidTags* cur = NULL;
STidTags* prev = NULL;
SArray* tagCond = NULL;
int32_t ret = doCompare(pp1->tag, pp2->tag, pColSchema->type, pColSchema->bytes); for (int16_t tidx = 0; tidx < joinNum; tidx++) {
pctx = &ctxlist[tidx];
if (pctx->compared) {
continue;
}
assert(pctx->idx == 0 && taosArrayGetSize(pctx->res) == 0);
tagCond = pQueryInfo->tagCond.joinInfo.joinTables[tidx]->tagJoin;
tableNum = taosArrayGetSize(tagCond);
assert(tableNum >= 2);
for (int32_t i = 0; i < tableNum; ++i) {
tableMIdx = taosArrayGet(tagCond, i);
SMergeCtx* tctx = &ctxlist[*tableMIdx];
tctx->compared = 1;
}
for (int32_t i = 0; i < tableNum; ++i) {
tableMIdx = taosArrayGet(tagCond, i);
SMergeCtx* tctx = &ctxlist[*tableMIdx];
if (tctx->p->num <= 0 || tctx->p->pIdTagList == NULL) {
mergeDone = 1;
break;
}
}
if (mergeDone) {
mergeDone = 0;
continue;
}
tableMIdx = taosArrayGet(tagCond, slot);
pctx = &ctxlist[*tableMIdx];
prev = (STidTags*) varDataVal(pctx->p->pIdTagList + pctx->idx * pctx->p->tagSize);
ctxStack[stackidx++] = pctx;
tableMIdx = taosArrayGet(tagCond, ++slot);
equalNum = 1;
while (1) {
ctx = &ctxlist[*tableMIdx];
cur = (STidTags*) varDataVal(ctx->p->pIdTagList + ctx->idx * ctx->p->tagSize);
assert(cur->tid != 0 && prev->tid != 0);
ctxStack[stackidx++] = ctx;
int32_t ret = doCompare(prev->tag, cur->tag, pColSchema->type, pColSchema->bytes);
if (ret == 0) { if (ret == 0) {
tscDebug("%p tag matched, vgId:%d, val:%d, tid:%d, uid:%"PRIu64", tid:%d, uid:%"PRIu64, pParentSql, pp1->vgId, if (++equalNum < tableNum) {
*(int*) pp1->tag, pp1->tid, pp1->uid, pp2->tid, pp2->uid); prev = cur;
pctx = ctx;
taosArrayPush(*s1, pp1); if (++slot >= tableNum) {
taosArrayPush(*s2, pp2); slot = 0;
j++; }
i++;
tableMIdx = taosArrayGet(tagCond, slot);
continue;
}
tscDebug("%p tag matched, vgId:%d, val:%d, tid:%d, uid:%"PRIu64", tid:%d, uid:%"PRIu64, pParentSql, prev->vgId,
*(int*) prev->tag, prev->tid, prev->uid, cur->tid, cur->uid);
assert(stackidx == tableNum);
for (int32_t i = 0; i < stackidx; ++i) {
SMergeCtx* tctx = ctxStack[i];
prev = (STidTags*) varDataVal(tctx->p->pIdTagList + tctx->idx * tctx->p->tagSize);
taosArrayPush(tctx->res, prev);
}
for (int32_t i = 0; i < stackidx; ++i) {
SMergeCtx* tctx = ctxStack[i];
if (++tctx->idx >= tctx->p->num) {
mergeDone = 1;
break;
}
}
if (mergeDone) {
break;
}
stackidx = 0;
equalNum = 1;
prev = (STidTags*) varDataVal(pctx->p->pIdTagList + pctx->idx * pctx->p->tagSize);
ctxStack[stackidx++] = pctx;
} else if (ret > 0) { } else if (ret > 0) {
j++; stackidx--;
if (++ctx->idx >= ctx->p->num) {
break;
}
} else { } else {
i++; stackidx--;
for (int32_t i = 0; i < stackidx; ++i) {
SMergeCtx* tctx = ctxStack[i];
if (++tctx->idx >= tctx->p->num) {
mergeDone = 1;
break;
} }
} }
if (mergeDone) {
break;
}
stackidx = 0;
equalNum = 1;
prev = (STidTags*) varDataVal(pctx->p->pIdTagList + pctx->idx * pctx->p->tagSize);
ctxStack[stackidx++] = pctx;
}
}
slot = 0;
mergeDone = 0;
stackidx = 0;
}
for (int32_t i = 0; i < joinNum; ++i) {
// reorganize the tid-tag value according to both the vgroup id and tag values // reorganize the tid-tag value according to both the vgroup id and tag values
// sort according to the tag value // sort according to the tag value
size_t t1 = taosArrayGetSize(*s1); size_t num = taosArrayGetSize(ctxlist[i].res);
size_t t2 = taosArrayGetSize(*s2);
qsort((*s1)->pData, t1, size, tidTagsCompar); qsort((ctxlist[i].res)->pData, num, size, tidTagsCompar);
qsort((*s2)->pData, t2, size, tidTagsCompar);
#if 0 taosArrayPush(resList, &ctxlist[i].res);
for(int32_t k = 0; k < t1; ++k) {
STidTags* p = (*s1)->pData + size * k; tscDebug("%p tags match complete, result num: %"PRIzu, pParentSql, num);
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; return TSDB_CODE_SUCCESS;
} }
bool emptyTagList(SArray* resList, int32_t size) {
size_t rsize = taosArrayGetSize(resList);
if (rsize != size) {
return true;
}
for (int32_t i = 0; i < size; ++i) {
SArray** s = taosArrayGet(resList, i);
if (taosArrayGetSize(*s) <= 0) {
return true;
}
}
return false;
}
static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRows) { static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRows) {
SJoinSupporter* pSupporter = (SJoinSupporter*)param; SJoinSupporter* pSupporter = (SJoinSupporter*)param;
@ -939,19 +1202,19 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
return; return;
} }
SArray *s1 = NULL, *s2 = NULL; SArray* resList = taosArrayInit(pParentSql->subState.numOfSub, sizeof(SArray *));
int32_t code = getIntersectionOfTableTuple(pQueryInfo, pParentSql, &s1, &s2);
int32_t code = getIntersectionOfTableTuple(pQueryInfo, pParentSql, resList);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
freeJoinSubqueryObj(pParentSql); freeJoinSubqueryObj(pParentSql);
pParentSql->res.code = code; pParentSql->res.code = code;
tscAsyncResultOnError(pParentSql); tscAsyncResultOnError(pParentSql);
taosArrayDestroy(s1); taosArrayDestroy(resList);
taosArrayDestroy(s2);
return; return;
} }
if (taosArrayGetSize(s1) == 0 || taosArrayGetSize(s2) == 0) { // no results,return. if (emptyTagList(resList, pParentSql->subState.numOfSub)) { // no results,return.
assert(pParentSql->fp != tscJoinQueryCallback); assert(pParentSql->fp != tscJoinQueryCallback);
tscDebug("%p tag intersect does not generated qualified tables for join, free all sub SqlObj and quit", pParentSql); tscDebug("%p tag intersect does not generated qualified tables for join, free all sub SqlObj and quit", pParentSql);
@ -963,37 +1226,34 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
(*pParentSql->fp)(pParentSql->param, pParentSql, 0); (*pParentSql->fp)(pParentSql->param, pParentSql, 0);
} else { } else {
for (int32_t m = 0; m < pParentSql->subState.numOfSub; ++m) {
// proceed to for ts_comp query // proceed to for ts_comp query
SSqlCmd* pSubCmd1 = &pParentSql->pSubs[0]->cmd; SSqlCmd* pSubCmd = &pParentSql->pSubs[m]->cmd;
SSqlCmd* pSubCmd2 = &pParentSql->pSubs[1]->cmd; SArray** s = taosArrayGet(resList, m);
SQueryInfo* pQueryInfo1 = tscGetQueryInfoDetail(pSubCmd1, 0); SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pSubCmd, 0);
STableMetaInfo* pTableMetaInfo1 = tscGetMetaInfo(pQueryInfo1, 0); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
tscBuildVgroupTableInfo(pParentSql, pTableMetaInfo1, s1); tscBuildVgroupTableInfo(pParentSql, pTableMetaInfo, *s);
SQueryInfo* pQueryInfo2 = tscGetQueryInfoDetail(pSubCmd2, 0); SSqlObj* psub = pParentSql->pSubs[m];
STableMetaInfo* pTableMetaInfo2 = tscGetMetaInfo(pQueryInfo2, 0); ((SJoinSupporter*)psub->param)->pVgroupTables = tscVgroupTableInfoDup(pTableMetaInfo->pVgroupTables);
tscBuildVgroupTableInfo(pParentSql, pTableMetaInfo2, s2);
SSqlObj* psub1 = pParentSql->pSubs[0];
((SJoinSupporter*)psub1->param)->pVgroupTables = tscVgroupTableInfoDup(pTableMetaInfo1->pVgroupTables);
SSqlObj* psub2 = pParentSql->pSubs[1];
((SJoinSupporter*)psub2->param)->pVgroupTables = tscVgroupTableInfoDup(pTableMetaInfo2->pVgroupTables);
pParentSql->subState.numOfSub = 2;
memset(pParentSql->subState.states, 0, sizeof(pParentSql->subState.states[0]) * pParentSql->subState.numOfSub); memset(pParentSql->subState.states, 0, sizeof(pParentSql->subState.states[0]) * pParentSql->subState.numOfSub);
tscDebug("%p reset all sub states to 0", pParentSql); tscDebug("%p reset all sub states to 0", pParentSql);
for (int32_t m = 0; m < pParentSql->subState.numOfSub; ++m) { issueTsCompQuery(psub, psub->param, pParentSql);
SSqlObj* sub = pParentSql->pSubs[m];
issueTsCompQuery(sub, sub->param, pParentSql);
} }
} }
taosArrayDestroy(s1); size_t rsize = taosArrayGetSize(resList);
taosArrayDestroy(s2); for (int32_t i = 0; i < rsize; ++i) {
SArray** s = taosArrayGet(resList, i);
if (*s) {
taosArrayDestroy(*s);
}
}
taosArrayDestroy(resList);
} }
static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRows) { static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRows) {
@ -1124,12 +1384,8 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
tscDebug("%p all subquery retrieve ts complete, do ts block intersect", pParentSql); tscDebug("%p all subquery retrieve ts complete, do ts block intersect", pParentSql);
// proceeds to launched secondary query to retrieve final data
SJoinSupporter* p1 = pParentSql->pSubs[0]->param;
SJoinSupporter* p2 = pParentSql->pSubs[1]->param;
STimeWindow win = TSWINDOW_INITIALIZER; STimeWindow win = TSWINDOW_INITIALIZER;
int64_t num = doTSBlockIntersect(pParentSql, p1, p2, &win); int64_t num = doTSBlockIntersect(pParentSql, &win);
if (num <= 0) { // no result during ts intersect if (num <= 0) { // no result during ts intersect
tscDebug("%p no results generated in ts intersection, free all sub SqlObj and quit", pParentSql); tscDebug("%p no results generated in ts intersection, free all sub SqlObj and quit", pParentSql);
freeJoinSubqueryObj(pParentSql); freeJoinSubqueryObj(pParentSql);
@ -1639,6 +1895,8 @@ int32_t tscCreateJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter
pNewQueryInfo->limit.limit = -1; pNewQueryInfo->limit.limit = -1;
pNewQueryInfo->limit.offset = 0; pNewQueryInfo->limit.offset = 0;
pNewQueryInfo->order.orderColId = INT32_MIN;
// backup the data and clear it in the sqlcmd object // backup the data and clear it in the sqlcmd object
memset(&pNewQueryInfo->groupbyExpr, 0, sizeof(SSqlGroupbyExpr)); memset(&pNewQueryInfo->groupbyExpr, 0, sizeof(SSqlGroupbyExpr));

View File

@ -447,7 +447,7 @@ void tscFreeSqlResult(SSqlObj* pSql) {
memset(&pSql->res, 0, sizeof(SSqlRes)); memset(&pSql->res, 0, sizeof(SSqlRes));
} }
static void tscFreeSubobj(SSqlObj* pSql) { void tscFreeSubobj(SSqlObj* pSql) {
if (pSql->subState.numOfSub == 0) { if (pSql->subState.numOfSub == 0) {
return; return;
} }
@ -1279,6 +1279,34 @@ int32_t tscSqlExprCopy(SArray* dst, const SArray* src, uint64_t uid, bool deepco
return 0; return 0;
} }
bool tscColumnExists(SArray* pColumnList, SColumnIndex* pColIndex) {
// ignore the tbname columnIndex to be inserted into source list
if (pColIndex->columnIndex < 0) {
return false;
}
size_t numOfCols = taosArrayGetSize(pColumnList);
int16_t col = pColIndex->columnIndex;
int32_t i = 0;
while (i < numOfCols) {
SColumn* pCol = taosArrayGetP(pColumnList, i);
if ((pCol->colIndex.columnIndex != col) || (pCol->colIndex.tableIndex != pColIndex->tableIndex)) {
++i;
continue;
} else {
break;
}
}
if (i >= numOfCols || numOfCols == 0) {
return false;
}
return true;
}
SColumn* tscColumnListInsert(SArray* pColumnList, SColumnIndex* pColIndex) { SColumn* tscColumnListInsert(SArray* pColumnList, SColumnIndex* pColIndex) {
// ignore the tbname columnIndex to be inserted into source list // ignore the tbname columnIndex to be inserted into source list
if (pColIndex->columnIndex < 0) { if (pColIndex->columnIndex < 0) {
@ -1583,7 +1611,25 @@ int32_t tscTagCondCopy(STagCond* dest, const STagCond* src) {
dest->tbnameCond.uid = src->tbnameCond.uid; dest->tbnameCond.uid = src->tbnameCond.uid;
dest->tbnameCond.len = src->tbnameCond.len; dest->tbnameCond.len = src->tbnameCond.len;
memcpy(&dest->joinInfo, &src->joinInfo, sizeof(SJoinInfo)); dest->joinInfo.hasJoin = src->joinInfo.hasJoin;
for (int32_t i = 0; i < TSDB_MAX_JOIN_TABLE_NUM; ++i) {
if (src->joinInfo.joinTables[i]) {
dest->joinInfo.joinTables[i] = calloc(1, sizeof(SJoinNode));
memcpy(dest->joinInfo.joinTables[i], src->joinInfo.joinTables[i], sizeof(SJoinNode));
if (src->joinInfo.joinTables[i]->tsJoin) {
dest->joinInfo.joinTables[i]->tsJoin = taosArrayDup(src->joinInfo.joinTables[i]->tsJoin);
}
if (src->joinInfo.joinTables[i]->tagJoin) {
dest->joinInfo.joinTables[i]->tagJoin = taosArrayDup(src->joinInfo.joinTables[i]->tagJoin);
}
}
}
dest->relType = src->relType; dest->relType = src->relType;
if (src->pCond == NULL) { if (src->pCond == NULL) {
@ -1629,6 +1675,23 @@ void tscTagCondRelease(STagCond* pTagCond) {
taosArrayDestroy(pTagCond->pCond); taosArrayDestroy(pTagCond->pCond);
} }
for (int32_t i = 0; i < TSDB_MAX_JOIN_TABLE_NUM; ++i) {
SJoinNode *node = pTagCond->joinInfo.joinTables[i];
if (node == NULL) {
continue;
}
if (node->tsJoin != NULL) {
taosArrayDestroy(node->tsJoin);
}
if (node->tagJoin != NULL) {
taosArrayDestroy(node->tagJoin);
}
tfree(node);
}
memset(pTagCond, 0, sizeof(STagCond)); memset(pTagCond, 0, sizeof(STagCond));
} }
@ -2318,15 +2381,20 @@ void tscDoQuery(SSqlObj* pSql) {
} }
int16_t tscGetJoinTagColIdByUid(STagCond* pTagCond, uint64_t uid) { int16_t tscGetJoinTagColIdByUid(STagCond* pTagCond, uint64_t uid) {
if (pTagCond->joinInfo.left.uid == uid) { int32_t i = 0;
return pTagCond->joinInfo.left.tagColId; while (i < TSDB_MAX_JOIN_TABLE_NUM) {
} else if (pTagCond->joinInfo.right.uid == uid) { SJoinNode* node = pTagCond->joinInfo.joinTables[i];
return pTagCond->joinInfo.right.tagColId; if (node && node->uid == uid) {
} else { return node->tagColId;
}
i++;
}
assert(0); assert(0);
return -1; return -1;
} }
}
int16_t tscGetTagColIndexById(STableMeta* pTableMeta, int16_t colId) { int16_t tscGetTagColIndexById(STableMeta* pTableMeta, int16_t colId) {
int32_t numOfTags = tscGetNumOfTags(pTableMeta); int32_t numOfTags = tscGetNumOfTags(pTableMeta);

View File

@ -51,7 +51,7 @@ int32_t tsMaxShellConns = 50000;
int32_t tsMaxConnections = 5000; int32_t tsMaxConnections = 5000;
int32_t tsShellActivityTimer = 3; // second int32_t tsShellActivityTimer = 3; // second
float tsNumOfThreadsPerCore = 1.0f; float tsNumOfThreadsPerCore = 1.0f;
int32_t tsNumOfCommitThreads = 1; int32_t tsNumOfCommitThreads = 4;
float tsRatioOfQueryCores = 1.0f; float tsRatioOfQueryCores = 1.0f;
int8_t tsDaylight = 0; int8_t tsDaylight = 0;
char tsTimezone[TSDB_TIMEZONE_LEN] = {0}; char tsTimezone[TSDB_TIMEZONE_LEN] = {0};
@ -71,7 +71,7 @@ int32_t tsMaxBinaryDisplayWidth = 30;
int32_t tsCompressMsgSize = -1; int32_t tsCompressMsgSize = -1;
// client // client
int32_t tsMaxSQLStringLen = TSDB_MAX_SQL_LEN; int32_t tsMaxSQLStringLen = TSDB_MAX_ALLOWED_SQL_LEN;
int8_t tsTscEnableRecordSql = 0; int8_t tsTscEnableRecordSql = 0;
// the maximum number of results for projection query on super table that are returned from // the maximum number of results for projection query on super table that are returned from

View File

@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED)
ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME} ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME}
POST_BUILD POST_BUILD
COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.22-dist.jar ${LIBRARY_OUTPUT_PATH} COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.24-dist.jar ${LIBRARY_OUTPUT_PATH}
COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
COMMENT "build jdbc driver") COMMENT "build jdbc driver")
ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME}) ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME})

View File

@ -5,7 +5,7 @@
<groupId>com.taosdata.jdbc</groupId> <groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId> <artifactId>taos-jdbcdriver</artifactId>
<version>2.0.22</version> <version>2.0.24</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>JDBCDriver</name> <name>JDBCDriver</name>
@ -37,17 +37,6 @@
</developers> </developers>
<dependencies> <dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
@ -61,21 +50,20 @@
<artifactId>httpclient</artifactId> <artifactId>httpclient</artifactId>
<version>4.5.8</version> <version>4.5.8</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
<version>1.2.58</version> <version>1.2.58</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.taosdata.jdbc</groupId> <groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId> <artifactId>taos-jdbcdriver</artifactId>
<version>2.0.22</version> <version>2.0.24</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>JDBCDriver</name> <name>JDBCDriver</name>
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url> <url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
@ -43,7 +43,6 @@
<version>4.13</version> <version>4.13</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- for restful --> <!-- for restful -->
<dependency> <dependency>
<groupId>org.apache.httpcomponents</groupId> <groupId>org.apache.httpcomponents</groupId>
@ -55,7 +54,11 @@
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
<version>1.2.58</version> <version>1.2.58</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -30,9 +30,12 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
// do nothing // do nothing
return sql; return sql;
} }
@Override @Override
public void setAutoCommit(boolean autoCommit) throws SQLException { public void setAutoCommit(boolean autoCommit) throws SQLException {
if (isClosed()) if (isClosed())
@ -448,7 +451,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
if (isClosed) if (isClosed)
throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED); throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED);
for (Enumeration<Object> enumer = properties.keys(); enumer.hasMoreElements(); ) { for (Enumeration<Object> enumer = properties.keys(); enumer.hasMoreElements(); ) {
String name = (String) enumer.nextElement(); String name = (String) enumer.nextElement();
clientInfoProps.put(name, properties.getProperty(name)); clientInfoProps.put(name, properties.getProperty(name));

View File

@ -0,0 +1,138 @@
package com.taosdata.jdbc;
import java.sql.ParameterMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
public abstract class AbstractParameterMetaData extends WrapperImpl implements ParameterMetaData {
private final Object[] parameters;
public AbstractParameterMetaData(Object[] parameters) {
this.parameters = parameters;
}
@Override
public int getParameterCount() throws SQLException {
return parameters.length;
}
@Override
public int isNullable(int param) throws SQLException {
return ParameterMetaData.parameterNullableUnknown;
}
@Override
public boolean isSigned(int param) throws SQLException {
if (param < 1 && param >= parameters.length)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
if (parameters[param - 1] instanceof Byte)
return true;
if (parameters[param - 1] instanceof Short)
return true;
if (parameters[param - 1] instanceof Integer)
return true;
if (parameters[param - 1] instanceof Long)
return true;
if (parameters[param - 1] instanceof Float)
return true;
if (parameters[param - 1] instanceof Double)
return true;
return false;
}
@Override
public int getPrecision(int param) throws SQLException {
if (param < 1 && param >= parameters.length)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
if (parameters[param - 1] instanceof String)
return ((String) parameters[param - 1]).length();
if (parameters[param - 1] instanceof byte[])
return ((byte[]) parameters[param - 1]).length;
return 0;
}
@Override
public int getScale(int param) throws SQLException {
if (param < 1 && param >= parameters.length)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
return 0;
}
@Override
public int getParameterType(int param) throws SQLException {
if (param < 1 && param >= parameters.length)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
if (parameters[param - 1] instanceof Timestamp)
return Types.TIMESTAMP;
if (parameters[param - 1] instanceof Byte)
return Types.TINYINT;
if (parameters[param - 1] instanceof Short)
return Types.SMALLINT;
if (parameters[param - 1] instanceof Integer)
return Types.INTEGER;
if (parameters[param - 1] instanceof Long)
return Types.BIGINT;
if (parameters[param - 1] instanceof Float)
return Types.FLOAT;
if (parameters[param - 1] instanceof Double)
return Types.DOUBLE;
if (parameters[param - 1] instanceof String)
return Types.NCHAR;
if (parameters[param - 1] instanceof byte[])
return Types.BINARY;
if (parameters[param - 1] instanceof Boolean)
return Types.BOOLEAN;
return Types.OTHER;
}
@Override
public String getParameterTypeName(int param) throws SQLException {
if (param < 1 && param >= parameters.length)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
if (parameters[param - 1] instanceof Timestamp)
return TSDBConstants.jdbcType2TaosTypeName(Types.TIMESTAMP);
if (parameters[param - 1] instanceof Byte)
return TSDBConstants.jdbcType2TaosTypeName(Types.TINYINT);
if (parameters[param - 1] instanceof Short)
return TSDBConstants.jdbcType2TaosTypeName(Types.SMALLINT);
if (parameters[param - 1] instanceof Integer)
return TSDBConstants.jdbcType2TaosTypeName(Types.INTEGER);
if (parameters[param - 1] instanceof Long)
return TSDBConstants.jdbcType2TaosTypeName(Types.BIGINT);
if (parameters[param - 1] instanceof Float)
return TSDBConstants.jdbcType2TaosTypeName(Types.FLOAT);
if (parameters[param - 1] instanceof Double)
return TSDBConstants.jdbcType2TaosTypeName(Types.DOUBLE);
if (parameters[param - 1] instanceof String)
return TSDBConstants.jdbcType2TaosTypeName(Types.NCHAR);
if (parameters[param - 1] instanceof byte[])
return TSDBConstants.jdbcType2TaosTypeName(Types.BINARY);
if (parameters[param - 1] instanceof Boolean)
return TSDBConstants.jdbcType2TaosTypeName(Types.BOOLEAN);
return parameters[param - 1].getClass().getName();
}
@Override
public String getParameterClassName(int param) throws SQLException {
if (param < 1 && param >= parameters.length)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
return parameters[param - 1].getClass().getName();
}
@Override
public int getParameterMode(int param) throws SQLException {
if (param < 1 && param >= parameters.length)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
return ParameterMetaData.parameterModeUnknown;
}
}

View File

@ -11,6 +11,15 @@ import java.util.Map;
public abstract class AbstractResultSet extends WrapperImpl implements ResultSet { public abstract class AbstractResultSet extends WrapperImpl implements ResultSet {
private int fetchSize; private int fetchSize;
protected void checkAvailability(int columnIndex, int bounds) throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
if (columnIndex < 1)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " < 1");
if (columnIndex > bounds)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + bounds);
}
@Override @Override
public abstract boolean next() throws SQLException; public abstract boolean next() throws SQLException;
@ -46,38 +55,20 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet
@Override @Override
public abstract double getDouble(int columnIndex) throws SQLException; public abstract double getDouble(int columnIndex) throws SQLException;
@Deprecated
@Override @Override
public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
if (isClosed()) return getBigDecimal(columnIndex);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
@Override @Override
public byte[] getBytes(int columnIndex) throws SQLException { public abstract byte[] getBytes(int columnIndex) throws SQLException;
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
@Override @Override
public Date getDate(int columnIndex) throws SQLException { public abstract Date getDate(int columnIndex) throws SQLException;
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
@Override @Override
public Time getTime(int columnIndex) throws SQLException { public abstract Time getTime(int columnIndex) throws SQLException;
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
@Override @Override
public abstract Timestamp getTimestamp(int columnIndex) throws SQLException; public abstract Timestamp getTimestamp(int columnIndex) throws SQLException;
@ -147,9 +138,10 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet
return getDouble(findColumn(columnLabel)); return getDouble(findColumn(columnLabel));
} }
@Deprecated
@Override @Override
public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException {
return getBigDecimal(findColumn(columnLabel)); return getBigDecimal(findColumn(columnLabel), scale);
} }
@Override @Override
@ -214,12 +206,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet
public abstract ResultSetMetaData getMetaData() throws SQLException; public abstract ResultSetMetaData getMetaData() throws SQLException;
@Override @Override
public Object getObject(int columnIndex) throws SQLException { public abstract Object getObject(int columnIndex) throws SQLException;
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
@Override @Override
public Object getObject(String columnLabel) throws SQLException { public Object getObject(String columnLabel) throws SQLException {
@ -243,12 +230,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet
} }
@Override @Override
public BigDecimal getBigDecimal(int columnIndex) throws SQLException { public abstract BigDecimal getBigDecimal(int columnIndex) throws SQLException;
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
@Override @Override
public BigDecimal getBigDecimal(String columnLabel) throws SQLException { public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
@ -718,9 +700,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet
@Override @Override
public Object getObject(String columnLabel, Map<String, Class<?>> map) throws SQLException { public Object getObject(String columnLabel, Map<String, Class<?>> map) throws SQLException {
if (isClosed()) return getObject(findColumn(columnLabel), map);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
@Override @Override
@ -760,9 +740,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet
@Override @Override
public Date getDate(String columnLabel, Calendar cal) throws SQLException { public Date getDate(String columnLabel, Calendar cal) throws SQLException {
if (isClosed()) return getDate(findColumn(columnLabel), cal);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
@Override @Override
@ -774,23 +752,15 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet
@Override @Override
public Time getTime(String columnLabel, Calendar cal) throws SQLException { public Time getTime(String columnLabel, Calendar cal) throws SQLException {
if (isClosed()) return getTime(findColumn(columnLabel), cal);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
@Override @Override
public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { public abstract Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException;
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
@Override @Override
public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException {
if (isClosed()) return getTimestamp(findColumn(columnLabel), cal);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
@Override @Override
@ -1198,9 +1168,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet
@Override @Override
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException { public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
if (isClosed()) return getObject(findColumn(columnLabel), type);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
} }

View File

@ -9,6 +9,8 @@ public abstract class AbstractStatement extends WrapperImpl implements Statement
protected List<String> batchedArgs; protected List<String> batchedArgs;
private int fetchSize; private int fetchSize;
@Override @Override
public abstract ResultSet executeQuery(String sql) throws SQLException; public abstract ResultSet executeQuery(String sql) throws SQLException;

View File

@ -1,452 +0,0 @@
package com.taosdata.jdbc;
import com.taosdata.jdbc.bean.TSDBPreparedParam;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* this class is used to precompile the sql of tdengine insert or import ops
*/
public class SavedPreparedStatement {
private TSDBPreparedStatement tsdbPreparedStatement;
/**
* sql param List
*/
private List<TSDBPreparedParam> sqlParamList;
/**
* init param according the sql
*/
private TSDBPreparedParam initPreparedParam;
/**
* is table name dynamic in the prepared sql
*/
private boolean isTableNameDynamic;
/**
* insert or import sql template pattern, the template are the following:
* <p>
* insert/import into tableName [(field1, field2, ...)] [using stables tags(?, ?, ...) ] values(?, ?, ...) (?, ?, ...)
* <p>
* we split it to three part:
* 1. prefix, insert/import
* 2. middle, tableName [(field1, field2, ...)] [using stables tags(?, ?, ...) ]
* 3. valueList, the content after values, for example (?, ?, ...) (?, ?, ...)
*/
private Pattern sqlPattern = Pattern.compile("(?s)(?i)^\\s*(INSERT|IMPORT)\\s+INTO\\s+((?<tablename>\\S+)\\s*(\\(.*\\))?\\s+(USING\\s+(?<stableName>\\S+)\\s+TAGS\\s*\\((?<tagValue>.+)\\))?)\\s*VALUES\\s*(?<valueList>\\(.*\\)).*");
/**
* the raw sql template
*/
private String sql;
/**
* the prefix part of sql
*/
private String prefix;
/**
* the middle part of sql
*/
private String middle;
private int middleParamSize;
/**
* the valueList part of sql
*/
private String valueList;
private int valueListSize;
/**
* default param value
*/
private static final String DEFAULT_VALUE = "NULL";
private static final String PLACEHOLDER = "?";
private String tableName;
/**
* is the parameter add to batch list
*/
private boolean isAddBatch;
public SavedPreparedStatement(String sql, TSDBPreparedStatement tsdbPreparedStatement) throws SQLException {
this.sql = sql;
this.tsdbPreparedStatement = tsdbPreparedStatement;
this.sqlParamList = new ArrayList<>();
parsePreparedParam(this.sql);
}
/**
* parse the init param according the sql param
*
* @param sql
*/
private void parsePreparedParam(String sql) throws SQLException {
Matcher matcher = sqlPattern.matcher(sql);
if (matcher.find()) {
tableName = matcher.group("tablename");
if (tableName != null && PLACEHOLDER.equals(tableName)) {
// the table name is dynamic
this.isTableNameDynamic = true;
}
prefix = matcher.group(1);
middle = matcher.group(2);
valueList = matcher.group("valueList");
if (middle != null && !"".equals(middle)) {
middleParamSize = parsePlaceholder(middle);
}
if (valueList != null && !"".equals(valueList)) {
valueListSize = parsePlaceholder(valueList);
}
initPreparedParam = initDefaultParam(tableName, middleParamSize, valueListSize);
} else {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_SQL);
}
}
private TSDBPreparedParam initDefaultParam(String tableName, int middleParamSize, int valueListSize) {
TSDBPreparedParam tsdbPreparedParam = new TSDBPreparedParam(tableName);
tsdbPreparedParam.setMiddleParamList(getDefaultParamList(middleParamSize));
tsdbPreparedParam.setValueList(getDefaultParamList(valueListSize));
return tsdbPreparedParam;
}
/**
* generate the default param value list
*
* @param paramSize
* @return
*/
private List<Object> getDefaultParamList(int paramSize) {
List<Object> paramList = new ArrayList<>(paramSize);
if (paramSize > 0) {
for (int i = 0; i < paramSize; i++) {
paramList.add(i, DEFAULT_VALUE);
}
}
return paramList;
}
/**
* calculate the placeholder num
*
* @param value
* @return
*/
private int parsePlaceholder(String value) {
Pattern pattern = Pattern.compile("[?]");
Matcher matcher = pattern.matcher(value);
int result = 0;
while (matcher.find()) {
result++;
}
return result;
}
/**
* set current row params
*
* @param parameterIndex the first parameter is 1, the second is 2, ...
* @param x the parameter value
*/
public void setParam(int parameterIndex, Object x) throws SQLException {
int paramSize = this.middleParamSize + this.valueListSize;
String errorMsg = String.format("the parameterIndex %s out of the range [1, %s]", parameterIndex, paramSize);
if (parameterIndex < 1 || parameterIndex > paramSize) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE,errorMsg);
}
this.isAddBatch = false; //set isAddBatch to false
if (x == null) {
x = DEFAULT_VALUE; // set default null string
}
parameterIndex = parameterIndex - 1; // start from 0 in param list
if (this.middleParamSize > 0 && parameterIndex >= 0 && parameterIndex < this.middleParamSize) {
this.initPreparedParam.setMiddleParam(parameterIndex, x);
return;
}
if (this.valueListSize > 0 && parameterIndex >= this.middleParamSize && parameterIndex < paramSize) {
this.initPreparedParam.setValueParam(parameterIndex - this.middleParamSize, x);
return;
}
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE,errorMsg);
}
public void addBatch() {
addCurrentRowParamToList();
this.initPreparedParam = initDefaultParam(tableName, middleParamSize, valueListSize);
}
/**
* add current param to batch list
*/
private void addCurrentRowParamToList() {
if (initPreparedParam != null && (this.middleParamSize > 0 || this.valueListSize > 0)) {
this.sqlParamList.add(initPreparedParam); // add current param to batch list
}
this.isAddBatch = true;
}
/**
* execute the sql with batch sql
*
* @return
* @throws SQLException
*/
public int[] executeBatch() throws SQLException {
int result = executeBatchInternal();
return new int[]{result};
}
public int executeBatchInternal() throws SQLException {
if (!isAddBatch) {
addCurrentRowParamToList(); // add current param to batch list
}
//1. generate batch sql
String sql = generateExecuteSql();
//2. execute batch sql
int result = executeSql(sql);
//3. clear batch param list
this.sqlParamList.clear();
return result;
}
/**
* generate the batch sql
*
* @return
*/
private String generateExecuteSql() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(prefix);
stringBuilder.append(" into ");
if (!isTableNameDynamic) {
// tablename will not need to be replaced
String middleValue = replaceMiddleListParam(middle, sqlParamList);
stringBuilder.append(middleValue);
stringBuilder.append(" values");
stringBuilder.append(replaceValueListParam(valueList, sqlParamList));
} else {
// need to replace tablename
if (sqlParamList.size() > 0) {
TSDBPreparedParam firstPreparedParam = sqlParamList.get(0);
//replace middle part and value part of first row
String firstRow = replaceMiddleAndValuePart(firstPreparedParam);
stringBuilder.append(firstRow);
//the first param in the middleParamList is the tableName
String lastTableName = firstPreparedParam.getMiddleParamList().get(0).toString();
if (sqlParamList.size() > 1) {
for (int i = 1; i < sqlParamList.size(); i++) {
TSDBPreparedParam currentParam = sqlParamList.get(i);
String currentTableName = currentParam.getMiddleParamList().get(0).toString();
if (lastTableName.equalsIgnoreCase(currentTableName)) {
// tablename is same with the last row ,so only need to append the part of value
String values = replaceTemplateParam(valueList, currentParam.getValueList());
stringBuilder.append(values);
} else {
// tablename difference with the last row
//need to replace middle part and value part
String row = replaceMiddleAndValuePart(currentParam);
stringBuilder.append(row);
lastTableName = currentTableName;
}
}
}
} else {
stringBuilder.append(middle);
stringBuilder.append(" values");
stringBuilder.append(valueList);
}
}
return stringBuilder.toString();
}
/**
* replace the middle and value part
*
* @param tsdbPreparedParam
* @return
*/
private String replaceMiddleAndValuePart(TSDBPreparedParam tsdbPreparedParam) {
StringBuilder stringBuilder = new StringBuilder(" ");
String middlePart = replaceTemplateParam(middle, tsdbPreparedParam.getMiddleParamList());
stringBuilder.append(middlePart);
stringBuilder.append(" values ");
String valuePart = replaceTemplateParam(valueList, tsdbPreparedParam.getValueList());
stringBuilder.append(valuePart);
stringBuilder.append(" ");
return stringBuilder.toString();
}
/**
* replace the placeholder of the middle part of sql template with TSDBPreparedParam list
*
* @param template
* @param sqlParamList
* @return
*/
private String replaceMiddleListParam(String template, List<TSDBPreparedParam> sqlParamList) {
if (sqlParamList.size() > 0) {
//becase once the subTableName is static then will be ignore the tag which after the first setTag
return replaceTemplateParam(template, sqlParamList.get(0).getMiddleParamList());
}
return template;
}
/**
* replace the placeholder of the template with TSDBPreparedParam list
*
* @param template
* @param sqlParamList
* @return
*/
private String replaceValueListParam(String template, List<TSDBPreparedParam> sqlParamList) {
StringBuilder stringBuilder = new StringBuilder();
if (sqlParamList.size() > 0) {
for (TSDBPreparedParam tsdbPreparedParam : sqlParamList) {
String tmp = replaceTemplateParam(template, tsdbPreparedParam.getValueList());
stringBuilder.append(tmp);
}
} else {
stringBuilder.append(template);
}
return stringBuilder.toString();
}
/**
* replace the placeholder of the template with paramList
*
* @param template
* @param paramList
* @return
*/
private String replaceTemplateParam(String template, List<Object> paramList) {
if (paramList.size() > 0) {
String tmp = template;
for (int i = 0; i < paramList.size(); ++i) {
String paraStr = getParamString(paramList.get(i));
tmp = tmp.replaceFirst("[" + PLACEHOLDER + "]", paraStr);
}
return tmp;
} else {
return template;
}
}
/**
* get the string of param object
*
* @param paramObj
* @return
*/
private String getParamString(Object paramObj) {
String paraStr = paramObj.toString();
if (paramObj instanceof Timestamp || (paramObj instanceof String && !DEFAULT_VALUE.equalsIgnoreCase(paraStr))) {
paraStr = "'" + paraStr + "'";
}
return paraStr;
}
private int executeSql(String sql) throws SQLException {
return tsdbPreparedStatement.executeUpdate(sql);
}
}

View File

@ -27,10 +27,6 @@ public class TSDBConnection extends AbstractConnection {
return this.batchFetch; return this.batchFetch;
} }
public void setBatchFetch(Boolean batchFetch) {
this.batchFetch = batchFetch;
}
public TSDBConnection(Properties info, TSDBDatabaseMetaData meta) throws SQLException { public TSDBConnection(Properties info, TSDBDatabaseMetaData meta) throws SQLException {
this.databaseMetaData = meta; this.databaseMetaData = meta;
connect(info.getProperty(TSDBDriver.PROPERTY_KEY_HOST), connect(info.getProperty(TSDBDriver.PROPERTY_KEY_HOST),
@ -61,9 +57,7 @@ public class TSDBConnection extends AbstractConnection {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
} }
TSDBStatement statement = new TSDBStatement(this, this.connector); return new TSDBStatement(this, this.connector);
statement.setConnection(this);
return statement;
} }
public TSDBSubscribe subscribe(String topic, String sql, boolean restart) throws SQLException { public TSDBSubscribe subscribe(String topic, String sql, boolean restart) throws SQLException {
@ -79,10 +73,8 @@ public class TSDBConnection extends AbstractConnection {
} }
public PreparedStatement prepareStatement(String sql) throws SQLException { public PreparedStatement prepareStatement(String sql) throws SQLException {
if (isClosed()) { if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
}
return new TSDBPreparedStatement(this, this.connector, sql); return new TSDBPreparedStatement(this, this.connector, sql);
} }
@ -104,11 +96,4 @@ public class TSDBConnection extends AbstractConnection {
return this.databaseMetaData; return this.databaseMetaData;
} }
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
if (isClosed()) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
}
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
} }

View File

@ -0,0 +1,8 @@
package com.taosdata.jdbc;
public class TSDBParameterMetaData extends AbstractParameterMetaData {
public TSDBParameterMetaData(Object[] parameters) {
super(parameters);
}
}

View File

@ -18,6 +18,7 @@ import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.net.URL; import java.net.URL;
import java.nio.charset.Charset;
import java.sql.*; import java.sql.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
@ -30,36 +31,49 @@ import java.util.regex.Pattern;
* compatibility needs. * compatibility needs.
*/ */
public class TSDBPreparedStatement extends TSDBStatement implements PreparedStatement { public class TSDBPreparedStatement extends TSDBStatement implements PreparedStatement {
protected String rawSql;
protected String sql; private String rawSql;
protected ArrayList<Object> parameters = new ArrayList<>(); private String sql;
// private ArrayList<Object> parameters = new ArrayList<>();
private Object[] parameters;
private boolean isPrepared;
//start with insert or import and is case-insensitive //start with insert or import and is case-insensitive
private static Pattern savePattern = Pattern.compile("(?i)^\\s*(insert|import)"); private static Pattern savePattern = Pattern.compile("(?i)^\\s*(insert|import)");
// is insert or import // is insert or import
private boolean isSaved; private boolean isSaved;
private SavedPreparedStatement savedPreparedStatement; // private SavedPreparedStatement savedPreparedStatement;
private ParameterMetaData parameterMetaData; private volatile TSDBParameterMetaData parameterMetaData;
TSDBPreparedStatement(TSDBConnection connection, TSDBJNIConnector connecter, String sql) { TSDBPreparedStatement(TSDBConnection connection, TSDBJNIConnector connecter, String sql) {
super(connection, connecter); super(connection, connecter);
init(sql); init(sql);
if (sql.contains("?")) {
int parameterCnt = 0;
for (int i = 0; i < sql.length(); i++) {
if ('?' == sql.charAt(i)) {
parameterCnt++;
}
}
parameters = new Object[parameterCnt];
this.isPrepared = true;
}
} }
private void init(String sql) { private void init(String sql) {
this.rawSql = sql; this.rawSql = sql;
preprocessSql(); preprocessSql();
// this.isSaved = isSavedSql(this.rawSql);
// if (this.isSaved) {
// try {
// this.savedPreparedStatement = new SavedPreparedStatement(this.rawSql, this);
// } catch (SQLException e) {
// e.printStackTrace();
// }
// }
this.isSaved = isSavedSql(this.rawSql);
if (this.isSaved) {
try {
this.savedPreparedStatement = new SavedPreparedStatement(this.rawSql, this);
} catch (SQLException e) {
e.printStackTrace();
}
}
} }
/** /**
@ -75,19 +89,11 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
@Override @Override
public int[] executeBatch() throws SQLException { public int[] executeBatch() throws SQLException {
if (isSaved) { // if (isSaved) {
return this.savedPreparedStatement.executeBatch(); // return this.savedPreparedStatement.executeBatch();
} else { // } else {
return super.executeBatch(); return super.executeBatch();
} // }
}
public ArrayList<Object> getParameters() {
return parameters;
}
public void setParameters(ArrayList<Object> parameters) {
this.parameters = parameters;
} }
/* /*
@ -151,41 +157,73 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
* *
* @return a string of the native sql statement for TSDB * @return a string of the native sql statement for TSDB
*/ */
private String getNativeSql() { // private String getNativeSql(String rawSql) {
this.sql = this.rawSql; // for (int i = 0; i < parameters.length; i++) {
for (int i = 0; i < parameters.size(); ++i) { // Object para = parameters[i];
Object para = parameters.get(i); // if (para != null) {
// String paraStr = para.toString();
// if (para instanceof Timestamp || para instanceof String) {
// paraStr = "'" + paraStr + "'";
// }
// this.sql = this.sql.replaceFirst("[?]", paraStr);
// } else {
// this.sql = this.sql.replaceFirst("[?]", "NULL");
// }
// }
// parameters = new Object[parameters.length];
// return sql;
// }
private String getNativeSql(String rawSql) throws SQLException {
String sql = rawSql;
for (int i = 0; i < parameters.length; ++i) {
Object para = parameters[i];
if (para != null) { if (para != null) {
String paraStr = para.toString(); String paraStr;
if (para instanceof Timestamp || para instanceof String) { if (para instanceof byte[]) {
paraStr = new String((byte[]) para, Charset.forName("UTF-8"));
} else {
paraStr = para.toString();
}
// if para is timestamp or String or byte[] need to translate ' character
if (para instanceof Timestamp || para instanceof String || para instanceof byte[]) {
paraStr = paraStr.replaceAll("'", "\\\\\\\\'");
paraStr = "'" + paraStr + "'"; paraStr = "'" + paraStr + "'";
} }
this.sql = this.sql.replaceFirst("[?]", paraStr); sql = sql.replaceFirst("[?]", paraStr);
} else { } else {
this.sql = this.sql.replaceFirst("[?]", "NULL"); sql = sql.replaceFirst("[?]", "NULL");
} }
} }
parameters.clear(); clearParameters();
return sql; return sql;
} }
@Override @Override
public ResultSet executeQuery() throws SQLException { public ResultSet executeQuery() throws SQLException {
if (isSaved) { // if (isSaved) {
this.savedPreparedStatement.executeBatchInternal(); // this.savedPreparedStatement.executeBatchInternal();
return null; // return null;
} else { // } else {
return super.executeQuery(getNativeSql());
} if (!isPrepared)
return executeQuery(this.rawSql);
final String sql = getNativeSql(this.rawSql);
return executeQuery(sql);
// }
} }
@Override @Override
public int executeUpdate() throws SQLException { public int executeUpdate() throws SQLException {
if (isSaved) { // if (isSaved) {
return this.savedPreparedStatement.executeBatchInternal(); // return this.savedPreparedStatement.executeBatchInternal();
} else { // } else {
return super.executeUpdate(getNativeSql()); if (!isPrepared)
} return executeUpdate(this.rawSql);
String sql = getNativeSql(this.rawSql);
return executeUpdate(sql);
// }
} }
private boolean isSupportedSQLType(int sqlType) { private boolean isSupportedSQLType(int sqlType) {
@ -201,35 +239,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
case Types.BINARY: case Types.BINARY:
case Types.NCHAR: case Types.NCHAR:
return true; return true;
case Types.ARRAY:
case Types.BIT:
case Types.BLOB:
case Types.CHAR:
case Types.CLOB:
case Types.DATALINK:
case Types.DATE:
case Types.DECIMAL:
case Types.DISTINCT:
case Types.JAVA_OBJECT:
case Types.LONGNVARCHAR:
case Types.LONGVARBINARY:
case Types.LONGVARCHAR:
case Types.NCLOB:
case Types.NULL:
case Types.NUMERIC:
case Types.NVARCHAR:
case Types.OTHER:
case Types.REAL:
case Types.REF:
case Types.REF_CURSOR:
case Types.ROWID:
case Types.SQLXML:
case Types.STRUCT:
case Types.TIME:
case Types.TIME_WITH_TIMEZONE:
case Types.TIMESTAMP_WITH_TIMEZONE:
case Types.VARBINARY:
case Types.VARCHAR:
default: default:
return false; return false;
} }
@ -259,7 +268,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
public void setByte(int parameterIndex, byte x) throws SQLException { public void setByte(int parameterIndex, byte x) throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); setObject(parameterIndex,x);
} }
@Override @Override
@ -315,7 +324,8 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
public void setBytes(int parameterIndex, byte[] x) throws SQLException { public void setBytes(int parameterIndex, byte[] x) throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
setObject(parameterIndex,x);
} }
@Override @Override
@ -365,45 +375,63 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
public void clearParameters() throws SQLException { public void clearParameters() throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
parameters.clear();
// parameters.clear();
parameters = new Object[parameters.length];
} }
@Override @Override
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
@Override @Override
public void setObject(int parameterIndex, Object x) throws SQLException { public void setObject(int parameterIndex, Object x) throws SQLException {
if (isSaved) { // if (isSaved) {
this.savedPreparedStatement.setParam(parameterIndex, x); // this.savedPreparedStatement.setParam(parameterIndex, x);
} else { // } else {
parameters.add(x); if (parameterIndex < 1 && parameterIndex >= parameters.length)
} throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
parameters[parameterIndex - 1] = x;
// parameters.add(x);
// }
} }
@Override @Override
public boolean execute() throws SQLException { public boolean execute() throws SQLException {
if (isSaved) { // if (isSaved) {
int result = this.savedPreparedStatement.executeBatchInternal(); // int result = this.savedPreparedStatement.executeBatchInternal();
return result > 0; // return result > 0;
} else { // } else {
return super.execute(getNativeSql()); if (!isPrepared)
} return execute(this.rawSql);
final String sql = getNativeSql(this.rawSql);
return execute(sql);
// }
} }
@Override @Override
public void addBatch() throws SQLException { public void addBatch() throws SQLException {
if (isSaved) { // if (isSaved) {
this.savedPreparedStatement.addBatch(); // this.savedPreparedStatement.addBatch();
} else { // } else {
if (this.batchedArgs == null) { if (this.batchedArgs == null) {
batchedArgs = new ArrayList<>(); batchedArgs = new ArrayList<>();
} }
super.addBatch(getNativeSql());
if (!isPrepared) {
addBatch(this.rawSql);
} else {
String sql = this.getConnection().nativeSQL(this.rawSql);
addBatch(sql);
} }
// }
} }
@Override @Override
@ -491,9 +519,11 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
public ParameterMetaData getParameterMetaData() throws SQLException { public ParameterMetaData getParameterMetaData() throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
//TODO: parameterMetaData not supported
// return null; if (parameterMetaData == null) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); this.parameterMetaData = new TSDBParameterMetaData(parameters);
}
return this.parameterMetaData;
} }
@Override @Override

View File

@ -14,9 +14,14 @@
*****************************************************************************/ *****************************************************************************/
package com.taosdata.jdbc; package com.taosdata.jdbc;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.*; import java.sql.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.List; import java.util.List;
public class TSDBResultSet extends AbstractResultSet implements ResultSet { public class TSDBResultSet extends AbstractResultSet implements ResultSet {
@ -120,158 +125,189 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
} }
public String getString(int columnIndex) throws SQLException { public String getString(int columnIndex) throws SQLException {
checkAvailability(columnIndex, this.columnMetaDataList.size());
String res = null; String res = null;
int colIndex = getTrueColumnIndex(columnIndex);
if (this.getBatchFetch()) if (this.getBatchFetch())
return this.blockData.getString(colIndex); return this.blockData.getString(columnIndex - 1);
this.lastWasNull = this.rowData.wasNull(colIndex); this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
if (!lastWasNull) { if (!lastWasNull) {
res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType()); res = this.rowData.getString(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType());
} }
return res; return res;
} }
public boolean getBoolean(int columnIndex) throws SQLException { public boolean getBoolean(int columnIndex) throws SQLException {
checkAvailability(columnIndex, this.columnMetaDataList.size());
boolean res = false; boolean res = false;
int colIndex = getTrueColumnIndex(columnIndex);
if (this.getBatchFetch()) if (this.getBatchFetch())
return this.blockData.getBoolean(colIndex); return this.blockData.getBoolean(columnIndex - 1);
this.lastWasNull = this.rowData.wasNull(colIndex); this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
if (!lastWasNull) { if (!lastWasNull) {
res = this.rowData.getBoolean(colIndex, this.columnMetaDataList.get(colIndex).getColType()); res = this.rowData.getBoolean(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType());
} }
return res; return res;
} }
public byte getByte(int columnIndex) throws SQLException { public byte getByte(int columnIndex) throws SQLException {
checkAvailability(columnIndex, this.columnMetaDataList.size());
byte res = 0; byte res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
if (this.getBatchFetch()) if (this.getBatchFetch())
return (byte) this.blockData.getInt(colIndex); return (byte) this.blockData.getInt(columnIndex - 1);
this.lastWasNull = this.rowData.wasNull(colIndex); this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
if (!lastWasNull) { if (!lastWasNull) {
res = (byte) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); res = (byte) this.rowData.getInt(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType());
} }
return res; return res;
} }
public short getShort(int columnIndex) throws SQLException { public short getShort(int columnIndex) throws SQLException {
checkAvailability(columnIndex, this.columnMetaDataList.size());
short res = 0; short res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
if (this.getBatchFetch()) if (this.getBatchFetch())
return (short) this.blockData.getInt(colIndex); return (short) this.blockData.getInt(columnIndex - 1);
this.lastWasNull = this.rowData.wasNull(colIndex); this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
if (!lastWasNull) { if (!lastWasNull) {
res = (short) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); res = (short) this.rowData.getInt(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType());
} }
return res; return res;
} }
public int getInt(int columnIndex) throws SQLException { public int getInt(int columnIndex) throws SQLException {
checkAvailability(columnIndex, this.columnMetaDataList.size());
int res = 0; int res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
if (this.getBatchFetch()) if (this.getBatchFetch())
return this.blockData.getInt(colIndex); return this.blockData.getInt(columnIndex - 1);
this.lastWasNull = this.rowData.wasNull(colIndex); this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
if (!lastWasNull) { if (!lastWasNull) {
res = this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); res = this.rowData.getInt(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType());
} }
return res; return res;
} }
public long getLong(int columnIndex) throws SQLException { public long getLong(int columnIndex) throws SQLException {
checkAvailability(columnIndex, this.columnMetaDataList.size());
long res = 0L; long res = 0L;
int colIndex = getTrueColumnIndex(columnIndex);
if (this.getBatchFetch()) if (this.getBatchFetch())
return this.blockData.getLong(colIndex); return this.blockData.getLong(columnIndex - 1);
this.lastWasNull = this.rowData.wasNull(colIndex); this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
if (!lastWasNull) { if (!lastWasNull) {
res = this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType()); res = this.rowData.getLong(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType());
} }
return res; return res;
} }
public float getFloat(int columnIndex) throws SQLException { public float getFloat(int columnIndex) throws SQLException {
checkAvailability(columnIndex, this.columnMetaDataList.size());
float res = 0; float res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
if (this.getBatchFetch()) if (this.getBatchFetch())
return (float) this.blockData.getDouble(colIndex); return (float) this.blockData.getDouble(columnIndex - 1);
this.lastWasNull = this.rowData.wasNull(colIndex); this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
if (!lastWasNull) if (!lastWasNull)
res = this.rowData.getFloat(colIndex, this.columnMetaDataList.get(colIndex).getColType()); res = this.rowData.getFloat(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType());
return res; return res;
} }
public double getDouble(int columnIndex) throws SQLException { public double getDouble(int columnIndex) throws SQLException {
checkAvailability(columnIndex, this.columnMetaDataList.size());
double res = 0; double res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
if (this.getBatchFetch()) if (this.getBatchFetch())
return this.blockData.getDouble(colIndex); return this.blockData.getDouble(columnIndex - 1);
this.lastWasNull = this.rowData.wasNull(colIndex); this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
if (!lastWasNull) { if (!lastWasNull) {
res = this.rowData.getDouble(colIndex, this.columnMetaDataList.get(colIndex).getColType()); res = this.rowData.getDouble(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType());
} }
return res; return res;
} }
@Deprecated public byte[] getBytes(int columnIndex) throws SQLException {
public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { checkAvailability(columnIndex, this.columnMetaDataList.size());
return new BigDecimal(getLong(columnIndex));
Object value = this.rowData.get(columnIndex - 1);
if (value == null)
return null;
int colType = this.columnMetaDataList.get(columnIndex - 1).getColType();
switch (colType) {
case TSDBConstants.TSDB_DATA_TYPE_BIGINT:
return Longs.toByteArray((Long) value);
case TSDBConstants.TSDB_DATA_TYPE_INT:
return Ints.toByteArray((int) value);
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:
return Shorts.toByteArray((Short) value);
case TSDBConstants.TSDB_DATA_TYPE_TINYINT:
return new byte[]{(byte) value};
}
return value.toString().getBytes();
} }
public byte[] getBytes(int columnIndex) throws SQLException { @Override
return getString(columnIndex).getBytes(); public Date getDate(int columnIndex) throws SQLException {
Timestamp timestamp = getTimestamp(columnIndex);
return timestamp == null ? null : new Date(timestamp.getTime());
}
@Override
public Time getTime(int columnIndex) throws SQLException {
Timestamp timestamp = getTimestamp(columnIndex);
return timestamp == null ? null : new Time(timestamp.getTime());
} }
public Timestamp getTimestamp(int columnIndex) throws SQLException { public Timestamp getTimestamp(int columnIndex) throws SQLException {
checkAvailability(columnIndex, this.columnMetaDataList.size());
Timestamp res = null; Timestamp res = null;
int colIndex = getTrueColumnIndex(columnIndex);
if (this.getBatchFetch()) if (this.getBatchFetch())
return this.blockData.getTimestamp(columnIndex); return this.blockData.getTimestamp(columnIndex - 1);
this.lastWasNull = this.rowData.wasNull(colIndex); this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
if (!lastWasNull) { if (!lastWasNull) {
res = this.rowData.getTimestamp(colIndex); res = this.rowData.getTimestamp(columnIndex - 1);
} }
return res; return res;
} }
public ResultSetMetaData getMetaData() throws SQLException { public ResultSetMetaData getMetaData() throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
return new TSDBResultSetMetaData(this.columnMetaDataList); return new TSDBResultSetMetaData(this.columnMetaDataList);
} }
@Override @Override
public Object getObject(int columnIndex) throws SQLException { public Object getObject(int columnIndex) throws SQLException {
int colIndex = getTrueColumnIndex(columnIndex); checkAvailability(columnIndex, this.columnMetaDataList.size());
Object res = null;
if (this.getBatchFetch()) if (this.getBatchFetch())
return this.blockData.get(colIndex); return this.blockData.get(columnIndex - 1);
this.lastWasNull = this.rowData.wasNull(colIndex); this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
return this.rowData.get(colIndex); if (!lastWasNull) {
int colType = this.columnMetaDataList.get(columnIndex - 1).getColType();
if (colType == TSDBConstants.TSDB_DATA_TYPE_BINARY)
res = ((String) this.rowData.get(columnIndex - 1)).getBytes();
else
res = this.rowData.get(columnIndex - 1);
} }
return res;
@Override
public Object getObject(String columnLabel) throws SQLException {
return this.getObject(this.findColumn(columnLabel));
} }
public int findColumn(String columnLabel) throws SQLException { public int findColumn(String columnLabel) throws SQLException {
@ -285,15 +321,32 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
@Override @Override
public BigDecimal getBigDecimal(int columnIndex) throws SQLException { public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
int colIndex = getTrueColumnIndex(columnIndex); if (this.getBatchFetch())
return new BigDecimal(this.blockData.getLong(columnIndex - 1));
if (!this.getBatchFetch()) { this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
this.lastWasNull = this.rowData.wasNull(colIndex); BigDecimal res = null;
return new BigDecimal(this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType())); if (!lastWasNull) {
} else { int colType = this.columnMetaDataList.get(columnIndex - 1).getColType();
return new BigDecimal(this.blockData.getLong(colIndex)); switch (colType) {
case TSDBConstants.TSDB_DATA_TYPE_TINYINT:
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:
case TSDBConstants.TSDB_DATA_TYPE_INT:
case TSDBConstants.TSDB_DATA_TYPE_BIGINT:
res = new BigDecimal(Long.valueOf(this.rowData.get(columnIndex - 1).toString()));
break;
case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
res = new BigDecimal(Double.valueOf(this.rowData.get(columnIndex - 1).toString()));
break;
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
return new BigDecimal(((Timestamp) this.rowData.get(columnIndex - 1)).getTime());
default:
res = new BigDecimal(this.rowData.get(columnIndex - 1).toString());
} }
} }
return res;
}
@Override @Override
public boolean isBeforeFirst() throws SQLException { public boolean isBeforeFirst() throws SQLException {
@ -398,6 +451,12 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
return this.statement; return this.statement;
} }
@Override
public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
//TODOdid not use the specified timezone in cal
return getTimestamp(columnIndex);
}
public boolean isClosed() throws SQLException { public boolean isClosed() throws SQLException {
if (isClosed) if (isClosed)
return true; return true;
@ -408,17 +467,7 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
} }
public String getNString(int columnIndex) throws SQLException { public String getNString(int columnIndex) throws SQLException {
int colIndex = getTrueColumnIndex(columnIndex); return getString(columnIndex);
return (String) rowData.get(colIndex);
} }
private int getTrueColumnIndex(int columnIndex) throws SQLException {
if (columnIndex < 1)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "columnIndex(" + columnIndex + "): < 1");
int numOfCols = this.columnMetaDataList.size();
if (columnIndex > numOfCols)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "columnIndex: " + columnIndex);
return columnIndex - 1;
}
} }

View File

@ -22,7 +22,7 @@ import java.util.List;
public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaData { public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaData {
List<ColumnMetaData> colMetaDataList = null; List<ColumnMetaData> colMetaDataList;
public TSDBResultSetMetaData(List<ColumnMetaData> metaDataList) { public TSDBResultSetMetaData(List<ColumnMetaData> metaDataList) {
this.colMetaDataList = metaDataList; this.colMetaDataList = metaDataList;
@ -52,6 +52,9 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD
} }
public int isNullable(int column) throws SQLException { public int isNullable(int column) throws SQLException {
if (column < 1 && column >= colMetaDataList.size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
if (column == 1) { if (column == 1) {
return columnNoNulls; return columnNoNulls;
} }
@ -59,6 +62,9 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD
} }
public boolean isSigned(int column) throws SQLException { public boolean isSigned(int column) throws SQLException {
if (column < 1 && column >= colMetaDataList.size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
ColumnMetaData meta = this.colMetaDataList.get(column - 1); ColumnMetaData meta = this.colMetaDataList.get(column - 1);
switch (meta.getColType()) { switch (meta.getColType()) {
case TSDBConstants.TSDB_DATA_TYPE_TINYINT: case TSDBConstants.TSDB_DATA_TYPE_TINYINT:
@ -74,22 +80,37 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD
} }
public int getColumnDisplaySize(int column) throws SQLException { public int getColumnDisplaySize(int column) throws SQLException {
if (column < 1 && column >= colMetaDataList.size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
return colMetaDataList.get(column - 1).getColSize(); return colMetaDataList.get(column - 1).getColSize();
} }
public String getColumnLabel(int column) throws SQLException { public String getColumnLabel(int column) throws SQLException {
if (column < 1 && column >= colMetaDataList.size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
return colMetaDataList.get(column - 1).getColName(); return colMetaDataList.get(column - 1).getColName();
} }
public String getColumnName(int column) throws SQLException { public String getColumnName(int column) throws SQLException {
if (column < 1 && column >= colMetaDataList.size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
return colMetaDataList.get(column - 1).getColName(); return colMetaDataList.get(column - 1).getColName();
} }
public String getSchemaName(int column) throws SQLException { public String getSchemaName(int column) throws SQLException {
if (column < 1 && column >= colMetaDataList.size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
} }
public int getPrecision(int column) throws SQLException { public int getPrecision(int column) throws SQLException {
if (column < 1 && column >= colMetaDataList.size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
ColumnMetaData columnMetaData = this.colMetaDataList.get(column - 1); ColumnMetaData columnMetaData = this.colMetaDataList.get(column - 1);
switch (columnMetaData.getColType()) { switch (columnMetaData.getColType()) {
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
@ -105,6 +126,9 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD
} }
public int getScale(int column) throws SQLException { public int getScale(int column) throws SQLException {
if (column < 1 && column >= colMetaDataList.size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
ColumnMetaData meta = this.colMetaDataList.get(column - 1); ColumnMetaData meta = this.colMetaDataList.get(column - 1);
switch (meta.getColType()) { switch (meta.getColType()) {
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: case TSDBConstants.TSDB_DATA_TYPE_FLOAT:

View File

@ -21,18 +21,13 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
public class TSDBResultSetRowData { public class TSDBResultSetRowData {
private ArrayList<Object> data = null; private ArrayList<Object> data;
private int colSize = 0; private int colSize = 0;
public TSDBResultSetRowData(int colSize) { public TSDBResultSetRowData(int colSize) {
this.setColSize(colSize); this.setColSize(colSize);
} }
public TSDBResultSetRowData() {
this.data = new ArrayList<>();
this.setColSize(0);
}
public void clear() { public void clear() {
if (this.data != null) { if (this.data != null) {
this.data.clear(); this.data.clear();
@ -71,9 +66,9 @@ public class TSDBResultSetRowData {
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: case TSDBConstants.TSDB_DATA_TYPE_BIGINT:
return ((Long) obj) == 1L ? Boolean.TRUE : Boolean.FALSE; return ((Long) obj) == 1L ? Boolean.TRUE : Boolean.FALSE;
default:
return false;
} }
return Boolean.TRUE;
} }
public void setByte(int col, byte value) { public void setByte(int col, byte value) {
@ -198,7 +193,7 @@ public class TSDBResultSetRowData {
data.set(col, value); data.set(col, value);
} }
public float getFloat(int col, int srcType) throws SQLException { public float getFloat(int col, int srcType) {
Object obj = data.get(col); Object obj = data.get(col);
switch (srcType) { switch (srcType) {
@ -226,7 +221,7 @@ public class TSDBResultSetRowData {
data.set(col, value); data.set(col, value);
} }
public double getDouble(int col, int srcType) throws SQLException { public double getDouble(int col, int srcType) {
Object obj = data.get(col); Object obj = data.get(col);
switch (srcType) { switch (srcType) {
@ -267,9 +262,8 @@ public class TSDBResultSetRowData {
* *
* @param col column index * @param col column index
* @return * @return
* @throws SQLException
*/ */
public String getString(int col, int srcType) throws SQLException { public String getString(int col, int srcType) {
switch (srcType) { switch (srcType) {
case TSDBConstants.TSDB_DATA_TYPE_BINARY: case TSDBConstants.TSDB_DATA_TYPE_BINARY:
case TSDBConstants.TSDB_DATA_TYPE_NCHAR: case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
@ -305,11 +299,11 @@ public class TSDBResultSetRowData {
} }
public void setTimestamp(int col, long ts) { public void setTimestamp(int col, long ts) {
data.set(col, ts); data.set(col, new Timestamp(ts));
} }
public Timestamp getTimestamp(int col) { public Timestamp getTimestamp(int col) {
return new Timestamp((Long) data.get(col)); return (Timestamp) data.get(col);
} }
public Object get(int col) { public Object get(int col) {
@ -320,7 +314,7 @@ public class TSDBResultSetRowData {
return colSize; return colSize;
} }
public void setColSize(int colSize) { private void setColSize(int colSize) {
this.colSize = colSize; this.colSize = colSize;
this.clear(); this.clear();
} }

View File

@ -1,62 +0,0 @@
package com.taosdata.jdbc.bean;
import java.util.List;
/**
* tdengine batch insert or import param object
*/
public class TSDBPreparedParam {
/**
* tableName, if sTable Name is not null, and this is sub table name.
*/
private String tableName;
/**
* sub middle param list
*/
private List<Object> middleParamList;
/**
* value list
*/
private List<Object> valueList;
public TSDBPreparedParam(String tableName) {
this.tableName = tableName;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public List<Object> getMiddleParamList() {
return middleParamList;
}
public void setMiddleParamList(List<Object> middleParamList) {
this.middleParamList = middleParamList;
}
public void setMiddleParam(int parameterIndex, Object x) {
this.middleParamList.set(parameterIndex, x);
}
public List<Object> getValueList() {
return valueList;
}
public void setValueList(List<Object> valueList) {
this.valueList = valueList;
}
public void setValueParam(int parameterIndex, Object x) {
this.valueList.set(parameterIndex, x);
}
}

View File

@ -1,8 +1,14 @@
package com.taosdata.jdbc.rs; package com.taosdata.jdbc.rs;
import com.taosdata.jdbc.*; import com.taosdata.jdbc.AbstractConnection;
import com.taosdata.jdbc.TSDBDriver;
import com.taosdata.jdbc.TSDBError;
import com.taosdata.jdbc.TSDBErrorNumbers;
import java.sql.*; import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties; import java.util.Properties;
public class RestfulConnection extends AbstractConnection { public class RestfulConnection extends AbstractConnection {
@ -55,7 +61,6 @@ public class RestfulConnection extends AbstractConnection {
public DatabaseMetaData getMetaData() throws SQLException { public DatabaseMetaData getMetaData() throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
;
return this.metadata; return this.metadata;
} }

View File

@ -17,7 +17,7 @@ public class RestfulDriver extends AbstractDriver {
static { static {
try { try {
DriverManager.registerDriver(new RestfulDriver()); java.sql.DriverManager.registerDriver(new RestfulDriver());
} catch (SQLException e) { } catch (SQLException e) {
throw TSDBError.createRuntimeException(TSDBErrorNumbers.ERROR_URL_NOT_SET, e); throw TSDBError.createRuntimeException(TSDBErrorNumbers.ERROR_URL_NOT_SET, e);
} }

View File

@ -0,0 +1,10 @@
package com.taosdata.jdbc.rs;
import com.taosdata.jdbc.AbstractParameterMetaData;
public class RestfulParameterMetaData extends AbstractParameterMetaData {
RestfulParameterMetaData(Object[] parameters) {
super(parameters);
}
}

View File

@ -7,6 +7,7 @@ import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.net.URL; import java.net.URL;
import java.nio.charset.Charset;
import java.sql.*; import java.sql.*;
import java.util.Calendar; import java.util.Calendar;
@ -30,7 +31,9 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar
parameters = new Object[parameterCnt]; parameters = new Object[parameterCnt];
this.isPrepared = true; this.isPrepared = true;
} }
//TODO: build parameterMetaData
// build parameterMetaData
this.parameterMetaData = new RestfulParameterMetaData(parameters);
} }
@Override @Override
@ -60,8 +63,15 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar
for (int i = 0; i < parameters.length; ++i) { for (int i = 0; i < parameters.length; ++i) {
Object para = parameters[i]; Object para = parameters[i];
if (para != null) { if (para != null) {
String paraStr = para.toString(); String paraStr;
if (para instanceof Timestamp || para instanceof String) { if (para instanceof byte[]) {
paraStr = new String((byte[]) para, Charset.forName("UTF-8"));
} else {
paraStr = para.toString();
}
// if para is timestamp or String or byte[] need to translate ' character
if (para instanceof Timestamp || para instanceof String || para instanceof byte[]) {
paraStr = paraStr.replaceAll("'", "\\\\\\\\'");
paraStr = "'" + paraStr + "'"; paraStr = "'" + paraStr + "'";
} }
sql = sql.replaceFirst("[?]", paraStr); sql = sql.replaceFirst("[?]", paraStr);
@ -92,7 +102,7 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar
public void setByte(int parameterIndex, byte x) throws SQLException { public void setByte(int parameterIndex, byte x) throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); setObject(parameterIndex, x);
} }
@Override @Override
@ -153,7 +163,7 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar
public void setBytes(int parameterIndex, byte[] x) throws SQLException { public void setBytes(int parameterIndex, byte[] x) throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); setObject(parameterIndex, x);
} }
@Override @Override
@ -210,19 +220,16 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
setObject(parameterIndex,x);
} }
@Override @Override
public void setObject(int parameterIndex, Object x) throws SQLException { public void setObject(int parameterIndex, Object x) throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
if (parameterIndex < 1 && parameterIndex >= parameters.length) if (parameterIndex < 1 && parameterIndex >= parameters.length)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
parameters[parameterIndex - 1] = x; parameters[parameterIndex - 1] = x;
} }
@Override @Override

View File

@ -2,13 +2,18 @@ package com.taosdata.jdbc.rs;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import com.taosdata.jdbc.AbstractResultSet; import com.taosdata.jdbc.AbstractResultSet;
import com.taosdata.jdbc.TSDBConstants; import com.taosdata.jdbc.TSDBConstants;
import com.taosdata.jdbc.TSDBError; import com.taosdata.jdbc.TSDBError;
import com.taosdata.jdbc.TSDBErrorNumbers; import com.taosdata.jdbc.TSDBErrorNumbers;
import java.math.BigDecimal;
import java.sql.*; import java.sql.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
public class RestfulResultSet extends AbstractResultSet implements ResultSet { public class RestfulResultSet extends AbstractResultSet implements ResultSet {
private volatile boolean isClosed; private volatile boolean isClosed;
@ -16,7 +21,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
private final String database; private final String database;
private final Statement statement; private final Statement statement;
// private final JSONObject resultJson;
// data // data
private final ArrayList<ArrayList<Object>> resultSet; private final ArrayList<ArrayList<Object>> resultSet;
// meta // meta
@ -32,7 +36,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
public RestfulResultSet(String database, Statement statement, JSONObject resultJson) throws SQLException { public RestfulResultSet(String database, Statement statement, JSONObject resultJson) throws SQLException {
this.database = database; this.database = database;
this.statement = statement; this.statement = statement;
// this.resultJson = resultJson;
// column metadata // column metadata
JSONArray columnMeta = resultJson.getJSONArray("column_meta"); JSONArray columnMeta = resultJson.getJSONArray("column_meta");
@ -73,7 +76,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
case TSDBConstants.TSDB_DATA_TYPE_INT: case TSDBConstants.TSDB_DATA_TYPE_INT:
return row.getInteger(colIndex); return row.getInteger(colIndex);
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: case TSDBConstants.TSDB_DATA_TYPE_BIGINT:
return row.getBigInteger(colIndex); return row.getLong(colIndex);
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
return row.getFloat(colIndex); return row.getFloat(colIndex);
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
@ -81,9 +84,11 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
return new Timestamp(row.getDate(colIndex).getTime()); return new Timestamp(row.getDate(colIndex).getTime());
case TSDBConstants.TSDB_DATA_TYPE_BINARY: case TSDBConstants.TSDB_DATA_TYPE_BINARY:
return row.getString(colIndex).getBytes();
case TSDBConstants.TSDB_DATA_TYPE_NCHAR: case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
default:
return row.getString(colIndex); return row.getString(colIndex);
default:
return row.get(colIndex);
} }
} }
@ -130,37 +135,33 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
@Override @Override
public String getString(int columnIndex) throws SQLException { public String getString(int columnIndex) throws SQLException {
if (isClosed()) checkAvailability(columnIndex, resultSet.get(pos).size());
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
if (columnIndex > resultSet.get(pos).size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size());
columnIndex = getTrueColumnIndex(columnIndex); Object value = resultSet.get(pos).get(columnIndex - 1);
Object value = resultSet.get(pos).get(columnIndex); if (value == null)
return value == null ? null : value.toString(); return null;
if (value instanceof byte[])
return new String((byte[]) value);
return value.toString();
} }
@Override @Override
public boolean getBoolean(int columnIndex) throws SQLException { public boolean getBoolean(int columnIndex) throws SQLException {
if (isClosed()) checkAvailability(columnIndex, resultSet.get(pos).size());
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
if (columnIndex > resultSet.get(pos).size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size());
columnIndex = getTrueColumnIndex(columnIndex); Object value = resultSet.get(pos).get(columnIndex - 1);
int result = getInt(columnIndex); if (value == null)
return result == 0 ? false : true; return false;
if (value instanceof Boolean)
return (boolean) value;
return Boolean.valueOf(value.toString());
} }
@Override @Override
public byte getByte(int columnIndex) throws SQLException { public byte getByte(int columnIndex) throws SQLException {
if (isClosed()) checkAvailability(columnIndex, resultSet.get(pos).size());
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
if (columnIndex > resultSet.get(pos).size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size());
columnIndex = getTrueColumnIndex(columnIndex); Object value = resultSet.get(pos).get(columnIndex - 1);
Object value = resultSet.get(pos).get(columnIndex);
if (value == null) if (value == null)
return 0; return 0;
long valueAsLong = Long.parseLong(value.toString()); long valueAsLong = Long.parseLong(value.toString());
@ -179,13 +180,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
@Override @Override
public short getShort(int columnIndex) throws SQLException { public short getShort(int columnIndex) throws SQLException {
if (isClosed()) checkAvailability(columnIndex, resultSet.get(pos).size());
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
if (columnIndex > resultSet.get(pos).size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size());
columnIndex = getTrueColumnIndex(columnIndex); Object value = resultSet.get(pos).get(columnIndex - 1);
Object value = resultSet.get(pos).get(columnIndex);
if (value == null) if (value == null)
return 0; return 0;
long valueAsLong = Long.parseLong(value.toString()); long valueAsLong = Long.parseLong(value.toString());
@ -198,13 +195,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
@Override @Override
public int getInt(int columnIndex) throws SQLException { public int getInt(int columnIndex) throws SQLException {
if (isClosed()) checkAvailability(columnIndex, resultSet.get(pos).size());
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
if (columnIndex > resultSet.get(pos).size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size());
columnIndex = getTrueColumnIndex(columnIndex); Object value = resultSet.get(pos).get(columnIndex - 1);
Object value = resultSet.get(pos).get(columnIndex);
if (value == null) if (value == null)
return 0; return 0;
long valueAsLong = Long.parseLong(value.toString()); long valueAsLong = Long.parseLong(value.toString());
@ -217,13 +210,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
@Override @Override
public long getLong(int columnIndex) throws SQLException { public long getLong(int columnIndex) throws SQLException {
if (isClosed()) checkAvailability(columnIndex, resultSet.get(pos).size());
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
if (columnIndex > resultSet.get(pos).size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size());
columnIndex = getTrueColumnIndex(columnIndex); Object value = resultSet.get(pos).get(columnIndex - 1);
Object value = resultSet.get(pos).get(columnIndex);
if (value == null) if (value == null)
return 0; return 0;
@ -240,64 +229,99 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
@Override @Override
public float getFloat(int columnIndex) throws SQLException { public float getFloat(int columnIndex) throws SQLException {
if (isClosed()) checkAvailability(columnIndex, resultSet.get(pos).size());
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
if (columnIndex > resultSet.get(pos).size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size());
columnIndex = getTrueColumnIndex(columnIndex); Object value = resultSet.get(pos).get(columnIndex - 1);
return Float.parseFloat(resultSet.get(pos).get(columnIndex).toString()); if (value == null)
return 0;
if (value instanceof Float || value instanceof Double)
return (float) value;
return Float.parseFloat(value.toString());
} }
@Override @Override
public double getDouble(int columnIndex) throws SQLException { public double getDouble(int columnIndex) throws SQLException {
if (isClosed()) checkAvailability(columnIndex, resultSet.get(pos).size());
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
if (columnIndex > resultSet.get(pos).size())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size());
columnIndex = getTrueColumnIndex(columnIndex); Object value = resultSet.get(pos).get(columnIndex - 1);
return Double.parseDouble(resultSet.get(pos).get(columnIndex).toString()); if (value == null)
return 0;
if (value instanceof Double || value instanceof Float)
return (double) value;
return Double.parseDouble(value.toString());
} }
private int getTrueColumnIndex(int columnIndex) throws SQLException { @Override
if (columnIndex < 1) { public byte[] getBytes(int columnIndex) throws SQLException {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE checkAvailability(columnIndex, resultSet.get(pos).size());
, "Column Index out of range, " + columnIndex + " < 1");
Object value = resultSet.get(pos).get(columnIndex - 1);
if (value == null)
return null;
if (value instanceof byte[])
return (byte[]) value;
if (value instanceof String)
return ((String) value).getBytes();
if (value instanceof Long)
return Longs.toByteArray((long) value);
if (value instanceof Integer)
return Ints.toByteArray((int) value);
if (value instanceof Short)
return Shorts.toByteArray((short) value);
if (value instanceof Byte)
return new byte[]{(byte) value};
return value.toString().getBytes();
} }
int numOfCols = resultSet.get(pos).size(); @Override
if (columnIndex > numOfCols) { public Date getDate(int columnIndex) throws SQLException {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE checkAvailability(columnIndex, resultSet.get(pos).size());
, "Column Index out of range, " + columnIndex + " > " + numOfCols);
Object value = resultSet.get(pos).get(columnIndex - 1);
if (value == null)
return null;
if (value instanceof Timestamp)
return new Date(((Timestamp) value).getTime());
return Date.valueOf(value.toString());
} }
return columnIndex - 1; @Override
public Time getTime(int columnIndex) throws SQLException {
checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1);
if (value == null)
return null;
if (value instanceof Timestamp)
return new Time(((Timestamp) value).getTime());
return Time.valueOf(value.toString());
} }
@Override @Override
public Timestamp getTimestamp(int columnIndex) throws SQLException { public Timestamp getTimestamp(int columnIndex) throws SQLException {
if (isClosed()) checkAvailability(columnIndex, resultSet.get(pos).size());
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
columnIndex = getTrueColumnIndex(columnIndex); Object value = resultSet.get(pos).get(columnIndex - 1);
String strDate = resultSet.get(pos).get(columnIndex).toString(); if (value == null)
// strDate = strDate.substring(1, strDate.length() - 1); return null;
return Timestamp.valueOf(strDate); if (value instanceof Timestamp)
return (Timestamp) value;
return Timestamp.valueOf(value.toString());
} }
/*************************************************************************************************************/
@Override @Override
public ResultSetMetaData getMetaData() throws SQLException { public ResultSetMetaData getMetaData() throws SQLException {
if (isClosed()) if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
return this.metaData; return this.metaData;
} }
@Override @Override
public Object getObject(String columnLabel) throws SQLException { public Object getObject(int columnIndex) throws SQLException {
return getObject(findColumn(columnLabel)); checkAvailability(columnIndex, resultSet.get(pos).size());
return resultSet.get(pos).get(columnIndex - 1);
} }
@Override @Override
@ -311,6 +335,23 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
return columnIndex + 1; return columnIndex + 1;
} }
@Override
public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
checkAvailability(columnIndex, resultSet.get(pos).size());
Object value = resultSet.get(pos).get(columnIndex - 1);
if (value == null)
return null;
if (value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Byte)
return new BigDecimal(Long.valueOf(value.toString()));
if (value instanceof Double || value instanceof Float)
return new BigDecimal(Double.valueOf(value.toString()));
if (value instanceof Timestamp)
return new BigDecimal(((Timestamp) value).getTime());
return new BigDecimal(value.toString());
}
@Override @Override
public boolean isBeforeFirst() throws SQLException { public boolean isBeforeFirst() throws SQLException {
if (isClosed()) if (isClosed())
@ -471,6 +512,12 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
return this.statement; return this.statement;
} }
@Override
public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
//TODOdid not use the specified timezone in cal
return getTimestamp(columnIndex);
}
@Override @Override
public boolean isClosed() throws SQLException { public boolean isClosed() throws SQLException {
return isClosed; return isClosed;

View File

@ -1 +1,2 @@
com.taosdata.jdbc.TSDBDriver com.taosdata.jdbc.TSDBDriver
com.taosdata.jdbc.rs.RestfulDriver

View File

@ -1,266 +0,0 @@
package com.taosdata.jdbc;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.sql.rowset.serial.SerialBlob;
import javax.sql.rowset.serial.SerialClob;
import java.io.UnsupportedEncodingException;
import java.sql.*;
import java.util.HashMap;
import java.util.Properties;
import static org.junit.Assert.assertEquals;
public class ResultSetTest {
static Connection connection;
static Statement statement;
static String dbName = "test";
static String tName = "t0";
static String host = "localhost";
static ResultSet resSet;
@BeforeClass
public static void createDatabaseAndTable() {
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
statement = connection.createStatement();
statement.executeUpdate("drop database if exists " + dbName);
statement.executeUpdate("create database if not exists " + dbName);
statement.execute("use " + dbName);
statement.executeUpdate("create table if not exists " + dbName + "." + tName + " (ts timestamp, k1 int, k2 bigint, k3 float, k4 double, k5 binary(30), k6 smallint, k7 bool, k8 nchar(20))");
} catch (ClassNotFoundException | SQLException e) {
return;
}
}
@Test
public void testResultSet() {
String sql;
long ts = 1496732686000l;
int v1 = 2147483600;
long v2 = ts + 1000;
float v3 = 3.1415926f;
double v4 = 3.1415926535897;
String v5 = "涛思数据,强~";
short v6 = 12;
boolean v7 = false;
String v8 = "TDengine is powerful";
sql = "insert into " + dbName + "." + tName + " values (" + ts + "," + v1 + "," + v2 + "," + v3 + "," + v4
+ ",\"" + v5 + "\"," + v6 + "," + v7 + ",\"" + v8 + "\")";
try {
statement.executeUpdate(sql);
assertEquals(1, statement.getUpdateCount());
} catch (SQLException e) {
assert false : "insert error " + e.getMessage();
}
try {
statement.execute("select * from " + dbName + "." + tName + " where ts = " + ts);
resSet = statement.getResultSet();
System.out.println(((TSDBResultSet) resSet).getRowData());
while (resSet.next()) {
assertEquals(ts, resSet.getLong(1));
assertEquals(ts, resSet.getLong("ts"));
System.out.println(resSet.getTimestamp(1));
assertEquals(v1, resSet.getInt(2));
assertEquals(v1, resSet.getInt("k1"));
assertEquals(v2, resSet.getLong(3));
assertEquals(v2, resSet.getLong("k2"));
assertEquals(v3, resSet.getFloat(4), 7);
assertEquals(v3, resSet.getFloat("k3"), 7);
assertEquals(v4, resSet.getDouble(5), 13);
assertEquals(v4, resSet.getDouble("k4"), 13);
assertEquals(v5, resSet.getString(6));
assertEquals(v5, resSet.getString("k5"));
assertEquals(v6, resSet.getShort(7));
assertEquals(v6, resSet.getShort("k6"));
assertEquals(v7, resSet.getBoolean(8));
assertEquals(v7, resSet.getBoolean("k7"));
assertEquals(v8, resSet.getString(9));
assertEquals(v8, resSet.getString("k8"));
resSet.getBytes(9);
resSet.getObject(6);
resSet.getObject("k8");
}
if (!resSet.isClosed()) {
resSet.close();
}
} catch (SQLException e) {
assert false : "insert error " + e.getMessage();
}
}
@Test(expected = SQLException.class)
public void testUnsupport() throws SQLException, UnsupportedEncodingException {
statement.execute("show databases");
resSet = statement.getResultSet();
Assert.assertNotNull(resSet.unwrap(TSDBResultSet.class));
Assert.assertTrue(resSet.isWrapperFor(TSDBResultSet.class));
resSet.getUnicodeStream(null);
resSet.getBinaryStream(null);
resSet.getAsciiStream("");
resSet.getUnicodeStream(null);
resSet.getBinaryStream(null);
resSet.getWarnings();
resSet.clearWarnings();
resSet.getCursorName();
resSet.getCharacterStream(null);
resSet.getCharacterStream(null);
resSet.isBeforeFirst();
resSet.isAfterLast();
resSet.isFirst();
resSet.isLast();
resSet.beforeFirst();
resSet.afterLast();
resSet.first();
resSet.last();
resSet.getRow();
resSet.absolute(1);
resSet.relative(1);
resSet.previous();
resSet.setFetchDirection(0);
resSet.getFetchDirection();
resSet.setFetchSize(0);
resSet.getFetchSize();
resSet.getConcurrency();
resSet.rowUpdated();
resSet.rowInserted();
resSet.rowDeleted();
resSet.updateNull(null);
resSet.updateBoolean(0, true);
resSet.updateByte(0, (byte) 2);
resSet.updateShort(0, (short) 1);
resSet.updateInt(0, 0);
resSet.updateLong(0, 0l);
resSet.updateFloat(0, 3.14f);
resSet.updateDouble(0, 3.1415);
resSet.updateBigDecimal(null, null);
resSet.updateString(null, null);
resSet.updateBytes(null, null);
resSet.updateDate(null, null);
resSet.updateTime(null, null);
resSet.updateTimestamp(null, null);
resSet.updateAsciiStream(null, null);
resSet.updateBinaryStream(null, null);
resSet.updateCharacterStream(null, null);
resSet.updateObject(null, null);
resSet.updateObject(null, null);
resSet.updateNull(null);
resSet.updateBoolean("", false);
resSet.updateByte("", (byte) 1);
resSet.updateShort("", (short) 1);
resSet.updateInt("", 0);
resSet.updateLong("", 0l);
resSet.updateFloat("", 3.14f);
resSet.updateDouble("", 3.1415);
resSet.updateBigDecimal(null, null);
resSet.updateString(null, null);
resSet.updateBytes(null, null);
resSet.updateDate(null, null);
resSet.updateTime(null, null);
resSet.updateTimestamp(null, null);
resSet.updateAsciiStream(null, null);
resSet.updateBinaryStream(null, null);
resSet.updateCharacterStream(null, null);
resSet.updateObject(null, null);
resSet.updateObject(null, null);
resSet.insertRow();
resSet.updateRow();
resSet.deleteRow();
resSet.refreshRow();
resSet.cancelRowUpdates();
resSet.moveToInsertRow();
resSet.moveToCurrentRow();
resSet.getStatement();
resSet.getObject(0, new HashMap<>());
resSet.getRef(null);
resSet.getBlob(null);
resSet.getClob(null);
resSet.getArray(null);
resSet.getObject("", new HashMap<>());
resSet.getRef(null);
resSet.getBlob(null);
resSet.getClob(null);
resSet.getArray(null);
resSet.getDate(null, null);
resSet.getDate(null, null);
resSet.getTime(null, null);
resSet.getTime(null, null);
resSet.getTimestamp(null, null);
resSet.getTimestamp(null, null);
resSet.getURL(null);
resSet.getURL(null);
resSet.updateRef(null, null);
resSet.updateRef(null, null);
resSet.updateBlob(0, new SerialBlob("".getBytes("UTF8")));
resSet.updateBlob("", new SerialBlob("".getBytes("UTF8")));
resSet.updateClob("", new SerialClob("".toCharArray()));
resSet.updateClob(0, new SerialClob("".toCharArray()));
resSet.updateArray(null, null);
resSet.updateArray(null, null);
resSet.getRowId(null);
resSet.getRowId(null);
resSet.updateRowId(null, null);
resSet.updateRowId(null, null);
resSet.getHoldability();
resSet.updateNString(null, null);
resSet.updateNString(null, null);
resSet.getNClob(null);
resSet.getNClob(null);
resSet.getSQLXML(null);
resSet.getSQLXML(null);
resSet.updateSQLXML(null, null);
resSet.updateSQLXML(null, null);
resSet.getNCharacterStream(null);
resSet.getNCharacterStream(null);
resSet.updateNCharacterStream(null, null);
resSet.updateNCharacterStream(null, null);
resSet.updateAsciiStream(null, null);
resSet.updateBinaryStream(null, null);
resSet.updateCharacterStream(null, null);
resSet.updateAsciiStream(null, null);
resSet.updateBinaryStream(null, null);
resSet.updateCharacterStream(null, null);
resSet.updateNCharacterStream(null, null);
resSet.updateNCharacterStream(null, null);
resSet.updateAsciiStream(null, null);
resSet.updateBinaryStream(null, null);
resSet.updateCharacterStream(null, null);
resSet.updateAsciiStream(null, null);
resSet.updateBinaryStream(null, null);
resSet.updateCharacterStream(null, null);
}
@Test
public void testBatch() throws SQLException {
String[] sqls = new String[]{"insert into test.t0 values (1496732686001,2147483600,1496732687000,3.1415925,3.1415926535897," +
"'涛思数据,强~',12,0,'TDengine is powerful')", "insert into test.t0 values (1496732686002,2147483600,1496732687000,3.1415925,3.1415926535897," +
"'涛思数据,强~',12,1,'TDengine is powerful')"};
for (String sql : sqls) {
statement.addBatch(sql);
}
int[] res = statement.executeBatch();
assertEquals(res.length, 2);
statement.clearBatch();
}
@AfterClass
public static void close() {
try {
statement.executeUpdate("drop database " + dbName);
if (statement != null)
statement.close();
if (connection != null)
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -233,7 +233,7 @@ public class TSDBConnectionTest {
int status = rs.getInt("server_status()"); int status = rs.getInt("server_status()");
Assert.assertEquals(1, status); Assert.assertEquals(1, status);
conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)

View File

@ -0,0 +1,194 @@
package com.taosdata.jdbc;
import com.taosdata.jdbc.rs.RestfulParameterMetaData;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import java.sql.*;
public class TSDBParameterMetaDataTest {
private static final String host = "127.0.0.1";
private static Connection conn;
private static final String sql_insert = "insert into t1 values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
private static PreparedStatement pstmt_insert;
private static final String sql_select = "select * from t1 where ts > ? and ts <= ? and f1 >= ?";
private static PreparedStatement pstmt_select;
private static ParameterMetaData parameterMetaData_insert;
private static ParameterMetaData parameterMetaData_select;
@Test
public void getParameterCount() throws SQLException {
Assert.assertEquals(10, parameterMetaData_insert.getParameterCount());
}
@Test
public void isNullable() throws SQLException {
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(1));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(2));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(3));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(4));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(5));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(6));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(7));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(8));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(9));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(10));
}
@Test
public void isSigned() throws SQLException {
Assert.assertEquals(false, parameterMetaData_insert.isSigned(1));
Assert.assertEquals(true, parameterMetaData_insert.isSigned(2));
Assert.assertEquals(true, parameterMetaData_insert.isSigned(3));
Assert.assertEquals(true, parameterMetaData_insert.isSigned(4));
Assert.assertEquals(true, parameterMetaData_insert.isSigned(5));
Assert.assertEquals(true, parameterMetaData_insert.isSigned(6));
Assert.assertEquals(true, parameterMetaData_insert.isSigned(7));
Assert.assertEquals(false, parameterMetaData_insert.isSigned(8));
Assert.assertEquals(false, parameterMetaData_insert.isSigned(9));
Assert.assertEquals(false, parameterMetaData_insert.isSigned(10));
}
@Test
public void getPrecision() throws SQLException {
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(1));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(2));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(3));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(4));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(5));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(6));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(7));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(8));
Assert.assertEquals(5, parameterMetaData_insert.getPrecision(9));
Assert.assertEquals(5, parameterMetaData_insert.getPrecision(10));
}
@Test
public void getScale() throws SQLException {
Assert.assertEquals(0, parameterMetaData_insert.getScale(1));
Assert.assertEquals(0, parameterMetaData_insert.getScale(2));
Assert.assertEquals(0, parameterMetaData_insert.getScale(3));
Assert.assertEquals(0, parameterMetaData_insert.getScale(4));
Assert.assertEquals(0, parameterMetaData_insert.getScale(5));
Assert.assertEquals(0, parameterMetaData_insert.getScale(6));
Assert.assertEquals(0, parameterMetaData_insert.getScale(7));
Assert.assertEquals(0, parameterMetaData_insert.getScale(8));
Assert.assertEquals(0, parameterMetaData_insert.getScale(9));
Assert.assertEquals(0, parameterMetaData_insert.getScale(10));
}
@Test
public void getParameterType() throws SQLException {
Assert.assertEquals(Types.TIMESTAMP, parameterMetaData_insert.getParameterType(1));
Assert.assertEquals(Types.INTEGER, parameterMetaData_insert.getParameterType(2));
Assert.assertEquals(Types.BIGINT, parameterMetaData_insert.getParameterType(3));
Assert.assertEquals(Types.FLOAT, parameterMetaData_insert.getParameterType(4));
Assert.assertEquals(Types.DOUBLE, parameterMetaData_insert.getParameterType(5));
Assert.assertEquals(Types.SMALLINT, parameterMetaData_insert.getParameterType(6));
Assert.assertEquals(Types.TINYINT, parameterMetaData_insert.getParameterType(7));
Assert.assertEquals(Types.BOOLEAN, parameterMetaData_insert.getParameterType(8));
Assert.assertEquals(Types.BINARY, parameterMetaData_insert.getParameterType(9));
Assert.assertEquals(Types.NCHAR, parameterMetaData_insert.getParameterType(10));
}
@Test
public void getParameterTypeName() throws SQLException {
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.TIMESTAMP), parameterMetaData_insert.getParameterTypeName(1));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.INTEGER), parameterMetaData_insert.getParameterTypeName(2));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.BIGINT), parameterMetaData_insert.getParameterTypeName(3));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.FLOAT), parameterMetaData_insert.getParameterTypeName(4));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.DOUBLE), parameterMetaData_insert.getParameterTypeName(5));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.SMALLINT), parameterMetaData_insert.getParameterTypeName(6));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.TINYINT), parameterMetaData_insert.getParameterTypeName(7));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.BOOLEAN), parameterMetaData_insert.getParameterTypeName(8));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.BINARY), parameterMetaData_insert.getParameterTypeName(9));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.NCHAR), parameterMetaData_insert.getParameterTypeName(10));
}
@Test
public void getParameterClassName() throws SQLException {
Assert.assertEquals(Timestamp.class.getName(), parameterMetaData_insert.getParameterClassName(1));
Assert.assertEquals(Integer.class.getName(), parameterMetaData_insert.getParameterClassName(2));
Assert.assertEquals(Long.class.getName(), parameterMetaData_insert.getParameterClassName(3));
Assert.assertEquals(Float.class.getName(), parameterMetaData_insert.getParameterClassName(4));
Assert.assertEquals(Double.class.getName(), parameterMetaData_insert.getParameterClassName(5));
Assert.assertEquals(Short.class.getName(), parameterMetaData_insert.getParameterClassName(6));
Assert.assertEquals(Byte.class.getName(), parameterMetaData_insert.getParameterClassName(7));
Assert.assertEquals(Boolean.class.getName(), parameterMetaData_insert.getParameterClassName(8));
Assert.assertEquals(byte[].class.getName(), parameterMetaData_insert.getParameterClassName(9));
Assert.assertEquals(String.class.getName(), parameterMetaData_insert.getParameterClassName(10));
}
@Test
public void getParameterMode() throws SQLException {
for (int i = 1; i <= parameterMetaData_insert.getParameterCount(); i++) {
int parameterMode = parameterMetaData_insert.getParameterMode(i);
Assert.assertEquals(ParameterMetaData.parameterModeUnknown, parameterMode);
}
}
@Test
public void unwrap() throws SQLException {
TSDBParameterMetaData unwrap = parameterMetaData_insert.unwrap(TSDBParameterMetaData.class);
Assert.assertNotNull(unwrap);
}
@Test
public void isWrapperFor() throws SQLException {
Assert.assertTrue(parameterMetaData_insert.isWrapperFor(TSDBParameterMetaData.class));
}
@BeforeClass
public static void beforeClass() {
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata");
try (Statement stmt = conn.createStatement()) {
stmt.execute("drop database if exists test_pstmt");
stmt.execute("create database if not exists test_pstmt");
stmt.execute("use test_pstmt");
stmt.execute("create table weather(ts timestamp, f1 int, f2 bigint, f3 float, f4 double, f5 smallint, f6 tinyint, f7 bool, f8 binary(64), f9 nchar(64)) tags(loc nchar(64))");
stmt.execute("create table t1 using weather tags('beijing')");
}
pstmt_insert = conn.prepareStatement(sql_insert);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(2, 111);
pstmt_insert.setObject(3, Long.MAX_VALUE);
pstmt_insert.setObject(4, 3.14159265354f);
pstmt_insert.setObject(5, Double.MAX_VALUE);
pstmt_insert.setObject(6, Short.MAX_VALUE);
pstmt_insert.setObject(7, Byte.MAX_VALUE);
pstmt_insert.setObject(8, true);
pstmt_insert.setObject(9, "hello".getBytes());
pstmt_insert.setObject(10, "Hello");
parameterMetaData_insert = pstmt_insert.getParameterMetaData();
pstmt_select = conn.prepareStatement(sql_select);
pstmt_select.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_select.setTimestamp(2, new Timestamp(System.currentTimeMillis() + 10000));
pstmt_select.setInt(3, 0);
parameterMetaData_select = pstmt_select.getParameterMetaData();
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
@AfterClass
public static void afterClass() {
try {
if (pstmt_insert != null)
pstmt_insert.close();
if (pstmt_select != null)
pstmt_select.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -5,14 +5,16 @@ import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import java.io.IOException;
import java.io.Serializable;
import java.sql.*; import java.sql.*;
public class TSDBPreparedStatementTest { public class TSDBPreparedStatementTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
private static Connection conn; private static Connection conn;
private static final String sql_insert = "insert into t1 values(?, ?)"; private static final String sql_insert = "insert into t1 values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
private static PreparedStatement pstmt_insert; private static PreparedStatement pstmt_insert;
private static final String sql_select = "select * from t1 where ts > ? and ts <= ? and temperature >= ?"; private static final String sql_select = "select * from t1 where ts > ? and ts <= ? and f1 >= ?";
private static PreparedStatement pstmt_select; private static PreparedStatement pstmt_select;
@Test @Test
@ -21,7 +23,7 @@ public class TSDBPreparedStatementTest {
long start = end - 1000 * 60 * 60; long start = end - 1000 * 60 * 60;
pstmt_select.setTimestamp(1, new Timestamp(start)); pstmt_select.setTimestamp(1, new Timestamp(start));
pstmt_select.setTimestamp(2, new Timestamp(end)); pstmt_select.setTimestamp(2, new Timestamp(end));
pstmt_select.setFloat(3, 0); pstmt_select.setInt(3, 0);
ResultSet rs = pstmt_select.executeQuery(); ResultSet rs = pstmt_select.executeQuery();
Assert.assertNotNull(rs); Assert.assertNotNull(rs);
@ -37,48 +39,73 @@ public class TSDBPreparedStatementTest {
@Test @Test
public void executeUpdate() throws SQLException { public void executeUpdate() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis())); pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setFloat(2, 3.14f); pstmt_insert.setFloat(4, 3.14f);
int result = pstmt_insert.executeUpdate(); int result = pstmt_insert.executeUpdate();
Assert.assertEquals(1, result); Assert.assertEquals(1, result);
} }
@Test @Test
public void setNull() throws SQLException { public void setNull() throws SQLException {
pstmt_insert.setNull(2, Types.FLOAT); pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setNull(2, Types.INTEGER);
int result = pstmt_insert.executeUpdate();
Assert.assertEquals(1, result);
} }
@Test @Test
public void setBoolean() throws SQLException { public void setBoolean() throws SQLException {
pstmt_insert.setBoolean(2, true); pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setBoolean(8, true);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test
public void setByte() throws SQLException { public void setByte() throws SQLException {
pstmt_insert.setByte(1, (byte) 0x001); pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setByte(7, (byte) 0x001);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test @Test
public void setShort() { public void setShort() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setShort(6, (short) 2);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test @Test
public void setInt() { public void setInt() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setInt(2, 10086);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test @Test
public void setLong() { public void setLong() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setLong(3, Long.MAX_VALUE);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test @Test
public void setFloat() { public void setFloat() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setFloat(4, 3.14f);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test @Test
public void setDouble() { public void setDouble() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setDouble(5, 3.14444);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
@ -87,12 +114,56 @@ public class TSDBPreparedStatementTest {
} }
@Test @Test
public void setString() { public void setString() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setString(10, "aaaa");
boolean execute = pstmt_insert.execute();
Assert.assertFalse(execute);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setString(10, new Person("john", 33, true).toString());
Assert.assertFalse(pstmt_insert.execute());
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setString(10, new Person("john", 33, true).toString().replaceAll("'", "\""));
Assert.assertFalse(pstmt_insert.execute());
} }
@Test(expected = SQLFeatureNotSupportedException.class) class Person implements Serializable {
public void setBytes() throws SQLException { String name;
pstmt_insert.setBytes(1, new byte[]{}); int age;
boolean sex;
public Person(String name, int age, boolean sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
}
@Test
public void setBytes() throws SQLException, IOException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
// ObjectOutputStream oos = new ObjectOutputStream(baos);
// oos.writeObject(new Person("john", 33, true));
// oos.flush();
// byte[] bytes = baos.toByteArray();
// pstmt_insert.setBytes(9, bytes);
pstmt_insert.setBytes(9, new Person("john", 33, true).toString().getBytes());
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
@ -106,8 +177,10 @@ public class TSDBPreparedStatementTest {
} }
@Test @Test
public void setTimestamp() { public void setTimestamp() throws SQLException {
//TODO pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
@ -121,24 +194,69 @@ public class TSDBPreparedStatementTest {
} }
@Test @Test
public void clearParameters() { public void clearParameters() throws SQLException {
//TODO pstmt_insert.clearParameters();
} }
@Test @Test
public void setObject() throws SQLException { public void setObject() throws SQLException {
pstmt_insert.setObject(1, System.currentTimeMillis()); pstmt_insert.setObject(1, new Timestamp(System.currentTimeMillis()));
//TODO int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(2, 111);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(3, Long.MAX_VALUE);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(4, 3.14159265354f);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(5, Double.MAX_VALUE);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(6, Short.MAX_VALUE);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(7, Byte.MAX_VALUE);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(8, true);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(9, "hello".getBytes());
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(10, "Hello");
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test @Test
public void execute() { public void execute() throws SQLException {
//TODO pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
} int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
@Test executeQuery();
public void addBatch() {
//TODO:
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
@ -176,11 +294,11 @@ public class TSDBPreparedStatementTest {
pstmt_insert.setURL(1, null); pstmt_insert.setURL(1, null);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test
public void getParameterMetaData() throws SQLException { public void getParameterMetaData() throws SQLException {
ParameterMetaData parameterMetaData = pstmt_insert.getParameterMetaData(); ParameterMetaData parameterMetaData = pstmt_insert.getParameterMetaData();
// Assert.assertNotNull(parameterMetaData); Assert.assertNotNull(parameterMetaData);
//TODO: //TODO: modify the test case
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
@ -215,10 +333,10 @@ public class TSDBPreparedStatementTest {
Class.forName("com.taosdata.jdbc.TSDBDriver"); Class.forName("com.taosdata.jdbc.TSDBDriver");
conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata");
try (Statement stmt = conn.createStatement()) { try (Statement stmt = conn.createStatement()) {
stmt.execute("drop database if exists test_pstmt"); stmt.execute("drop database if exists test_pstmt_jni");
stmt.execute("create database if not exists test_pstmt"); stmt.execute("create database if not exists test_pstmt_jni");
stmt.execute("use test_pstmt"); stmt.execute("use test_pstmt_jni");
stmt.execute("create table weather(ts timestamp, temperature float) tags(loc nchar(64))"); stmt.execute("create table weather(ts timestamp, f1 int, f2 bigint, f3 float, f4 double, f5 smallint, f6 tinyint, f7 bool, f8 binary(64), f9 nchar(64)) tags(loc nchar(64))");
stmt.execute("create table t1 using weather tags('beijing')"); stmt.execute("create table t1 using weather tags('beijing')");
} }
pstmt_insert = conn.prepareStatement(sql_insert); pstmt_insert = conn.prepareStatement(sql_insert);
@ -231,7 +349,10 @@ public class TSDBPreparedStatementTest {
@AfterClass @AfterClass
public static void afterClass() { public static void afterClass() {
try { try {
if (pstmt_insert != null)
pstmt_insert.close();
if (pstmt_select != null)
pstmt_select.close();
if (conn != null) if (conn != null)
conn.close(); conn.close();
} catch (SQLException e) { } catch (SQLException e) {

View File

@ -0,0 +1,678 @@
package com.taosdata.jdbc;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import com.taosdata.jdbc.rs.RestfulResultSet;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class TSDBResultSetTest {
private static final String host = "127.0.0.1";
private static Connection conn;
private static Statement stmt;
private static ResultSet rs;
@Test
public void wasNull() throws SQLException {
Assert.assertFalse(rs.wasNull());
}
@Test
public void getString() throws SQLException {
String f10 = rs.getString("f10");
Assert.assertEquals("涛思数据", f10);
f10 = rs.getString(10);
Assert.assertEquals("涛思数据", f10);
}
@Test
public void getBoolean() throws SQLException {
Boolean f9 = rs.getBoolean("f9");
Assert.assertEquals(true, f9);
f9 = rs.getBoolean(9);
Assert.assertEquals(true, f9);
}
@Test
public void getByte() throws SQLException {
byte f8 = rs.getByte("f8");
Assert.assertEquals(10, f8);
f8 = rs.getByte(8);
Assert.assertEquals(10, f8);
}
@Test
public void getShort() throws SQLException {
short f7 = rs.getShort("f7");
Assert.assertEquals(10, f7);
f7 = rs.getShort(7);
Assert.assertEquals(10, f7);
}
@Test
public void getInt() throws SQLException {
int f2 = rs.getInt("f2");
Assert.assertEquals(1, f2);
f2 = rs.getInt(2);
Assert.assertEquals(1, f2);
}
@Test
public void getLong() throws SQLException {
long f3 = rs.getLong("f3");
Assert.assertEquals(100, f3);
f3 = rs.getLong(3);
Assert.assertEquals(100, f3);
}
@Test
public void getFloat() throws SQLException {
float f4 = rs.getFloat("f4");
Assert.assertEquals(3.1415f, f4, 0f);
f4 = rs.getFloat(4);
Assert.assertEquals(3.1415f, f4, 0f);
}
@Test
public void getDouble() throws SQLException {
double f5 = rs.getDouble("f5");
Assert.assertEquals(3.1415926, f5, 0.0);
f5 = rs.getDouble(5);
Assert.assertEquals(3.1415926, f5, 0.0);
}
@Test
public void getBigDecimal() throws SQLException {
BigDecimal f1 = rs.getBigDecimal("f1");
Assert.assertEquals(1609430400000l, f1.longValue());
BigDecimal f2 = rs.getBigDecimal("f2");
Assert.assertEquals(1, f2.intValue());
BigDecimal f3 = rs.getBigDecimal("f3");
Assert.assertEquals(100l, f3.longValue());
BigDecimal f4 = rs.getBigDecimal("f4");
Assert.assertEquals(3.1415f, f4.floatValue(), 0.00000f);
BigDecimal f5 = rs.getBigDecimal("f5");
Assert.assertEquals(3.1415926, f5.doubleValue(), 0.0000000);
BigDecimal f7 = rs.getBigDecimal("f7");
Assert.assertEquals(10, f7.intValue());
BigDecimal f8 = rs.getBigDecimal("f8");
Assert.assertEquals(10, f8.intValue());
}
@Test
public void getBytes() throws SQLException {
byte[] f1 = rs.getBytes("f1");
Assert.assertEquals("2021-01-01 00:00:00.0", new String(f1));
byte[] f2 = rs.getBytes("f2");
Assert.assertEquals(1, Ints.fromByteArray(f2));
byte[] f3 = rs.getBytes("f3");
Assert.assertEquals(100l, Longs.fromByteArray(f3));
byte[] f4 = rs.getBytes("f4");
Assert.assertEquals(3.1415f, Float.valueOf(new String(f4)), 0.000000f);
byte[] f5 = rs.getBytes("f5");
Assert.assertEquals(3.1415926, Double.valueOf(new String(f5)), 0.000000f);
byte[] f6 = rs.getBytes("f6");
Assert.assertEquals("abc", new String(f6));
byte[] f7 = rs.getBytes("f7");
Assert.assertEquals((short) 10, Shorts.fromByteArray(f7));
byte[] f8 = rs.getBytes("f8");
Assert.assertEquals(1, f8.length);
Assert.assertEquals((byte) 10, f8[0]);
byte[] f9 = rs.getBytes("f9");
Assert.assertEquals("true", new String(f9));
byte[] f10 = rs.getBytes("f10");
Assert.assertEquals("涛思数据", new String(f10));
}
@Test
public void getDate() throws SQLException, ParseException {
Date f1 = rs.getDate("f1");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Assert.assertEquals(sdf.parse("2021-01-01"), f1);
}
@Test
public void getTime() throws SQLException {
Time f1 = rs.getTime("f1");
Assert.assertEquals("00:00:00", f1.toString());
}
@Test
public void getTimestamp() throws SQLException {
Timestamp f1 = rs.getTimestamp("f1");
Assert.assertEquals("2021-01-01 00:00:00.0", f1.toString());
f1 = rs.getTimestamp(1);
Assert.assertEquals("2021-01-01 00:00:00.0", f1.toString());
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getAsciiStream() throws SQLException {
rs.getAsciiStream("f1");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getUnicodeStream() throws SQLException {
rs.getUnicodeStream("f1");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getBinaryStream() throws SQLException {
rs.getBinaryStream("f1");
}
@Test
public void getWarnings() throws SQLException {
Assert.assertNull(rs.getWarnings());
}
@Test
public void clearWarnings() throws SQLException {
rs.clearWarnings();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getCursorName() throws SQLException {
rs.getCursorName();
}
@Test
public void getMetaData() throws SQLException {
ResultSetMetaData meta = rs.getMetaData();
Assert.assertNotNull(meta);
}
@Test
public void getObject() throws SQLException, ParseException {
Object f1 = rs.getObject("f1");
Assert.assertEquals(Timestamp.class, f1.getClass());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.sss");
java.util.Date date = sdf.parse("2021-01-01 00:00:00.000");
Assert.assertEquals(new Timestamp(date.getTime()), f1);
Object f2 = rs.getObject("f2");
Assert.assertEquals(Integer.class, f2.getClass());
Assert.assertEquals(1, f2);
Object f3 = rs.getObject("f3");
Assert.assertEquals(Long.class, f3.getClass());
Assert.assertEquals(100l, f3);
Object f4 = rs.getObject("f4");
Assert.assertEquals(Float.class, f4.getClass());
Assert.assertEquals(3.1415f, f4);
Object f5 = rs.getObject("f5");
Assert.assertEquals(Double.class, f5.getClass());
Assert.assertEquals(3.1415926, f5);
Object f6 = rs.getObject("f6");
Assert.assertEquals(byte[].class, f6.getClass());
Assert.assertEquals("abc", new String((byte[]) f6));
Object f7 = rs.getObject("f7");
Assert.assertEquals(Short.class, f7.getClass());
Assert.assertEquals((short) 10, f7);
Object f8 = rs.getObject("f8");
Assert.assertEquals(Byte.class, f8.getClass());
Assert.assertEquals((byte) 10, f8);
Object f9 = rs.getObject("f9");
Assert.assertEquals(Boolean.class, f9.getClass());
Assert.assertEquals(true, f9);
Object f10 = rs.getObject("f10");
Assert.assertEquals(String.class, f10.getClass());
Assert.assertEquals("涛思数据", f10);
}
@Test(expected = SQLException.class)
public void findColumn() throws SQLException {
int columnIndex = rs.findColumn("f1");
Assert.assertEquals(1, columnIndex);
columnIndex = rs.findColumn("f2");
Assert.assertEquals(2, columnIndex);
columnIndex = rs.findColumn("f3");
Assert.assertEquals(3, columnIndex);
columnIndex = rs.findColumn("f4");
Assert.assertEquals(4, columnIndex);
columnIndex = rs.findColumn("f5");
Assert.assertEquals(5, columnIndex);
columnIndex = rs.findColumn("f6");
Assert.assertEquals(6, columnIndex);
columnIndex = rs.findColumn("f7");
Assert.assertEquals(7, columnIndex);
columnIndex = rs.findColumn("f8");
Assert.assertEquals(8, columnIndex);
columnIndex = rs.findColumn("f9");
Assert.assertEquals(9, columnIndex);
columnIndex = rs.findColumn("f10");
Assert.assertEquals(10, columnIndex);
rs.findColumn("f11");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getCharacterStream() throws SQLException {
rs.getCharacterStream(1);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void isBeforeFirst() throws SQLException {
rs.isBeforeFirst();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void isAfterLast() throws SQLException {
rs.isAfterLast();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void isFirst() throws SQLException {
rs.isFirst();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void isLast() throws SQLException {
rs.isLast();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void beforeFirst() throws SQLException {
rs.beforeFirst();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void afterLast() throws SQLException {
rs.afterLast();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void first() throws SQLException {
rs.first();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void last() throws SQLException {
rs.last();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getRow() throws SQLException {
int row = rs.getRow();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void absolute() throws SQLException {
rs.absolute(-1);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void relative() throws SQLException {
rs.relative(-1);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void previous() throws SQLException {
rs.previous();
}
@Test
public void setFetchDirection() throws SQLException {
rs.setFetchDirection(ResultSet.FETCH_FORWARD);
Assert.assertEquals(ResultSet.FETCH_FORWARD, rs.getFetchDirection());
rs.setFetchDirection(ResultSet.FETCH_UNKNOWN);
Assert.assertEquals(ResultSet.FETCH_FORWARD, rs.getFetchDirection());
}
@Test
public void getFetchDirection() throws SQLException {
Assert.assertEquals(ResultSet.FETCH_FORWARD, rs.getFetchDirection());
}
@Test
public void setFetchSize() throws SQLException {
rs.setFetchSize(0);
Assert.assertEquals(0, rs.getFetchSize());
}
@Test
public void getFetchSize() throws SQLException {
Assert.assertEquals(0, rs.getFetchSize());
}
@Test
public void getType() throws SQLException {
Assert.assertEquals(ResultSet.TYPE_FORWARD_ONLY, rs.getType());
}
@Test
public void getConcurrency() throws SQLException {
Assert.assertEquals(ResultSet.CONCUR_READ_ONLY, rs.getConcurrency());
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void rowUpdated() throws SQLException {
rs.rowUpdated();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void rowInserted() throws SQLException {
rs.rowInserted();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void rowDeleted() throws SQLException {
rs.rowDeleted();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateNull() throws SQLException {
rs.updateNull("f1");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateBoolean() throws SQLException {
rs.updateBoolean(1, false);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateByte() throws SQLException {
rs.updateByte(1, new Byte("0"));
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateShort() throws SQLException {
rs.updateShort(1, new Short("0"));
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateInt() throws SQLException {
rs.updateInt(1, 1);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateLong() throws SQLException {
rs.updateLong(1, 1l);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateFloat() throws SQLException {
rs.updateFloat(1, 1f);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateDouble() throws SQLException {
rs.updateDouble(1, 1.0);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateBigDecimal() throws SQLException {
rs.updateBigDecimal(1, new BigDecimal(1));
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateString() throws SQLException {
rs.updateString(1, "abc");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateBytes() throws SQLException {
rs.updateBytes(1, new byte[]{});
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateDate() throws SQLException {
rs.updateDate(1, new Date(System.currentTimeMillis()));
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateTime() throws SQLException {
rs.updateTime(1, new Time(System.currentTimeMillis()));
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateTimestamp() throws SQLException {
rs.updateTimestamp(1, new Timestamp(System.currentTimeMillis()));
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateAsciiStream() throws SQLException {
rs.updateAsciiStream(1, null);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateBinaryStream() throws SQLException {
rs.updateBinaryStream(1, null);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateCharacterStream() throws SQLException {
rs.updateCharacterStream(1, null);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateObject() throws SQLException {
rs.updateObject(1, null);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void insertRow() throws SQLException {
rs.insertRow();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateRow() throws SQLException {
rs.updateRow();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void deleteRow() throws SQLException {
rs.deleteRow();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void refreshRow() throws SQLException {
rs.refreshRow();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void cancelRowUpdates() throws SQLException {
rs.cancelRowUpdates();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void moveToInsertRow() throws SQLException {
rs.moveToInsertRow();
}
@Test
public void getStatement() throws SQLException {
Statement stmt = rs.getStatement();
Assert.assertNotNull(stmt);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void moveToCurrentRow() throws SQLException {
rs.moveToCurrentRow();
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getRef() throws SQLException {
rs.getRef(1);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getBlob() throws SQLException {
rs.getBlob("f1");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getClob() throws SQLException {
rs.getClob("f1");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getArray() throws SQLException {
rs.getArray("f1");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getURL() throws SQLException {
rs.getURL("f1");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateRef() throws SQLException {
rs.updateRef("f1", null);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateBlob() throws SQLException {
rs.updateBlob(1, (InputStream) null);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateClob() throws SQLException {
rs.updateClob(1, (Reader) null);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateArray() throws SQLException {
rs.updateArray(1, null);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getRowId() throws SQLException {
rs.getRowId("f1");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateRowId() throws SQLException {
rs.updateRowId(1, null);
}
@Test
public void getHoldability() throws SQLException {
Assert.assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, rs.getHoldability());
}
@Test
public void isClosed() throws SQLException {
Assert.assertFalse(rs.isClosed());
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateNString() throws SQLException {
rs.updateNString(1, null);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateNClob() throws SQLException {
rs.updateNClob(1, (Reader) null);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getNClob() throws SQLException {
rs.getNClob("f1");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getSQLXML() throws SQLException {
rs.getSQLXML("f1");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateSQLXML() throws SQLException {
rs.updateSQLXML(1, null);
}
@Test
public void getNString() throws SQLException {
String f10 = rs.getNString("f10");
Assert.assertEquals("涛思数据", f10);
f10 = rs.getNString(10);
Assert.assertEquals("涛思数据", f10);
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void getNCharacterStream() throws SQLException {
rs.getNCharacterStream("f1");
}
@Test(expected = SQLFeatureNotSupportedException.class)
public void updateNCharacterStream() throws SQLException {
rs.updateNCharacterStream(1, null);
}
@Test
public void unwrap() throws SQLException {
TSDBResultSet unwrap = rs.unwrap(TSDBResultSet.class);
Assert.assertNotNull(unwrap);
}
@Test
public void isWrapperFor() throws SQLException {
Assert.assertTrue(rs.isWrapperFor(TSDBResultSet.class));
}
@BeforeClass
public static void beforeClass() {
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata");
stmt = conn.createStatement();
stmt.execute("create database if not exists restful_test");
stmt.execute("use restful_test");
stmt.execute("drop table if exists weather");
stmt.execute("create table if not exists weather(f1 timestamp, f2 int, f3 bigint, f4 float, f5 double, f6 binary(64), f7 smallint, f8 tinyint, f9 bool, f10 nchar(64))");
stmt.execute("insert into restful_test.weather values('2021-01-01 00:00:00.000', 1, 100, 3.1415, 3.1415926, 'abc', 10, 10, true, '涛思数据')");
rs = stmt.executeQuery("select * from restful_test.weather");
rs.next();
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
@AfterClass
public static void afterClass() {
try {
if (rs != null)
rs.close();
if (stmt != null)
stmt.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,42 @@
package com.taosdata.jdbc.cases;
import com.taosdata.jdbc.TSDBDriver;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class DriverAutoloadTest {
private Properties properties;
private String host = "127.0.0.1";
@Test
public void testRestful() throws SQLException {
// Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
final String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata";
Connection conn = DriverManager.getConnection(url, properties);
Assert.assertNotNull(conn);
}
@Test
public void testJni() throws SQLException {
final String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata";
Connection conn = DriverManager.getConnection(url, properties);
Assert.assertNotNull(conn);
}
@Before
public void before() {
properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
}
}

View File

@ -14,7 +14,6 @@ import java.util.Random;
public class InsertDbwithoutUseDbTest { public class InsertDbwithoutUseDbTest {
private static String host = "127.0.0.1"; private static String host = "127.0.0.1";
// private static String host = "master";
private static Properties properties; private static Properties properties;
private static Random random = new Random(System.currentTimeMillis()); private static Random random = new Random(System.currentTimeMillis());

View File

@ -10,8 +10,8 @@ import java.util.Properties;
@FixMethodOrder(MethodSorters.NAME_ASCENDING) @FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class UnsignedNumberRestfulTest { public class UnsignedNumberRestfulTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
// private static final String host = "master";
private static Connection conn; private static Connection conn;
@Test @Test

View File

@ -8,7 +8,6 @@ import java.sql.*;
public class AuthenticationTest { public class AuthenticationTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
// private static final String host = "master";
private static final String user = "root"; private static final String user = "root";
private static final String password = "taos?data"; private static final String password = "taos?data";
private Connection conn; private Connection conn;

View File

@ -12,7 +12,6 @@ import java.util.Properties;
public class RestfulConnectionTest { public class RestfulConnectionTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
// private static final String host = "master";
private static Connection conn; private static Connection conn;

View File

@ -10,7 +10,6 @@ import java.sql.*;
import java.util.Properties; import java.util.Properties;
public class RestfulDatabaseMetaDataTest { public class RestfulDatabaseMetaDataTest {
// private static final String host = "master";
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
private static final String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata"; private static final String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata";
private static Connection connection; private static Connection connection;

View File

@ -10,7 +10,6 @@ import java.util.Random;
public class RestfulJDBCTest { public class RestfulJDBCTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
// private static final String host = "master";
private static Connection connection; private static Connection connection;
private Random random = new Random(System.currentTimeMillis()); private Random random = new Random(System.currentTimeMillis());

View File

@ -0,0 +1,194 @@
package com.taosdata.jdbc.rs;
import com.taosdata.jdbc.TSDBConstants;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import java.sql.*;
public class RestfulParameterMetaDataTest {
private static final String host = "127.0.0.1";
private static Connection conn;
private static final String sql_insert = "insert into t1 values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
private static PreparedStatement pstmt_insert;
private static final String sql_select = "select * from t1 where ts > ? and ts <= ? and f1 >= ?";
private static PreparedStatement pstmt_select;
private static ParameterMetaData parameterMetaData_insert;
private static ParameterMetaData parameterMetaData_select;
@Test
public void getParameterCount() throws SQLException {
Assert.assertEquals(10, parameterMetaData_insert.getParameterCount());
}
@Test
public void isNullable() throws SQLException {
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(1));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(2));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(3));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(4));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(5));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(6));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(7));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(8));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(9));
Assert.assertEquals(ParameterMetaData.parameterNullableUnknown, parameterMetaData_insert.isNullable(10));
}
@Test
public void isSigned() throws SQLException {
Assert.assertEquals(false, parameterMetaData_insert.isSigned(1));
Assert.assertEquals(true, parameterMetaData_insert.isSigned(2));
Assert.assertEquals(true, parameterMetaData_insert.isSigned(3));
Assert.assertEquals(true, parameterMetaData_insert.isSigned(4));
Assert.assertEquals(true, parameterMetaData_insert.isSigned(5));
Assert.assertEquals(true, parameterMetaData_insert.isSigned(6));
Assert.assertEquals(true, parameterMetaData_insert.isSigned(7));
Assert.assertEquals(false, parameterMetaData_insert.isSigned(8));
Assert.assertEquals(false, parameterMetaData_insert.isSigned(9));
Assert.assertEquals(false, parameterMetaData_insert.isSigned(10));
}
@Test
public void getPrecision() throws SQLException {
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(1));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(2));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(3));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(4));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(5));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(6));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(7));
Assert.assertEquals(0, parameterMetaData_insert.getPrecision(8));
Assert.assertEquals(5, parameterMetaData_insert.getPrecision(9));
Assert.assertEquals(5, parameterMetaData_insert.getPrecision(10));
}
@Test
public void getScale() throws SQLException {
Assert.assertEquals(0, parameterMetaData_insert.getScale(1));
Assert.assertEquals(0, parameterMetaData_insert.getScale(2));
Assert.assertEquals(0, parameterMetaData_insert.getScale(3));
Assert.assertEquals(0, parameterMetaData_insert.getScale(4));
Assert.assertEquals(0, parameterMetaData_insert.getScale(5));
Assert.assertEquals(0, parameterMetaData_insert.getScale(6));
Assert.assertEquals(0, parameterMetaData_insert.getScale(7));
Assert.assertEquals(0, parameterMetaData_insert.getScale(8));
Assert.assertEquals(0, parameterMetaData_insert.getScale(9));
Assert.assertEquals(0, parameterMetaData_insert.getScale(10));
}
@Test
public void getParameterType() throws SQLException {
Assert.assertEquals(Types.TIMESTAMP, parameterMetaData_insert.getParameterType(1));
Assert.assertEquals(Types.INTEGER, parameterMetaData_insert.getParameterType(2));
Assert.assertEquals(Types.BIGINT, parameterMetaData_insert.getParameterType(3));
Assert.assertEquals(Types.FLOAT, parameterMetaData_insert.getParameterType(4));
Assert.assertEquals(Types.DOUBLE, parameterMetaData_insert.getParameterType(5));
Assert.assertEquals(Types.SMALLINT, parameterMetaData_insert.getParameterType(6));
Assert.assertEquals(Types.TINYINT, parameterMetaData_insert.getParameterType(7));
Assert.assertEquals(Types.BOOLEAN, parameterMetaData_insert.getParameterType(8));
Assert.assertEquals(Types.BINARY, parameterMetaData_insert.getParameterType(9));
Assert.assertEquals(Types.NCHAR, parameterMetaData_insert.getParameterType(10));
}
@Test
public void getParameterTypeName() throws SQLException {
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.TIMESTAMP), parameterMetaData_insert.getParameterTypeName(1));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.INTEGER), parameterMetaData_insert.getParameterTypeName(2));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.BIGINT), parameterMetaData_insert.getParameterTypeName(3));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.FLOAT), parameterMetaData_insert.getParameterTypeName(4));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.DOUBLE), parameterMetaData_insert.getParameterTypeName(5));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.SMALLINT), parameterMetaData_insert.getParameterTypeName(6));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.TINYINT), parameterMetaData_insert.getParameterTypeName(7));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.BOOLEAN), parameterMetaData_insert.getParameterTypeName(8));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.BINARY), parameterMetaData_insert.getParameterTypeName(9));
Assert.assertEquals(TSDBConstants.jdbcType2TaosTypeName(Types.NCHAR), parameterMetaData_insert.getParameterTypeName(10));
}
@Test
public void getParameterClassName() throws SQLException {
Assert.assertEquals(Timestamp.class.getName(), parameterMetaData_insert.getParameterClassName(1));
Assert.assertEquals(Integer.class.getName(), parameterMetaData_insert.getParameterClassName(2));
Assert.assertEquals(Long.class.getName(), parameterMetaData_insert.getParameterClassName(3));
Assert.assertEquals(Float.class.getName(), parameterMetaData_insert.getParameterClassName(4));
Assert.assertEquals(Double.class.getName(), parameterMetaData_insert.getParameterClassName(5));
Assert.assertEquals(Short.class.getName(), parameterMetaData_insert.getParameterClassName(6));
Assert.assertEquals(Byte.class.getName(), parameterMetaData_insert.getParameterClassName(7));
Assert.assertEquals(Boolean.class.getName(), parameterMetaData_insert.getParameterClassName(8));
Assert.assertEquals(byte[].class.getName(), parameterMetaData_insert.getParameterClassName(9));
Assert.assertEquals(String.class.getName(), parameterMetaData_insert.getParameterClassName(10));
}
@Test
public void getParameterMode() throws SQLException {
for (int i = 1; i <= parameterMetaData_insert.getParameterCount(); i++) {
int parameterMode = parameterMetaData_insert.getParameterMode(i);
Assert.assertEquals(ParameterMetaData.parameterModeUnknown, parameterMode);
}
}
@Test
public void unwrap() throws SQLException {
RestfulParameterMetaData unwrap = parameterMetaData_insert.unwrap(RestfulParameterMetaData.class);
Assert.assertNotNull(unwrap);
}
@Test
public void isWrapperFor() throws SQLException {
Assert.assertTrue(parameterMetaData_insert.isWrapperFor(RestfulParameterMetaData.class));
}
@BeforeClass
public static void beforeClass() {
try {
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata");
try (Statement stmt = conn.createStatement()) {
stmt.execute("drop database if exists test_pstmt");
stmt.execute("create database if not exists test_pstmt");
stmt.execute("use test_pstmt");
stmt.execute("create table weather(ts timestamp, f1 int, f2 bigint, f3 float, f4 double, f5 smallint, f6 tinyint, f7 bool, f8 binary(64), f9 nchar(64)) tags(loc nchar(64))");
stmt.execute("create table t1 using weather tags('beijing')");
}
pstmt_insert = conn.prepareStatement(sql_insert);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(2, 111);
pstmt_insert.setObject(3, Long.MAX_VALUE);
pstmt_insert.setObject(4, 3.14159265354f);
pstmt_insert.setObject(5, Double.MAX_VALUE);
pstmt_insert.setObject(6, Short.MAX_VALUE);
pstmt_insert.setObject(7, Byte.MAX_VALUE);
pstmt_insert.setObject(8, true);
pstmt_insert.setObject(9, "hello".getBytes());
pstmt_insert.setObject(10, "Hello");
parameterMetaData_insert = pstmt_insert.getParameterMetaData();
pstmt_select = conn.prepareStatement(sql_select);
pstmt_select.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_select.setTimestamp(2, new Timestamp(System.currentTimeMillis() + 10000));
pstmt_select.setInt(3, 0);
parameterMetaData_select = pstmt_select.getParameterMetaData();
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
@AfterClass
public static void afterClass() {
try {
if (pstmt_insert != null)
pstmt_insert.close();
if (pstmt_select != null)
pstmt_select.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -5,11 +5,12 @@ import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import java.io.IOException;
import java.io.Serializable;
import java.sql.*; import java.sql.*;
public class RestfulPreparedStatementTest { public class RestfulPreparedStatementTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
// private static final String host = "master";
private static Connection conn; private static Connection conn;
private static final String sql_insert = "insert into t1 values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; private static final String sql_insert = "insert into t1 values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
private static PreparedStatement pstmt_insert; private static PreparedStatement pstmt_insert;
@ -38,48 +39,73 @@ public class RestfulPreparedStatementTest {
@Test @Test
public void executeUpdate() throws SQLException { public void executeUpdate() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis())); pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setFloat(2, 3.14f); pstmt_insert.setFloat(4, 3.14f);
int result = pstmt_insert.executeUpdate(); int result = pstmt_insert.executeUpdate();
Assert.assertEquals(1, result); Assert.assertEquals(1, result);
} }
@Test @Test
public void setNull() throws SQLException { public void setNull() throws SQLException {
pstmt_insert.setNull(2, Types.FLOAT); pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setNull(2, Types.INTEGER);
int result = pstmt_insert.executeUpdate();
Assert.assertEquals(1, result);
} }
@Test @Test
public void setBoolean() throws SQLException { public void setBoolean() throws SQLException {
pstmt_insert.setBoolean(2, true); pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setBoolean(8, true);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test
public void setByte() throws SQLException { public void setByte() throws SQLException {
pstmt_insert.setByte(1, (byte) 0x001); pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setByte(7, (byte) 0x001);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test @Test
public void setShort() { public void setShort() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setShort(6, (short) 2);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test @Test
public void setInt() { public void setInt() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setInt(2, 10086);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test @Test
public void setLong() { public void setLong() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setLong(3, Long.MAX_VALUE);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test @Test
public void setFloat() { public void setFloat() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setFloat(4, 3.14f);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test @Test
public void setDouble() { public void setDouble() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setDouble(5, 3.14444);
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
@ -88,12 +114,56 @@ public class RestfulPreparedStatementTest {
} }
@Test @Test
public void setString() { public void setString() throws SQLException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setString(10, "aaaa");
boolean execute = pstmt_insert.execute();
Assert.assertFalse(execute);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setString(10, new Person("john", 33, true).toString());
Assert.assertFalse(pstmt_insert.execute());
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setString(10, new Person("john", 33, true).toString().replaceAll("'", "\""));
Assert.assertFalse(pstmt_insert.execute());
} }
@Test(expected = SQLFeatureNotSupportedException.class) class Person implements Serializable {
public void setBytes() throws SQLException { String name;
pstmt_insert.setBytes(1, new byte[]{}); int age;
boolean sex;
public Person(String name, int age, boolean sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
}
@Test
public void setBytes() throws SQLException, IOException {
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
// ObjectOutputStream oos = new ObjectOutputStream(baos);
// oos.writeObject(new Person("john", 33, true));
// oos.flush();
// byte[] bytes = baos.toByteArray();
// pstmt_insert.setBytes(9, bytes);
pstmt_insert.setBytes(9, new Person("john", 33, true).toString().getBytes());
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
@ -107,8 +177,10 @@ public class RestfulPreparedStatementTest {
} }
@Test @Test
public void setTimestamp() { public void setTimestamp() throws SQLException {
//TODO pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
@ -122,24 +194,69 @@ public class RestfulPreparedStatementTest {
} }
@Test @Test
public void clearParameters() { public void clearParameters() throws SQLException {
//TODO pstmt_insert.clearParameters();
} }
@Test @Test
public void setObject() throws SQLException { public void setObject() throws SQLException {
pstmt_insert.setObject(1, System.currentTimeMillis()); pstmt_insert.setObject(1, new Timestamp(System.currentTimeMillis()));
//TODO int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(2, 111);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(3, Long.MAX_VALUE);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(4, 3.14159265354f);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(5, Double.MAX_VALUE);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(6, Short.MAX_VALUE);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(7, Byte.MAX_VALUE);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(8, true);
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(9, "hello".getBytes());
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
pstmt_insert.setObject(10, "Hello");
ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
} }
@Test @Test
public void execute() { public void execute() throws SQLException {
//TODO pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
} int ret = pstmt_insert.executeUpdate();
Assert.assertEquals(1, ret);
@Test executeQuery();
public void addBatch() {
//TODO:
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
@ -180,8 +297,8 @@ public class RestfulPreparedStatementTest {
@Test @Test
public void getParameterMetaData() throws SQLException { public void getParameterMetaData() throws SQLException {
ParameterMetaData parameterMetaData = pstmt_insert.getParameterMetaData(); ParameterMetaData parameterMetaData = pstmt_insert.getParameterMetaData();
Assert.assertNull(parameterMetaData); Assert.assertNotNull(parameterMetaData);
//TODO: //TODO: modify the test case
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)

View File

@ -10,7 +10,6 @@ import java.sql.*;
public class RestfulResultSetMetaDataTest { public class RestfulResultSetMetaDataTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
// private static final String host = "master";
private static Connection conn; private static Connection conn;
private static Statement stmt; private static Statement stmt;

View File

@ -1,5 +1,8 @@
package com.taosdata.jdbc.rs; package com.taosdata.jdbc.rs;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -9,11 +12,12 @@ import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.*; import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class RestfulResultSetTest { public class RestfulResultSetTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
// private static final String host = "master";
private static Connection conn; private static Connection conn;
private static Statement stmt; private static Statement stmt;
@ -88,24 +92,75 @@ public class RestfulResultSetTest {
Assert.assertEquals(3.1415926, f5, 0.0); Assert.assertEquals(3.1415926, f5, 0.0);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test
public void getBigDecimal() throws SQLException { public void getBigDecimal() throws SQLException {
rs.getBigDecimal("f1"); BigDecimal f1 = rs.getBigDecimal("f1");
Assert.assertEquals(1609430400000l, f1.longValue());
BigDecimal f2 = rs.getBigDecimal("f2");
Assert.assertEquals(1, f2.intValue());
BigDecimal f3 = rs.getBigDecimal("f3");
Assert.assertEquals(100l, f3.longValue());
BigDecimal f4 = rs.getBigDecimal("f4");
Assert.assertEquals(3.1415f, f4.floatValue(), 0.00000f);
BigDecimal f5 = rs.getBigDecimal("f5");
Assert.assertEquals(3.1415926, f5.doubleValue(), 0.0000000);
BigDecimal f7 = rs.getBigDecimal("f7");
Assert.assertEquals(10, f7.intValue());
BigDecimal f8 = rs.getBigDecimal("f8");
Assert.assertEquals(10, f8.intValue());
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test
public void getBytes() throws SQLException { public void getBytes() throws SQLException {
rs.getBytes("f1"); byte[] f1 = rs.getBytes("f1");
Assert.assertEquals("2021-01-01 00:00:00.0", new String(f1));
byte[] f2 = rs.getBytes("f2");
Assert.assertEquals(1, Ints.fromByteArray(f2));
byte[] f3 = rs.getBytes("f3");
Assert.assertEquals(100l, Longs.fromByteArray(f3));
byte[] f4 = rs.getBytes("f4");
Assert.assertEquals(3.1415f, Float.valueOf(new String(f4)), 0.000000f);
byte[] f5 = rs.getBytes("f5");
Assert.assertEquals(3.1415926, Double.valueOf(new String(f5)), 0.000000f);
byte[] f6 = rs.getBytes("f6");
Assert.assertEquals("abc", new String(f6));
byte[] f7 = rs.getBytes("f7");
Assert.assertEquals((short) 10, Shorts.fromByteArray(f7));
byte[] f8 = rs.getBytes("f8");
Assert.assertEquals(1, f8.length);
Assert.assertEquals((byte) 10, f8[0]);
byte[] f9 = rs.getBytes("f9");
Assert.assertEquals("true", new String(f9));
byte[] f10 = rs.getBytes("f10");
Assert.assertEquals("涛思数据", new String(f10));
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test
public void getDate() throws SQLException { public void getDate() throws SQLException, ParseException {
rs.getDate("f1"); Date f1 = rs.getDate("f1");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Assert.assertEquals(sdf.parse("2021-01-01"), f1);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test
public void getTime() throws SQLException { public void getTime() throws SQLException {
rs.getTime("f1"); Time f1 = rs.getTime("f1");
Assert.assertEquals("00:00:00", f1.toString());
} }
@Test @Test
@ -152,9 +207,49 @@ public class RestfulResultSetTest {
Assert.assertNotNull(meta); Assert.assertNotNull(meta);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test
public void getObject() throws SQLException { public void getObject() throws SQLException, ParseException {
rs.getObject("f1"); Object f1 = rs.getObject("f1");
Assert.assertEquals(Timestamp.class, f1.getClass());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.sss");
java.util.Date date = sdf.parse("2021-01-01 00:00:00.000");
Assert.assertEquals(new Timestamp(date.getTime()), f1);
Object f2 = rs.getObject("f2");
Assert.assertEquals(Integer.class, f2.getClass());
Assert.assertEquals(1, f2);
Object f3 = rs.getObject("f3");
Assert.assertEquals(Long.class, f3.getClass());
Assert.assertEquals(100l, f3);
Object f4 = rs.getObject("f4");
Assert.assertEquals(Float.class, f4.getClass());
Assert.assertEquals(3.1415f, f4);
Object f5 = rs.getObject("f5");
Assert.assertEquals(Double.class, f5.getClass());
Assert.assertEquals(3.1415926, f5);
Object f6 = rs.getObject("f6");
Assert.assertEquals(byte[].class, f6.getClass());
Assert.assertEquals("abc", new String((byte[]) f6));
Object f7 = rs.getObject("f7");
Assert.assertEquals(Short.class, f7.getClass());
Assert.assertEquals((short) 10, f7);
Object f8 = rs.getObject("f8");
Assert.assertEquals(Byte.class, f8.getClass());
Assert.assertEquals((byte) 10, f8);
Object f9 = rs.getObject("f9");
Assert.assertEquals(Boolean.class, f9.getClass());
Assert.assertEquals(true, f9);
Object f10 = rs.getObject("f10");
Assert.assertEquals(String.class, f10.getClass());
Assert.assertEquals("涛思数据", f10);
} }
@Test(expected = SQLException.class) @Test(expected = SQLException.class)

View File

@ -12,7 +12,6 @@ import java.util.UUID;
public class RestfulStatementTest { public class RestfulStatementTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
// private static final String host = "master";
private static Connection conn; private static Connection conn;
private static Statement stmt; private static Statement stmt;

View File

@ -12,7 +12,6 @@ import java.sql.*;
@FixMethodOrder(MethodSorters.NAME_ASCENDING) @FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SQLTest { public class SQLTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
// private static final String host = "master";
private static Connection connection; private static Connection connection;
@Test @Test

View File

@ -35,6 +35,10 @@ IF (TD_TOPIC)
TARGET_LINK_LIBRARIES(taosd topic) TARGET_LINK_LIBRARIES(taosd topic)
ENDIF () ENDIF ()
IF (TD_MODULE AND TD_LINUX)
TARGET_LINK_LIBRARIES(taosd module dl)
ENDIF ()
SET(PREPARE_ENV_CMD "prepare_env_cmd") SET(PREPARE_ENV_CMD "prepare_env_cmd")
SET(PREPARE_ENV_TARGET "prepare_env_target") SET(PREPARE_ENV_TARGET "prepare_env_target")
ADD_CUSTOM_COMMAND(OUTPUT ${PREPARE_ENV_CMD} ADD_CUSTOM_COMMAND(OUTPUT ${PREPARE_ENV_CMD}

View File

@ -39,6 +39,13 @@
#include "dnodeMPeer.h" #include "dnodeMPeer.h"
#include "dnodeShell.h" #include "dnodeShell.h"
#include "dnodeTelemetry.h" #include "dnodeTelemetry.h"
#include "module.h"
#if !defined(_MODULE) || !defined(_TD_LINUX)
int32_t moduleStart() { return 0; }
void moduleStop() {}
#endif
void *tsDnodeTmr = NULL; void *tsDnodeTmr = NULL;
static SRunStatus tsRunStatus = TSDB_RUN_STATUS_STOPPED; static SRunStatus tsRunStatus = TSDB_RUN_STATUS_STOPPED;
@ -63,13 +70,16 @@ static SStep tsDnodeSteps[] = {
{"dnode-vread", dnodeInitVRead, dnodeCleanupVRead}, {"dnode-vread", dnodeInitVRead, dnodeCleanupVRead},
{"dnode-vwrite", dnodeInitVWrite, dnodeCleanupVWrite}, {"dnode-vwrite", dnodeInitVWrite, dnodeCleanupVWrite},
{"dnode-vmgmt", dnodeInitVMgmt, dnodeCleanupVMgmt}, {"dnode-vmgmt", dnodeInitVMgmt, dnodeCleanupVMgmt},
{"dnode-mread", dnodeInitMRead, dnodeCleanupMRead}, {"dnode-mread", dnodeInitMRead, NULL},
{"dnode-mwrite", dnodeInitMWrite, dnodeCleanupMWrite}, {"dnode-mwrite", dnodeInitMWrite, NULL},
{"dnode-mpeer", dnodeInitMPeer, dnodeCleanupMPeer}, {"dnode-mpeer", dnodeInitMPeer, NULL},
{"dnode-client", dnodeInitClient, dnodeCleanupClient}, {"dnode-client", dnodeInitClient, dnodeCleanupClient},
{"dnode-server", dnodeInitServer, dnodeCleanupServer}, {"dnode-server", dnodeInitServer, dnodeCleanupServer},
{"dnode-vnodes", dnodeInitVnodes, dnodeCleanupVnodes}, {"dnode-vnodes", dnodeInitVnodes, dnodeCleanupVnodes},
{"dnode-modules", dnodeInitModules, dnodeCleanupModules}, {"dnode-modules", dnodeInitModules, dnodeCleanupModules},
{"dnode-mread", NULL, dnodeCleanupMRead},
{"dnode-mwrite", NULL, dnodeCleanupMWrite},
{"dnode-mpeer", NULL, dnodeCleanupMPeer},
{"dnode-shell", dnodeInitShell, dnodeCleanupShell}, {"dnode-shell", dnodeInitShell, dnodeCleanupShell},
{"dnode-statustmr", dnodeInitStatusTimer,dnodeCleanupStatusTimer}, {"dnode-statustmr", dnodeInitStatusTimer,dnodeCleanupStatusTimer},
{"dnode-telemetry", dnodeInitTelemetry, dnodeCleanupTelemetry}, {"dnode-telemetry", dnodeInitTelemetry, dnodeCleanupTelemetry},
@ -146,6 +156,7 @@ int32_t dnodeInitSystem() {
} }
dnodeSetRunStatus(TSDB_RUN_STATUS_RUNING); dnodeSetRunStatus(TSDB_RUN_STATUS_RUNING);
moduleStart();
dnodeReportStep("TDengine", "initialized successfully", 1); dnodeReportStep("TDengine", "initialized successfully", 1);
dInfo("TDengine is initialized successfully"); dInfo("TDengine is initialized successfully");
@ -155,6 +166,7 @@ int32_t dnodeInitSystem() {
void dnodeCleanUpSystem() { void dnodeCleanUpSystem() {
if (dnodeGetRunStatus() != TSDB_RUN_STATUS_STOPPED) { if (dnodeGetRunStatus() != TSDB_RUN_STATUS_STOPPED) {
moduleStop();
dnodeSetRunStatus(TSDB_RUN_STATUS_STOPPED); dnodeSetRunStatus(TSDB_RUN_STATUS_STOPPED);
dnodeCleanupTmr(); dnodeCleanupTmr();
dnodeCleanupComponents(); dnodeCleanupComponents();

View File

@ -43,6 +43,7 @@ int32_t dnodeInitServer() {
dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_CREATE_VNODE] = dnodeDispatchToVMgmtQueue; dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_CREATE_VNODE] = dnodeDispatchToVMgmtQueue;
dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_ALTER_VNODE] = dnodeDispatchToVMgmtQueue; dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_ALTER_VNODE] = dnodeDispatchToVMgmtQueue;
dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_SYNC_VNODE] = dnodeDispatchToVMgmtQueue;
dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_DROP_VNODE] = dnodeDispatchToVMgmtQueue; dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_DROP_VNODE] = dnodeDispatchToVMgmtQueue;
dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_ALTER_STREAM] = dnodeDispatchToVMgmtQueue; dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_ALTER_STREAM] = dnodeDispatchToVMgmtQueue;
dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_CONFIG_DNODE] = dnodeDispatchToVMgmtQueue; dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_CONFIG_DNODE] = dnodeDispatchToVMgmtQueue;

View File

@ -30,6 +30,7 @@ static taos_queue tsVMgmtQueue = NULL;
static void * dnodeProcessMgmtQueue(void *param); static void * dnodeProcessMgmtQueue(void *param);
static int32_t dnodeProcessCreateVnodeMsg(SRpcMsg *pMsg); static int32_t dnodeProcessCreateVnodeMsg(SRpcMsg *pMsg);
static int32_t dnodeProcessAlterVnodeMsg(SRpcMsg *pMsg); static int32_t dnodeProcessAlterVnodeMsg(SRpcMsg *pMsg);
static int32_t dnodeProcessSyncVnodeMsg(SRpcMsg *pMsg);
static int32_t dnodeProcessDropVnodeMsg(SRpcMsg *pMsg); static int32_t dnodeProcessDropVnodeMsg(SRpcMsg *pMsg);
static int32_t dnodeProcessAlterStreamMsg(SRpcMsg *pMsg); static int32_t dnodeProcessAlterStreamMsg(SRpcMsg *pMsg);
static int32_t dnodeProcessConfigDnodeMsg(SRpcMsg *pMsg); static int32_t dnodeProcessConfigDnodeMsg(SRpcMsg *pMsg);
@ -39,6 +40,7 @@ static int32_t (*dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MAX])(SRpcMsg *pMsg);
int32_t dnodeInitVMgmt() { int32_t dnodeInitVMgmt() {
dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MD_CREATE_VNODE] = dnodeProcessCreateVnodeMsg; dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MD_CREATE_VNODE] = dnodeProcessCreateVnodeMsg;
dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MD_ALTER_VNODE] = dnodeProcessAlterVnodeMsg; dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MD_ALTER_VNODE] = dnodeProcessAlterVnodeMsg;
dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MD_SYNC_VNODE] = dnodeProcessSyncVnodeMsg;
dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MD_DROP_VNODE] = dnodeProcessDropVnodeMsg; dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MD_DROP_VNODE] = dnodeProcessDropVnodeMsg;
dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MD_ALTER_STREAM] = dnodeProcessAlterStreamMsg; dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MD_ALTER_STREAM] = dnodeProcessAlterStreamMsg;
dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MD_CONFIG_DNODE] = dnodeProcessConfigDnodeMsg; dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MD_CONFIG_DNODE] = dnodeProcessConfigDnodeMsg;
@ -179,6 +181,13 @@ static int32_t dnodeProcessAlterVnodeMsg(SRpcMsg *rpcMsg) {
} }
} }
static int32_t dnodeProcessSyncVnodeMsg(SRpcMsg *rpcMsg) {
SSyncVnodeMsg *pSyncVnode = rpcMsg->pCont;
pSyncVnode->vgId = htonl(pSyncVnode->vgId);
return vnodeSync(pSyncVnode->vgId);
}
static int32_t dnodeProcessDropVnodeMsg(SRpcMsg *rpcMsg) { static int32_t dnodeProcessDropVnodeMsg(SRpcMsg *rpcMsg) {
SDropVnodeMsg *pDrop = rpcMsg->pCont; SDropVnodeMsg *pDrop = rpcMsg->pCont;
pDrop->vgId = htonl(pDrop->vgId); pDrop->vgId = htonl(pDrop->vgId);

View File

@ -206,6 +206,7 @@ static void dnodeProcessStatusRsp(SRpcMsg *pMsg) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
taosTmrReset(dnodeSendStatusMsg, tsStatusInterval * 1000, NULL, tsDnodeTmr, &tsStatusTimer); taosTmrReset(dnodeSendStatusMsg, tsStatusInterval * 1000, NULL, tsDnodeTmr, &tsStatusTimer);
return; return;
} }

30
src/inc/module.h Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_MODULE
#define TDENGINE_MODULE
#ifdef __cplusplus
extern "C" {
#endif
int32_t moduleStart();
void moduleStop();
#ifdef __cplusplus
}
#endif
#endif

View File

@ -259,7 +259,7 @@ do { \
#define TSDB_MIN_TABLES 4 #define TSDB_MIN_TABLES 4
#define TSDB_MAX_TABLES 10000000 #define TSDB_MAX_TABLES 10000000
#define TSDB_DEFAULT_TABLES 1000000 #define TSDB_DEFAULT_TABLES 1000000
#define TSDB_TABLES_STEP 1000 #define TSDB_TABLES_STEP 100
#define TSDB_MIN_DAYS_PER_FILE 1 #define TSDB_MIN_DAYS_PER_FILE 1
#define TSDB_MAX_DAYS_PER_FILE 3650 #define TSDB_MAX_DAYS_PER_FILE 3650
@ -317,7 +317,7 @@ do { \
#define TSDB_MAX_DB_QUORUM_OPTION 2 #define TSDB_MAX_DB_QUORUM_OPTION 2
#define TSDB_DEFAULT_DB_QUORUM_OPTION 1 #define TSDB_DEFAULT_DB_QUORUM_OPTION 1
#define TSDB_MAX_JOIN_TABLE_NUM 5 #define TSDB_MAX_JOIN_TABLE_NUM 10
#define TSDB_MAX_UNION_CLAUSE 5 #define TSDB_MAX_UNION_CLAUSE 5
#define TSDB_MAX_BINARY_LEN (TSDB_MAX_BYTES_PER_ROW-TSDB_KEYSIZE) #define TSDB_MAX_BINARY_LEN (TSDB_MAX_BYTES_PER_ROW-TSDB_KEYSIZE)

View File

@ -59,6 +59,7 @@ TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_MD_DROP_STABLE, "drop-stable" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_MD_ALTER_STREAM, "alter-stream" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_MD_ALTER_STREAM, "alter-stream" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_MD_CONFIG_DNODE, "config-dnode" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_MD_CONFIG_DNODE, "config-dnode" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_MD_ALTER_VNODE, "alter-vnode" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_MD_ALTER_VNODE, "alter-vnode" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_MD_SYNC_VNODE, "sync-vnode" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_MD_CREATE_MNODE, "create-mnode" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_MD_CREATE_MNODE, "create-mnode" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_DUMMY6, "dummy6" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_DUMMY6, "dummy6" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_DUMMY7, "dummy7" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_DUMMY7, "dummy7" )
@ -389,7 +390,7 @@ typedef struct {
typedef struct { typedef struct {
int32_t vgId; int32_t vgId;
} SDropVnodeMsg; } SDropVnodeMsg, SSyncVnodeMsg;
typedef struct SColIndex { typedef struct SColIndex {
int16_t colId; // column id int16_t colId; // column id

View File

@ -60,6 +60,7 @@ int32_t vnodeCreate(SCreateVnodeMsg *pVnodeCfg);
int32_t vnodeDrop(int32_t vgId); int32_t vnodeDrop(int32_t vgId);
int32_t vnodeOpen(int32_t vgId); int32_t vnodeOpen(int32_t vgId);
int32_t vnodeAlter(void *pVnode, SCreateVnodeMsg *pVnodeCfg); int32_t vnodeAlter(void *pVnode, SCreateVnodeMsg *pVnodeCfg);
int32_t vnodeSync(int32_t vgId);
int32_t vnodeClose(int32_t vgId); int32_t vnodeClose(int32_t vgId);
// vnodeMgmt // vnodeMgmt

View File

@ -74,6 +74,7 @@ void source_file(TAOS* con, char* fptr);
void source_dir(TAOS* con, SShellArguments* args); void source_dir(TAOS* con, SShellArguments* args);
void shellCheck(TAOS* con, SShellArguments* args); void shellCheck(TAOS* con, SShellArguments* args);
void get_history_path(char* history); void get_history_path(char* history);
void shellCheck(TAOS* con, SShellArguments* args);
void cleanup_handler(void* arg); void cleanup_handler(void* arg);
void exitShell(); void exitShell();
int shellDumpResult(TAOS_RES* con, char* fname, int* error_no, bool printMode); int shellDumpResult(TAOS_RES* con, char* fname, int* error_no, bool printMode);

View File

@ -132,7 +132,6 @@ TAOS *shellInit(SShellArguments *args) {
return con; return con;
} }
static bool isEmptyCommand(const char* cmd) { static bool isEmptyCommand(const char* cmd) {
for (char c = *cmd++; c != 0; c = *cmd++) { for (char c = *cmd++; c != 0; c = *cmd++) {
if (c != ' ' && c != '\t' && c != ';') { if (c != ' ' && c != '\t' && c != ';') {

View File

@ -3,6 +3,55 @@ PROJECT(TDengine)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc)
FIND_PACKAGE(Git)
IF (GIT_FOUND)
MESSAGE("Git found")
EXECUTE_PROCESS(
COMMAND ${GIT_EXECUTABLE} log --pretty=oneline -n 1 ${CMAKE_CURRENT_LIST_DIR}/taosdemo.c
RESULT_VARIABLE RESULT
OUTPUT_VARIABLE TAOSDEMO_COMMIT)
EXECUTE_PROCESS(
COMMAND bash "-c" "echo '${TAOSDEMO_COMMIT}' | awk '{print $1}' | cut -c -9"
RESULT_VARIABLE RESULT
OUTPUT_VARIABLE TAOSDEMO_COMMIT_SHA1)
EXECUTE_PROCESS(
COMMAND ${GIT_EXECUTABLE} status -z -s ${CMAKE_CURRENT_LIST_DIR}/taosdemo.c
RESULT_VARIABLE RESULT
OUTPUT_VARIABLE TAOSDEMO_STATUS)
EXECUTE_PROCESS(
COMMAND bash "-c" "echo '${TAOSDEMO_STATUS}' | awk '{print $1}'"
RESULT_VARIABLE RESULT
OUTPUT_VARIABLE TAOSDEMO_STATUS)
MESSAGE("taosdemo.c status: " ${TAOSDEMO_STATUS})
ELSE()
MESSAGE("Git not found")
SET(TAOSDEMO_COMMIT_SHA1 "unknown")
SET(TAOSDEMO_STATUS "unknown")
ENDIF (GIT_FOUND)
STRING(STRIP ${TAOSDEMO_COMMIT_SHA1} TAOSDEMO_COMMIT_SHA1)
MESSAGE("taosdemo's latest commit in short is:" ${TAOSDEMO_COMMIT_SHA1})
STRING(STRIP ${TAOSDEMO_STATUS} TAOSDEMO_STATUS)
IF (TAOSDEMO_STATUS MATCHES "M")
SET(TAOSDEMO_STATUS "modified")
ELSE()
SET(TAOSDEMO_STATUS "")
ENDIF ()
MESSAGE("taosdemo's status is:" ${TAOSDEMO_STATUS})
ADD_DEFINITIONS(-DTAOSDEMO_COMMIT_SHA1="${TAOSDEMO_COMMIT_SHA1}")
ADD_DEFINITIONS(-DTAOSDEMO_STATUS="${TAOSDEMO_STATUS}")
MESSAGE("VERNUMBER is:" ${VERNUMBER})
IF ("${VERNUMBER}" STREQUAL "")
SET(TD_VERSION_NUMBER "TDengine-version-unknown")
ELSE()
SET(TD_VERSION_NUMBER ${VERNUMBER})
ENDIF ()
MESSAGE("TD_VERSION_NUMBER is:" ${TD_VERSION_NUMBER})
ADD_DEFINITIONS(-DTD_VERNUMBER="${TD_VERSION_NUMBER}")
IF (TD_LINUX) IF (TD_LINUX)
AUX_SOURCE_DIRECTORY(. SRC) AUX_SOURCE_DIRECTORY(. SRC)
ADD_EXECUTABLE(taosdemo ${SRC}) ADD_EXECUTABLE(taosdemo ${SRC})

View File

@ -41,7 +41,7 @@
"insert_mode": "taosc", "insert_mode": "taosc",
"insert_rows": 1000, "insert_rows": 1000,
"multi_thread_write_one_tbl": "no", "multi_thread_write_one_tbl": "no",
"rows_per_tbl": 20, "interlace_rows": 20,
"max_sql_len": 1024000, "max_sql_len": 1024000,
"disorder_ratio": 0, "disorder_ratio": 0,
"disorder_range": 1000, "disorder_range": 1000,

View File

@ -41,7 +41,7 @@
"insert_mode": "taosc", "insert_mode": "taosc",
"insert_rows": 100000, "insert_rows": 100000,
"multi_thread_write_one_tbl": "no", "multi_thread_write_one_tbl": "no",
"rows_per_tbl": 0, "interlace_rows": 0,
"max_sql_len": 1024000, "max_sql_len": 1024000,
"disorder_ratio": 0, "disorder_ratio": 0,
"disorder_range": 1000, "disorder_range": 1000,

File diff suppressed because it is too large Load Diff

View File

@ -49,6 +49,7 @@ void mnodeRemoveTableFromVgroup(SVgObj *pVgroup, SCTableObj *pTable);
void mnodeSendDropVnodeMsg(int32_t vgId, SRpcEpSet *epSet, void *ahandle); void mnodeSendDropVnodeMsg(int32_t vgId, SRpcEpSet *epSet, void *ahandle);
void mnodeSendCreateVgroupMsg(SVgObj *pVgroup, void *ahandle); void mnodeSendCreateVgroupMsg(SVgObj *pVgroup, void *ahandle);
void mnodeSendAlterVgroupMsg(SVgObj *pVgroup); void mnodeSendAlterVgroupMsg(SVgObj *pVgroup);
void mnodeSendSyncVgroupMsg(SVgObj *pVgroup);
SRpcEpSet mnodeGetEpSetFromVgroup(SVgObj *pVgroup); SRpcEpSet mnodeGetEpSetFromVgroup(SVgObj *pVgroup);
SRpcEpSet mnodeGetEpSetFromIp(char *ep); SRpcEpSet mnodeGetEpSetFromIp(char *ep);

View File

@ -1186,8 +1186,44 @@ static int32_t mnodeProcessDropDbMsg(SMnodeMsg *pMsg) {
return mnodeDropDb(pMsg); return mnodeDropDb(pMsg);
} }
static int32_t mnodeSyncDb(SDbObj *pDb, SMnodeMsg *pMsg) {
void *pIter = NULL;
SVgObj *pVgroup = NULL;
while (1) {
pIter = mnodeGetNextVgroup(pIter, &pVgroup);
if (pVgroup == NULL) break;
if (pVgroup->pDb == pDb) {
mnodeSendSyncVgroupMsg(pVgroup);
}
mnodeDecVgroupRef(pVgroup);
}
mLInfo("db:%s, is synced by %s", pDb->name, mnodeGetUserFromMsg(pMsg));
return TSDB_CODE_SUCCESS;
}
static int32_t mnodeProcessSyncDbMsg(SMnodeMsg *pMsg) { static int32_t mnodeProcessSyncDbMsg(SMnodeMsg *pMsg) {
return 0; SSyncDbMsg *pSyncDb = pMsg->rpcMsg.pCont;
mDebug("db:%s, syncdb is received from thandle:%p, ignore:%d", pSyncDb->db, pMsg->rpcMsg.handle, pSyncDb->ignoreNotExists);
if (pMsg->pDb == NULL) pMsg->pDb = mnodeGetDb(pSyncDb->db);
if (pMsg->pDb == NULL) {
if (pSyncDb->ignoreNotExists) {
mDebug("db:%s, db is not exist, treat as success", pSyncDb->db);
return TSDB_CODE_SUCCESS;
} else {
mError("db:%s, failed to sync, invalid db", pSyncDb->db);
return TSDB_CODE_MND_INVALID_DB;
}
}
if (pMsg->pDb->status != TSDB_DB_STATUS_READY) {
mError("db:%s, status:%d, in dropping", pSyncDb->db, pMsg->pDb->status);
return TSDB_CODE_MND_DB_IN_DROPPING;
}
return mnodeSyncDb(pMsg->pDb, pMsg);
} }
void mnodeDropAllDbs(SAcctObj *pAcct) { void mnodeDropAllDbs(SAcctObj *pAcct) {

View File

@ -722,6 +722,10 @@ int32_t mnodeDropDnode(SDnodeObj *pDnode, void *pMsg) {
static int32_t mnodeDropDnodeByEp(char *ep, SMnodeMsg *pMsg) { static int32_t mnodeDropDnodeByEp(char *ep, SMnodeMsg *pMsg) {
SDnodeObj *pDnode = mnodeGetDnodeByEp(ep); SDnodeObj *pDnode = mnodeGetDnodeByEp(ep);
if (pDnode == NULL) { if (pDnode == NULL) {
if (strspn(ep, "0123456789 ;") != strlen(ep)) {
return TSDB_CODE_MND_DNODE_NOT_EXIST;
}
int32_t dnodeId = (int32_t)strtol(ep, NULL, 10); int32_t dnodeId = (int32_t)strtol(ep, NULL, 10);
pDnode = mnodeGetDnode(dnodeId); pDnode = mnodeGetDnode(dnodeId);
if (pDnode == NULL) { if (pDnode == NULL) {

View File

@ -60,6 +60,7 @@ static int32_t mnodeGetVgroupMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *p
static int32_t mnodeRetrieveVgroups(SShowObj *pShow, char *data, int32_t rows, void *pConn); static int32_t mnodeRetrieveVgroups(SShowObj *pShow, char *data, int32_t rows, void *pConn);
static void mnodeProcessCreateVnodeRsp(SRpcMsg *rpcMsg); static void mnodeProcessCreateVnodeRsp(SRpcMsg *rpcMsg);
static void mnodeProcessAlterVnodeRsp(SRpcMsg *rpcMsg); static void mnodeProcessAlterVnodeRsp(SRpcMsg *rpcMsg);
static void mnodeProcessSyncVnodeRsp(SRpcMsg *rpcMsg);
static void mnodeProcessDropVnodeRsp(SRpcMsg *rpcMsg); static void mnodeProcessDropVnodeRsp(SRpcMsg *rpcMsg);
static int32_t mnodeProcessVnodeCfgMsg(SMnodeMsg *pMsg) ; static int32_t mnodeProcessVnodeCfgMsg(SMnodeMsg *pMsg) ;
static void mnodeSendDropVgroupMsg(SVgObj *pVgroup, void *ahandle); static void mnodeSendDropVgroupMsg(SVgObj *pVgroup, void *ahandle);
@ -236,6 +237,7 @@ int32_t mnodeInitVgroups() {
mnodeAddShowFreeIterHandle(TSDB_MGMT_TABLE_VGROUP, mnodeCancelGetNextVgroup); mnodeAddShowFreeIterHandle(TSDB_MGMT_TABLE_VGROUP, mnodeCancelGetNextVgroup);
mnodeAddPeerRspHandle(TSDB_MSG_TYPE_MD_CREATE_VNODE_RSP, mnodeProcessCreateVnodeRsp); mnodeAddPeerRspHandle(TSDB_MSG_TYPE_MD_CREATE_VNODE_RSP, mnodeProcessCreateVnodeRsp);
mnodeAddPeerRspHandle(TSDB_MSG_TYPE_MD_ALTER_VNODE_RSP, mnodeProcessAlterVnodeRsp); mnodeAddPeerRspHandle(TSDB_MSG_TYPE_MD_ALTER_VNODE_RSP, mnodeProcessAlterVnodeRsp);
mnodeAddPeerRspHandle(TSDB_MSG_TYPE_MD_ALTER_VNODE_RSP, mnodeProcessSyncVnodeRsp);
mnodeAddPeerRspHandle(TSDB_MSG_TYPE_MD_DROP_VNODE_RSP, mnodeProcessDropVnodeRsp); mnodeAddPeerRspHandle(TSDB_MSG_TYPE_MD_DROP_VNODE_RSP, mnodeProcessDropVnodeRsp);
mnodeAddPeerMsgHandle(TSDB_MSG_TYPE_DM_CONFIG_VNODE, mnodeProcessVnodeCfgMsg); mnodeAddPeerMsgHandle(TSDB_MSG_TYPE_DM_CONFIG_VNODE, mnodeProcessVnodeCfgMsg);
@ -967,6 +969,38 @@ void mnodeSendAlterVgroupMsg(SVgObj *pVgroup) {
} }
} }
static SSyncVnodeMsg *mnodeBuildSyncVnodeMsg(int32_t vgId) {
SSyncVnodeMsg *pSyncVnode = rpcMallocCont(sizeof(SSyncVnodeMsg));
if (pSyncVnode == NULL) return NULL;
pSyncVnode->vgId = htonl(vgId);
return pSyncVnode;
}
static void mnodeSendSyncVnodeMsg(SVgObj *pVgroup, SRpcEpSet *epSet) {
SSyncVnodeMsg *pSyncVnode = mnodeBuildSyncVnodeMsg(pVgroup->vgId);
SRpcMsg rpcMsg = {
.ahandle = NULL,
.pCont = pSyncVnode,
.contLen = pSyncVnode ? sizeof(SSyncVnodeMsg) : 0,
.code = 0,
.msgType = TSDB_MSG_TYPE_MD_SYNC_VNODE
};
dnodeSendMsgToDnode(epSet, &rpcMsg);
}
void mnodeSendSyncVgroupMsg(SVgObj *pVgroup) {
mDebug("vgId:%d, send sync all vnodes msg, numOfVnodes:%d db:%s", pVgroup->vgId, pVgroup->numOfVnodes,
pVgroup->dbName);
for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) {
SRpcEpSet epSet = mnodeGetEpSetFromIp(pVgroup->vnodeGid[i].pDnode->dnodeEp);
mDebug("vgId:%d, index:%d, send sync vnode msg to dnode %s", pVgroup->vgId, i,
pVgroup->vnodeGid[i].pDnode->dnodeEp);
mnodeSendSyncVnodeMsg(pVgroup, &epSet);
}
}
static void mnodeSendCreateVnodeMsg(SVgObj *pVgroup, SRpcEpSet *epSet, void *ahandle) { static void mnodeSendCreateVnodeMsg(SVgObj *pVgroup, SRpcEpSet *epSet, void *ahandle) {
SCreateVnodeMsg *pCreate = mnodeBuildVnodeMsg(pVgroup); SCreateVnodeMsg *pCreate = mnodeBuildVnodeMsg(pVgroup);
SRpcMsg rpcMsg = { SRpcMsg rpcMsg = {
@ -994,6 +1028,10 @@ static void mnodeProcessAlterVnodeRsp(SRpcMsg *rpcMsg) {
mDebug("alter vnode rsp received"); mDebug("alter vnode rsp received");
} }
static void mnodeProcessSyncVnodeRsp(SRpcMsg *rpcMsg) {
mDebug("sync vnode rsp received");
}
static void mnodeProcessCreateVnodeRsp(SRpcMsg *rpcMsg) { static void mnodeProcessCreateVnodeRsp(SRpcMsg *rpcMsg) {
if (rpcMsg->ahandle == NULL) return; if (rpcMsg->ahandle == NULL) return;

View File

@ -1017,6 +1017,13 @@ static SRpcConn *rpcProcessMsgHead(SRpcInfo *pRpc, SRecvInfo *pRecv, SRpcReqCont
return pConn; return pConn;
} }
static void doRpcReportBrokenLinkToServer(void *param, void *id) {
SRpcMsg *pRpcMsg = (SRpcMsg *)(param);
SRpcConn *pConn = (SRpcConn *)(pRpcMsg->handle);
SRpcInfo *pRpc = pConn->pRpc;
(*(pRpc->cfp))(pRpcMsg, NULL);
free(pRpcMsg);
}
static void rpcReportBrokenLinkToServer(SRpcConn *pConn) { static void rpcReportBrokenLinkToServer(SRpcConn *pConn) {
SRpcInfo *pRpc = pConn->pRpc; SRpcInfo *pRpc = pConn->pRpc;
if (pConn->pReqMsg == NULL) return; if (pConn->pReqMsg == NULL) return;
@ -1025,16 +1032,20 @@ static void rpcReportBrokenLinkToServer(SRpcConn *pConn) {
rpcAddRef(pRpc); rpcAddRef(pRpc);
tDebug("%s, notify the server app, connection is gone", pConn->info); tDebug("%s, notify the server app, connection is gone", pConn->info);
SRpcMsg rpcMsg; SRpcMsg *rpcMsg = malloc(sizeof(SRpcMsg));
rpcMsg.pCont = pConn->pReqMsg; // pReqMsg is re-used to store the APP context from server rpcMsg->pCont = pConn->pReqMsg; // pReqMsg is re-used to store the APP context from server
rpcMsg.contLen = pConn->reqMsgLen; // reqMsgLen is re-used to store the APP context length rpcMsg->contLen = pConn->reqMsgLen; // reqMsgLen is re-used to store the APP context length
rpcMsg.ahandle = pConn->ahandle; rpcMsg->ahandle = pConn->ahandle;
rpcMsg.handle = pConn; rpcMsg->handle = pConn;
rpcMsg.msgType = pConn->inType; rpcMsg->msgType = pConn->inType;
rpcMsg.code = TSDB_CODE_RPC_NETWORK_UNAVAIL; rpcMsg->code = TSDB_CODE_RPC_NETWORK_UNAVAIL;
pConn->pReqMsg = NULL; pConn->pReqMsg = NULL;
pConn->reqMsgLen = 0; pConn->reqMsgLen = 0;
if (pRpc->cfp) (*(pRpc->cfp))(&rpcMsg, NULL); if (pRpc->cfp) {
taosTmrStart(doRpcReportBrokenLinkToServer, 0, rpcMsg, pRpc->tmrCtrl);
} else {
free(rpcMsg);
}
} }
static void rpcProcessBrokenLink(SRpcConn *pConn) { static void rpcProcessBrokenLink(SRpcConn *pConn) {

View File

@ -410,7 +410,7 @@ void syncConfirmForward(int64_t rid, uint64_t version, int32_t code, bool force)
syncReleaseNode(pNode); syncReleaseNode(pNode);
} }
#if 0 #if 1
void syncRecover(int64_t rid) { void syncRecover(int64_t rid) {
SSyncPeer *pPeer; SSyncPeer *pPeer;

View File

@ -17,7 +17,7 @@
#define TSDB_MAX_SUBBLOCKS 8 #define TSDB_MAX_SUBBLOCKS 8
static FORCE_INLINE int TSDB_KEY_FID(TSKEY key, int32_t days, int8_t precision) { static FORCE_INLINE int TSDB_KEY_FID(TSKEY key, int32_t days, int8_t precision) {
if (key < 0) { if (key < 0) {
return (int)(-((-key) / tsMsPerDay[precision] / days + 1)); return (int)((key + 1) / tsMsPerDay[precision] / days - 1);
} else { } else {
return (int)((key / tsMsPerDay[precision] / days)); return (int)((key / tsMsPerDay[precision] / days));
} }
@ -452,6 +452,14 @@ static int tsdbCommitToFile(SCommitH *pCommith, SDFileSet *pSet, int fid) {
return -1; return -1;
} }
if (tsdbUpdateDFileSetHeader(&(pCommith->wSet)) < 0) {
tsdbError("vgId:%d failed to update FSET %d header since %s", REPO_ID(pRepo), fid, tstrerror(terrno));
tsdbCloseCommitFile(pCommith, true);
// revert the file change
tsdbApplyDFileSetChange(TSDB_COMMIT_WRITE_FSET(pCommith), pSet);
return -1;
}
// Close commit file // Close commit file
tsdbCloseCommitFile(pCommith, false); tsdbCloseCommitFile(pCommith, false);

View File

@ -33,6 +33,7 @@ static int tsdbScanDataDir(STsdbRepo *pRepo);
static bool tsdbIsTFileInFS(STsdbFS *pfs, const TFILE *pf); static bool tsdbIsTFileInFS(STsdbFS *pfs, const TFILE *pf);
static int tsdbRestoreCurrent(STsdbRepo *pRepo); static int tsdbRestoreCurrent(STsdbRepo *pRepo);
static int tsdbComparTFILE(const void *arg1, const void *arg2); static int tsdbComparTFILE(const void *arg1, const void *arg2);
static void tsdbScanAndTryFixDFilesHeader(STsdbRepo *pRepo);
// ================== CURRENT file header info // ================== CURRENT file header info
static int tsdbEncodeFSHeader(void **buf, SFSHeader *pHeader) { static int tsdbEncodeFSHeader(void **buf, SFSHeader *pHeader) {
@ -246,6 +247,8 @@ int tsdbOpenFS(STsdbRepo *pRepo) {
tsdbError("vgId:%d failed to open FS since %s", REPO_ID(pRepo), tstrerror(terrno)); tsdbError("vgId:%d failed to open FS since %s", REPO_ID(pRepo), tstrerror(terrno));
return -1; return -1;
} }
tsdbScanAndTryFixDFilesHeader(pRepo);
} else { } else {
if (tsdbRestoreCurrent(pRepo) < 0) { if (tsdbRestoreCurrent(pRepo) < 0) {
tsdbError("vgId:%d failed to restore current file since %s", REPO_ID(pRepo), tstrerror(terrno)); tsdbError("vgId:%d failed to restore current file since %s", REPO_ID(pRepo), tstrerror(terrno));
@ -1202,3 +1205,40 @@ static int tsdbComparTFILE(const void *arg1, const void *arg2) {
} }
} }
} }
static void tsdbScanAndTryFixDFilesHeader(STsdbRepo *pRepo) {
STsdbFS * pfs = REPO_FS(pRepo);
SFSStatus *pStatus = pfs->cstatus;
SDFInfo info;
for (size_t i = 0; i < taosArrayGetSize(pStatus->df); i++) {
SDFileSet fset;
tsdbInitDFileSetEx(&fset, (SDFileSet *)taosArrayGet(pStatus->df, i));
tsdbDebug("vgId:%d scan DFileSet %d header", REPO_ID(pRepo), fset.fid);
if (tsdbOpenDFileSet(&fset, O_RDWR) < 0) {
tsdbError("vgId:%d failed to open DFileSet %d since %s, continue", REPO_ID(pRepo), fset.fid, tstrerror(terrno));
continue;
}
for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
SDFile *pDFile = TSDB_DFILE_IN_SET(&fset, ftype);
if ((tsdbLoadDFileHeader(pDFile, &info) < 0) || pDFile->info.size != info.size ||
pDFile->info.magic != info.magic) {
if (tsdbUpdateDFileHeader(pDFile) < 0) {
tsdbError("vgId:%d failed to update DFile header of %s since %s, continue", REPO_ID(pRepo),
TSDB_FILE_FULL_NAME(pDFile), tstrerror(terrno));
} else {
tsdbInfo("vgId:%d DFile header of %s is updated", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile));
TSDB_FILE_FSYNC(pDFile);
}
} else {
tsdbDebug("vgId:%d DFile header of %s is correct", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile));
}
}
tsdbCloseDFileSet(&fset);
}
}

View File

@ -134,14 +134,14 @@ int tsdbCreateMFile(SMFile *pMFile, bool updateHeader) {
return 0; return 0;
} }
pMFile->info.size += TSDB_FILE_HEAD_SIZE;
if (tsdbUpdateMFileHeader(pMFile) < 0) { if (tsdbUpdateMFileHeader(pMFile) < 0) {
tsdbCloseMFile(pMFile); tsdbCloseMFile(pMFile);
tsdbRemoveMFile(pMFile); tsdbRemoveMFile(pMFile);
return -1; return -1;
} }
pMFile->info.size += TSDB_FILE_HEAD_SIZE;
return 0; return 0;
} }
@ -378,14 +378,14 @@ int tsdbCreateDFile(SDFile *pDFile, bool updateHeader) {
return 0; return 0;
} }
pDFile->info.size += TSDB_FILE_HEAD_SIZE;
if (tsdbUpdateDFileHeader(pDFile) < 0) { if (tsdbUpdateDFileHeader(pDFile) < 0) {
tsdbCloseDFile(pDFile); tsdbCloseDFile(pDFile);
tsdbRemoveDFile(pDFile); tsdbRemoveDFile(pDFile);
return -1; return -1;
} }
pDFile->info.size += TSDB_FILE_HEAD_SIZE;
return 0; return 0;
} }
@ -567,6 +567,7 @@ void tsdbInitDFileSet(SDFileSet *pSet, SDiskID did, int vid, int fid, uint32_t v
} }
void tsdbInitDFileSetEx(SDFileSet *pSet, SDFileSet *pOSet) { void tsdbInitDFileSetEx(SDFileSet *pSet, SDFileSet *pOSet) {
pSet->fid = pOSet->fid;
for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) { for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
tsdbInitDFileEx(TSDB_DFILE_IN_SET(pSet, ftype), TSDB_DFILE_IN_SET(pOSet, ftype)); tsdbInitDFileEx(TSDB_DFILE_IN_SET(pSet, ftype), TSDB_DFILE_IN_SET(pOSet, ftype));
} }

View File

@ -917,7 +917,9 @@ static int32_t loadBlockInfo(STsdbQueryHandle * pQueryHandle, int32_t index, int
pCheckInfo->compSize = compIndex->len; pCheckInfo->compSize = compIndex->len;
} }
tsdbLoadBlockInfo(&(pQueryHandle->rhelper), (void*)(pCheckInfo->pCompInfo)); if (tsdbLoadBlockInfo(&(pQueryHandle->rhelper), (void*)(pCheckInfo->pCompInfo)) < 0) {
return terrno;
}
SBlockInfo* pCompInfo = pCheckInfo->pCompInfo; SBlockInfo* pCompInfo = pCheckInfo->pCompInfo;
TSKEY s = TSKEY_INITIAL_VAL, e = TSKEY_INITIAL_VAL; TSKEY s = TSKEY_INITIAL_VAL, e = TSKEY_INITIAL_VAL;
@ -2832,7 +2834,9 @@ int32_t tsdbRetrieveDataBlockStatisInfo(TsdbQueryHandleT* pQueryHandle, SDataSta
} }
int64_t stime = taosGetTimestampUs(); int64_t stime = taosGetTimestampUs();
tsdbLoadBlockStatis(&pHandle->rhelper, pBlockInfo->compBlock); if (tsdbLoadBlockStatis(&pHandle->rhelper, pBlockInfo->compBlock) < 0) {
return terrno;
}
int16_t* colIds = pHandle->defaultLoadColumn->pData; int16_t* colIds = pHandle->defaultLoadColumn->pData;

View File

@ -194,8 +194,8 @@ static int32_t tsdbSyncRecvMeta(SSyncH *pSynch) {
return 0; return 0;
} }
if (pLMFile == NULL || memcmp(&(pSynch->pmf->info), &(pLMFile->info), sizeof(SMFInfo)) != 0 || if (pLMFile == NULL || pSynch->pmf->info.size != pLMFile->info.size ||
TSDB_FILE_IS_BAD(pLMFile)) { pSynch->pmf->info.magic != pLMFile->info.magic || TSDB_FILE_IS_BAD(pLMFile)) {
// Local has no meta file or has a different meta file, need to copy from remote // Local has no meta file or has a different meta file, need to copy from remote
pSynch->mfChanged = true; pSynch->mfChanged = true;
@ -536,7 +536,7 @@ static bool tsdbIsTowFSetSame(SDFileSet *pSet1, SDFileSet *pSet2) {
SDFile *pDFile1 = TSDB_DFILE_IN_SET(pSet1, ftype); SDFile *pDFile1 = TSDB_DFILE_IN_SET(pSet1, ftype);
SDFile *pDFile2 = TSDB_DFILE_IN_SET(pSet2, ftype); SDFile *pDFile2 = TSDB_DFILE_IN_SET(pSet2, ftype);
if (memcmp((void *)(TSDB_FILE_INFO(pDFile1)), (void *)(TSDB_FILE_INFO(pDFile2)), sizeof(SDFInfo)) != 0) { if (pDFile1->info.size != pDFile2->info.size || pDFile1->info.magic != pDFile2->info.magic) {
return false; return false;
} }
} }

View File

@ -25,6 +25,7 @@ int32_t vnodeCreate(SCreateVnodeMsg *pVnodeCfg);
int32_t vnodeDrop(int32_t vgId); int32_t vnodeDrop(int32_t vgId);
int32_t vnodeOpen(int32_t vgId); int32_t vnodeOpen(int32_t vgId);
int32_t vnodeAlter(void *pVnode, SCreateVnodeMsg *pVnodeCfg); int32_t vnodeAlter(void *pVnode, SCreateVnodeMsg *pVnodeCfg);
int32_t vnodeSync(int32_t vgId);
int32_t vnodeClose(int32_t vgId); int32_t vnodeClose(int32_t vgId);
void vnodeCleanUp(SVnodeObj *pVnode); void vnodeCleanUp(SVnodeObj *pVnode);
void vnodeDestroy(SVnodeObj *pVnode); void vnodeDestroy(SVnodeObj *pVnode);

View File

@ -91,6 +91,23 @@ int32_t vnodeCreate(SCreateVnodeMsg *pVnodeCfg) {
return code; return code;
} }
int32_t vnodeSync(int32_t vgId) {
SVnodeObj *pVnode = vnodeAcquire(vgId);
if (pVnode == NULL) {
vDebug("vgId:%d, failed to sync, vnode not find", vgId);
return TSDB_CODE_VND_INVALID_VGROUP_ID;
}
if (pVnode->role != TAOS_SYNC_ROLE_MASTER) {
vInfo("vgId:%d, vnode will sync, refCount:%d pVnode:%p", pVnode->vgId, pVnode->refCount, pVnode);
syncRecover(pVnode->sync);
}
vnodeRelease(pVnode);
return TSDB_CODE_SUCCESS;
}
int32_t vnodeDrop(int32_t vgId) { int32_t vnodeDrop(int32_t vgId) {
SVnodeObj *pVnode = vnodeAcquire(vgId); SVnodeObj *pVnode = vnodeAcquire(vgId);
if (pVnode == NULL) { if (pVnode == NULL) {

39
tests/Jenkinsfile vendored
View File

@ -1,9 +1,8 @@
def pre_test(){ def pre_test(){
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh ''' sh '''
sudo rmtaos sudo rmtaos||echo 'no taosd installed'
''' '''
}
sh ''' sh '''
cd ${WKC} cd ${WKC}
git reset --hard git reset --hard
@ -56,14 +55,8 @@ pipeline {
cd ${WKC}/tests cd ${WKC}/tests
./test-all.sh b1 ./test-all.sh b1
date''' date'''
sh '''
cd ${WKC}/tests
./test-all.sh full jdbc
date'''
sh '''
cd ${WKC}/tests
./test-all.sh full unit
date'''
} }
} }
@ -83,9 +76,20 @@ pipeline {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh ''' sh '''
cd ${WKC}/tests/pytest cd ${WKC}/tests/pytest
rm -rf /var/lib/taos/*
rm -rf /var/log/taos/*
./handle_crash_gen_val_log.sh ./handle_crash_gen_val_log.sh
''' '''
} }
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh '''
cd ${WKC}/tests/pytest
rm -rf /var/lib/taos/*
rm -rf /var/log/taos/*
./handle_taosd_val_log.sh
'''
}
sh''' sh'''
systemctl start taosd systemctl start taosd
sleep 10 sleep 10
@ -136,6 +140,10 @@ pipeline {
./test-all.sh b2 ./test-all.sh b2
date date
''' '''
sh '''
cd ${WKC}/tests
./test-all.sh full unit
date'''
} }
} }
@ -154,6 +162,10 @@ pipeline {
''' '''
} }
sh ''' sh '''
cd ${WKC}/tests
./test-all.sh full jdbc
date'''
sh '''
cd ${WKC}/tests/pytest cd ${WKC}/tests/pytest
./valgrind-test.sh 2>&1 > mem-error-out.log ./valgrind-test.sh 2>&1 > mem-error-out.log
./handle_val_log.sh ./handle_val_log.sh
@ -162,6 +174,11 @@ pipeline {
cd ${WKC}/tests cd ${WKC}/tests
./test-all.sh b3 ./test-all.sh b3
date''' date'''
sh '''
date
cd ${WKC}/tests
./test-all.sh full example
date'''
} }
} }

View File

@ -13,7 +13,7 @@
<dependency> <dependency>
<groupId>com.taosdata.jdbc</groupId> <groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId> <artifactId>taos-jdbcdriver</artifactId>
<version>2.0.20</version> <version>2.0.22</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -38,7 +38,7 @@
"insert_rows": 100, "insert_rows": 100,
"multi_thread_write_one_tbl": "no", "multi_thread_write_one_tbl": "no",
"number_of_tbl_in_one_sql": 0, "number_of_tbl_in_one_sql": 0,
"rows_per_tbl": 3, "interlace_rows": 3,
"max_sql_len": 1024, "max_sql_len": 1024,
"disorder_ratio": 0, "disorder_ratio": 0,
"disorder_range": 1000, "disorder_range": 1000,

View File

@ -163,6 +163,16 @@ int main(int argc, char *argv[])
getchar(); getchar();
while(1) {
if (tablesProcessed < numOfTables) {
printf("wait for process finished\n");
sleep(1);
continue;
}
break;
}
taos_close(taos); taos_close(taos);
free(tableList); free(tableList);

View File

@ -50,7 +50,7 @@ function buildTDengine {
echo "repo up-to-date" echo "repo up-to-date"
else else
echo "repo need to pull" echo "repo need to pull"
git pull > /dev/null git pull > /dev/null 2>&1
LOCAL_COMMIT=`git rev-parse --short @` LOCAL_COMMIT=`git rev-parse --short @`
cd debug cd debug
@ -72,26 +72,13 @@ function runQueryPerfTest {
python3 insert/insertFromCSVPerformance.py -c $LOCAL_COMMIT | tee -a $PERFORMANCE_TEST_REPORT python3 insert/insertFromCSVPerformance.py -c $LOCAL_COMMIT | tee -a $PERFORMANCE_TEST_REPORT
yes | taosdemo -c /etc/taosperf/ -d taosdemo_insert_test -x > taosdemoperf.txt python3 tools/taosdemoPerformance.py -c $LOCAL_COMMIT | tee -a $PERFORMANCE_TEST_REPORT
CREATETABLETIME=`grep 'Spent' taosdemoperf.txt | awk 'NR==1{print $2}'`
INSERTRECORDSTIME=`grep 'Spent' taosdemoperf.txt | awk 'NR==2{print $2}'`
REQUESTSPERSECOND=`grep 'Spent' taosdemoperf.txt | awk 'NR==2{print $13}'`
delay=`grep 'delay' taosdemoperf.txt | awk '{print $4}'`
AVGDELAY=`echo ${delay:0:${#delay}-3}`
delay=`grep 'delay' taosdemoperf.txt | awk '{print $6}'`
MAXDELAY=`echo ${delay:0:${#delay}-3}`
delay=`grep 'delay' taosdemoperf.txt | awk '{print $8}'`
MINDELAY=`echo ${delay:0:${#delay}-2}`
python3 tools/taosdemoPerformance.py -c $LOCAL_COMMIT -t $CREATETABLETIME -i $INSERTRECORDSTIME -r $REQUESTSPERSECOND -avg $AVGDELAY -max $MAXDELAY -min $MINDELAY | tee -a $PERFORMANCE_TEST_REPORT
[ -f taosdemoperf.txt ] && rm taosdemoperf.txt
} }
function sendReport { function sendReport {
echo "send report" echo "send report"
receiver="pxiao@taosdata.com" receiver="develop@taosdata.com"
mimebody="MIME-Version: 1.0\nContent-Type: text/html; charset=utf-8\n" mimebody="MIME-Version: 1.0\nContent-Type: text/html; charset=utf-8\n"
cd $TDENGINE_DIR cd $TDENGINE_DIR

View File

@ -68,20 +68,14 @@ function prepareBuild {
rm -rf $CURR_DIR/../../../../release/* rm -rf $CURR_DIR/../../../../release/*
fi fi
if [ ! -e $DOCKER_DIR/TDengine-server-$VERSION-Linux-x64.tar.gz ] || [ ! -e $DOCKER_DIR/TDengine-arbitrator-$VERSION-Linux-x64.tar.gz ]; then
cd $CURR_DIR/../../../../packaging cd $CURR_DIR/../../../../packaging
echo $CURR_DIR
echo $IN_TDINTERNAL
echo "generating TDeninger packages"
if [[ "$CURR_DIR" == *"$IN_TDINTERNAL"* ]]; then
pwd
./release.sh -v cluster -n $VERSION >> /dev/null 2>&1
else
pwd
./release.sh -v edge -n $VERSION >> /dev/null 2>&1
fi
if [[ "$CURR_DIR" == *"$IN_TDINTERNAL"* ]]; then if [[ "$CURR_DIR" == *"$IN_TDINTERNAL"* ]]; then
if [ ! -e $DOCKER_DIR/TDengine-enterprise-server-$VERSION-Linux-x64.tar.gz ] || [ ! -e $DOCKER_DIR/TDengine-enterprise-arbitrator-$VERSION-Linux-x64.tar.gz ]; then
echo "generating TDeninge enterprise packages"
./release.sh -v cluster -n $VERSION >> /dev/null 2>&1
if [ ! -e $CURR_DIR/../../../../release/TDengine-enterprise-server-$VERSION-Linux-x64.tar.gz ]; then if [ ! -e $CURR_DIR/../../../../release/TDengine-enterprise-server-$VERSION-Linux-x64.tar.gz ]; then
echo "no TDengine install package found" echo "no TDengine install package found"
exit 1 exit 1
@ -91,7 +85,17 @@ function prepareBuild {
echo "no arbitrator install package found" echo "no arbitrator install package found"
exit 1 exit 1
fi fi
cd $CURR_DIR/../../../../release
mv TDengine-enterprise-server-$VERSION-Linux-x64.tar.gz $DOCKER_DIR
mv TDengine-enterprise-arbitrator-$VERSION-Linux-x64.tar.gz $DOCKER_DIR
fi
else else
if [ ! -e $DOCKER_DIR/TDengine-server-$VERSION-Linux-x64.tar.gz ] || [ ! -e $DOCKER_DIR/TDengine-arbitrator-$VERSION-Linux-x64.tar.gz ]; then
echo "generating TDeninge community packages"
./release.sh -v edge -n $VERSION >> /dev/null 2>&1
if [ ! -e $CURR_DIR/../../../../release/TDengine-server-$VERSION-Linux-x64.tar.gz ]; then if [ ! -e $CURR_DIR/../../../../release/TDengine-server-$VERSION-Linux-x64.tar.gz ]; then
echo "no TDengine install package found" echo "no TDengine install package found"
exit 1 exit 1
@ -101,13 +105,8 @@ function prepareBuild {
echo "no arbitrator install package found" echo "no arbitrator install package found"
exit 1 exit 1
fi fi
fi
cd $CURR_DIR/../../../../release cd $CURR_DIR/../../../../release
if [[ "$CURR_DIR" == *"$IN_TDINTERNAL"* ]]; then
mv TDengine-enterprise-server-$VERSION-Linux-x64.tar.gz $DOCKER_DIR
mv TDengine-enterprise-arbitrator-$VERSION-Linux-x64.tar.gz $DOCKER_DIR
else
mv TDengine-server-$VERSION-Linux-x64.tar.gz $DOCKER_DIR mv TDengine-server-$VERSION-Linux-x64.tar.gz $DOCKER_DIR
mv TDengine-arbitrator-$VERSION-Linux-x64.tar.gz $DOCKER_DIR mv TDengine-arbitrator-$VERSION-Linux-x64.tar.gz $DOCKER_DIR
fi fi

View File

@ -39,7 +39,7 @@
"insert_rows": 100000, "insert_rows": 100000,
"multi_thread_write_one_tbl": "no", "multi_thread_write_one_tbl": "no",
"number_of_tbl_in_one_sql": 1, "number_of_tbl_in_one_sql": 1,
"rows_per_tbl": 100, "interlace_rows": 100,
"max_sql_len": 1024000, "max_sql_len": 1024000,
"disorder_ratio": 0, "disorder_ratio": 0,
"disorder_range": 1000, "disorder_range": 1000,

View File

@ -164,6 +164,11 @@ python3 ./test.py -f user/pass_len.py
# stable # stable
python3 ./test.py -f stable/query_after_reset.py python3 ./test.py -f stable/query_after_reset.py
# perfbenchmark
python3 ./test.py -f perfbenchmark/bug3433.py
python3 ./test.py -f perfbenchmark/bug3589.py
#query #query
python3 ./test.py -f query/filter.py python3 ./test.py -f query/filter.py
python3 ./test.py -f query/filterCombo.py python3 ./test.py -f query/filterCombo.py
@ -196,6 +201,9 @@ python3 ./test.py -f query/bug2119.py
python3 ./test.py -f query/isNullTest.py python3 ./test.py -f query/isNullTest.py
python3 ./test.py -f query/queryWithTaosdKilled.py python3 ./test.py -f query/queryWithTaosdKilled.py
python3 ./test.py -f query/floatCompare.py python3 ./test.py -f query/floatCompare.py
python3 ./test.py -f query/bug3375.py
#stream #stream
python3 ./test.py -f stream/metric_1.py python3 ./test.py -f stream/metric_1.py
@ -230,16 +238,6 @@ python3 client/twoClients.py
python3 test.py -f query/queryInterval.py python3 test.py -f query/queryInterval.py
python3 test.py -f query/queryFillTest.py python3 test.py -f query/queryFillTest.py
# tools
python3 test.py -f tools/taosdemoTest.py
python3 test.py -f tools/taosdemoTestWithoutMetric.py
python3 test.py -f tools/taosdemoTestWithJson.py
python3 test.py -f tools/taosdemoTestLimitOffset.py
python3 test.py -f tools/taosdumpTest.py
python3 test.py -f tools/taosdemoTest2.py
python3 test.py -f tools/taosdemoTestSampleData.py
python3 test.py -f tools/taosdemoTestInterlace.py
# subscribe # subscribe
python3 test.py -f subscribe/singlemeter.py python3 test.py -f subscribe/singlemeter.py
#python3 test.py -f subscribe/stability.py #python3 test.py -f subscribe/stability.py
@ -249,6 +247,18 @@ python3 test.py -f subscribe/supertable.py
#======================p3-end=============== #======================p3-end===============
#======================p4-start=============== #======================p4-start===============
# tools
python3 test.py -f tools/taosdumpTest.py
python3 test.py -f tools/taosdemoTest.py
python3 test.py -f tools/taosdemoTestWithoutMetric.py
python3 test.py -f tools/taosdemoTestWithJson.py
python3 test.py -f tools/taosdemoTestLimitOffset.py
python3 test.py -f tools/taosdemoTest2.py
python3 test.py -f tools/taosdemoTestSampleData.py
python3 test.py -f tools/taosdemoTestInterlace.py
python3 test.py -f tools/taosdemoTestQuery.py
python3 ./test.py -f update/merge_commit_data-0.py python3 ./test.py -f update/merge_commit_data-0.py
# wal # wal
python3 ./test.py -f wal/addOldWalTest.py python3 ./test.py -f wal/addOldWalTest.py

View File

@ -0,0 +1,68 @@
#!/bin/bash
# Color setting
RED='\033[0;31m'
GREEN='\033[1;32m'
GREEN_DARK='\033[0;32m'
GREEN_UNDERLINE='\033[4;32m'
NC='\033[0m'
IN_TDINTERNAL="community"
TDIR=`pwd`
if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]]; then
cd ../..
else
cd ../../..
fi
TOP_DIR=`pwd`
TAOSD_DIR=`find . -name "taosd"|grep -v community|grep debug|head -n1`
VALGRIND_OUT=taosd_valgrind.out
VALGRIND_ERR=taosd_valgrind.err
rm -rf /var/lib/taos/*
# nohup valgrind --tool=memcheck --leak-check=yes $TAOSD_DIR > $TDIR/$VALGRIND_OUT 2> $TDIR/$VALGRIND_ERR &
nohup valgrind --leak-check=yes $TAOSD_DIR > $TDIR/$VALGRIND_OUT 2> $TDIR/$VALGRIND_ERR &
sleep 20
cd -
./crash_gen.sh -p -t 10 -s 200
ps -ef |grep valgrind|grep -v grep|awk '{print $2}'|xargs kill -term
while true
do
monitoring=` ps -ef|grep valgrind |grep -v grep| wc -l`
if [ $monitoring -eq 0 ]
then
echo "Manipulator is not running "
break
else
sleep 1
fi
done
grep 'start to execute\|ERROR SUMMARY' $VALGRIND_ERR | grep -v 'grep' | uniq | tee taosd_mem_err.log
for memError in `grep 'ERROR SUMMARY' taosd_mem_err.log | awk '{print $4}'`
do
memError=(${memError//,/})
if [ -n "$memError" ]; then
if [ "$memError" -gt 12 ]; then
echo -e "${RED} ## Memory errors number valgrind reports is $memError.\
More than our threshold! ## ${NC}"
fi
fi
done
grep 'start to execute\|definitely lost:' $VALGRIND_ERR|grep -v 'grep'|uniq|tee taosd-definitely-lost-out.log
for defiMemError in `grep 'definitely lost:' taosd-definitely-lost-out.log | awk '{print $7}'`
do
defiMemError=(${defiMemError//,/})
if [ -n "$defiMemError" ]; then
if [ "$defiMemError" -gt 0 -a "$defiMemError" -lt 1013 ]; then
cat $VALGRIND_ERR
echo -e "${RED} ## Memory errors number valgrind reports \
Definitely lost is $defiMemError. More than our threshold! ## ${NC}"
exit 8
elif [ "$defiMemError" -gt 1013 ];then #add for azure
cat $VALGRIND_ERR
echo -e "${RED} ## Memory errors number valgrind reports \
Definitely lost is $defiMemError. More than our threshold! ## ${NC}"
exit 8
fi
fi
done

View File

@ -25,6 +25,8 @@ class TDTestCase:
tdSql.init(conn.cursor(), logSql) tdSql.init(conn.cursor(), logSql)
self.ts = 1538548685000 self.ts = 1538548685000
self.tables = 10
self.rows = 1000
def updateMetadata(self): def updateMetadata(self):
self.host = "127.0.0.1" self.host = "127.0.0.1"
@ -37,6 +39,29 @@ class TDTestCase:
self.cursor.execute("alter table db.tb add column col2 int") self.cursor.execute("alter table db.tb add column col2 int")
print("alter table done") print("alter table done")
def deleteTableAndRecreate(self):
self.host = "127.0.0.1"
self.user = "root"
self.password = "taosdata"
self.config = tdDnodes.getSimCfgPath()
self.conn = taos.connect(host = self.host, user = self.user, password = self.password, config = self.config)
self.cursor = self.conn.cursor()
self.cursor.execute("use test")
print("drop table stb")
self.cursor.execute("drop table stb")
print("create table stb")
self.cursor.execute("create table if not exists stb (ts timestamp, col1 int) tags(areaid int, city nchar(20))")
print("insert data")
for i in range(self.tables):
city = "beijing" if i % 2 == 0 else "shanghai"
self.cursor.execute("create table tb%d using stb tags(%d, '%s')" % (i, i, city))
for j in range(self.rows):
self.cursor.execute("insert into tb%d values(%d, %d)" % (i, self.ts + j, j * 100000))
def run(self): def run(self):
tdSql.prepare() tdSql.prepare()
@ -59,6 +84,36 @@ class TDTestCase:
tdSql.query("select * from tb") tdSql.query("select * from tb")
tdSql.checkRows(2) tdSql.checkRows(2)
# Add test case: https://jira.taosdata.com:18080/browse/TD-3474
print("==============step1")
tdSql.execute("create database test")
tdSql.execute("use test")
tdSql.execute("create table if not exists stb (ts timestamp, col1 int) tags(areaid int, city nchar(20))")
for i in range(self.tables):
city = "beijing" if i % 2 == 0 else "shanghai"
tdSql.execute("create table tb%d using stb tags(%d, '%s')" % (i, i, city))
for j in range(self.rows):
tdSql.execute("insert into tb%d values(%d, %d)" % (i, self.ts + j, j * 100000))
tdSql.query("select count(*) from stb")
tdSql.checkData(0, 0, 10000)
tdSql.query("select count(*) from tb1")
tdSql.checkData(0, 0, 1000)
p = Process(target=self.deleteTableAndRecreate, args=())
p.start()
p.join()
p.terminate()
tdSql.query("select count(*) from stb")
tdSql.checkData(0, 0, 10000)
tdSql.query("select count(*) from tb1")
tdSql.checkData(0, 0, 1000)
def stop(self): def stop(self):
tdSql.close() tdSql.close()
tdLog.success("%s successfully executed" % __file__) tdLog.success("%s successfully executed" % __file__)

Some files were not shown because too many files have changed in this diff Show More