[td-225] merge develop

This commit is contained in:
Haojun Liao 2021-04-02 16:40:44 +08:00
commit 0146d60cbb
166 changed files with 10685 additions and 4549 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)

35
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()
@ -24,7 +25,7 @@ def abortPreviousBuilds() {
build.doKill() //doTerm(),doKill(),doTerm() build.doKill() //doTerm(),doKill(),doTerm()
} }
} }
//abort previous build // abort previous build
abortPreviousBuilds() abortPreviousBuilds()
def abort_previous(){ def abort_previous(){
def buildNumber = env.BUILD_NUMBER as int def buildNumber = env.BUILD_NUMBER as int
@ -32,20 +33,21 @@ def abort_previous(){
milestone(buildNumber) milestone(buildNumber)
} }
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 reset --hard HEAD~10 >/dev/null git reset --hard HEAD~10 >/dev/null
git checkout develop
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' git clean -dfx
find ${WKC}/tests/pytest -name \'*\'.sql -exec rm -rf {} \\;
cd ${WK} cd ${WK}
git reset --hard HEAD~10 git reset --hard HEAD~10
git checkout develop git checkout develop
@ -53,7 +55,7 @@ def pre_test(){
cd ${WK} cd ${WK}
export TZ=Asia/Harbin export TZ=Asia/Harbin
date date
rm -rf ${WK}/debug git clean -dfx
mkdir debug mkdir debug
cd debug cd debug
cmake .. > /dev/null cmake .. > /dev/null
@ -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'''
} }
} }
} }
@ -266,7 +285,7 @@ pipeline {
date date
cd ${WKC}/tests cd ${WKC}/tests
./test-all.sh b7fq ./test-all.sh b7fq
date''' date'''
} }
} }
} }

View File

@ -258,10 +258,16 @@ TDengine 社区生态中也有一些非常友好的第三方连接器,可以
TDengine 的测试框架和所有测试例全部开源。 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.25-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,19 +179,20 @@ 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** | **华为 EulerOS** |
| -------------- | --------------------- | ------------------------ | --------------- | --------------- | ------------------------- | --------------------- | | -------------- | --------------------- | ------------------------ | --------------- | --------------- | ------------------------- | --------------------- | --------------------- |
| X64 | ● | ● | | ○ | ● | ● | | X64 | ● | ● | | ○ | ● | ● | ● |
| 树莓派ARM32 | | ● | ● | | | | | 树莓派 ARM32 | | ● | ● | | | | |
| 龙芯MIPS64 | | | ● | | | | | 龙芯 MIPS64 | | | ● | | | | |
| 鲲鹏 ARM64 | | ○ | ○ | | ● | | | 鲲鹏 ARM64 | | ○ | ○ | | ● | | |
| 申威 Alpha64 | | | ○ | ● | | | | 申威 Alpha64 | | | ○ | ● | | | |
| 飞腾ARM64 | | ○优麒麟 | | | | | | 飞腾 ARM64 | | ○ 优麒麟 | | | | | |
| 海光X64 | ● | ● | ● | ○ | ● | ● | | 海光 X64 | ● | ● | ● | ○ | ● | ● | |
| 瑞芯微ARM64/32 | | | ○ | | | | | 瑞芯微 ARM64/32 | | | ○ | | | | |
| 全志ARM64/32 | | | ○ | | | | | 全志 ARM64/32 | | | ○ | | | | |
| 炬力ARM64/32 | | | ○ | | | | | 炬力 ARM64/32 | | | ○ | | | | |
| TI ARM32 | | | ○ | | | | | TI ARM32 | | | ○ | | | | |
| 华为云 ARM64 | | | | | | | ● |
注: ● 表示经过官方测试验证, ○ 表示非官方测试验证。 注: ● 表示经过官方测试验证, ○ 表示非官方测试验证。
@ -203,7 +204,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

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

@ -29,21 +29,21 @@ taos> DESCRIBE meters;
## <a class="anchor" id="data-type"></a>支持的数据类型 ## <a class="anchor" id="data-type"></a>支持的数据类型
使用TDengine最重要的是时间戳。创建并插入记录、查询历史记录的时候均需要指定时间戳。时间戳有如下规则 使用 TDengine最重要的是时间戳。创建并插入记录、查询历史记录的时候均需要指定时间戳。时间戳有如下规则
- 时间格式为```YYYY-MM-DD HH:mm:ss.MS```, 默认时间分辨率为毫秒。比如:```2017-08-12 18:25:58.128``` - 时间格式为 ```YYYY-MM-DD HH:mm:ss.MS```默认时间分辨率为毫秒。比如:```2017-08-12 18:25:58.128```
- 内部函数now是服务器的当前时间 - 内部函数 now 是客户端的当前时间
- 插入记录时,如果时间戳为now插入数据时使用服务器当前时间 - 插入记录时,如果时间戳为 now插入数据时使用提交这条记录的客户端的当前时间
- Epoch Time: 时间戳也可以是一个长整数表示从1970-01-01 08:00:00.000开始的毫秒数 - Epoch Time:时间戳也可以是一个长整数,表示从 1970-01-01 08:00:00.000 开始的毫秒数
- 时间可以加减,比如 now-2h表明查询时刻向前推2个小时(最近2小时)。 数字后面的时间单位可以是 a(毫秒)、s(秒)、 m(分)、h(小时)、d(天)、w(周)。 比如select * from t1 where ts > now-2w and ts <= now-1w, 表示查询两周前整整一周的数据。 在指定降频操作(down sampling)的时间窗口(interval)时,时间单位还可以使用 n(自然月) 和 y(自然年)。 - 时间可以加减,比如 now-2h表明查询时刻向前推 2 个小时(最近 2 小时)。数字后面的时间单位可以是 u(微秒)、a(毫秒)、s(秒)、m(分)、h(小时)、d(天)、w(周)。 比如 `select * from t1 where ts > now-2w and ts <= now-1w`表示查询两周前整整一周的数据。在指定降频操作down sampling的时间窗口interval时,时间单位还可以使用 n(自然月) 和 y(自然年)。
TDengine缺省的时间戳是毫秒精度但通过修改配置参数enableMicrosecond就可支持微秒。 TDengine 缺省的时间戳是毫秒精度,但通过修改配置参数 enableMicrosecond 就可支持微秒。
在TDengine中普通表的数据模型中可使用以下10种数据类型。 在TDengine中普通表的数据模型中可使用以下 10 种数据类型。
| | 类型 | Bytes | 说明 | | | 类型 | Bytes | 说明 |
| ---- | :-------: | ------ | ------------------------------------------------------------ | | ---- | :-------: | ------ | ------------------------------------------------------------ |
| 1 | TIMESTAMP | 8 | 时间戳。缺省精度毫秒,可支持微秒。从格林威治时间 1970-01-01 00:00:00.000 (UTC/GMT) 开始,计时不能早于该时间。 | | 1 | TIMESTAMP | 8 | 时间戳。缺省精度毫秒,可支持微秒。从格林威治时间 1970-01-01 00:00:00.000 (UTC/GMT) 开始,计时不能早于该时间。(从 2.0.18 版本开始,已经去除了这一时间范围限制) |
| 2 | INT | 4 | 整型,范围 [-2^31+1, 2^31-1], -2^31 用作 NULL | | 2 | INT | 4 | 整型,范围 [-2^31+1, 2^31-1], -2^31 用作 NULL |
| 3 | BIGINT | 8 | 长整型,范围 [-2^63+1, 2^63-1], -2^63 用于 NULL | | 3 | BIGINT | 8 | 长整型,范围 [-2^63+1, 2^63-1], -2^63 用于 NULL |
| 4 | FLOAT | 4 | 浮点型,有效位数 6-7范围 [-3.4E38, 3.4E38] | | 4 | FLOAT | 4 | 浮点型,有效位数 6-7范围 [-3.4E38, 3.4E38] |

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

@ -120,7 +120,7 @@ function clean_service_on_systemd() {
if [ "$verMode" == "cluster" ]; then if [ "$verMode" == "cluster" ]; then
nginx_service_config="${service_config_dir}/${nginx_service_name}.service" nginx_service_config="${service_config_dir}/${nginx_service_name}.service"
if [ -d ${bin_dir}/web ]; then if [ -d ${install_nginxd_dir} ]; then
if systemctl is-active --quiet ${nginx_service_name}; then if systemctl is-active --quiet ${nginx_service_name}; then
echo "Nginx for TDengine is running, stopping it..." echo "Nginx for TDengine is running, stopping it..."
${csudo} systemctl stop ${nginx_service_name} &> /dev/null || echo &> /dev/null ${csudo} systemctl stop ${nginx_service_name} &> /dev/null || echo &> /dev/null

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>
@ -192,7 +208,9 @@ void tscSqlExprAssign(SExprInfo* dst, const SExprInfo* src);
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, SSchema* pSchema); SColumn* tscColumnListInsert(SArray* pColList, SColumnIndex* colIndex, SSchema* pSchema);
SArray* tscColumnListClone(const SArray* src, int16_t tableIndex);
void tscColumnListDestroy(SArray* pColList); void tscColumnListDestroy(SArray* pColList);
void tscDequoteAndTrimToken(SStrToken* pToken); void tscDequoteAndTrimToken(SStrToken* pToken);

View File

@ -126,15 +126,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 {
@ -279,7 +279,7 @@ typedef struct {
char * pRsp; char * pRsp;
int32_t rspType; int32_t rspType;
int32_t rspLen; int32_t rspLen;
uint64_t qid; uint64_t qId;
int64_t useconds; int64_t useconds;
int64_t offset; // offset value from vnode during projection query of stable int64_t offset; // offset value from vnode during projection query of stable
int32_t row; int32_t row;
@ -362,7 +362,7 @@ typedef struct SSqlObj {
int64_t svgroupRid; int64_t svgroupRid;
int64_t squeryLock; int64_t squeryLock;
int32_t retryReason; // previous error code
struct SSqlObj *prev, *next; struct SSqlObj *prev, *next;
int64_t self; int64_t self;
} SSqlObj; } SSqlObj;
@ -435,6 +435,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

@ -161,8 +161,8 @@ static void tscProcessAsyncRetrieveImpl(void *param, TAOS_RES *tres, int numOfRo
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
if ((pRes->qid == 0 || numOfRows != 0) && pCmd->command < TSDB_SQL_LOCAL) { if ((pRes->qId == 0 || numOfRows != 0) && pCmd->command < TSDB_SQL_LOCAL) {
if (pRes->qid == 0 && numOfRows != 0) { if (pRes->qId == 0 && numOfRows != 0) {
tscError("qhandle is NULL"); tscError("qhandle is NULL");
} else { } else {
pRes->code = numOfRows; pRes->code = numOfRows;
@ -210,7 +210,7 @@ void taos_fetch_rows_a(TAOS_RES *tres, __async_cb_func_t fp, void *param) {
pSql->fp = tscAsyncFetchRowsProxy; pSql->fp = tscAsyncFetchRowsProxy;
pSql->param = param; pSql->param = param;
if (pRes->qid == 0) { if (pRes->qId == 0) {
tscError("qhandle is invalid"); tscError("qhandle is invalid");
pRes->code = TSDB_CODE_TSC_INVALID_QHANDLE; pRes->code = TSDB_CODE_TSC_INVALID_QHANDLE;
tscAsyncResultOnError(pSql); tscAsyncResultOnError(pSql);
@ -301,7 +301,7 @@ static void tscAsyncResultCallback(SSchedMsg *pMsg) {
taosReleaseRef(tscObjRef, pSql->self); taosReleaseRef(tscObjRef, pSql->self);
} }
void tscAsyncResultOnError(SSqlObj* pSql) { void tscAsyncResultOnError(SSqlObj* pSql) {
SSchedMsg schedMsg = {0}; SSchedMsg schedMsg = {0};
schedMsg.fp = tscAsyncResultCallback; schedMsg.fp = tscAsyncResultCallback;
schedMsg.ahandle = (void *)pSql->self; schedMsg.ahandle = (void *)pSql->self;
@ -310,10 +310,51 @@ void tscAsyncResultOnError(SSqlObj* pSql) {
taosScheduleTask(tscQhandle, &schedMsg); taosScheduleTask(tscQhandle, &schedMsg);
} }
int tscSendMsgToServer(SSqlObj *pSql); int tscSendMsgToServer(SSqlObj *pSql);
static int32_t updateMetaBeforeRetryQuery(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SQueryInfo* pQueryInfo) {
// handle the invalid table error code for super table.
// update the pExpr info, colList info, number of table columns
// TODO Re-parse this sql and issue the corresponding subquery as an alternative for this case.
if (pSql->retryReason == TSDB_CODE_TDB_INVALID_TABLE_ID) {
int32_t numOfExprs = (int32_t) tscSqlExprNumOfExprs(pQueryInfo);
int32_t numOfCols = tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
int32_t numOfTags = tscGetNumOfTags(pTableMetaInfo->pTableMeta);
SSchema *pSchema = tscGetTableSchema(pTableMetaInfo->pTableMeta);
for (int32_t i = 0; i < numOfExprs; ++i) {
SSqlExpr *pExpr = &(tscSqlExprGet(pQueryInfo, i)->base);
pExpr->uid = pTableMetaInfo->pTableMeta->id.uid;
if (pExpr->colInfo.colIndex >= 0) {
int32_t index = pExpr->colInfo.colIndex;
if ((TSDB_COL_IS_NORMAL_COL(pExpr->colInfo.flag) && index >= numOfCols) ||
(TSDB_COL_IS_TAG(pExpr->colInfo.flag) && (index < numOfCols || index >= (numOfCols + numOfTags)))) {
return pSql->retryReason;
}
if ((pSchema[pExpr->colInfo.colIndex].colId != pExpr->colInfo.colId) &&
strcasecmp(pExpr->colInfo.name, pSchema[pExpr->colInfo.colIndex].name) != 0) {
return pSql->retryReason;
}
}
}
// validate the table columns information
for (int32_t i = 0; i < taosArrayGetSize(pQueryInfo->colList); ++i) {
SColumn *pCol = taosArrayGetP(pQueryInfo->colList, i);
if (pCol->colIndex.columnIndex >= numOfCols) {
return pSql->retryReason;
}
}
} else {
// do nothing
}
return TSDB_CODE_SUCCESS;
}
void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) { void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
SSqlObj* pSql = (SSqlObj*)taosAcquireRef(tscObjRef, (int64_t)param); SSqlObj* pSql = (SSqlObj*)taosAcquireRef(tscObjRef, (int64_t)param);
if (pSql == NULL) return; if (pSql == NULL) return;
@ -339,7 +380,8 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, (TSDB_QUERY_TYPE_STABLE_SUBQUERY|TSDB_QUERY_TYPE_SUBQUERY|TSDB_QUERY_TYPE_TAG_FILTER_QUERY))) { if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, (TSDB_QUERY_TYPE_STABLE_SUBQUERY|TSDB_QUERY_TYPE_SUBQUERY|TSDB_QUERY_TYPE_TAG_FILTER_QUERY))) {
tscDebug("%p update local table meta, continue to process sql and send the corresponding query", pSql); tscDebug("%p update local table meta, continue to process sql and send the corresponding query", pSql);
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
code = tscGetTableMeta(pSql, pTableMetaInfo); code = tscGetTableMeta(pSql, pTableMetaInfo);
assert(code == TSDB_CODE_TSC_ACTION_IN_PROGRESS || code == TSDB_CODE_SUCCESS); assert(code == TSDB_CODE_TSC_ACTION_IN_PROGRESS || code == TSDB_CODE_SUCCESS);
@ -349,6 +391,10 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
} }
assert((tscGetNumOfTags(pTableMetaInfo->pTableMeta) != 0)); assert((tscGetNumOfTags(pTableMetaInfo->pTableMeta) != 0));
code = updateMetaBeforeRetryQuery(pSql, pTableMetaInfo, pQueryInfo);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
}
// tscProcessSql can add error into async res // tscProcessSql can add error into async res
tscProcessSql(pSql, NULL); tscProcessSql(pSql, NULL);
@ -463,10 +509,7 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
return; return;
_error: _error:
if (code != TSDB_CODE_SUCCESS) { pRes->code = code;
pSql->res.code = code; tscAsyncResultOnError(pSql);
tscAsyncResultOnError(pSql);
}
taosReleaseRef(tscObjRef, pSql->self); taosReleaseRef(tscObjRef, pSql->self);
} }

View File

@ -309,7 +309,7 @@ TAOS_ROW tscFetchRow(void *param) {
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
if (pRes->qid == 0 || if (pRes->qId == 0 ||
pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
pCmd->command == TSDB_SQL_INSERT) { pCmd->command == TSDB_SQL_INSERT) {
return NULL; return NULL;
@ -905,7 +905,7 @@ int tscProcessLocalCmd(SSqlObj *pSql) {
* set the qhandle to be 1 in order to pass the qhandle check, and to call partial release function to * set the qhandle to be 1 in order to pass the qhandle check, and to call partial release function to
* free allocated resources and remove the SqlObj from sql query linked list * free allocated resources and remove the SqlObj from sql query linked list
*/ */
pRes->qid = 0x1; pRes->qId = 0x1;
pRes->numOfRows = 0; pRes->numOfRows = 0;
} else if (pCmd->command == TSDB_SQL_SHOW_CREATE_TABLE) { } else if (pCmd->command == TSDB_SQL_SHOW_CREATE_TABLE) {
pRes->code = tscProcessShowCreateTable(pSql); pRes->code = tscProcessShowCreateTable(pSql);

View File

@ -381,6 +381,8 @@ void tscCreateLocalMerger(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrde
tsCreateSQLFunctionCtx(pQueryInfo, pReducer->pCtx, pschema); tsCreateSQLFunctionCtx(pQueryInfo, pReducer->pCtx, pschema);
setCtxInputOutputBuffer(pQueryInfo, pReducer->pCtx, pReducer, pDesc); setCtxInputOutputBuffer(pQueryInfo, pReducer->pCtx, pReducer, pDesc);
tfree(pschema);
// we change the capacity of schema to denote that there is only one row in temp buffer // we change the capacity of schema to denote that there is only one row in temp buffer
pReducer->pDesc->pColumnModel->capacity = 1; pReducer->pDesc->pColumnModel->capacity = 1;
@ -1624,7 +1626,7 @@ void tscInitResObjForLocalQuery(SSqlObj *pObj, int32_t numOfRes, int32_t rowLen)
tscDestroyLocalMerger(pObj); tscDestroyLocalMerger(pObj);
} }
pRes->qid = 1; // hack to pass the safety check in fetch_row function pRes->qId = 1; // hack to pass the safety check in fetch_row function
pRes->numOfRows = 0; pRes->numOfRows = 0;
pRes->row = 0; pRes->row = 0;

View File

@ -903,7 +903,7 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
return TSDB_CODE_TSC_OUT_OF_MEMORY; return TSDB_CODE_TSC_OUT_OF_MEMORY;
} }
pRes->qid = 0; pRes->qId = 0;
pRes->numOfRows = 1; pRes->numOfRows = 1;
strtolower(pSql->sqlstr, sql); strtolower(pSql->sqlstr, sql);

View File

@ -250,7 +250,7 @@ int tscBuildQueryStreamDesc(void *pMsg, STscObj *pObj) {
pQdesc->queryId = htonl(pSql->queryId); pQdesc->queryId = htonl(pSql->queryId);
//pQdesc->useconds = htobe64(pSql->res.useconds); //pQdesc->useconds = htobe64(pSql->res.useconds);
pQdesc->useconds = htobe64(now - pSql->stime); pQdesc->useconds = htobe64(now - pSql->stime);
pQdesc->qid = htobe64(pSql->res.qid); pQdesc->qId = htobe64(pSql->res.qId);
pHeartbeat->numOfQueries++; pHeartbeat->numOfQueries++;
pQdesc++; pQdesc++;

View File

@ -673,7 +673,18 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
if ((code = setKillInfo(pSql, pInfo, pInfo->type)) != TSDB_CODE_SUCCESS) { if ((code = setKillInfo(pSql, pInfo, pInfo->type)) != TSDB_CODE_SUCCESS) {
return code; return code;
} }
break;
}
case TSDB_SQL_SYNC_DB_REPLICA: {
const char* msg1 = "invalid db name";
SStrToken* pzName = taosArrayGet(pInfo->pMiscInfo->a, 0);
assert(taosArrayGetSize(pInfo->pMiscInfo->a) == 1);
code = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pzName);
if (code != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
break; break;
} }
@ -969,12 +980,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);
} }
@ -3288,7 +3305,8 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC
} }
if (pSchema->type == TSDB_DATA_TYPE_BOOL) { if (pSchema->type == TSDB_DATA_TYPE_BOOL) {
if (pExpr->tokenId != TK_EQ && pExpr->tokenId != TK_NE) { int32_t t = pExpr->tokenId;
if (t != TK_EQ && t != TK_NE && t != TK_NOTNULL && t != TK_ISNULL) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
} }
} }
@ -3354,23 +3372,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) {
@ -3380,14 +3400,28 @@ 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);
@ -3396,20 +3430,56 @@ 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, pTagSchema2);
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,
@ -3436,7 +3506,8 @@ static int32_t validateSQLExpr(SSqlCmd* pCmd, tSqlExpr* pExpr, SQueryInfo* pQuer
} }
pList->ids[pList->num++] = index; pList->ids[pList->num++] = index;
} else if (pExpr->tokenId == TK_FLOAT && (isnan(pExpr->value.dKey) || isinf(pExpr->value.dKey))) { } else if ((pExpr->tokenId == TK_FLOAT && (isnan(pExpr->value.dKey) || isinf(pExpr->value.dKey))) ||
pExpr->tokenId == TK_NULL) {
return TSDB_CODE_TSC_INVALID_SQL; return TSDB_CODE_TSC_INVALID_SQL;
} else if (pExpr->type == SQL_NODE_SQLFUNCTION) { } else if (pExpr->type == SQL_NODE_SQLFUNCTION) {
if (*type == NON_ARITHMEIC_EXPR) { if (*type == NON_ARITHMEIC_EXPR) {
@ -3670,17 +3741,49 @@ static int32_t setExprToCond(tSqlExpr** parent, tSqlExpr* pExpr, const char* msg
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
static int32_t validateNullExpr(tSqlExpr* pExpr, char* msgBuf) {
const char* msg = "only support is [not] null";
tSqlExpr* pRight = pExpr->pRight;
if (pRight->tokenId == TK_NULL && (!(pExpr->tokenId == TK_ISNULL || pExpr->tokenId == TK_NOTNULL))) {
return invalidSqlErrMsg(msgBuf, msg);
}
return TSDB_CODE_SUCCESS;
}
// check for like expression
static int32_t validateLikeExpr(tSqlExpr* pExpr, STableMeta* pTableMeta, int32_t index, char* msgBuf) {
const char* msg1 = "wildcard string should be less than 20 characters";
const char* msg2 = "illegal column name";
tSqlExpr* pLeft = pExpr->pLeft;
tSqlExpr* pRight = pExpr->pRight;
if (pExpr->tokenId == TK_LIKE) {
if (pRight->value.nLen > TSDB_PATTERN_STRING_MAX_LEN) {
return invalidSqlErrMsg(msgBuf, msg1);
}
SSchema* pSchema = tscGetTableSchema(pTableMeta);
if ((!isTablenameToken(&pLeft->colInfo)) && !IS_VAR_DATA_TYPE(pSchema[index].type)) {
return invalidSqlErrMsg(msgBuf, msg2);
}
}
return TSDB_CODE_SUCCESS;
}
static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr, static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr,
int32_t* type, int32_t parentOptr) { int32_t* type, int32_t parentOptr) {
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";
const char* msg8 = "wildcard string should be less than 20 characters";
tSqlExpr* pLeft = (*pExpr)->pLeft; tSqlExpr* pLeft = (*pExpr)->pLeft;
tSqlExpr* pRight = (*pExpr)->pRight; tSqlExpr* pRight = (*pExpr)->pRight;
@ -3696,6 +3799,18 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
// validate the null expression
int32_t code = validateNullExpr(*pExpr, tscGetErrorMsgPayload(pCmd));
if (code != TSDB_CODE_SUCCESS) {
return code;
}
// validate the like expression
code = validateLikeExpr(*pExpr, pTableMeta, index.columnIndex, tscGetErrorMsgPayload(pCmd));
if (code != TSDB_CODE_SUCCESS) {
return code;
}
if (index.columnIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) { // query on time range if (index.columnIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) { // query on time range
if (!validateJoinExprNode(pCmd, pQueryInfo, *pExpr, &index)) { if (!validateJoinExprNode(pCmd, pQueryInfo, *pExpr, &index)) {
return TSDB_CODE_TSC_INVALID_SQL; return TSDB_CODE_TSC_INVALID_SQL;
@ -3706,6 +3821,46 @@ 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;
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
@ -3723,20 +3878,6 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
} }
// check for like expression
if ((*pExpr)->tokenId == TK_LIKE) {
if (pRight->value.nLen > TSDB_PATTERN_STRING_MAX_LEN) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg8);
}
SSchema* pSchema = tscGetTableSchema(pTableMetaInfo->pTableMeta);
if ((!isTablenameToken(&pLeft->colInfo)) && pSchema[index.columnIndex].type != TSDB_DATA_TYPE_BINARY &&
pSchema[index.columnIndex].type != TSDB_DATA_TYPE_NCHAR) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
}
// in case of in operator, keep it in a seprate attribute // in case of in operator, keep it in a seprate attribute
if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
if (!validTableNameOptr(*pExpr)) { if (!validTableNameOptr(*pExpr)) {
@ -3763,10 +3904,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;
@ -3994,6 +4131,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;
@ -4004,7 +4142,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 {
@ -4086,6 +4227,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)) {
@ -4112,6 +4254,7 @@ static void doAddJoinTagsColumnsIntoTagList(SSqlCmd* pCmd, SQueryInfo* pQueryInf
tscColumnListInsert(pTableMetaInfo->tagColList, &index, &pSchema[index.columnIndex]); tscColumnListInsert(pTableMetaInfo->tagColList, &index, &pSchema[index.columnIndex]);
} }
} }
*/
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";
@ -4257,6 +4400,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 validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql) { int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql) {
if (pExpr == NULL) { if (pExpr == NULL) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
@ -4302,17 +4541,17 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq
// 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
@ -4320,12 +4559,29 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq
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;
@ -6648,14 +6904,13 @@ int32_t validateSqlNode(SSqlObj* pSql, SQuerySqlNode* pQuerySqlNode, int32_t ind
const char* msg1 = "point interpolation query needs timestamp"; const char* msg1 = "point interpolation query needs timestamp";
const char* msg2 = "too many tables in from clause"; const char* msg2 = "too many tables in from clause";
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";
int32_t code = TSDB_CODE_SUCCESS; int32_t code = TSDB_CODE_SUCCESS;
SSqlCmd* pCmd = &pSql->cmd; SSqlCmd* pCmd = &pSql->cmd;
SQueryInfo* pQueryInfo = tscGetQueryInfo(pCmd, index); SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd, index);
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
if (pTableMetaInfo == NULL) { if (pTableMetaInfo == NULL) {
pTableMetaInfo = tscAddEmptyMetaInfo(pQueryInfo); pTableMetaInfo = tscAddEmptyMetaInfo(pQueryInfo);
} }
@ -6675,48 +6930,6 @@ int32_t validateSqlNode(SSqlObj* pSql, SQuerySqlNode* pQuerySqlNode, int32_t ind
return doLocalQueryProcess(pCmd, pQueryInfo, pQuerySqlNode); return doLocalQueryProcess(pCmd, pQueryInfo, pQuerySqlNode);
} }
//validate the subquery recursively
if (pQuerySqlNode->from->type == SQL_NODE_FROM_SUBQUERY) {
for(int32_t j = 0; j < pQuerySqlNode->from->pNode.numOfClause; ++j) {
int32_t ret = validateSqlNode(pSql, pQuerySqlNode->from->pNode.pClause[j], 0);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
}
SQueryInfo* pQueryInfo1 = calloc(1, sizeof(SQueryInfo));
tscInitQueryInfo(pQueryInfo1);
pQueryInfo1->pUpstream = taosArrayInit(4, POINTER_BYTES);
pQueryInfo1->pDownstream = taosArrayInit(4, POINTER_BYTES);
for(int32_t x = 0; x < pCmd->numOfClause; ++x) {
taosArrayPush(pQueryInfo1->pUpstream, &pCmd->pQueryInfo[x]);
taosArrayPush(pCmd->pQueryInfo[x]->pDownstream, &pQueryInfo1);
}
pQueryInfo1->numOfTables = 1;
pCmd->numOfClause = 1;
pQueryInfo1->command = TSDB_SQL_SELECT;
pCmd->pQueryInfo[0] = pQueryInfo1;
}
size_t numOfTables = 0;
if (pQuerySqlNode->from->type == SQL_NODE_FROM_SUBQUERY) {
numOfTables = 1;
} else {
numOfTables = taosArrayGetSize(pQuerySqlNode->from->tableList);
if (numOfTables > TSDB_MAX_JOIN_TABLE_NUM) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
}
}
pQueryInfo->command = TSDB_SQL_SELECT;
if (numOfTables > 2) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
if (pQuerySqlNode->from->type == SQL_NODE_FROM_SUBQUERY) { if (pQuerySqlNode->from->type == SQL_NODE_FROM_SUBQUERY) {
// support only one nestquery // support only one nestquery
pQueryInfo = pCmd->pQueryInfo[0]; pQueryInfo = pCmd->pQueryInfo[0];
@ -6734,8 +6947,15 @@ int32_t validateSqlNode(SSqlObj* pSql, SQuerySqlNode* pQuerySqlNode, int32_t ind
} }
} else { } else {
pQueryInfo->command = TSDB_SQL_SELECT;
size_t fromSize = taosArrayGetSize(pQuerySqlNode->from->tableList);
if (fromSize > TSDB_MAX_JOIN_TABLE_NUM) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
// set all query tables, which are maybe more than one. // set all query tables, which are maybe more than one.
code = doLoadAllTableMeta(pSql, index, pQuerySqlNode, numOfTables); code = doLoadAllTableMeta(pSql, index, pQuerySqlNode, fromSize);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
return code; return code;
} }

View File

@ -351,8 +351,8 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
taosMsleep(duration); taosMsleep(duration);
} }
pSql->retryReason = rpcMsg->code;
rpcMsg->code = tscRenewTableMeta(pSql, 0); rpcMsg->code = tscRenewTableMeta(pSql, 0);
// if there is an error occurring, proceed to the following error handling procedure. // if there is an error occurring, proceed to the following error handling procedure.
if (rpcMsg->code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) { if (rpcMsg->code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
taosReleaseRef(tscObjRef, handle); taosReleaseRef(tscObjRef, handle);
@ -510,7 +510,7 @@ int tscBuildFetchMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SQueryInfo *pQueryInfo = tscGetActiveQueryInfo(&pSql->cmd); SQueryInfo *pQueryInfo = tscGetActiveQueryInfo(&pSql->cmd);
pRetrieveMsg->free = htons(pQueryInfo->type); pRetrieveMsg->free = htons(pQueryInfo->type);
pRetrieveMsg->qid = htobe64(pSql->res.qid); pRetrieveMsg->qId = htobe64(pSql->res.qId);
// todo valid the vgroupId at the client side // todo valid the vgroupId at the client side
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
@ -522,7 +522,7 @@ int tscBuildFetchMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
assert(pVgroupInfo->vgroups[vgIndex].vgId > 0 && vgIndex < pTableMetaInfo->vgroupList->numOfVgroups); assert(pVgroupInfo->vgroups[vgIndex].vgId > 0 && vgIndex < pTableMetaInfo->vgroupList->numOfVgroups);
pRetrieveMsg->header.vgId = htonl(pVgroupInfo->vgroups[vgIndex].vgId); pRetrieveMsg->header.vgId = htonl(pVgroupInfo->vgroups[vgIndex].vgId);
tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d, qid:%" PRIu64, pSql, pVgroupInfo->vgroups[vgIndex].vgId, vgIndex, pSql->res.qid); tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d, qId:%" PRIu64, pSql, pVgroupInfo->vgroups[vgIndex].vgId, vgIndex, pSql->res.qId);
} else { } else {
int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables); int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables);
assert(vgIndex >= 0 && vgIndex < numOfVgroups); assert(vgIndex >= 0 && vgIndex < numOfVgroups);
@ -530,12 +530,12 @@ int tscBuildFetchMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SVgroupTableInfo* pTableIdList = taosArrayGet(pTableMetaInfo->pVgroupTables, vgIndex); SVgroupTableInfo* pTableIdList = taosArrayGet(pTableMetaInfo->pVgroupTables, vgIndex);
pRetrieveMsg->header.vgId = htonl(pTableIdList->vgInfo.vgId); pRetrieveMsg->header.vgId = htonl(pTableIdList->vgInfo.vgId);
tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d, qid:%" PRIu64, pSql, pTableIdList->vgInfo.vgId, vgIndex, pSql->res.qid); tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d, qId:%" PRIu64, pSql, pTableIdList->vgInfo.vgId, vgIndex, pSql->res.qId);
} }
} else { } else {
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
pRetrieveMsg->header.vgId = htonl(pTableMeta->vgId); pRetrieveMsg->header.vgId = htonl(pTableMeta->vgId);
tscDebug("%p build fetch msg from only one vgroup, vgId:%d, qid:%" PRIu64, pSql, pTableMeta->vgId, pSql->res.qid); tscDebug("%p build fetch msg from only one vgroup, vgId:%d, qId:%" PRIu64, pSql, pTableMeta->vgId, pSql->res.qId);
} }
pSql->cmd.payloadLen = sizeof(SRetrieveTableMsg); pSql->cmd.payloadLen = sizeof(SRetrieveTableMsg);
@ -615,10 +615,8 @@ 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) {
SQueryInfo* pQueryInfo = tscGetActiveQueryInfo(&pSql->cmd); STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, pSql->cmd.clauseIndex, 0);
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
TSKEY dfltKey = htobe64(pQueryMsg->window.skey); TSKEY dfltKey = htobe64(pQueryMsg->window.skey);
STableMeta * pTableMeta = pTableMetaInfo->pTableMeta; STableMeta * pTableMeta = pTableMetaInfo->pTableMeta;
@ -630,9 +628,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;
@ -711,7 +714,7 @@ static int32_t serializeSqlExpr(SSqlExpr* pExpr, STableMetaInfo* pTableMetaInfo,
SSqlExpr* pSqlExpr = (SSqlExpr *)(*pMsg); SSqlExpr* pSqlExpr = (SSqlExpr *)(*pMsg);
SColIndex* pIndex = &pSqlExpr->colInfo; SColIndex* pIndex = &pSqlExpr->colInfo;
pIndex->colId = htons(pExpr->colInfo.colId); pIndex->colId = htons(pExpr->colInfo.colId);
pIndex->colIndex = htons(pExpr->colInfo.colIndex); pIndex->colIndex = htons(pExpr->colInfo.colIndex);
pIndex->flag = htons(pExpr->colInfo.flag); pIndex->flag = htons(pExpr->colInfo.flag);
@ -876,11 +879,16 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
} }
} }
// serialize the table info (sid, uid, tags) int32_t succeed = 1;
pMsg = doSerializeTableInfo(pQueryMsg, pSql, pMsg);
// serialize the table info (sid, uid, tags)
pMsg = doSerializeTableInfo(pQueryMsg, pSql, pMsg, &succeed);
if (succeed == 0) {
return TSDB_CODE_TSC_APP_ERROR;
}
SSqlGroupbyExpr *pGroupbyExpr = query.pGroupbyExpr; SSqlGroupbyExpr *pGroupbyExpr = query.pGroupbyExpr;
if (pGroupbyExpr != NULL && pGroupbyExpr->numOfGroupCols > 0) { if (pGroupbyExpr->numOfGroupCols > 0) {
pQueryMsg->orderByIdx = htons(pGroupbyExpr->orderIndex); pQueryMsg->orderByIdx = htons(pGroupbyExpr->orderIndex);
pQueryMsg->orderType = htons(pGroupbyExpr->orderType); pQueryMsg->orderType = htons(pGroupbyExpr->orderType);
@ -1206,6 +1214,23 @@ int32_t tscBuildUseDbMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
int32_t tscBuildSyncDbReplicaMsg(SSqlObj* pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
pCmd->payloadLen = sizeof(SSyncDbMsg);
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, pCmd->payloadLen)) {
tscError("%p failed to malloc for query msg", pSql);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
SSyncDbMsg *pSyncMsg = (SSyncDbMsg *)pCmd->payload;
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
tNameExtractFullName(&pTableMetaInfo->name, pSyncMsg->db);
pCmd->msgType = TSDB_MSG_TYPE_CM_SYNC_DB;
return TSDB_CODE_SUCCESS;
}
int32_t tscBuildShowMsg(SSqlObj *pSql, SSqlInfo *pInfo) { int32_t tscBuildShowMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
STscObj *pObj = pSql->pTscObj; STscObj *pObj = pSql->pTscObj;
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
@ -1478,7 +1503,7 @@ int tscBuildRetrieveFromMgmtMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd, 0); SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd, 0);
SRetrieveTableMsg *pRetrieveMsg = (SRetrieveTableMsg*)pCmd->payload; SRetrieveTableMsg *pRetrieveMsg = (SRetrieveTableMsg*)pCmd->payload;
pRetrieveMsg->qid = htobe64(pSql->res.qid); pRetrieveMsg->qId = htobe64(pSql->res.qId);
pRetrieveMsg->free = htons(pQueryInfo->type); pRetrieveMsg->free = htons(pQueryInfo->type);
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
@ -1986,19 +2011,24 @@ int tscProcessSTableVgroupRsp(SSqlObj *pSql) {
assert(pInfo->vgroupList != NULL); assert(pInfo->vgroupList != NULL);
pInfo->vgroupList->numOfVgroups = pVgroupMsg->numOfVgroups; pInfo->vgroupList->numOfVgroups = pVgroupMsg->numOfVgroups;
for (int32_t j = 0; j < pInfo->vgroupList->numOfVgroups; ++j) { if (pInfo->vgroupList->numOfVgroups <= 0) {
//just init, no need to lock //tfree(pInfo->vgroupList);
SVgroupInfo *pVgroups = &pInfo->vgroupList->vgroups[j]; tscError("%p empty vgroup info", pSql);
} else {
for (int32_t j = 0; j < pInfo->vgroupList->numOfVgroups; ++j) {
//just init, no need to lock
SVgroupInfo *pVgroups = &pInfo->vgroupList->vgroups[j];
SVgroupMsg *vmsg = &pVgroupMsg->vgroups[j]; SVgroupMsg *vmsg = &pVgroupMsg->vgroups[j];
pVgroups->vgId = htonl(vmsg->vgId); pVgroups->vgId = htonl(vmsg->vgId);
pVgroups->numOfEps = vmsg->numOfEps; pVgroups->numOfEps = vmsg->numOfEps;
assert(pVgroups->numOfEps >= 1 && pVgroups->vgId >= 1); assert(pVgroups->numOfEps >= 1 && pVgroups->vgId >= 1);
for (int32_t k = 0; k < pVgroups->numOfEps; ++k) { for (int32_t k = 0; k < pVgroups->numOfEps; ++k) {
pVgroups->epAddr[k].port = htons(vmsg->epAddr[k].port); pVgroups->epAddr[k].port = htons(vmsg->epAddr[k].port);
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));
}
} }
} }
@ -2024,7 +2054,7 @@ int tscProcessShowRsp(SSqlObj *pSql) {
pShow = (SShowRsp *)pRes->pRsp; pShow = (SShowRsp *)pRes->pRsp;
pShow->qhandle = htobe64(pShow->qhandle); pShow->qhandle = htobe64(pShow->qhandle);
pRes->qid = pShow->qhandle; pRes->qId = pShow->qhandle;
tscResetForNextRetrieve(pRes); tscResetForNextRetrieve(pRes);
pMetaMsg = &(pShow->tableMeta); pMetaMsg = &(pShow->tableMeta);
@ -2206,12 +2236,13 @@ int tscProcessQueryRsp(SSqlObj *pSql) {
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
SQueryTableRsp *pQueryAttr = (SQueryTableRsp *)pRes->pRsp; SQueryTableRsp *pQueryAttr = (SQueryTableRsp *)pRes->pRsp;
pQueryAttr->qid = htobe64(pQueryAttr->qid); pQueryAttr->qId = htobe64(pQueryAttr->qId);
pRes->qid = pQueryAttr->qid; pRes->qId = pQueryAttr->qId;
pRes->data = NULL; pRes->data = NULL;
tscResetForNextRetrieve(pRes); tscResetForNextRetrieve(pRes);
tscDebug("%p query rsp received, qId:%"PRIu64, pSql, pRes->qId);
return 0; return 0;
} }
@ -2271,7 +2302,8 @@ int tscProcessRetrieveRspFromNode(SSqlObj *pSql) {
} }
pRes->row = 0; pRes->row = 0;
tscDebug("%p numOfRows:%d, offset:%" PRId64 ", complete:%d", pSql, pRes->numOfRows, pRes->offset, pRes->completed); tscDebug("%p numOfRows:%d, offset:%" PRId64 ", complete:%d, qId:%"PRIu64, pSql, pRes->numOfRows, pRes->offset,
pRes->completed, pRes->qId);
return 0; return 0;
} }
@ -2484,6 +2516,7 @@ void tscInitMsgsFp() {
tscBuildMsg[TSDB_SQL_DROP_USER] = tscBuildDropUserAcctMsg; tscBuildMsg[TSDB_SQL_DROP_USER] = tscBuildDropUserAcctMsg;
tscBuildMsg[TSDB_SQL_DROP_ACCT] = tscBuildDropUserAcctMsg; tscBuildMsg[TSDB_SQL_DROP_ACCT] = tscBuildDropUserAcctMsg;
tscBuildMsg[TSDB_SQL_DROP_DB] = tscBuildDropDbMsg; tscBuildMsg[TSDB_SQL_DROP_DB] = tscBuildDropDbMsg;
tscBuildMsg[TSDB_SQL_SYNC_DB_REPLICA] = tscBuildSyncDbReplicaMsg;
tscBuildMsg[TSDB_SQL_DROP_TABLE] = tscBuildDropTableMsg; tscBuildMsg[TSDB_SQL_DROP_TABLE] = tscBuildDropTableMsg;
tscBuildMsg[TSDB_SQL_ALTER_USER] = tscBuildUserMsg; tscBuildMsg[TSDB_SQL_ALTER_USER] = tscBuildUserMsg;
tscBuildMsg[TSDB_SQL_CREATE_DNODE] = tscBuildCreateDnodeMsg; tscBuildMsg[TSDB_SQL_CREATE_DNODE] = tscBuildCreateDnodeMsg;
@ -2536,7 +2569,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;

View File

@ -476,7 +476,7 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) {
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
if (pRes->qid == 0 || if (pRes->qId == 0 ||
pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED || pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED ||
pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
pCmd->command == TSDB_SQL_INSERT) { pCmd->command == TSDB_SQL_INSERT) {
@ -508,7 +508,7 @@ int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
if (pRes->qid == 0 || if (pRes->qId == 0 ||
pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED || pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED ||
pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
pCmd->command == TSDB_SQL_INSERT) { pCmd->command == TSDB_SQL_INSERT) {
@ -554,7 +554,7 @@ static bool tscKillQueryInDnode(SSqlObj* pSql) {
SSqlCmd* pCmd = &pSql->cmd; SSqlCmd* pCmd = &pSql->cmd;
SSqlRes* pRes = &pSql->res; SSqlRes* pRes = &pSql->res;
if (pRes == NULL || pRes->qid == 0) { if (pRes == NULL || pRes->qId == 0) {
return true; return true;
} }
@ -1050,7 +1050,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
* If qhandle is NOT set 0, the function of taos_free_result() will send message to server by calling tscProcessSql() * If qhandle is NOT set 0, the function of taos_free_result() will send message to server by calling tscProcessSql()
* to free connection, which may cause segment fault, when the parse phrase is not even successfully executed. * to free connection, which may cause segment fault, when the parse phrase is not even successfully executed.
*/ */
pRes->qid = 0; pRes->qId = 0;
free(str); free(str);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {

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

@ -149,7 +149,7 @@ static SSub* tscCreateSubscription(STscObj* pObj, const char* topic, const char*
} }
strtolower(pSql->sqlstr, pSql->sqlstr); strtolower(pSql->sqlstr, pSql->sqlstr);
pRes->qid = 0; pRes->qId = 0;
pRes->numOfRows = 1; pRes->numOfRows = 1;
code = tscAllocPayload(pCmd, TSDB_DEFAULT_PAYLOAD_SIZE); code = tscAllocPayload(pCmd, TSDB_DEFAULT_PAYLOAD_SIZE);
@ -448,7 +448,7 @@ SSqlObj* recreateSqlObj(SSub* pSub) {
return NULL; return NULL;
} }
pRes->qid = 0; pRes->qId = 0;
pRes->numOfRows = 1; pRes->numOfRows = 1;
int code = tscAllocPayload(pCmd, TSDB_DEFAULT_PAYLOAD_SIZE); int code = tscAllocPayload(pCmd, TSDB_DEFAULT_PAYLOAD_SIZE);
@ -548,7 +548,7 @@ TAOS_RES *taos_consume(TAOS_SUB *tsub) {
uint32_t type = pQueryInfo->type; uint32_t type = pQueryInfo->type;
tscFreeSqlResult(pSql); tscFreeSqlResult(pSql);
pRes->numOfRows = 1; pRes->numOfRows = 1;
pRes->qid = 0; pRes->qId = 0;
pSql->cmd.command = TSDB_SQL_SELECT; pSql->cmd.command = TSDB_SQL_SELECT;
pQueryInfo->type = type; pQueryInfo->type = type;

View File

@ -47,6 +47,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);
@ -117,123 +124,235 @@ static bool subAndCheckDone(SSqlObj *pSql, SSqlObj *pParentSql, int idx) {
return done; return done;
} }
static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJoinSupporter* pSupporter2, STimeWindow * win) {
SQueryInfo* pQueryInfo = tscGetQueryInfo(&pSql->cmd, pSql->cmd.clauseIndex);
STSBuf* output1 = tsBufCreate(true, pQueryInfo->order.order);
STSBuf* output2 = tsBufCreate(true, pQueryInfo->order.order); static int64_t doTSBlockIntersect(SSqlObj* pSql, STimeWindow * win) {
SQueryInfo* pQueryInfo = tscGetQueryInfo(&pSql->cmd, pSql->cmd.clauseIndex);
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 = tscGetQueryInfo(&pSql->pSubs[0]->cmd, 0); for (int32_t i = 0; i < joinNum; ++i) {
SQueryInfo* pSubQueryInfo2 = tscGetQueryInfo(&pSql->pSubs[1]->cmd, 0); STSBuf* output = tsBufCreate(true, pQueryInfo->order.order);
SQueryInfo* pSubQueryInfo = tscGetQueryInfo(&pSql->pSubs[i]->cmd, 0);
pSubQueryInfo1->tsBuf = output1; pSubQueryInfo->tsBuf = output;
pSubQueryInfo2->tsBuf = output2;
SJoinSupporter* pSupporter = pSql->pSubs[i]->param;
if (pSupporter->pTSBuf == NULL) {
tscDebug("%p at least one ts-comp is empty, 0 for secondary query after ts blocks intersecting", pSql);
return 0;
}
tsBufResetPos(pSupporter->pTSBuf);
if (!tsBufNextPos(pSupporter->pTSBuf)) {
tscDebug("%p input1 is empty, 0 for secondary query after ts blocks intersecting", pSql);
return 0;
}
tscDebug("%p sub:%p table idx:%d, input group number:%d", pSql, pSql->pSubs[i], i, pSupporter->pTSBuf->numOfGroups);
ctxlist[i].p = pSupporter;
ctxlist[i].res = output;
}
TSKEY st = taosGetTimestampUs(); TSKEY st = taosGetTimestampUs();
// no result generated, return directly for (int16_t tidx = 0; tidx < joinNum; tidx++) {
if (pSupporter1->pTSBuf == NULL || pSupporter2->pTSBuf == NULL) { pctx = &ctxlist[tidx];
tscDebug("%p at least one ts-comp is empty, 0 for secondary query after ts blocks intersecting", pSql); if (pctx->compared) {
return 0; continue;
}
tsBufResetPos(pSupporter1->pTSBuf);
tsBufResetPos(pSupporter2->pTSBuf);
if (!tsBufNextPos(pSupporter1->pTSBuf)) {
tsBufFlush(output1);
tsBufFlush(output2);
tscDebug("%p input1 is empty, 0 for secondary query after ts blocks intersecting", pSql);
return 0;
}
if (!tsBufNextPos(pSupporter2->pTSBuf)) {
tsBufFlush(output1);
tsBufFlush(output2);
tscDebug("%p input2 is empty, 0 for secondary query after ts blocks intersecting", pSql);
return 0;
}
int64_t numOfInput1 = 1;
int64_t numOfInput2 = 1;
while(1) {
STSElem elem = tsBufGetElem(pSupporter1->pTSBuf);
// no data in pSupporter1 anymore, jump out of loop
if (!tsBufIsValidElem(&elem)) {
break;
} }
// find the data in supporter2 with the same tag value assert(pctx->numOfInput == 0);
STSElem e2 = tsBufFindElemStartPosByTag(pSupporter2->pTSBuf, elem.tag);
/** tsCond = pQueryInfo->tagCond.joinInfo.joinTables[tidx]->tsJoin;
* there are elements in pSupporter2 with the same tag, continue
*/ tableNum = taosArrayGetSize(tsCond);
tVariant tag1 = {0}; assert(tableNum >= 2);
tVariantAssign(&tag1, elem.tag);
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) {
pctx = mainCtx;
prev = tsBufGetElem(pctx->p->pTSBuf);
ctxStack[stackidx++] = pctx;
if (!tsBufIsValidElem(&prev)) {
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
STSElem e2 = tsBufFindElemStartPosByTag(tctx->p->pTSBuf, &tag);
if (!tsBufIsValidElem(&e2)) {
skipRemainValue(pctx->p->pTSBuf, &tag);
skipped = 1;
break;
}
}
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++;
}
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;
} }
} }
} else { // no data in pSupporter2, ignore current data in pSupporter2
skipRemainValue(pSupporter1->pTSBuf, &tag1); if (mergeDone) {
break;
}
slot = 0;
stackidx = 0;
skipRemainValue(mainCtx->p->pTSBuf, &tag);
} }
stackidx = 0;
slot = 0;
mergeDone = 0;
} }
/* /*
@ -241,28 +360,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));
@ -771,76 +894,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++) {
return TSDB_CODE_QRY_DUP_JOIN_KEY; SJoinSupporter* p = pParentSql->pSubs[i]->param;
}
int32_t i = 0, j = 0; ctxlist[i].p = p;
while(i < p1->num && j < p2->num) { ctxlist[i].res = taosArrayInit(p->num, size);
STidTags* pp1 = (STidTags*) varDataVal(p1->pIdTagList + i * p1->tagSize);
STidTags* pp2 = (STidTags*) varDataVal(p2->pIdTagList + j * p2->tagSize);
assert(pp1->tid != 0 && pp2->tid != 0);
int32_t ret = doCompare(pp1->tag, pp2->tag, pColSchema->type, pColSchema->bytes); tscDebug("Join %d - num:%d", i, p->num);
if (ret == 0) {
tscDebug("%p tag matched, vgId:%d, val:%d, tid:%d, uid:%"PRIu64", tid:%d, uid:%"PRIu64, pParentSql, pp1->vgId,
*(int*) pp1->tag, pp1->tid, pp1->uid, pp2->tid, pp2->uid);
taosArrayPush(*s1, pp1); // sort according to the tag valu
taosArrayPush(*s2, pp2); qsort(p->pIdTagList, p->num, p->tagSize, tagValCompar);
j++;
i++; if (!checkForDuplicateTagVal(pColSchema, p, pParentSql)) {
} else if (ret > 0) { for (int32_t j = 0; j <= i; j++) {
j++; taosArrayDestroy(ctxlist[j].res);
} else { }
i++; return TSDB_CODE_QRY_DUP_JOIN_KEY;
} }
} }
// reorganize the tid-tag value according to both the vgroup id and tag values int32_t slot = 0;
// sort according to the tag value size_t tableNum = 0;
size_t t1 = taosArrayGetSize(*s1); int16_t* tableMIdx = 0;
size_t t2 = taosArrayGetSize(*s2); int32_t equalNum = 0;
int32_t stackidx = 0;
int32_t mergeDone = 0;
SMergeCtx* ctx = NULL;
SMergeCtx* pctx = NULL;
STidTags* cur = NULL;
STidTags* prev = NULL;
SArray* tagCond = NULL;
qsort((*s1)->pData, t1, size, tidTagsCompar); for (int16_t tidx = 0; tidx < joinNum; tidx++) {
qsort((*s2)->pData, t2, size, tidTagsCompar); pctx = &ctxlist[tidx];
if (pctx->compared) {
continue;
}
#if 0 assert(pctx->idx == 0 && taosArrayGetSize(pctx->res) == 0);
for(int32_t k = 0; k < t1; ++k) {
STidTags* p = (*s1)->pData + size * k; tagCond = pQueryInfo->tagCond.joinInfo.joinTables[tidx]->tagJoin;
printf("%d, tag:%s\n", p->vgId, ((tstr*)(p->tag))->data);
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 (++equalNum < tableNum) {
prev = cur;
pctx = ctx;
if (++slot >= tableNum) {
slot = 0;
}
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) {
stackidx--;
if (++ctx->idx >= ctx->p->num) {
break;
}
} else {
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 k = 0; k < t1; ++k) { for (int32_t i = 0; i < joinNum; ++i) {
STidTags* p = (*s2)->pData + size * k; // reorganize the tid-tag value according to both the vgroup id and tag values
printf("%d, tag:%s\n", p->vgId, ((tstr*)(p->tag))->data); // sort according to the tag value
} size_t num = taosArrayGetSize(ctxlist[i].res);
#endif
qsort((ctxlist[i].res)->pData, num, size, tidTagsCompar);
taosArrayPush(resList, &ctxlist[i].res);
tscDebug("%p tags match complete, result num: %"PRIzu, pParentSql, num);
}
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;
@ -942,19 +1207,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);
@ -966,37 +1231,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 {
// proceed to for ts_comp query
SSqlCmd* pSubCmd1 = &pParentSql->pSubs[0]->cmd;
SSqlCmd* pSubCmd2 = &pParentSql->pSubs[1]->cmd;
SQueryInfo* pQueryInfo1 = tscGetQueryInfo(pSubCmd1, 0);
STableMetaInfo* pTableMetaInfo1 = tscGetMetaInfo(pQueryInfo1, 0);
tscBuildVgroupTableInfo(pParentSql, pTableMetaInfo1, s1);
SQueryInfo* pQueryInfo2 = tscGetQueryInfo(pSubCmd2, 0);
STableMetaInfo* pTableMetaInfo2 = tscGetMetaInfo(pQueryInfo2, 0);
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);
tscDebug("%p reset all sub states to 0", pParentSql);
for (int32_t m = 0; m < pParentSql->subState.numOfSub; ++m) { for (int32_t m = 0; m < pParentSql->subState.numOfSub; ++m) {
SSqlObj* sub = pParentSql->pSubs[m]; // proceed to for ts_comp query
issueTsCompQuery(sub, sub->param, pParentSql); SSqlCmd* pSubCmd = &pParentSql->pSubs[m]->cmd;
SArray** s = taosArrayGet(resList, m);
SQueryInfo* pQueryInfo1 = tscGetQueryInfo(pSubCmd, 0);
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo1, 0);
tscBuildVgroupTableInfo(pParentSql, pTableMetaInfo, *s);
SSqlObj* psub = pParentSql->pSubs[m];
((SJoinSupporter*)psub->param)->pVgroupTables = tscVgroupTableInfoDup(pTableMetaInfo->pVgroupTables);
memset(pParentSql->subState.states, 0, sizeof(pParentSql->subState.states[0]) * pParentSql->subState.numOfSub);
tscDebug("%p reset all sub states to 0", pParentSql);
issueTsCompQuery(psub, psub->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) {
@ -1127,12 +1389,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);
@ -1585,7 +1843,7 @@ int32_t tscCreateJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter
SSqlCmd * pCmd = &pSql->cmd; SSqlCmd * pCmd = &pSql->cmd;
SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd, pCmd->clauseIndex); SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd, pCmd->clauseIndex);
pSql->res.qid = 0x1; pSql->res.qId = 0x1;
assert(pSql->res.numOfRows == 0); assert(pSql->res.numOfRows == 0);
if (pSql->pSubs == NULL) { if (pSql->pSubs == NULL) {
@ -1640,6 +1898,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));
@ -1744,7 +2004,7 @@ void tscHandleMasterJoinQuery(SSqlObj* pSql) {
memset(pSql->subState.states, 0, sizeof(*pSql->subState.states) * pSql->subState.numOfSub); memset(pSql->subState.states, 0, sizeof(*pSql->subState.states) * pSql->subState.numOfSub);
tscDebug("%p reset all sub states to 0", pSql); tscDebug("%p reset all sub states to 0", pSql);
tscDebug("%p start subquery, total:%d", pSql, pQueryInfo->numOfTables); tscDebug("%p start subquery, total:%d", pSql, pQueryInfo->numOfTables);
for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
@ -2179,7 +2439,7 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
SColumnModel *pModel = NULL; SColumnModel *pModel = NULL;
SColumnModel *pFinalModel = NULL; SColumnModel *pFinalModel = NULL;
pRes->qid = 0x1; // hack the qhandle check pRes->qId = 0x1; // hack the qhandle check
const uint32_t nBufferSize = (1u << 16u); // 64KB const uint32_t nBufferSize = (1u << 16u); // 64KB
@ -2727,7 +2987,7 @@ void tscRetrieveDataRes(void *param, TAOS_RES *tres, int code) {
tscDebug("%p sub:%p query complete, ep:%s, vgId:%d, orderOfSub:%d, retrieve data", trsupport->pParentSql, pSql, tscDebug("%p sub:%p query complete, ep:%s, vgId:%d, orderOfSub:%d, retrieve data", trsupport->pParentSql, pSql,
pVgroup->epAddr[0].fqdn, pVgroup->vgId, trsupport->subqueryIndex); pVgroup->epAddr[0].fqdn, pVgroup->vgId, trsupport->subqueryIndex);
if (pSql->res.qid == 0) { // qhandle is 0, code is TSDB_CODE_SUCCESS means no results generated from this vnode if (pSql->res.qId == 0) { // qhandle is NULL, code is TSDB_CODE_SUCCESS means no results generated from this vnode
tscRetrieveFromDnodeCallBack(param, pSql, 0); tscRetrieveFromDnodeCallBack(param, pSql, 0);
} else { } else {
taos_fetch_rows_a(tres, tscRetrieveFromDnodeCallBack, param); taos_fetch_rows_a(tres, tscRetrieveFromDnodeCallBack, param);
@ -3325,9 +3585,9 @@ void* createQueryInfoFromQueryNode(SQueryInfo* pQueryInfo, SExprInfo* pExprs, ST
STsBufInfo bufInfo = {0}; STsBufInfo bufInfo = {0};
SQueryParam param = {.pOperator = pa}; SQueryParam param = {.pOperator = pa};
/*int32_t code = */initQInfo(&bufInfo, NULL, pQInfo, &param, NULL, 0); /*int32_t code = */initQInfo(&bufInfo, NULL, pQInfo, &param, NULL, 0);
pQInfo->runtimeEnv.proot->upstream = pOperator; pQInfo->runtimeEnv.proot->upstream = pOperator;
qTableQuery(pQInfo);
qTableQuery(pQInfo, NULL);
return pQInfo; return pQInfo;

View File

@ -711,7 +711,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;
} }
@ -1533,6 +1533,33 @@ 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;
}
void tscSqlExprAssign(SExprInfo* dst, const SExprInfo* src) { void tscSqlExprAssign(SExprInfo* dst, const SExprInfo* src) {
assert(dst != NULL && src != NULL); assert(dst != NULL && src != NULL);
@ -1860,7 +1887,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) {
@ -1906,6 +1951,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));
} }
@ -2037,7 +2099,7 @@ void tscInitQueryInfo(SQueryInfo* pQueryInfo) {
pQueryInfo->resColumnId = TSDB_RES_COL_ID; pQueryInfo->resColumnId = TSDB_RES_COL_ID;
pQueryInfo->limit.limit = -1; pQueryInfo->limit.limit = -1;
pQueryInfo->limit.offset = 0; pQueryInfo->limit.offset = 0;
pQueryInfo->slimit.limit = -1; pQueryInfo->slimit.limit = -1;
pQueryInfo->slimit.offset = 0; pQueryInfo->slimit.offset = 0;
pQueryInfo->pUpstream = taosArrayInit(4, POINTER_BYTES); pQueryInfo->pUpstream = taosArrayInit(4, POINTER_BYTES);
@ -2598,7 +2660,7 @@ void tscDoQuery(SSqlObj* pSql) {
} else { } else {
SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd, pCmd->clauseIndex); SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd, pCmd->clauseIndex);
uint16_t type = pQueryInfo->type; uint16_t type = pQueryInfo->type;
if (QUERY_IS_JOIN_QUERY(type)) { if (QUERY_IS_JOIN_QUERY(type)) {
if (!TSDB_QUERY_HAS_TYPE(type, TSDB_QUERY_TYPE_SUBQUERY)) { if (!TSDB_QUERY_HAS_TYPE(type, TSDB_QUERY_TYPE_SUBQUERY)) {
tscHandleMasterJoinQuery(pSql); tscHandleMasterJoinQuery(pSql);
@ -2632,16 +2694,21 @@ 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;
assert(0); }
return -1;
i++;
} }
assert(0);
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);
@ -3240,7 +3307,7 @@ int32_t tscCreateQueryFromQueryInfo(SQueryInfo* pQueryInfo, SQueryAttr* pQueryAt
pQueryAttr->queryBlockDist = isBlockDistQuery(pQueryInfo); pQueryAttr->queryBlockDist = isBlockDistQuery(pQueryInfo);
pQueryAttr->pointInterpQuery = tscIsPointInterpQuery(pQueryInfo); pQueryAttr->pointInterpQuery = tscIsPointInterpQuery(pQueryInfo);
pQueryAttr->timeWindowInterpo = timeWindowInterpoRequired(pQueryInfo); pQueryAttr->timeWindowInterpo = timeWindowInterpoRequired(pQueryInfo);
pQueryAttr->numOfCols = numOfCols; pQueryAttr->numOfCols = numOfCols;
pQueryAttr->numOfOutput = numOfOutput; pQueryAttr->numOfOutput = numOfOutput;
pQueryAttr->limit = pQueryInfo->limit; pQueryAttr->limit = pQueryInfo->limit;
@ -3256,6 +3323,12 @@ int32_t tscCreateQueryFromQueryInfo(SQueryInfo* pQueryInfo, SQueryAttr* pQueryAt
pQueryAttr->pGroupbyExpr = calloc(1, sizeof(SSqlGroupbyExpr)); pQueryAttr->pGroupbyExpr = calloc(1, sizeof(SSqlGroupbyExpr));
*(pQueryAttr->pGroupbyExpr) = pQueryInfo->groupbyExpr; *(pQueryAttr->pGroupbyExpr) = pQueryInfo->groupbyExpr;
if (pQueryInfo->groupbyExpr.numOfGroupCols > 0) {
pQueryAttr->pGroupbyExpr->columnInfo = taosArrayDup(pQueryInfo->groupbyExpr.columnInfo);
} else {
assert(pQueryInfo->groupbyExpr.columnInfo == NULL);
}
pQueryAttr->pExpr1 = calloc(pQueryAttr->numOfOutput, sizeof(SExprInfo)); pQueryAttr->pExpr1 = calloc(pQueryAttr->numOfOutput, sizeof(SExprInfo));
for(int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) { for(int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
SExprInfo* pExpr = tscSqlExprGet(pQueryInfo, i); SExprInfo* pExpr = tscSqlExprGet(pQueryInfo, i);

View File

@ -51,6 +51,7 @@ enum {
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_ALTER_ACCT, "alter-acct" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_ALTER_ACCT, "alter-acct" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_ALTER_TABLE, "alter-table" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_ALTER_TABLE, "alter-table" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_ALTER_DB, "alter-db" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_ALTER_DB, "alter-db" )
TSDB_DEFINE_SQL_TYPE(TSDB_SQL_SYNC_DB_REPLICA, "sync db-replica")
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CREATE_MNODE, "create-mnode" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CREATE_MNODE, "create-mnode" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_DROP_MNODE, "drop-mnode" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_DROP_MNODE, "drop-mnode" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CREATE_DNODE, "create-dnode" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CREATE_DNODE, "create-dnode" )
@ -87,13 +88,13 @@ enum {
*/ */
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_RETRIEVE_EMPTY_RESULT, "retrieve-empty-result" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_RETRIEVE_EMPTY_RESULT, "retrieve-empty-result" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_RESET_CACHE, "reset-cache" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_RESET_CACHE, "reset-cache" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_SERV_STATUS, "serv-status" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_SERV_STATUS, "serv-status" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CURRENT_DB, "current-db" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CURRENT_DB, "current-db" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_SERV_VERSION, "serv-version" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_SERV_VERSION, "serv-version" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CLI_VERSION, "cli-version" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CLI_VERSION, "cli-version" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CURRENT_USER, "current-user ") TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CURRENT_USER, "current-user ")
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CFG_LOCAL, "cfg-local" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CFG_LOCAL, "cfg-local" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_MAX, "max" ) TSDB_DEFINE_SQL_TYPE( TSDB_SQL_MAX, "max" )
}; };

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.25-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.25</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.25</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,10 +54,22 @@
<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>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/*.md</exclude>
</excludes>
</resource>
</resources>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>

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 == null ? 0 : 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

@ -29,45 +29,25 @@ public class TSDBJNIConnector {
private static volatile Boolean isInitialized = false; private static volatile Boolean isInitialized = false;
private TaosInfo taosInfo = TaosInfo.getInstance(); private TaosInfo taosInfo = TaosInfo.getInstance();
// Connection pointer used in C
private long taos = TSDBConstants.JNI_NULL_POINTER;
// result set status in current connection
private boolean isResultsetClosed = true;
private int affectedRows = -1;
static { static {
System.loadLibrary("taos"); System.loadLibrary("taos");
System.out.println("java.library.path:" + System.getProperty("java.library.path")); System.out.println("java.library.path:" + System.getProperty("java.library.path"));
} }
/**
* Connection pointer used in C
*/
private long taos = TSDBConstants.JNI_NULL_POINTER;
/**
* Result set pointer for the current connection
*/
// private long taosResultSetPointer = TSDBConstants.JNI_NULL_POINTER;
/**
* result set status in current connection
*/
private boolean isResultsetClosed = true;
private int affectedRows = -1;
/**
* Whether the connection is closed
*/
public boolean isClosed() { public boolean isClosed() {
return this.taos == TSDBConstants.JNI_NULL_POINTER; return this.taos == TSDBConstants.JNI_NULL_POINTER;
} }
/**
* Returns the status of last result set in current connection
*/
public boolean isResultsetClosed() { public boolean isResultsetClosed() {
return this.isResultsetClosed; return this.isResultsetClosed;
} }
/**
* Initialize static variables in JNI to optimize performance
*/
public static void init(String configDir, String locale, String charset, String timezone) throws SQLWarning { public static void init(String configDir, String locale, String charset, String timezone) throws SQLWarning {
synchronized (isInitialized) { synchronized (isInitialized) {
if (!isInitialized) { if (!isInitialized) {
@ -93,11 +73,6 @@ public class TSDBJNIConnector {
public static native String getTsCharset(); public static native String getTsCharset();
/**
* Get connection pointer
*
* @throws SQLException
*/
public boolean connect(String host, int port, String dbName, String user, String password) throws SQLException { public boolean connect(String host, int port, String dbName, String user, String password) throws SQLException {
if (this.taos != TSDBConstants.JNI_NULL_POINTER) { if (this.taos != TSDBConstants.JNI_NULL_POINTER) {
// this.closeConnectionImp(this.taos); // this.closeConnectionImp(this.taos);
@ -185,13 +160,6 @@ public class TSDBJNIConnector {
private native String getErrMsgImp(long pSql); private native String getErrMsgImp(long pSql);
/**
* Get resultset pointer
* Each connection should have a single open result set at a time
*/
// public long getResultSet() {
// return taosResultSetPointer;
// }
private native long getResultSetImp(long connection, long pSql); private native long getResultSetImp(long connection, long pSql);
public boolean isUpdateQuery(long pSql) { public boolean isUpdateQuery(long pSql) {
@ -231,6 +199,7 @@ public class TSDBJNIConnector {
// } // }
// return resCode; // return resCode;
// } // }
private native int freeResultSetImp(long connection, long result); private native int freeResultSetImp(long connection, long result);
/** /**
@ -323,8 +292,7 @@ public class TSDBJNIConnector {
* Validate if a <I>create table</I> sql statement is correct without actually creating that table * Validate if a <I>create table</I> sql statement is correct without actually creating that table
*/ */
public boolean validateCreateTableSql(String sql) { public boolean validateCreateTableSql(String sql) {
long connection = taos; int res = validateCreateTableSqlImp(taos, sql.getBytes());
int res = validateCreateTableSqlImp(connection, sql.getBytes());
return res != 0 ? false : true; return res != 0 ? false : true;
} }

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)
@Override res = ((String) this.rowData.get(columnIndex - 1)).getBytes();
public Object getObject(String columnLabel) throws SQLException { else
return this.getObject(this.findColumn(columnLabel)); res = this.rowData.get(columnIndex - 1);
}
return res;
} }
public int findColumn(String columnLabel) throws SQLException { public int findColumn(String columnLabel) throws SQLException {
@ -285,14 +321,31 @@ 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
@ -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,136 +22,160 @@ 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;
} }
public int getColumnCount() throws SQLException { public int getColumnCount() throws SQLException {
return colMetaDataList.size(); return colMetaDataList.size();
} }
public boolean isAutoIncrement(int column) throws SQLException { public boolean isAutoIncrement(int column) throws SQLException {
return false; return false;
} }
public boolean isCaseSensitive(int column) throws SQLException { public boolean isCaseSensitive(int column) throws SQLException {
return false; return false;
} }
public boolean isSearchable(int column) throws SQLException { public boolean isSearchable(int column) throws SQLException {
if (column == 1) { if (column == 1) {
return true; return true;
} }
return false; return false;
} }
public boolean isCurrency(int column) throws SQLException { public boolean isCurrency(int column) throws SQLException {
return false; return false;
} }
public int isNullable(int column) throws SQLException { public int isNullable(int column) throws SQLException {
if (column == 1) { if (column < 1 && column >= colMetaDataList.size())
return columnNoNulls; throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
}
return columnNullable;
}
public boolean isSigned(int column) throws SQLException { if (column == 1) {
ColumnMetaData meta = this.colMetaDataList.get(column - 1); return columnNoNulls;
switch (meta.getColType()) { }
case TSDBConstants.TSDB_DATA_TYPE_TINYINT: return columnNullable;
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: }
case TSDBConstants.TSDB_DATA_TYPE_INT:
case TSDBConstants.TSDB_DATA_TYPE_BIGINT:
case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
return true;
default:
return false;
}
}
public int getColumnDisplaySize(int column) throws SQLException { public boolean isSigned(int column) throws SQLException {
return colMetaDataList.get(column - 1).getColSize(); if (column < 1 && column >= colMetaDataList.size())
} throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
public String getColumnLabel(int column) throws SQLException { ColumnMetaData meta = this.colMetaDataList.get(column - 1);
return colMetaDataList.get(column - 1).getColName(); switch (meta.getColType()) {
} case TSDBConstants.TSDB_DATA_TYPE_TINYINT:
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:
case TSDBConstants.TSDB_DATA_TYPE_INT:
case TSDBConstants.TSDB_DATA_TYPE_BIGINT:
case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
return true;
default:
return false;
}
}
public String getColumnName(int column) throws SQLException { public int getColumnDisplaySize(int column) throws SQLException {
return colMetaDataList.get(column - 1).getColName(); if (column < 1 && column >= colMetaDataList.size())
} throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
public String getSchemaName(int column) throws SQLException { return colMetaDataList.get(column - 1).getColSize();
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); }
}
public int getPrecision(int column) throws SQLException { public String getColumnLabel(int column) throws SQLException {
ColumnMetaData columnMetaData = this.colMetaDataList.get(column - 1); if (column < 1 && column >= colMetaDataList.size())
switch (columnMetaData.getColType()) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
return 5;
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
return 9;
case TSDBConstants.TSDB_DATA_TYPE_BINARY:
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
return columnMetaData.getColSize();
default:
return 0;
}
}
public int getScale(int column) throws SQLException { return colMetaDataList.get(column - 1).getColName();
ColumnMetaData meta = this.colMetaDataList.get(column - 1); }
switch (meta.getColType()) {
case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
return 5;
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
return 9;
default:
return 0;
}
}
public String getTableName(int column) throws SQLException { public String getColumnName(int column) throws SQLException {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); if (column < 1 && column >= colMetaDataList.size())
} throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
public String getCatalogName(int column) throws SQLException { return colMetaDataList.get(column - 1).getColName();
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); }
}
public int getColumnType(int column) throws SQLException { public String getSchemaName(int column) throws SQLException {
ColumnMetaData meta = this.colMetaDataList.get(column - 1); if (column < 1 && column >= colMetaDataList.size())
return TSDBConstants.taosType2JdbcType(meta.getColType()); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
}
public String getColumnTypeName(int column) throws SQLException { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
ColumnMetaData meta = this.colMetaDataList.get(column - 1); }
return TSDBConstants.taosType2JdbcTypeName(meta.getColType());
}
public boolean isReadOnly(int column) throws SQLException { public int getPrecision(int column) throws SQLException {
return true; if (column < 1 && column >= colMetaDataList.size())
} throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
public boolean isWritable(int column) throws SQLException { ColumnMetaData columnMetaData = this.colMetaDataList.get(column - 1);
return false; switch (columnMetaData.getColType()) {
} case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
return 5;
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
return 9;
case TSDBConstants.TSDB_DATA_TYPE_BINARY:
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
return columnMetaData.getColSize();
default:
return 0;
}
}
public boolean isDefinitelyWritable(int column) throws SQLException { public int getScale(int column) throws SQLException {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); if (column < 1 && column >= colMetaDataList.size())
} throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
public String getColumnClassName(int column) throws SQLException { ColumnMetaData meta = this.colMetaDataList.get(column - 1);
int columnType = getColumnType(column); switch (meta.getColType()) {
String columnClassName = ""; case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
switch (columnType) { return 5;
case Types.TIMESTAMP: case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
columnClassName = Timestamp.class.getName(); return 9;
default:
return 0;
}
}
public String getTableName(int column) throws SQLException {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
public String getCatalogName(int column) throws SQLException {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
public int getColumnType(int column) throws SQLException {
ColumnMetaData meta = this.colMetaDataList.get(column - 1);
return TSDBConstants.taosType2JdbcType(meta.getColType());
}
public String getColumnTypeName(int column) throws SQLException {
ColumnMetaData meta = this.colMetaDataList.get(column - 1);
return TSDBConstants.taosType2JdbcTypeName(meta.getColType());
}
public boolean isReadOnly(int column) throws SQLException {
return true;
}
public boolean isWritable(int column) throws SQLException {
return false;
}
public boolean isDefinitelyWritable(int column) throws SQLException {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
}
public String getColumnClassName(int column) throws SQLException {
int columnType = getColumnType(column);
String columnClassName = "";
switch (columnType) {
case Types.TIMESTAMP:
columnClassName = Timestamp.class.getName();
break; break;
case Types.CHAR: case Types.CHAR:
columnClassName = String.class.getName(); columnClassName = String.class.getName();
@ -168,8 +192,8 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD
case Types.INTEGER: case Types.INTEGER:
columnClassName = Integer.class.getName(); columnClassName = Integer.class.getName();
break; break;
case Types.SMALLINT: case Types.SMALLINT:
columnClassName = Short.class.getName(); columnClassName = Short.class.getName();
break; break;
case Types.TINYINT: case Types.TINYINT:
columnClassName = Byte.class.getName(); columnClassName = Byte.class.getName();
@ -177,7 +201,7 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD
case Types.BIT: case Types.BIT:
columnClassName = Boolean.class.getName(); columnClassName = Boolean.class.getName();
break; break;
} }
return columnClassName; return columnClassName;
} }
} }

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) == null ? null : row.getString(colIndex).getBytes();
case TSDBConstants.TSDB_DATA_TYPE_NCHAR: case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
return row.getString(colIndex) == null ? null : row.getString(colIndex);
default: default:
return row.getString(colIndex); 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");
}
int numOfCols = resultSet.get(pos).size(); Object value = resultSet.get(pos).get(columnIndex - 1);
if (columnIndex > numOfCols) { if (value == null)
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE return null;
, "Column Index out of range, " + columnIndex + " > " + numOfCols); 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 columnIndex - 1; return value.toString().getBytes();
}
@Override
public Date getDate(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 Date(((Timestamp) value).getTime());
return Date.valueOf(value.toString());
}
@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

@ -0,0 +1,17 @@
package com.taosdata.jdbc.utils;
public class OSUtils {
private static final String OS = System.getProperty("os.name").toLowerCase();
public static boolean isWindows() {
return OS.indexOf("win") >= 0;
}
public static boolean isMac() {
return OS.indexOf("mac") >= 0;
}
public static boolean isLinux() {
return OS.indexOf("nux") >= 0;
}
}

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,41 @@
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 {
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

@ -0,0 +1,64 @@
package com.taosdata.jdbc.cases;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.sql.*;
public class NullValueInResultSetForJdbcRestfulTest {
private static final String host = "127.0.0.1";
Connection conn;
@Test
public void test() {
try (Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery("select * from weather");
ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) {
Object value = rs.getObject(i);
System.out.print(meta.getColumnLabel(i) + ": " + value + "\t");
}
System.out.println();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
@Before
public void before() throws SQLException {
final String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata";
conn = DriverManager.getConnection(url);
try (Statement stmt = conn.createStatement()) {
stmt.execute("drop database if exists test_null");
stmt.execute("create database if not exists test_null");
stmt.execute("use test_null");
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))");
stmt.executeUpdate("insert into weather(ts, f1) values(now+1s, 1)");
stmt.executeUpdate("insert into weather(ts, f2) values(now+2s, 2)");
stmt.executeUpdate("insert into weather(ts, f3) values(now+3s, 3.0)");
stmt.executeUpdate("insert into weather(ts, f4) values(now+4s, 4.0)");
stmt.executeUpdate("insert into weather(ts, f5) values(now+5s, 5)");
stmt.executeUpdate("insert into weather(ts, f6) values(now+6s, 6)");
stmt.executeUpdate("insert into weather(ts, f7) values(now+7s, true)");
stmt.executeUpdate("insert into weather(ts, f8) values(now+8s, 'hello')");
stmt.executeUpdate("insert into weather(ts, f9) values(now+9s, '涛思数据')");
} catch (SQLException e) {
e.printStackTrace();
}
}
@After
public void after() {
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

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

@ -0,0 +1,30 @@
package com.taosdata.jdbc.utils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class OSUtilsTest {
private String OS;
@Test
public void inWindows() {
Assert.assertEquals(OS.indexOf("win") >= 0, OSUtils.isWindows());
}
@Test
public void isMac() {
Assert.assertEquals(OS.indexOf("mac") >= 0, OSUtils.isMac());
}
@Test
public void isLinux() {
Assert.assertEquals(OS.indexOf("nux") >= 0, OSUtils.isLinux());
}
@Before
public void before() {
OS = System.getProperty("os.name").toLowerCase();
}
}

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();
@ -225,6 +237,20 @@ static int32_t dnodeInitStorage() {
return -1; return -1;
} }
TDIR *tdir = tfsOpendir("vnode_bak/.staging");
bool stagingNotEmpty = tfsReaddir(tdir) != NULL;
tfsClosedir(tdir);
if (stagingNotEmpty) {
dError("vnode_bak/.staging dir not empty, fix it first.");
return -1;
}
if (tfsMkdir("vnode_bak/.staging") < 0) {
dError("failed to create vnode_bak/.staging dir since %s", tstrerror(terrno));
return -1;
}
dnodeCheckDataDirOpenned(tsDnodeDir); dnodeCheckDataDirOpenned(tsDnodeDir);
dInfo("dnode storage is initialized at %s", tsDnodeDir); dInfo("dnode storage is initialized at %s", tsDnodeDir);

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

@ -49,6 +49,7 @@ int32_t dnodeInitShell() {
dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_CREATE_DB] = dnodeDispatchToMWriteQueue; dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_CREATE_DB] = dnodeDispatchToMWriteQueue;
dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_CREATE_TP] = dnodeDispatchToMWriteQueue; dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_CREATE_TP] = dnodeDispatchToMWriteQueue;
dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_DROP_DB] = dnodeDispatchToMWriteQueue; dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_DROP_DB] = dnodeDispatchToMWriteQueue;
dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_SYNC_DB] = dnodeDispatchToMWriteQueue;
dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_DROP_TP] = dnodeDispatchToMWriteQueue; dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_DROP_TP] = dnodeDispatchToMWriteQueue;
dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_ALTER_DB] = dnodeDispatchToMWriteQueue; dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_ALTER_DB] = dnodeDispatchToMWriteQueue;
dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_ALTER_TP] = dnodeDispatchToMWriteQueue; dnodeProcessShellMsgFp[TSDB_MSG_TYPE_CM_ALTER_TP] = dnodeDispatchToMWriteQueue;

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

@ -205,7 +205,7 @@ static void *dnodeProcessVWriteQueue(void *wparam) {
pWrite->rpcMsg.ahandle, taosMsg[pWrite->pHead.msgType], qtypeStr[qtype], pWrite->pHead.version); pWrite->rpcMsg.ahandle, taosMsg[pWrite->pHead.msgType], qtypeStr[qtype], pWrite->pHead.version);
pWrite->code = vnodeProcessWrite(pVnode, &pWrite->pHead, qtype, pWrite); pWrite->code = vnodeProcessWrite(pVnode, &pWrite->pHead, qtype, pWrite);
if (pWrite->code <= 0) pWrite->processedCount = 1; if (pWrite->code <= 0) atomic_add_fetch_32(&pWrite->processedCount, 1);
if (pWrite->code > 0) pWrite->code = 0; if (pWrite->code > 0) pWrite->code = 0;
if (pWrite->code == 0 && pWrite->pHead.msgType != TSDB_MSG_TYPE_SUBMIT) forceFsync = true; if (pWrite->code == 0 && pWrite->pHead.msgType != TSDB_MSG_TYPE_SUBMIT) forceFsync = true;

View File

@ -202,10 +202,11 @@ static void dnodeProcessStatusRsp(SRpcMsg *pMsg) {
char clusterId[TSDB_CLUSTER_ID_LEN]; char clusterId[TSDB_CLUSTER_ID_LEN];
dnodeGetClusterId(clusterId); dnodeGetClusterId(clusterId);
if (clusterId[0] != '\0') { if (clusterId[0] != '\0') {
dError("exit zombie dropped dnode"); dError("exit zombie dropped dnode");
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

@ -38,7 +38,7 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryTableMs
* @param qinfo * @param qinfo
* @return * @return
*/ */
bool qTableQuery(qinfo_t qinfo); bool qTableQuery(qinfo_t qinfo, uint64_t *qId);
/** /**
* Retrieve the produced results information, if current query is not paused or completed, * Retrieve the produced results information, if current query is not paused or completed,

View File

@ -318,7 +318,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" )
@ -77,6 +78,7 @@ TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_CREATE_DB, "create-db" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_DROP_DB, "drop-db" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_DROP_DB, "drop-db" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_USE_DB, "use-db" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_USE_DB, "use-db" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_ALTER_DB, "alter-db" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_ALTER_DB, "alter-db" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_SYNC_DB, "sync-db-replica" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_CREATE_TABLE, "create-table" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_CREATE_TABLE, "create-table" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_DROP_TABLE, "drop-table" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_DROP_TABLE, "drop-table" )
TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_ALTER_TABLE, "alter-table" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_CM_ALTER_TABLE, "alter-table" )
@ -388,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
@ -500,12 +502,13 @@ typedef struct {
typedef struct { typedef struct {
int32_t code; int32_t code;
uint64_t qid; // dnode generated query id union{uint64_t qhandle; uint64_t qId;}; // query handle
} SQueryTableRsp; } SQueryTableRsp;
// todo: the show handle should be replaced with id
typedef struct { typedef struct {
SMsgHead header; SMsgHead header;
union{uint64_t qid; uint64_t qhandle;}; union{uint64_t qhandle; uint64_t qId;}; // query handle
uint16_t free; uint16_t free;
} SRetrieveTableMsg; } SRetrieveTableMsg;
@ -561,7 +564,7 @@ typedef struct {
typedef struct { typedef struct {
char db[TSDB_TABLE_FNAME_LEN]; char db[TSDB_TABLE_FNAME_LEN];
uint8_t ignoreNotExists; uint8_t ignoreNotExists;
} SDropDbMsg, SUseDbMsg; } SDropDbMsg, SUseDbMsg, SSyncDbMsg;
// IMPORTANT: sizeof(SVnodeStatisticInfo) should not exceed // IMPORTANT: sizeof(SVnodeStatisticInfo) should not exceed
// TSDB_FILE_HEADER_LEN/4 - TSDB_FILE_HEADER_VERSION_SIZE // TSDB_FILE_HEADER_LEN/4 - TSDB_FILE_HEADER_VERSION_SIZE
@ -805,7 +808,7 @@ typedef struct {
uint32_t queryId; uint32_t queryId;
int64_t useconds; int64_t useconds;
int64_t stime; int64_t stime;
uint64_t qid; uint64_t qId;
} SQueryDesc; } SQueryDesc;
typedef struct { typedef struct {

View File

@ -245,7 +245,7 @@ typedef struct {
* @param qinfo query info handle from query processor * @param qinfo query info handle from query processor
* @return * @return
*/ */
TsdbQueryHandleT *tsdbQueryTables(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *tableInfoGroup, void *qinfo, TsdbQueryHandleT *tsdbQueryTables(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *tableInfoGroup, uint64_t qId,
SMemRef *pRef); SMemRef *pRef);
/** /**
@ -258,7 +258,7 @@ TsdbQueryHandleT *tsdbQueryTables(STsdbRepo *tsdb, STsdbQueryCond *pCond, STable
* @param tableInfo table list. * @param tableInfo table list.
* @return * @return
*/ */
TsdbQueryHandleT tsdbQueryLastRow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *tableInfo, void *qinfo, TsdbQueryHandleT tsdbQueryLastRow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *tableInfo, uint64_t qId,
SMemRef *pRef); SMemRef *pRef);
/** /**
@ -277,7 +277,7 @@ SArray *tsdbGetQueriedTableList(TsdbQueryHandleT *pHandle);
* @return * @return
*/ */
TsdbQueryHandleT tsdbQueryRowsInExternalWindow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList, TsdbQueryHandleT tsdbQueryRowsInExternalWindow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList,
void *qinfo, SMemRef *pRef); uint64_t qId, SMemRef *pRef);
/** /**

View File

@ -79,9 +79,6 @@ typedef void (*FStopSyncFile)(int32_t vgId, uint64_t fversion);
// get file version // get file version
typedef int32_t (*FGetVersion)(int32_t vgId, uint64_t *fver, uint64_t *vver); typedef int32_t (*FGetVersion)(int32_t vgId, uint64_t *fver, uint64_t *vver);
// reset version
typedef int32_t (*FResetVersion)(int32_t vgId, uint64_t fver);
typedef int32_t (*FSendFile)(void *tsdb, SOCKET socketFd); typedef int32_t (*FSendFile)(void *tsdb, SOCKET socketFd);
typedef int32_t (*FRecvFile)(void *tsdb, SOCKET socketFd); typedef int32_t (*FRecvFile)(void *tsdb, SOCKET socketFd);
@ -99,7 +96,6 @@ typedef struct {
FStartSyncFile startSyncFileFp; FStartSyncFile startSyncFileFp;
FStopSyncFile stopSyncFileFp; FStopSyncFile stopSyncFileFp;
FGetVersion getVersionFp; FGetVersion getVersionFp;
FResetVersion resetVersionFp;
FSendFile sendFileFp; FSendFile sendFileFp;
FRecvFile recvFileFp; FRecvFile recvFileFp;
} SSyncInfo; } SSyncInfo;

View File

@ -152,56 +152,57 @@
#define TK_NOW 133 #define TK_NOW 133
#define TK_RESET 134 #define TK_RESET 134
#define TK_QUERY 135 #define TK_QUERY 135
#define TK_ADD 136 #define TK_SYNCDB 136
#define TK_COLUMN 137 #define TK_ADD 137
#define TK_TAG 138 #define TK_COLUMN 138
#define TK_CHANGE 139 #define TK_TAG 139
#define TK_SET 140 #define TK_CHANGE 140
#define TK_KILL 141 #define TK_SET 141
#define TK_CONNECTION 142 #define TK_KILL 142
#define TK_STREAM 143 #define TK_CONNECTION 143
#define TK_COLON 144 #define TK_STREAM 144
#define TK_ABORT 145 #define TK_COLON 145
#define TK_AFTER 146 #define TK_ABORT 146
#define TK_ATTACH 147 #define TK_AFTER 147
#define TK_BEFORE 148 #define TK_ATTACH 148
#define TK_BEGIN 149 #define TK_BEFORE 149
#define TK_CASCADE 150 #define TK_BEGIN 150
#define TK_CLUSTER 151 #define TK_CASCADE 151
#define TK_CONFLICT 152 #define TK_CLUSTER 152
#define TK_COPY 153 #define TK_CONFLICT 153
#define TK_DEFERRED 154 #define TK_COPY 154
#define TK_DELIMITERS 155 #define TK_DEFERRED 155
#define TK_DETACH 156 #define TK_DELIMITERS 156
#define TK_EACH 157 #define TK_DETACH 157
#define TK_END 158 #define TK_EACH 158
#define TK_EXPLAIN 159 #define TK_END 159
#define TK_FAIL 160 #define TK_EXPLAIN 160
#define TK_FOR 161 #define TK_FAIL 161
#define TK_IGNORE 162 #define TK_FOR 162
#define TK_IMMEDIATE 163 #define TK_IGNORE 163
#define TK_INITIALLY 164 #define TK_IMMEDIATE 164
#define TK_INSTEAD 165 #define TK_INITIALLY 165
#define TK_MATCH 166 #define TK_INSTEAD 166
#define TK_KEY 167 #define TK_MATCH 167
#define TK_OF 168 #define TK_KEY 168
#define TK_RAISE 169 #define TK_OF 169
#define TK_REPLACE 170 #define TK_RAISE 170
#define TK_RESTRICT 171 #define TK_REPLACE 171
#define TK_ROW 172 #define TK_RESTRICT 172
#define TK_STATEMENT 173 #define TK_ROW 173
#define TK_TRIGGER 174 #define TK_STATEMENT 174
#define TK_VIEW 175 #define TK_TRIGGER 175
#define TK_SEMI 176 #define TK_VIEW 176
#define TK_NONE 177 #define TK_SEMI 177
#define TK_PREV 178 #define TK_NONE 178
#define TK_LINEAR 179 #define TK_PREV 179
#define TK_IMPORT 180 #define TK_LINEAR 180
#define TK_TBNAME 181 #define TK_IMPORT 181
#define TK_JOIN 182 #define TK_TBNAME 182
#define TK_INSERT 183 #define TK_JOIN 183
#define TK_INTO 184 #define TK_INSERT 184
#define TK_VALUES 185 #define TK_INTO 185
#define TK_VALUES 186
#define TK_SPACE 300 #define TK_SPACE 300

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
@ -89,4 +90,4 @@ int32_t vnodeProcessRead(void *pVnode, SVReadMsg *pRead);
} }
#endif #endif
#endif #endif

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

@ -50,6 +50,7 @@ static int32_t mnodeGetDbMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn
static int32_t mnodeRetrieveDbs(SShowObj *pShow, char *data, int32_t rows, void *pConn); static int32_t mnodeRetrieveDbs(SShowObj *pShow, char *data, int32_t rows, void *pConn);
static int32_t mnodeProcessCreateDbMsg(SMnodeMsg *pMsg); static int32_t mnodeProcessCreateDbMsg(SMnodeMsg *pMsg);
static int32_t mnodeProcessDropDbMsg(SMnodeMsg *pMsg); static int32_t mnodeProcessDropDbMsg(SMnodeMsg *pMsg);
static int32_t mnodeProcessSyncDbMsg(SMnodeMsg *pMsg);
int32_t mnodeProcessAlterDbMsg(SMnodeMsg *pMsg); int32_t mnodeProcessAlterDbMsg(SMnodeMsg *pMsg);
#ifndef _TOPIC #ifndef _TOPIC
@ -178,6 +179,7 @@ int32_t mnodeInitDbs() {
mnodeAddWriteMsgHandle(TSDB_MSG_TYPE_CM_CREATE_DB, mnodeProcessCreateDbMsg); mnodeAddWriteMsgHandle(TSDB_MSG_TYPE_CM_CREATE_DB, mnodeProcessCreateDbMsg);
mnodeAddWriteMsgHandle(TSDB_MSG_TYPE_CM_ALTER_DB, mnodeProcessAlterDbMsg); mnodeAddWriteMsgHandle(TSDB_MSG_TYPE_CM_ALTER_DB, mnodeProcessAlterDbMsg);
mnodeAddWriteMsgHandle(TSDB_MSG_TYPE_CM_DROP_DB, mnodeProcessDropDbMsg); mnodeAddWriteMsgHandle(TSDB_MSG_TYPE_CM_DROP_DB, mnodeProcessDropDbMsg);
mnodeAddWriteMsgHandle(TSDB_MSG_TYPE_CM_SYNC_DB, mnodeProcessSyncDbMsg);
mnodeAddShowMetaHandle(TSDB_MGMT_TABLE_DB, mnodeGetDbMeta); mnodeAddShowMetaHandle(TSDB_MGMT_TABLE_DB, mnodeGetDbMeta);
mnodeAddShowRetrieveHandle(TSDB_MGMT_TABLE_DB, mnodeRetrieveDbs); mnodeAddShowRetrieveHandle(TSDB_MGMT_TABLE_DB, mnodeRetrieveDbs);
mnodeAddShowFreeIterHandle(TSDB_MGMT_TABLE_DB, mnodeCancelGetNextDb); mnodeAddShowFreeIterHandle(TSDB_MGMT_TABLE_DB, mnodeCancelGetNextDb);
@ -1184,6 +1186,46 @@ 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) {
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) {
int32_t numOfDbs = 0; int32_t numOfDbs = 0;
SDbObj *pDb = NULL; SDbObj *pDb = NULL;

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) {

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