diff --git a/Jenkinsfile b/Jenkinsfile index daae5a5ad09f24a980bdcea5f5551b53a24c02aa..bac0cce33b9b645373170247fb91df31fad6f646 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -42,12 +42,12 @@ def pre_test(){ killall -9 taosd ||echo "no taosd running" killall -9 gdb || echo "no gdb running" cd ${WKC} - git checkout develop git reset --hard HEAD~10 >/dev/null + git checkout develop git pull >/dev/null git fetch origin +refs/pull/${CHANGE_ID}/merge git checkout -qf FETCH_HEAD - find ${WKC}/tests/pytest -name \'*\'.sql -exec rm -rf {} \\; + git clean -dfx cd ${WK} git reset --hard HEAD~10 git checkout develop @@ -55,7 +55,7 @@ def pre_test(){ cd ${WK} export TZ=Asia/Harbin date - rm -rf ${WK}/debug + git clean -dfx mkdir debug cd debug cmake .. > /dev/null @@ -185,6 +185,14 @@ pipeline { rm -rf /var/log/taos/* ./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'){ sh ''' date @@ -215,6 +223,11 @@ pipeline { cd ${WKC}/tests ./test-all.sh b3fq date''' + sh ''' + date + cd ${WKC}/tests + ./test-all.sh full example + date''' } } } @@ -272,7 +285,7 @@ pipeline { date cd ${WKC}/tests ./test-all.sh b7fq - date''' + date''' } } } diff --git a/cmake/install.inc b/cmake/install.inc index 1d50ca292d902461e0f77732da83076954224f06..5823ef743ed5b5b57f3915a82aa9e1e21f850d2f 100755 --- a/cmake/install.inc +++ b/cmake/install.inc @@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS) #INSTALL(TARGETS taos RUNTIME DESTINATION driver) #INSTALL(TARGETS shell RUNTIME DESTINATION .) IF (TD_MVN_INSTALLED) - INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.22-dist.jar DESTINATION connector/jdbc) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.25-dist.jar DESTINATION connector/jdbc) ENDIF () ELSEIF (TD_DARWIN) SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh") diff --git a/documentation20/cn/02.getting-started/docs.md b/documentation20/cn/02.getting-started/docs.md index c9c82942f3bd47fa774636dd5cf7c5b33f879209..f86e616c42a5e9948dbbaca7da3ffcca6f395208 100644 --- a/documentation20/cn/02.getting-started/docs.md +++ b/documentation20/cn/02.getting-started/docs.md @@ -179,18 +179,18 @@ taos> select avg(f1), max(f2), min(f3) from test.t10 interval(10s); ### TDengine服务器支持的平台列表 -| | **CentOS** **6/7/8** | **Ubuntu** **16/18/20** | **Other Linux** | **统信****UOS** | **银河****/****中标麒麟** | **凝思** **V60/V80** | +| | **CentOS 6/7/8** | **Ubuntu 16/18/20** | **Other Linux** | **统信 UOS** | **银河/中标麒麟** | **凝思 V60/V80** | | -------------- | --------------------- | ------------------------ | --------------- | --------------- | ------------------------- | --------------------- | | X64 | ● | ● | | ○ | ● | ● | -| 树莓派ARM32 | | ● | ● | | | | -| 龙芯MIPS64 | | | ● | | | | -| 鲲鹏 ARM64 | | ○ | ○ | | ● | | -| 申威 Alpha64 | | | ○ | ● | | | -| 飞腾ARM64 | | ○优麒麟 | | | | | -| 海光X64 | ● | ● | ● | ○ | ● | ● | -| 瑞芯微ARM64/32 | | | ○ | | | | -| 全志ARM64/32 | | | ○ | | | | -| 炬力ARM64/32 | | | ○ | | | | +| 树莓派 ARM32 | | ● | ● | | | | +| 龙芯 MIPS64 | | | ● | | | | +| 鲲鹏 ARM64 | | ○ | ○ | | ● | | +| 申威 Alpha64 | | | ○ | ● | | | +| 飞腾 ARM64 | | ○ 优麒麟 | | | | | +| 海光 X64 | ● | ● | ● | ○ | ● | ● | +| 瑞芯微 ARM64/32 | | | ○ | | | | +| 全志 ARM64/32 | | | ○ | | | | +| 炬力 ARM64/32 | | | ○ | | | | | TI ARM32 | | | ○ | | | | 注: ● 表示经过官方测试验证, ○ 表示非官方测试验证。 @@ -203,7 +203,7 @@ taos> select avg(f1), max(f2), min(f3) from test.t10 interval(10s); 对照矩阵如下: -| **CPU** | **X64 64bit** | | | **X86 32bit** | **ARM64** | **ARM32** | **MIPS ** **龙芯** | **Alpha ** **申威** | **X64 ** **海光** | +| **CPU** | **X64 64bit** | | | **X86 32bit** | **ARM64** | **ARM32** | **MIPS 龙芯** | **Alpha 申威** | **X64 海光** | | ----------- | --------------- | --------- | --------- | --------------- | --------- | --------- | ------------------- | -------------------- | ------------------ | | **OS** | **Linux** | **Win64** | **Win32** | **Win32** | **Linux** | **Linux** | **Linux** | **Linux** | **Linux** | | **C/C++** | ● | ● | ● | ○ | ● | ● | ● | ● | ● | diff --git a/documentation20/cn/07.advanced-features/docs.md b/documentation20/cn/07.advanced-features/docs.md index bdf93fdc3d74184bd7a6fd6f4eefaf3db6853c22..650a2ca96b759bd6b8123dbb64023496b654dcd0 100644 --- a/documentation20/cn/07.advanced-features/docs.md +++ b/documentation20/cn/07.advanced-features/docs.md @@ -1,27 +1,16 @@ # 高级功能 -## 连续查询(Continuous Query) +## 连续查询(Continuous Query) -连续查询是TDengine定期自动执行的查询,采用滑动窗口的方式进行计算,是一种简化的时间驱动的流式计算。 -针对库中的表或超级表,TDengine可提供定期自动执行的连续查询, -用户可让TDengine推送查询的结果,也可以将结果再写回到TDengine中。 -每次执行的查询是一个时间窗口,时间窗口随着时间流动向前滑动。 -在定义连续查询的时候需要指定时间窗口(time window, 参数interval)大小和每次前向增量时间(forward sliding times, 参数sliding)。 +连续查询是TDengine定期自动执行的查询,采用滑动窗口的方式进行计算,是一种简化的时间驱动的流式计算。针对库中的表或超级表,TDengine可提供定期自动执行的连续查询,用户可让TDengine推送查询的结果,也可以将结果再写回到TDengine中。每次执行的查询是一个时间窗口,时间窗口随着时间流动向前滑动。在定义连续查询的时候需要指定时间窗口(time window, 参数interval)大小和每次前向增量时间(forward sliding times, 参数sliding)。 -TDengine的连续查询采用时间驱动模式,可以直接使用TAOS SQL进行定义,不需要额外的操作。 -使用连续查询,可以方便快捷地按照时间窗口生成结果,从而对原始采集数据进行降采样(down sampling)。 -用户通过TAOS SQL定义连续查询以后,TDengine自动在最后的一个完整的时间周期末端拉起查询, -并将计算获得的结果推送给用户或者写回TDengine。 +TDengine的连续查询采用时间驱动模式,可以直接使用TAOS SQL进行定义,不需要额外的操作。使用连续查询,可以方便快捷地按照时间窗口生成结果,从而对原始采集数据进行降采样(down sampling)。用户通过TAOS SQL定义连续查询以后,TDengine自动在最后的一个完整的时间周期末端拉起查询,并将计算获得的结果推送给用户或者写回TDengine。 TDengine提供的连续查询与普通流计算中的时间窗口计算具有以下区别: -- 不同于流计算的实时反馈计算结果,连续查询只在时间窗口关闭以后才开始计算。 -例如时间周期是1天,那么当天的结果只会在23:59:59以后才会生成。 -- 如果有历史记录写入到已经计算完成的时间区间,连续查询并不会重新进行计算, -也不会重新将结果推送给用户。对于写回TDengine的模式,也不会更新已经存在的计算结果。 -- 使用连续查询推送结果的模式,服务端并不缓存客户端计算状态,也不提供Exactly-Once的语意保证。 -如果用户的应用端崩溃,再次拉起的连续查询将只会从再次拉起的时间开始重新计算最近的一个完整的时间窗口。 -如果使用写回模式,TDengine可确保数据写回的有效性和连续性。 +- 不同于流计算的实时反馈计算结果,连续查询只在时间窗口关闭以后才开始计算。例如时间周期是1天,那么当天的结果只会在23:59:59以后才会生成。 +- 如果有历史记录写入到已经计算完成的时间区间,连续查询并不会重新进行计算,也不会重新将结果推送给用户。对于写回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); ``` -每次执行这条语句,都会重新计算所有数据。 -如果需要每隔30秒执行一次来增量计算最近一分钟的数据, -可以把上面的语句改进成下面的样子,每次使用不同的 `startTime` 并定期执行: +每次执行这条语句,都会重新计算所有数据。 如果需要每隔30秒执行一次来增量计算最近一分钟的数据,可以把上面的语句改进成下面的样子,每次使用不同的 `startTime` 并定期执行: ```sql select avg(voltage) from meters where ts > {startTime} interval(1m) sliding(30s); ``` -这样做没有问题,但TDengine提供了更简单的方法, -只要在最初的查询语句前面加上 `create table {tableName} as ` 就可以了, 例如: +这样做没有问题,但TDengine提供了更简单的方法,只要在最初的查询语句前面加上 `create table {tableName} as ` 就可以了, 例如: ```sql create table avg_vol as select avg(voltage) from meters interval(1m) sliding(30s); ``` -会自动创建一个名为 `avg_vol` 的新表,然后每隔30秒,TDengine会增量执行 `as` 后面的 SQL 语句, -并将查询结果写入这个表中,用户程序后续只要从 `avg_vol` 中查询数据即可。 例如: +会自动创建一个名为 `avg_vol` 的新表,然后每隔30秒,TDengine会增量执行 `as` 后面的 SQL 语句,并将查询结果写入这个表中,用户程序后续只要从 `avg_vol` 中查询数据即可。 例如: ```mysql taos> select * from avg_vol; @@ -70,43 +55,27 @@ taos> select * from avg_vol; 需要注意,查询时间窗口的最小值是10毫秒,没有时间窗口范围的上限。 -此外,TDengine还支持用户指定连续查询的起止时间。 -如果不输入开始时间,连续查询将从第一条原始数据所在的时间窗口开始; -如果没有输入结束时间,连续查询将永久运行; -如果用户指定了结束时间,连续查询在系统时间达到指定的时间以后停止运行。 -比如使用下面的SQL创建的连续查询将运行一小时,之后会自动停止。 +此外,TDengine还支持用户指定连续查询的起止时间。如果不输入开始时间,连续查询将从第一条原始数据所在的时间窗口开始;如果没有输入结束时间,连续查询将永久运行;如果用户指定了结束时间,连续查询在系统时间达到指定的时间以后停止运行。比如使用下面的SQL创建的连续查询将运行一小时,之后会自动停止。 ```mysql create table avg_vol as select avg(voltage) from meters where ts > now and ts <= now + 1h interval(1m) sliding(30s); ``` -需要说明的是,上面例子中的 `now` 是指创建连续查询的时间,而不是查询执行的时间,否则,查询就无法自动停止了。 -另外,为了尽量避免原始数据延迟写入导致的问题,TDengine中连续查询的计算有一定的延迟。 -也就是说,一个时间窗口过去后,TDengine并不会立即计算这个窗口的数据, -所以要稍等一会(一般不会超过1分钟)才能查到计算结果。 +需要说明的是,上面例子中的 `now` 是指创建连续查询的时间,而不是查询执行的时间,否则,查询就无法自动停止了。另外,为了尽量避免原始数据延迟写入导致的问题,TDengine中连续查询的计算有一定的延迟。也就是说,一个时间窗口过去后,TDengine并不会立即计算这个窗口的数据,所以要稍等一会(一般不会超过1分钟)才能查到计算结果。 ### 管理连续查询 -用户可在控制台中通过 `show streams` 命令来查看系统中全部运行的连续查询, -并可以通过 `kill stream` 命令杀掉对应的连续查询。 -后续版本会提供更细粒度和便捷的连续查询管理命令。 +用户可在控制台中通过 `show streams` 命令来查看系统中全部运行的连续查询,并可以通过 `kill stream` 命令杀掉对应的连续查询。后续版本会提供更细粒度和便捷的连续查询管理命令。 -## 数据订阅(Publisher/Subscriber) +## 数据订阅(Publisher/Subscriber) -基于数据天然的时间序列特性,TDengine的数据写入(insert)与消息系统的数据发布(pub)逻辑上一致, -均可视为系统中插入一条带时间戳的新记录。 -同时,TDengine在内部严格按照数据时间序列单调递增的方式保存数据。 -本质上来说,TDengine中里每一张表均可视为一个标准的消息队列。 +基于数据天然的时间序列特性,TDengine的数据写入(insert)与消息系统的数据发布(pub)逻辑上一致,均可视为系统中插入一条带时间戳的新记录。同时,TDengine在内部严格按照数据时间序列单调递增的方式保存数据。本质上来说,TDengine中里每一张表均可视为一个标准的消息队列。 -TDengine内嵌支持轻量级的消息订阅与推送服务。 -使用系统提供的API,用户可使用普通查询语句订阅数据库中的一张或多张表。 -订阅的逻辑和操作状态的维护均是由客户端完成,客户端定时轮询服务器是否有新的记录到达, -有新的记录到达就会将结果反馈到客户。 +TDengine内嵌支持轻量级的消息订阅与推送服务。使用系统提供的API,用户可使用普通查询语句订阅数据库中的一张或多张表。订阅的逻辑和操作状态的维护均是由客户端完成,客户端定时轮询服务器是否有新的记录到达,有新的记录到达就会将结果反馈到客户。 -TDengine的订阅与推送服务的状态是客户端维持,TDengine服务器并不维持。 -因此如果应用重启,从哪个时间点开始获取最新数据,由应用决定。 +TDengine的订阅与推送服务的状态是客户端维持,TDengine服务器并不维持。因此如果应用重启,从哪个时间点开始获取最新数据,由应用决定。 TDengine的API中,与订阅相关的主要有以下三个: @@ -116,12 +85,9 @@ taos_consume taos_unsubscribe ``` -这些API的文档请见 [C/C++ Connector](https://www.taosdata.com/cn/documentation/connector/), -下面仍以智能电表场景为例介绍一下它们的具体用法(超级表和子表结构请参考上一节“连续查询”), -完整的示例代码可以在 [这里](https://github.com/taosdata/TDengine/blob/master/tests/examples/c/subscribe.c) 找到。 +这些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) 找到。 -如果我们希望当某个电表的电流超过一定限制(比如10A)后能得到通知并进行一些处理, 有两种方法: -一是分别对每张子表进行查询,每次查询后记录最后一条数据的时间戳,后续只查询这个时间戳之后的数据: +如果我们希望当某个电表的电流超过一定限制(比如10A)后能得到通知并进行一些处理, 有两种方法:一是分别对每张子表进行查询,每次查询后记录最后一条数据的时间戳,后续只查询这个时间戳之后的数据: ```sql 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; ``` -但是,如何选择 `last_timestamp` 就成了一个新的问题。 -因为,一方面数据的产生时间(也就是数据时间戳)和数据入库的时间一般并不相同,有时偏差还很大; -另一方面,不同电表的数据到达TDengine的时间也会有差异。 -所以,如果我们在查询中使用最慢的那台电表的数据的时间戳作为 `last_timestamp`, -就可能重复读入其它电表的数据; -如果使用最快的电表的时间戳,其它电表的数据就可能被漏掉。 +但是,如何选择 `last_timestamp` 就成了一个新的问题。因为,一方面数据的产生时间(也就是数据时间戳)和数据入库的时间一般并不相同,有时偏差还很大;另一方面,不同电表的数据到达TDengine的时间也会有差异。所以,如果我们在查询中使用最慢的那台电表的数据的时间戳作为 `last_timestamp`,就可能重复读入其它电表的数据;如果使用最快的电表的时间戳,其它电表的数据就可能被漏掉。 TDengine的订阅功能为上面这个问题提供了一个彻底的解决方案。 @@ -160,47 +120,29 @@ if (async) { } ``` -TDengine中的订阅既可以是同步的,也可以是异步的, -上面的代码会根据从命令行获取的参数`async`的值来决定使用哪种方式。 -这里,同步的意思是用户程序要直接调用`taos_consume`来拉取数据, -而异步则由API在内部的另一个线程中调用`taos_consume`, -然后把拉取到的数据交给回调函数`subscribe_callback`去处理。 +TDengine中的订阅既可以是同步的,也可以是异步的,上面的代码会根据从命令行获取的参数`async`的值来决定使用哪种方式。这里,同步的意思是用户程序要直接调用`taos_consume`来拉取数据,而异步则由API在内部的另一个线程中调用`taos_consume`,然后把拉取到的数据交给回调函数`subscribe_callback`去处理。 -参数`taos`是一个已经建立好的数据库连接,在同步模式下无特殊要求。 -但在异步模式下,需要注意它不会被其它线程使用,否则可能导致不可预计的错误, -因为回调函数在API的内部线程中被调用,而TDengine的部分API不是线程安全的。 +参数`taos`是一个已经建立好的数据库连接,在同步模式下无特殊要求。但在异步模式下,需要注意它不会被其它线程使用,否则可能导致不可预计的错误,因为回调函数在API的内部线程中被调用,而TDengine的部分API不是线程安全的。 -参数`sql`是查询语句,可以在其中使用where子句指定过滤条件。 -在我们的例子中,如果只想订阅电流超过10A时的数据,可以这样写: +参数`sql`是查询语句,可以在其中使用where子句指定过滤条件。在我们的例子中,如果只想订阅电流超过10A时的数据,可以这样写: ```sql select * from meters where current > 10; ``` -注意,这里没有指定起始时间,所以会读到所有时间的数据。 -如果只想从一天前的数据开始订阅,而不需要更早的历史数据,可以再加上一个时间条件: +注意,这里没有指定起始时间,所以会读到所有时间的数据。如果只想从一天前的数据开始订阅,而不需要更早的历史数据,可以再加上一个时间条件: ```sql select * from meters where ts > now - 1d and current > 10; ``` -订阅的`topic`实际上是它的名字,因为订阅功能是在客户端API中实现的, -所以没必要保证它全局唯一,但需要它在一台客户端机器上唯一。 +订阅的`topic`实际上是它的名字,因为订阅功能是在客户端API中实现的,所以没必要保证它全局唯一,但需要它在一台客户端机器上唯一。 -如果名`topic`的订阅不存在,参数`restart`没有意义; -但如果用户程序创建这个订阅后退出,当它再次启动并重新使用这个`topic`时, -`restart`就会被用于决定是从头开始读取数据,还是接续上次的位置进行读取。 -本例中,如果`restart`是 **true**(非零值),用户程序肯定会读到所有数据。 -但如果这个订阅之前就存在了,并且已经读取了一部分数据, -且`restart`是 **false**(**0**),用户程序就不会读到之前已经读取的数据了。 +如果名`topic`的订阅不存在,参数`restart`没有意义;但如果用户程序创建这个订阅后退出,当它再次启动并重新使用这个`topic`时,`restart`就会被用于决定是从头开始读取数据,还是接续上次的位置进行读取。本例中,如果`restart`是 **true**(非零值),用户程序肯定会读到所有数据。但如果这个订阅之前就存在了,并且已经读取了一部分数据,且`restart`是 **false**(**0**),用户程序就不会读到之前已经读取的数据了。 -`taos_subscribe`的最后一个参数是以毫秒为单位的轮询周期。 -在同步模式下,如果前后两次调用`taos_consume`的时间间隔小于此时间, -`taos_consume`会阻塞,直到间隔超过此时间。 -异步模式下,这个时间是两次调用回调函数的最小时间间隔。 +`taos_subscribe`的最后一个参数是以毫秒为单位的轮询周期。在同步模式下,如果前后两次调用`taos_consume`的时间间隔小于此时间,`taos_consume`会阻塞,直到间隔超过此时间。异步模式下,这个时间是两次调用回调函数的最小时间间隔。 -`taos_subscribe`的倒数第二个参数用于用户程序向回调函数传递附加参数, -订阅API不对其做任何处理,只原样传递给回调函数。此参数在同步模式下无意义。 +`taos_subscribe`的倒数第二个参数用于用户程序向回调函数传递附加参数,订阅API不对其做任何处理,只原样传递给回调函数。此参数在同步模式下无意义。 订阅创建以后,就可以消费其数据了,同步模式下,示例代码是下面的 else 部分: @@ -219,9 +161,7 @@ if (async) { } ``` -这里是一个 **while** 循环,用户每按一次回车键就调用一次`taos_consume`, -而`taos_consume`的返回值是查询到的结果集,与`taos_use_result`完全相同, -例子中使用这个结果集的代码是函数`print_result`: +这里是一个 **while** 循环,用户每按一次回车键就调用一次`taos_consume`,而`taos_consume`的返回值是查询到的结果集,与`taos_use_result`完全相同,例子中使用这个结果集的代码是函数`print_result`: ```c 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 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); ``` -其第二个参数,用于决定是否在客户端保留订阅的进度信息。 -如果这个参数是**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); ``` -这时,因为电流超过了10A,您应该可以看到示例程序将它输出到了屏幕上。 -您可以继续插入一些数据观察示例程序的输出。 +这时,因为电流超过了10A,您应该可以看到示例程序将它输出到了屏幕上。您可以继续插入一些数据观察示例程序的输出。 ### 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 的记录。 @@ -404,7 +338,7 @@ ts: 1597466400000 current: 12.4 voltage: 220 phase: 1 location: Beijing.Chaoyang ``` -## 缓存(Cache) +## 缓存(Cache) TDengine采用时间驱动缓存管理策略(First-In-First-Out,FIFO),又称为写驱动的缓存管理机制。这种策略有别于读驱动的数据缓存模式(Least-Recent-Use,LRU),直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候,将最早的数据批量写入磁盘。一般意义上来说,对于物联网数据的使用,用户最为关心最近产生的数据,即当前状态。TDengine充分利用了这一特性,将最近到达的(当前状态)数据保存在缓存中。 @@ -423,7 +357,7 @@ select last_row(voltage) from meters where location='Beijing.Chaoyang'; 该SQL语句将获取所有位于北京朝阳区的电表最后记录的电压值。 -## 报警监测(Alert) +## 报警监测(Alert) 在 TDengine 的应用场景中,报警监测是一个常见需求,从概念上说,它要求程序从最近一段时间的数据中筛选出符合一定条件的数据,并基于这些数据根据定义好的公式计算出一个结果,当这个结果符合某个条件且持续一定时间后,以某种形式通知用户。 diff --git a/documentation20/cn/08.connector/01.java/docs.md b/documentation20/cn/08.connector/01.java/docs.md index 3ed7343579ef7dc9c774367a8d9b41e2dabb7561..3442a2248cd3743cc93034fb5aa9d13b96079543 100644 --- a/documentation20/cn/08.connector/01.java/docs.md +++ b/documentation20/cn/08.connector/01.java/docs.md @@ -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/inc/taoserror.h -### 订阅 +### 订阅 #### 创建 @@ -471,9 +471,11 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对 | BIGINT | java.lang.Long | | FLOAT | java.lang.Float | | DOUBLE | java.lang.Double | -| SMALLINT, TINYINT | java.lang.Short | +| SMALLINT | java.lang.Short | +| TINYINT | java.lang.Byte | | BOOL | java.lang.Boolean | -| BINARY, NCHAR | java.lang.String | +| BINARY | byte array | +| NCHAR | java.lang.String | diff --git a/documentation20/cn/11.administrator/docs.md b/documentation20/cn/11.administrator/docs.md index c2c2927387449290dc892205561b59317c4ecf67..cc8689786d1725efdff82610190d4a6b1e34f906 100644 --- a/documentation20/cn/11.administrator/docs.md +++ b/documentation20/cn/11.administrator/docs.md @@ -120,17 +120,17 @@ taosd -C 不同应用场景的数据往往具有不同的数据特征,比如保留天数、副本数、采集频次、记录大小、采集点的数量、压缩等都可完全不同。为获得在存储上的最高效率,TDengine提供如下存储相关的系统配置参数: - days:一个数据文件存储数据的时间跨度,单位为天,默认值:10。 -- keep:数据库中数据保留的天数,单位为天,默认值:3650。 +- keep:数据库中数据保留的天数,单位为天,默认值:3650。(可通过 alter database 修改) - minRows:文件块中记录的最小条数,单位为条,默认值:100。 - maxRows:文件块中记录的最大条数,单位为条,默认值:4096。 -- comp:文件压缩标志位,0:关闭;1:一阶段压缩;2:两阶段压缩。默认值:2。 +- comp:文件压缩标志位,0:关闭;1:一阶段压缩;2:两阶段压缩。默认值:2。(可通过 alter database 修改) - walLevel:WAL级别。1:写wal,但不执行fsync;2:写wal, 而且执行fsync。默认值:1。 - fsync:当wal设置为2时,执行fsync的周期。设置为0,表示每次写入,立即执行fsync。单位为毫秒,默认值:3000。 - cache:内存块的大小,单位为兆字节(MB),默认值:16。 -- blocks:每个VNODE(TSDB)中有多少cache大小的内存块。因此一个VNODE的用的内存大小粗略为(cache * blocks)。单位为块,默认值:4。 -- replica:副本个数,取值范围:1-3。单位为个,默认值:1 -- precision:时间戳精度标识,ms表示毫秒,us表示微秒。默认值:ms -- cacheLast:是否在内存中缓存子表 last_row,0:关闭;1:开启。默认值:0。(从 2.0.11 版本开始支持此参数) +- blocks:每个VNODE(TSDB)中有多少cache大小的内存块。因此一个VNODE的用的内存大小粗略为(cache * blocks)。单位为块,默认值:4。(可通过 alter database 修改) +- replica:副本个数,取值范围:1-3。单位为个,默认值:1。(可通过 alter database 修改) +- precision:时间戳精度标识,ms表示毫秒,us表示微秒。默认值:ms。 +- cacheLast:是否在内存中缓存子表 last_row,0:关闭;1:开启。默认值:0。(可通过 alter database 修改)(从 2.0.11 版本开始支持此参数) 对于一个应用场景,可能有多种数据特征的数据并存,最佳的设计是将具有相同数据特征的表放在一个库里,这样一个应用有多个库,而每个库可以配置不同的存储参数,从而保证系统有最优的性能。TDengine允许应用在创建库时指定上述存储参数,如果指定,该参数就将覆盖对应的系统配置参数。举例,有下述SQL: diff --git a/documentation20/cn/12.taos-sql/docs.md b/documentation20/cn/12.taos-sql/docs.md index b4fa2b160aa8ec04ba3a45db0fbbca17022cbd23..58191e0bd8faa02b0ff2381f1cdd576b379ae9fc 100644 --- a/documentation20/cn/12.taos-sql/docs.md +++ b/documentation20/cn/12.taos-sql/docs.md @@ -29,21 +29,21 @@ taos> DESCRIBE meters; ## 支持的数据类型 -使用TDengine,最重要的是时间戳。创建并插入记录、查询历史记录的时候,均需要指定时间戳。时间戳有如下规则: +使用 TDengine,最重要的是时间戳。创建并插入记录、查询历史记录的时候,均需要指定时间戳。时间戳有如下规则: -- 时间格式为```YYYY-MM-DD HH:mm:ss.MS```, 默认时间分辨率为毫秒。比如:```2017-08-12 18:25:58.128``` -- 内部函数now是服务器的当前时间 -- 插入记录时,如果时间戳为now,插入数据时使用服务器当前时间 -- 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(自然年)。 +- 时间格式为 ```YYYY-MM-DD HH:mm:ss.MS```,默认时间分辨率为毫秒。比如:```2017-08-12 18:25:58.128``` +- 内部函数 now 是客户端的当前时间 +- 插入记录时,如果时间戳为 now,插入数据时使用提交这条记录的客户端的当前时间 +- Epoch Time:时间戳也可以是一个长整数,表示从 1970-01-01 08:00:00.000 开始的毫秒数 +- 时间可以加减,比如 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 | 说明 | | ---- | :-------: | ------ | ------------------------------------------------------------ | -| 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 | | 3 | BIGINT | 8 | 长整型,范围 [-2^63+1, 2^63-1], -2^63 用于 NULL | | 4 | FLOAT | 4 | 浮点型,有效位数 6-7,范围 [-3.4E38, 3.4E38] | diff --git a/documentation20/cn/13.faq/docs.md b/documentation20/cn/13.faq/docs.md index e2285b29e244641566661cf102c7b17616a6780a..c01247d345906bde021d88841d34f667c8991fa9 100644 --- a/documentation20/cn/13.faq/docs.md +++ b/documentation20/cn/13.faq/docs.md @@ -156,3 +156,13 @@ ALTER LOCAL RESETLOG; ``` 其含义是,清空本机所有由客户端生成的日志文件。 + +## 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`)来书写时间戳,此时这些时间戳的取值将不再受其他时区设置的影响。 diff --git a/packaging/cfg/taos.cfg b/packaging/cfg/taos.cfg index a1178e2eefd6c4e6a4433a451d2e4e865a39cfe6..83b70ed9f89e54ea336a4d066ab3d32bcfdd9c8a 100644 --- a/packaging/cfg/taos.cfg +++ b/packaging/cfg/taos.cfg @@ -29,6 +29,9 @@ # number of threads per CPU core # numOfThreadsPerCore 1.0 +# number of threads to commit cache data +# numOfCommitThreads 4 + # the proportion of total CPU cores available for query processing # 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]. diff --git a/packaging/tools/remove.sh b/packaging/tools/remove.sh index e63889aff1a6eceebfc9624576270200f6e79fa7..9241f01efaeb892afc020dc239e5e80eebc8bdd6 100755 --- a/packaging/tools/remove.sh +++ b/packaging/tools/remove.sh @@ -120,7 +120,7 @@ function clean_service_on_systemd() { if [ "$verMode" == "cluster" ]; then 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 echo "Nginx for TDengine is running, stopping it..." ${csudo} systemctl stop ${nginx_service_name} &> /dev/null || echo &> /dev/null diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h index 8983365e58c5657fc1a7604a66f309b745639d67..92603c46ba90e120a314b6c7c9a52a619f478838 100644 --- a/src/client/inc/tsclient.h +++ b/src/client/inc/tsclient.h @@ -451,6 +451,8 @@ void tscFreeSqlResult(SSqlObj *pSql); * @param pObj */ void tscFreeSqlObj(SSqlObj *pSql); +void tscFreeSubobj(SSqlObj* pSql); + void tscFreeRegisteredSqlObj(void *pSql); void tscCloseTscObj(void *pObj); diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 24d7e19c857e6012c6821c5b15a4be66bc659d6e..a7b8e957d4dcf07508f18775345b9494d5c4f969 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -2683,7 +2683,6 @@ void tscInitMsgsFp() { tscProcessMsgRsp[TSDB_SQL_SHOW_CREATE_TABLE] = tscProcessShowCreateRsp; tscProcessMsgRsp[TSDB_SQL_SHOW_CREATE_DATABASE] = tscProcessShowCreateRsp; - tscKeepConn[TSDB_SQL_SHOW] = 1; tscKeepConn[TSDB_SQL_RETRIEVE] = 1; tscKeepConn[TSDB_SQL_SELECT] = 1; diff --git a/src/client/src/tscStream.c b/src/client/src/tscStream.c index a9cd1965e8b3e6282aaf7601011e78e5ff4bc7bb..7699e6f45973c8ca834e0e93ad5f5f31797ec520 100644 --- a/src/client/src/tscStream.c +++ b/src/client/src/tscStream.c @@ -299,6 +299,7 @@ static void tscProcessStreamRetrieveResult(void *param, TAOS_RES *res, int numOf tfree(pTableMetaInfo->pTableMeta); tscFreeSqlResult(pSql); + tscFreeSubobj(pSql); tfree(pSql->pSubs); pSql->subState.numOfSub = 0; pTableMetaInfo->vgroupList = tscVgroupInfoClear(pTableMetaInfo->vgroupList); diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 59f193d596b3d4bffde55a2ddf52d09cc4e28411..560356c5e819cd3933cba1f24cc6f22f12b4ebcf 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -447,7 +447,7 @@ void tscFreeSqlResult(SSqlObj* pSql) { memset(&pSql->res, 0, sizeof(SSqlRes)); } -static void tscFreeSubobj(SSqlObj* pSql) { +void tscFreeSubobj(SSqlObj* pSql) { if (pSql->subState.numOfSub == 0) { return; } diff --git a/src/common/src/tglobal.c b/src/common/src/tglobal.c index 4fef3844c4f6ed93bb893d2e920f176ff4a1e9fa..5f4ce046ed5359bab8c0f175ff0c08d6da939700 100644 --- a/src/common/src/tglobal.c +++ b/src/common/src/tglobal.c @@ -51,7 +51,7 @@ int32_t tsMaxShellConns = 50000; int32_t tsMaxConnections = 5000; int32_t tsShellActivityTimer = 3; // second float tsNumOfThreadsPerCore = 1.0f; -int32_t tsNumOfCommitThreads = 1; +int32_t tsNumOfCommitThreads = 4; float tsRatioOfQueryCores = 1.0f; int8_t tsDaylight = 0; char tsTimezone[TSDB_TIMEZONE_LEN] = {0}; diff --git a/src/connector/jdbc/CMakeLists.txt b/src/connector/jdbc/CMakeLists.txt index 86ddfcb022f4467f7378b85dda5760b66366bbbc..eb158b1f769f97482a314f2797ec247f756b3b39 100644 --- a/src/connector/jdbc/CMakeLists.txt +++ b/src/connector/jdbc/CMakeLists.txt @@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED) ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME} POST_BUILD COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.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 COMMENT "build jdbc driver") ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME}) diff --git a/src/connector/jdbc/deploy-pom.xml b/src/connector/jdbc/deploy-pom.xml index fe93e54c69e969cd8f54b41b6275423157f56197..eb8c92575c4b9953e5b8155d2bf2b1ded4772a26 100755 --- a/src/connector/jdbc/deploy-pom.xml +++ b/src/connector/jdbc/deploy-pom.xml @@ -5,7 +5,7 @@ com.taosdata.jdbc taos-jdbcdriver - 2.0.22 + 2.0.25 jar JDBCDriver @@ -37,17 +37,6 @@ - - commons-logging - commons-logging - 1.2 - - - * - * - - - junit junit @@ -61,21 +50,20 @@ httpclient 4.5.8 - - org.apache.commons - commons-lang3 - 3.9 - com.alibaba fastjson 1.2.58 + + com.google.guava + guava + 29.0-jre + - org.apache.maven.plugins maven-assembly-plugin diff --git a/src/connector/jdbc/pom.xml b/src/connector/jdbc/pom.xml index 51cb0b380822c81137c1a5514c898b51ae0d85be..1f75754b0c46ec0afced88743c5aba1d308c24ec 100755 --- a/src/connector/jdbc/pom.xml +++ b/src/connector/jdbc/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.taosdata.jdbc taos-jdbcdriver - 2.0.22 + 2.0.25 jar JDBCDriver https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc @@ -43,7 +43,6 @@ 4.13 test - org.apache.httpcomponents @@ -55,10 +54,22 @@ fastjson 1.2.58 - + + com.google.guava + guava + 29.0-jre + + + + src/main/resources + + **/*.md + + + org.apache.maven.plugins diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractConnection.java index a2496b0099fe27c6380b1e2bac954ac361c939ba..976078da95c387110a2e5e55076a42a2c320ca18 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractConnection.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractConnection.java @@ -30,9 +30,12 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); // do nothing + return sql; } + + @Override public void setAutoCommit(boolean autoCommit) throws SQLException { if (isClosed()) @@ -448,7 +451,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti if (isClosed) throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED); - for (Enumeration enumer = properties.keys(); enumer.hasMoreElements(); ) { String name = (String) enumer.nextElement(); clientInfoProps.put(name, properties.getProperty(name)); diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractParameterMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractParameterMetaData.java new file mode 100644 index 0000000000000000000000000000000000000000..7df7252ae2010b5aa5e8f74de2cca55844e25b83 --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractParameterMetaData.java @@ -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; + } +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractResultSet.java index 238d18039de8ca6bf2f178263827bc4f1d6634f2..abd348e68c3ebac0d940b4c9789a85ddd68e238e 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractResultSet.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractResultSet.java @@ -11,6 +11,15 @@ import java.util.Map; public abstract class AbstractResultSet extends WrapperImpl implements ResultSet { 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 public abstract boolean next() throws SQLException; @@ -46,38 +55,20 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet @Override public abstract double getDouble(int columnIndex) throws SQLException; + @Deprecated @Override public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); - - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + return getBigDecimal(columnIndex); } @Override - public byte[] getBytes(int columnIndex) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); - - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); - } + public abstract byte[] getBytes(int columnIndex) throws SQLException; @Override - public Date getDate(int columnIndex) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); - - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); - - } + public abstract Date getDate(int columnIndex) throws SQLException; @Override - public Time getTime(int columnIndex) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); - - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); - } + public abstract Time getTime(int columnIndex) throws SQLException; @Override public abstract Timestamp getTimestamp(int columnIndex) throws SQLException; @@ -147,9 +138,10 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet return getDouble(findColumn(columnLabel)); } + @Deprecated @Override public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { - return getBigDecimal(findColumn(columnLabel)); + return getBigDecimal(findColumn(columnLabel), scale); } @Override @@ -214,12 +206,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet public abstract ResultSetMetaData getMetaData() throws SQLException; @Override - public Object getObject(int columnIndex) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); - - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); - } + public abstract Object getObject(int columnIndex) throws SQLException; @Override public Object getObject(String columnLabel) throws SQLException { @@ -243,12 +230,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet } @Override - public BigDecimal getBigDecimal(int columnIndex) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); - - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); - } + public abstract BigDecimal getBigDecimal(int columnIndex) throws SQLException; @Override public BigDecimal getBigDecimal(String columnLabel) throws SQLException { @@ -718,9 +700,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet @Override public Object getObject(String columnLabel, Map> map) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + return getObject(findColumn(columnLabel), map); } @Override @@ -760,9 +740,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet @Override public Date getDate(String columnLabel, Calendar cal) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + return getDate(findColumn(columnLabel), cal); } @Override @@ -774,23 +752,15 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet @Override public Time getTime(String columnLabel, Calendar cal) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + return getTime(findColumn(columnLabel), cal); } @Override - public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); - } + public abstract Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException; @Override public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + return getTimestamp(findColumn(columnLabel), cal); } @Override @@ -1198,9 +1168,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet @Override public T getObject(String columnLabel, Class type) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + return getObject(findColumn(columnLabel), type); } } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractStatement.java index 8b6c074d1b859f179aac04a83cafb24cfae7c190..9dc559339a4ef88b8423ffcd621c7498437dac5c 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractStatement.java @@ -9,6 +9,8 @@ public abstract class AbstractStatement extends WrapperImpl implements Statement protected List batchedArgs; private int fetchSize; + + @Override public abstract ResultSet executeQuery(String sql) throws SQLException; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/SavedPreparedStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/SavedPreparedStatement.java deleted file mode 100644 index 512fcd26b8ce01b9e673fd7ed9a266ed0372ba52..0000000000000000000000000000000000000000 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/SavedPreparedStatement.java +++ /dev/null @@ -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 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: - *

- * insert/import into tableName [(field1, field2, ...)] [using stables tags(?, ?, ...) ] values(?, ?, ...) (?, ?, ...) - *

- * 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+((?\\S+)\\s*(\\(.*\\))?\\s+(USING\\s+(?\\S+)\\s+TAGS\\s*\\((?.+)\\))?)\\s*VALUES\\s*(?\\(.*\\)).*"); - - /** - * 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 getDefaultParamList(int paramSize) { - - List 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 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 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 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); - } - -} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java index a8653eb1729dffa83fb556e1f7a1772257018699..5b4615485dd21b7d5e41e513f48116edf53594d0 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java @@ -27,10 +27,6 @@ public class TSDBConnection extends AbstractConnection { return this.batchFetch; } - public void setBatchFetch(Boolean batchFetch) { - this.batchFetch = batchFetch; - } - public TSDBConnection(Properties info, TSDBDatabaseMetaData meta) throws SQLException { this.databaseMetaData = meta; connect(info.getProperty(TSDBDriver.PROPERTY_KEY_HOST), @@ -61,9 +57,7 @@ public class TSDBConnection extends AbstractConnection { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); } - TSDBStatement statement = new TSDBStatement(this, this.connector); - statement.setConnection(this); - return statement; + return new TSDBStatement(this, this.connector); } 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 { - if (isClosed()) { + if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); - } - return new TSDBPreparedStatement(this, this.connector, sql); } @@ -104,11 +96,4 @@ public class TSDBConnection extends AbstractConnection { 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); - } - -} +} \ No newline at end of file diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java index 7d3741917cb9166a5b29e69ad2b4d3f5023bd43d..5e3ffffa4fe7326b8c1e89ac91a37e95c346784f 100755 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java @@ -29,45 +29,25 @@ public class TSDBJNIConnector { private static volatile Boolean isInitialized = false; private TaosInfo taosInfo = TaosInfo.getInstance(); + // Connection pointer used in C + private long taos = TSDBConstants.JNI_NULL_POINTER; + // result set status in current connection + private boolean isResultsetClosed = true; + private int affectedRows = -1; static { System.loadLibrary("taos"); 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() { return this.taos == TSDBConstants.JNI_NULL_POINTER; } - /** - * Returns the status of last result set in current connection - */ public boolean 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 { synchronized (isInitialized) { if (!isInitialized) { @@ -93,11 +73,6 @@ public class TSDBJNIConnector { 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 { if (this.taos != TSDBConstants.JNI_NULL_POINTER) { // this.closeConnectionImp(this.taos); @@ -185,13 +160,6 @@ public class TSDBJNIConnector { 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); public boolean isUpdateQuery(long pSql) { @@ -231,6 +199,7 @@ public class TSDBJNIConnector { // } // return resCode; // } + private native int freeResultSetImp(long connection, long result); /** @@ -323,8 +292,7 @@ public class TSDBJNIConnector { * Validate if a create table sql statement is correct without actually creating that table */ public boolean validateCreateTableSql(String sql) { - long connection = taos; - int res = validateCreateTableSqlImp(connection, sql.getBytes()); + int res = validateCreateTableSqlImp(taos, sql.getBytes()); return res != 0 ? false : true; } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBParameterMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBParameterMetaData.java new file mode 100644 index 0000000000000000000000000000000000000000..9ee23e3a265298632a953b4a3feedeaf933905ca --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBParameterMetaData.java @@ -0,0 +1,8 @@ +package com.taosdata.jdbc; + +public class TSDBParameterMetaData extends AbstractParameterMetaData { + + public TSDBParameterMetaData(Object[] parameters) { + super(parameters); + } +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java index d294c8974543db409187a60cf77ea03c98f5ff17..728b537f715e69b4c79e3e67d2b9672c2e3d0714 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java @@ -18,6 +18,7 @@ import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.net.URL; +import java.nio.charset.Charset; import java.sql.*; import java.util.ArrayList; import java.util.Calendar; @@ -30,36 +31,49 @@ import java.util.regex.Pattern; * compatibility needs. */ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStatement { - protected String rawSql; - protected String sql; - protected ArrayList parameters = new ArrayList<>(); + + private String rawSql; + private String sql; + // private ArrayList parameters = new ArrayList<>(); + private Object[] parameters; + private boolean isPrepared; //start with insert or import and is case-insensitive private static Pattern savePattern = Pattern.compile("(?i)^\\s*(insert|import)"); - // is insert or import private boolean isSaved; - private SavedPreparedStatement savedPreparedStatement; - private ParameterMetaData parameterMetaData; + // private SavedPreparedStatement savedPreparedStatement; + private volatile TSDBParameterMetaData parameterMetaData; TSDBPreparedStatement(TSDBConnection connection, TSDBJNIConnector connecter, String sql) { super(connection, connecter); 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) { this.rawSql = sql; 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 public int[] executeBatch() throws SQLException { - if (isSaved) { - return this.savedPreparedStatement.executeBatch(); - } else { - return super.executeBatch(); - } - } - - public ArrayList getParameters() { - return parameters; - } - - public void setParameters(ArrayList parameters) { - this.parameters = parameters; +// if (isSaved) { +// return this.savedPreparedStatement.executeBatch(); +// } else { + return super.executeBatch(); +// } } /* @@ -151,41 +157,73 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat * * @return a string of the native sql statement for TSDB */ - private String getNativeSql() { - this.sql = this.rawSql; - for (int i = 0; i < parameters.size(); ++i) { - Object para = parameters.get(i); +// private String getNativeSql(String rawSql) { +// for (int i = 0; i < parameters.length; i++) { +// Object para = parameters[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) { - String paraStr = para.toString(); - if (para instanceof Timestamp || para instanceof String) { + String paraStr; + 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 + "'"; } - this.sql = this.sql.replaceFirst("[?]", paraStr); + sql = sql.replaceFirst("[?]", paraStr); } else { - this.sql = this.sql.replaceFirst("[?]", "NULL"); + sql = sql.replaceFirst("[?]", "NULL"); } } - parameters.clear(); + clearParameters(); return sql; } @Override public ResultSet executeQuery() throws SQLException { - if (isSaved) { - this.savedPreparedStatement.executeBatchInternal(); - return null; - } else { - return super.executeQuery(getNativeSql()); - } +// if (isSaved) { +// this.savedPreparedStatement.executeBatchInternal(); +// return null; +// } else { + + if (!isPrepared) + return executeQuery(this.rawSql); + + final String sql = getNativeSql(this.rawSql); + return executeQuery(sql); +// } } @Override public int executeUpdate() throws SQLException { - if (isSaved) { - return this.savedPreparedStatement.executeBatchInternal(); - } else { - return super.executeUpdate(getNativeSql()); - } +// if (isSaved) { +// return this.savedPreparedStatement.executeBatchInternal(); +// } else { + if (!isPrepared) + return executeUpdate(this.rawSql); + String sql = getNativeSql(this.rawSql); + return executeUpdate(sql); +// } } private boolean isSupportedSQLType(int sqlType) { @@ -201,35 +239,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat case Types.BINARY: case Types.NCHAR: 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: return false; } @@ -259,7 +268,7 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat public void setByte(int parameterIndex, byte x) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + setObject(parameterIndex,x); } @Override @@ -315,7 +324,8 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat public void setBytes(int parameterIndex, byte[] x) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + + setObject(parameterIndex,x); } @Override @@ -365,45 +375,63 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat public void clearParameters() throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - parameters.clear(); + +// parameters.clear(); + parameters = new Object[parameters.length]; } @Override public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); } @Override public void setObject(int parameterIndex, Object x) throws SQLException { - if (isSaved) { - this.savedPreparedStatement.setParam(parameterIndex, x); - } else { - parameters.add(x); - } +// if (isSaved) { +// this.savedPreparedStatement.setParam(parameterIndex, x); +// } else { + if (parameterIndex < 1 && parameterIndex >= parameters.length) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE); + + parameters[parameterIndex - 1] = x; +// parameters.add(x); +// } } @Override public boolean execute() throws SQLException { - if (isSaved) { - int result = this.savedPreparedStatement.executeBatchInternal(); - return result > 0; - } else { - return super.execute(getNativeSql()); - } +// if (isSaved) { +// int result = this.savedPreparedStatement.executeBatchInternal(); +// return result > 0; +// } else { + if (!isPrepared) + return execute(this.rawSql); + + final String sql = getNativeSql(this.rawSql); + + return execute(sql); +// } } @Override public void addBatch() throws SQLException { - if (isSaved) { - this.savedPreparedStatement.addBatch(); +// if (isSaved) { +// this.savedPreparedStatement.addBatch(); +// } else { + if (this.batchedArgs == null) { + batchedArgs = new ArrayList<>(); + } + + if (!isPrepared) { + addBatch(this.rawSql); } else { - if (this.batchedArgs == null) { - batchedArgs = new ArrayList<>(); - } - super.addBatch(getNativeSql()); + String sql = this.getConnection().nativeSQL(this.rawSql); + addBatch(sql); } +// } } @Override @@ -491,9 +519,11 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat public ParameterMetaData getParameterMetaData() throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - //TODO: parameterMetaData not supported -// return null; - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + + if (parameterMetaData == null) { + this.parameterMetaData = new TSDBParameterMetaData(parameters); + } + return this.parameterMetaData; } @Override diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java index 7c2940fdc2c1a0cb15a5a0f1557598cb5b062e61..a20ddaa836535b2249ecc1a05e74a7903b9caeeb 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java @@ -14,9 +14,14 @@ *****************************************************************************/ 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.sql.*; import java.util.ArrayList; +import java.util.Calendar; import java.util.List; 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 { - String res = null; - int colIndex = getTrueColumnIndex(columnIndex); + checkAvailability(columnIndex, this.columnMetaDataList.size()); + String res = null; 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) { - res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + res = this.rowData.getString(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType()); } return res; } public boolean getBoolean(int columnIndex) throws SQLException { - boolean res = false; - int colIndex = getTrueColumnIndex(columnIndex); + checkAvailability(columnIndex, this.columnMetaDataList.size()); + boolean res = false; 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) { - res = this.rowData.getBoolean(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + res = this.rowData.getBoolean(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType()); } return res; } public byte getByte(int columnIndex) throws SQLException { - byte res = 0; - int colIndex = getTrueColumnIndex(columnIndex); + checkAvailability(columnIndex, this.columnMetaDataList.size()); + byte res = 0; 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) { - 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; } public short getShort(int columnIndex) throws SQLException { - short res = 0; - int colIndex = getTrueColumnIndex(columnIndex); + checkAvailability(columnIndex, this.columnMetaDataList.size()); + short res = 0; 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) { - 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; } public int getInt(int columnIndex) throws SQLException { - int res = 0; - int colIndex = getTrueColumnIndex(columnIndex); + checkAvailability(columnIndex, this.columnMetaDataList.size()); + int res = 0; 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) { - res = this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + res = this.rowData.getInt(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType()); } return res; } public long getLong(int columnIndex) throws SQLException { - long res = 0L; - int colIndex = getTrueColumnIndex(columnIndex); + checkAvailability(columnIndex, this.columnMetaDataList.size()); + long res = 0L; 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) { - res = this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + res = this.rowData.getLong(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType()); } return res; } public float getFloat(int columnIndex) throws SQLException { - float res = 0; - int colIndex = getTrueColumnIndex(columnIndex); + checkAvailability(columnIndex, this.columnMetaDataList.size()); + float res = 0; 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) - res = this.rowData.getFloat(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + res = this.rowData.getFloat(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType()); return res; } public double getDouble(int columnIndex) throws SQLException { - double res = 0; - int colIndex = getTrueColumnIndex(columnIndex); + checkAvailability(columnIndex, this.columnMetaDataList.size()); + double res = 0; 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) { - res = this.rowData.getDouble(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + res = this.rowData.getDouble(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType()); } return res; } - @Deprecated - public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { - return new BigDecimal(getLong(columnIndex)); + public byte[] getBytes(int columnIndex) throws SQLException { + checkAvailability(columnIndex, this.columnMetaDataList.size()); + + 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 { - return getString(columnIndex).getBytes(); + @Override + 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 { + checkAvailability(columnIndex, this.columnMetaDataList.size()); + Timestamp res = null; - int colIndex = getTrueColumnIndex(columnIndex); 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) { - res = this.rowData.getTimestamp(colIndex); + res = this.rowData.getTimestamp(columnIndex - 1); } return res; } public ResultSetMetaData getMetaData() throws SQLException { + if (isClosed()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); + return new TSDBResultSetMetaData(this.columnMetaDataList); } @Override public Object getObject(int columnIndex) throws SQLException { - int colIndex = getTrueColumnIndex(columnIndex); + checkAvailability(columnIndex, this.columnMetaDataList.size()); + Object res = null; if (this.getBatchFetch()) - return this.blockData.get(colIndex); + return this.blockData.get(columnIndex - 1); - this.lastWasNull = this.rowData.wasNull(colIndex); - return this.rowData.get(colIndex); - } - - @Override - public Object getObject(String columnLabel) throws SQLException { - return this.getObject(this.findColumn(columnLabel)); + this.lastWasNull = this.rowData.wasNull(columnIndex - 1); + if (!lastWasNull) { + int colType = this.columnMetaDataList.get(columnIndex - 1).getColType(); + if (colType == TSDBConstants.TSDB_DATA_TYPE_BINARY) + res = ((String) this.rowData.get(columnIndex - 1)).getBytes(); + else + res = this.rowData.get(columnIndex - 1); + } + return res; } public int findColumn(String columnLabel) throws SQLException { @@ -285,14 +321,31 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { @Override 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(colIndex); - return new BigDecimal(this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType())); - } else { - return new BigDecimal(this.blockData.getLong(colIndex)); + this.lastWasNull = this.rowData.wasNull(columnIndex - 1); + BigDecimal res = null; + if (!lastWasNull) { + int colType = this.columnMetaDataList.get(columnIndex - 1).getColType(); + 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 @@ -398,6 +451,12 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { return this.statement; } + @Override + public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { + //TODO:did not use the specified timezone in cal + return getTimestamp(columnIndex); + } + public boolean isClosed() throws SQLException { if (isClosed) return true; @@ -408,17 +467,7 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { } public String getNString(int columnIndex) throws SQLException { - int colIndex = getTrueColumnIndex(columnIndex); - return (String) rowData.get(colIndex); + return getString(columnIndex); } - 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; - } } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetMetaData.java index 7abd997459fd8478a0a3bd06aa3eb0f51d1584ae..e4ac5303d09f132279e29039bf6b5b812b6c5404 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetMetaData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetMetaData.java @@ -22,136 +22,160 @@ import java.util.List; public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaData { - List colMetaDataList = null; - - public TSDBResultSetMetaData(List metaDataList) { - this.colMetaDataList = metaDataList; - } - - public int getColumnCount() throws SQLException { - return colMetaDataList.size(); - } - - public boolean isAutoIncrement(int column) throws SQLException { - return false; - } - - public boolean isCaseSensitive(int column) throws SQLException { - return false; - } - - public boolean isSearchable(int column) throws SQLException { - if (column == 1) { - return true; - } - return false; - } - - public boolean isCurrency(int column) throws SQLException { - return false; - } - - public int isNullable(int column) throws SQLException { - if (column == 1) { - return columnNoNulls; - } - return columnNullable; - } - - public boolean isSigned(int column) throws SQLException { - ColumnMetaData meta = this.colMetaDataList.get(column - 1); - 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 int getColumnDisplaySize(int column) throws SQLException { - return colMetaDataList.get(column - 1).getColSize(); - } - - public String getColumnLabel(int column) throws SQLException { - return colMetaDataList.get(column - 1).getColName(); - } - - public String getColumnName(int column) throws SQLException { - return colMetaDataList.get(column - 1).getColName(); - } - - public String getSchemaName(int column) throws SQLException { - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); - } - - public int getPrecision(int column) throws SQLException { - ColumnMetaData columnMetaData = this.colMetaDataList.get(column - 1); - 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 int getScale(int column) throws SQLException { - 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 { - 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(); + List colMetaDataList; + + public TSDBResultSetMetaData(List metaDataList) { + this.colMetaDataList = metaDataList; + } + + public int getColumnCount() throws SQLException { + return colMetaDataList.size(); + } + + public boolean isAutoIncrement(int column) throws SQLException { + return false; + } + + public boolean isCaseSensitive(int column) throws SQLException { + return false; + } + + public boolean isSearchable(int column) throws SQLException { + if (column == 1) { + return true; + } + return false; + } + + public boolean isCurrency(int column) throws SQLException { + return false; + } + + public int isNullable(int column) throws SQLException { + if (column < 1 && column >= colMetaDataList.size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE); + + if (column == 1) { + return columnNoNulls; + } + return columnNullable; + } + + public boolean isSigned(int column) throws SQLException { + if (column < 1 && column >= colMetaDataList.size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE); + + ColumnMetaData meta = this.colMetaDataList.get(column - 1); + 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 int getColumnDisplaySize(int column) throws SQLException { + if (column < 1 && column >= colMetaDataList.size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE); + + return colMetaDataList.get(column - 1).getColSize(); + } + + public String getColumnLabel(int column) throws SQLException { + if (column < 1 && column >= colMetaDataList.size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE); + + return colMetaDataList.get(column - 1).getColName(); + } + + public String getColumnName(int column) throws SQLException { + if (column < 1 && column >= colMetaDataList.size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE); + + return colMetaDataList.get(column - 1).getColName(); + } + + public String getSchemaName(int column) throws SQLException { + if (column < 1 && column >= colMetaDataList.size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE); + + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + } + + public int getPrecision(int column) throws SQLException { + if (column < 1 && column >= colMetaDataList.size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE); + + ColumnMetaData columnMetaData = this.colMetaDataList.get(column - 1); + 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 int getScale(int column) throws SQLException { + if (column < 1 && column >= colMetaDataList.size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE); + + ColumnMetaData meta = this.colMetaDataList.get(column - 1); + 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 { + 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; case Types.CHAR: columnClassName = String.class.getName(); @@ -168,8 +192,8 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD case Types.INTEGER: columnClassName = Integer.class.getName(); break; - case Types.SMALLINT: - columnClassName = Short.class.getName(); + case Types.SMALLINT: + columnClassName = Short.class.getName(); break; case Types.TINYINT: columnClassName = Byte.class.getName(); @@ -177,7 +201,7 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD case Types.BIT: columnClassName = Boolean.class.getName(); break; - } + } return columnClassName; - } + } } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java index 44d760897b2cdac20c510e0c3f98910f25ac40d8..7cf5f0d79a89d0e6ed21d6b18136b92dc2c0b131 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java @@ -21,18 +21,13 @@ import java.util.ArrayList; import java.util.Collections; public class TSDBResultSetRowData { - private ArrayList data = null; + private ArrayList data; private int colSize = 0; public TSDBResultSetRowData(int colSize) { this.setColSize(colSize); } - public TSDBResultSetRowData() { - this.data = new ArrayList<>(); - this.setColSize(0); - } - public void clear() { if (this.data != null) { this.data.clear(); @@ -71,9 +66,9 @@ public class TSDBResultSetRowData { case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return ((Long) obj) == 1L ? Boolean.TRUE : Boolean.FALSE; + default: + return false; } - - return Boolean.TRUE; } public void setByte(int col, byte value) { @@ -198,7 +193,7 @@ public class TSDBResultSetRowData { 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); switch (srcType) { @@ -226,7 +221,7 @@ public class TSDBResultSetRowData { 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); switch (srcType) { @@ -267,9 +262,8 @@ public class TSDBResultSetRowData { * * @param col column index * @return - * @throws SQLException */ - public String getString(int col, int srcType) throws SQLException { + public String getString(int col, int srcType) { switch (srcType) { case TSDBConstants.TSDB_DATA_TYPE_BINARY: case TSDBConstants.TSDB_DATA_TYPE_NCHAR: @@ -305,11 +299,11 @@ public class TSDBResultSetRowData { } public void setTimestamp(int col, long ts) { - data.set(col, ts); + data.set(col, new Timestamp(ts)); } public Timestamp getTimestamp(int col) { - return new Timestamp((Long) data.get(col)); + return (Timestamp) data.get(col); } public Object get(int col) { @@ -320,7 +314,7 @@ public class TSDBResultSetRowData { return colSize; } - public void setColSize(int colSize) { + private void setColSize(int colSize) { this.colSize = colSize; this.clear(); } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/bean/TSDBPreparedParam.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/bean/TSDBPreparedParam.java deleted file mode 100644 index ef78292de60d11b535df7403cd27d622686fbba1..0000000000000000000000000000000000000000 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/bean/TSDBPreparedParam.java +++ /dev/null @@ -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 middleParamList; - - /** - * value list - */ - private List valueList; - - public TSDBPreparedParam(String tableName) { - this.tableName = tableName; - } - - public String getTableName() { - return tableName; - } - - public void setTableName(String tableName) { - this.tableName = tableName; - } - - public List getMiddleParamList() { - return middleParamList; - } - - public void setMiddleParamList(List middleParamList) { - this.middleParamList = middleParamList; - } - - public void setMiddleParam(int parameterIndex, Object x) { - this.middleParamList.set(parameterIndex, x); - } - - public List getValueList() { - return valueList; - } - - public void setValueList(List valueList) { - this.valueList = valueList; - } - - - public void setValueParam(int parameterIndex, Object x) { - this.valueList.set(parameterIndex, x); - } - -} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java index c1834a7b804428ab3875b8e6937223b651cd217f..1f3ed2d144a88b10c0b1a8947e70def2c3db42a9 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java @@ -1,8 +1,14 @@ package com.taosdata.jdbc.rs; -import com.taosdata.jdbc.*; - -import java.sql.*; +import com.taosdata.jdbc.AbstractConnection; +import com.taosdata.jdbc.TSDBDriver; +import com.taosdata.jdbc.TSDBError; +import com.taosdata.jdbc.TSDBErrorNumbers; + +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; import java.util.Properties; public class RestfulConnection extends AbstractConnection { @@ -55,7 +61,6 @@ public class RestfulConnection extends AbstractConnection { public DatabaseMetaData getMetaData() throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); - ; return this.metadata; } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java index a94cfa6e07c62ee9b163823aaad03bcc402bbffc..6efe13561d9509ee00d453e731bbc1ae4e3f0a75 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java @@ -17,7 +17,7 @@ public class RestfulDriver extends AbstractDriver { static { try { - DriverManager.registerDriver(new RestfulDriver()); + java.sql.DriverManager.registerDriver(new RestfulDriver()); } catch (SQLException e) { throw TSDBError.createRuntimeException(TSDBErrorNumbers.ERROR_URL_NOT_SET, e); } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulParameterMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulParameterMetaData.java new file mode 100644 index 0000000000000000000000000000000000000000..7a130eb72b528de0ef61aa94e69ab376d9d214ba --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulParameterMetaData.java @@ -0,0 +1,10 @@ +package com.taosdata.jdbc.rs; + +import com.taosdata.jdbc.AbstractParameterMetaData; + +public class RestfulParameterMetaData extends AbstractParameterMetaData { + + RestfulParameterMetaData(Object[] parameters) { + super(parameters); + } +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulPreparedStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulPreparedStatement.java index 3a0ff56dd71979f21b24f68b41ea9d7bb994586e..f82955ca9dae5e3712da511a576aee64528061b5 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulPreparedStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulPreparedStatement.java @@ -7,6 +7,7 @@ import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.net.URL; +import java.nio.charset.Charset; import java.sql.*; import java.util.Calendar; @@ -30,7 +31,9 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar parameters = new Object[parameterCnt]; this.isPrepared = true; } - //TODO: build parameterMetaData + + // build parameterMetaData + this.parameterMetaData = new RestfulParameterMetaData(parameters); } @Override @@ -60,8 +63,15 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar for (int i = 0; i < parameters.length; ++i) { Object para = parameters[i]; if (para != null) { - String paraStr = para.toString(); - if (para instanceof Timestamp || para instanceof String) { + String paraStr; + 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 + "'"; } sql = sql.replaceFirst("[?]", paraStr); @@ -92,7 +102,7 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar public void setByte(int parameterIndex, byte x) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + setObject(parameterIndex, x); } @Override @@ -153,7 +163,7 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar public void setBytes(int parameterIndex, byte[] x) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + setObject(parameterIndex, x); } @Override @@ -210,19 +220,16 @@ public class RestfulPreparedStatement extends RestfulStatement implements Prepar public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); + + setObject(parameterIndex,x); } @Override public void setObject(int parameterIndex, Object x) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - if (parameterIndex < 1 && parameterIndex >= parameters.length) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE); parameters[parameterIndex - 1] = x; - } @Override diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java index 0cbb40dbb69f9e3b6b8fb2cc5bfd6ddac6ea4aef..5c2d4c45b079974672843b232e38fcd9d010b0c4 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java @@ -2,13 +2,18 @@ package com.taosdata.jdbc.rs; import com.alibaba.fastjson.JSONArray; 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.TSDBConstants; import com.taosdata.jdbc.TSDBError; import com.taosdata.jdbc.TSDBErrorNumbers; +import java.math.BigDecimal; import java.sql.*; import java.util.ArrayList; +import java.util.Calendar; public class RestfulResultSet extends AbstractResultSet implements ResultSet { private volatile boolean isClosed; @@ -16,7 +21,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { private final String database; private final Statement statement; -// private final JSONObject resultJson; // data private final ArrayList> resultSet; // meta @@ -32,7 +36,6 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { public RestfulResultSet(String database, Statement statement, JSONObject resultJson) throws SQLException { this.database = database; this.statement = statement; -// this.resultJson = resultJson; // column metadata JSONArray columnMeta = resultJson.getJSONArray("column_meta"); @@ -73,7 +76,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { case TSDBConstants.TSDB_DATA_TYPE_INT: return row.getInteger(colIndex); case TSDBConstants.TSDB_DATA_TYPE_BIGINT: - return row.getBigInteger(colIndex); + return row.getLong(colIndex); case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return row.getFloat(colIndex); case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: @@ -81,9 +84,11 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: return new Timestamp(row.getDate(colIndex).getTime()); case TSDBConstants.TSDB_DATA_TYPE_BINARY: + return row.getString(colIndex) == null ? null : row.getString(colIndex).getBytes(); case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + return row.getString(colIndex) == null ? null : row.getString(colIndex); default: - return row.getString(colIndex); + return row.get(colIndex); } } @@ -130,37 +135,33 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { @Override public String getString(int columnIndex) throws SQLException { - if (isClosed()) - 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()); + checkAvailability(columnIndex, resultSet.get(pos).size()); - columnIndex = getTrueColumnIndex(columnIndex); - Object value = resultSet.get(pos).get(columnIndex); - return value == null ? null : value.toString(); + Object value = resultSet.get(pos).get(columnIndex - 1); + if (value == null) + return null; + if (value instanceof byte[]) + return new String((byte[]) value); + return value.toString(); } @Override public boolean getBoolean(int columnIndex) throws SQLException { - if (isClosed()) - 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()); + checkAvailability(columnIndex, resultSet.get(pos).size()); - columnIndex = getTrueColumnIndex(columnIndex); - int result = getInt(columnIndex); - return result == 0 ? false : true; + Object value = resultSet.get(pos).get(columnIndex - 1); + if (value == null) + return false; + if (value instanceof Boolean) + return (boolean) value; + return Boolean.valueOf(value.toString()); } @Override public byte getByte(int columnIndex) throws SQLException { - if (isClosed()) - 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()); + checkAvailability(columnIndex, resultSet.get(pos).size()); - columnIndex = getTrueColumnIndex(columnIndex); - Object value = resultSet.get(pos).get(columnIndex); + Object value = resultSet.get(pos).get(columnIndex - 1); if (value == null) return 0; long valueAsLong = Long.parseLong(value.toString()); @@ -179,13 +180,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { @Override public short getShort(int columnIndex) throws SQLException { - if (isClosed()) - 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()); + checkAvailability(columnIndex, resultSet.get(pos).size()); - columnIndex = getTrueColumnIndex(columnIndex); - Object value = resultSet.get(pos).get(columnIndex); + Object value = resultSet.get(pos).get(columnIndex - 1); if (value == null) return 0; long valueAsLong = Long.parseLong(value.toString()); @@ -198,13 +195,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { @Override public int getInt(int columnIndex) throws SQLException { - if (isClosed()) - 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()); + checkAvailability(columnIndex, resultSet.get(pos).size()); - columnIndex = getTrueColumnIndex(columnIndex); - Object value = resultSet.get(pos).get(columnIndex); + Object value = resultSet.get(pos).get(columnIndex - 1); if (value == null) return 0; long valueAsLong = Long.parseLong(value.toString()); @@ -217,13 +210,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { @Override public long getLong(int columnIndex) throws SQLException { - if (isClosed()) - 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()); + checkAvailability(columnIndex, resultSet.get(pos).size()); - columnIndex = getTrueColumnIndex(columnIndex); - Object value = resultSet.get(pos).get(columnIndex); + Object value = resultSet.get(pos).get(columnIndex - 1); if (value == null) return 0; @@ -240,64 +229,99 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { @Override public float getFloat(int columnIndex) throws SQLException { - if (isClosed()) - 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()); + checkAvailability(columnIndex, resultSet.get(pos).size()); - columnIndex = getTrueColumnIndex(columnIndex); - return Float.parseFloat(resultSet.get(pos).get(columnIndex).toString()); + Object value = resultSet.get(pos).get(columnIndex - 1); + if (value == null) + return 0; + if (value instanceof Float || value instanceof Double) + return (float) value; + return Float.parseFloat(value.toString()); } @Override public double getDouble(int columnIndex) throws SQLException { - if (isClosed()) - 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()); + checkAvailability(columnIndex, resultSet.get(pos).size()); - columnIndex = getTrueColumnIndex(columnIndex); - return Double.parseDouble(resultSet.get(pos).get(columnIndex).toString()); + Object value = resultSet.get(pos).get(columnIndex - 1); + 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 { - if (columnIndex < 1) { - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE - , "Column Index out of range, " + columnIndex + " < 1"); - } + @Override + public byte[] getBytes(int columnIndex) throws SQLException { + checkAvailability(columnIndex, resultSet.get(pos).size()); - int numOfCols = resultSet.get(pos).size(); - if (columnIndex > numOfCols) { - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE - , "Column Index out of range, " + columnIndex + " > " + numOfCols); - } + Object value = resultSet.get(pos).get(columnIndex - 1); + if (value == null) + return null; + if (value instanceof byte[]) + return (byte[]) value; + if (value instanceof String) + return ((String) value).getBytes(); + if (value instanceof Long) + return Longs.toByteArray((long) value); + if (value instanceof Integer) + return Ints.toByteArray((int) value); + if (value instanceof Short) + return Shorts.toByteArray((short) value); + if (value instanceof Byte) + return new byte[]{(byte) value}; + + return value.toString().getBytes(); + } - return columnIndex - 1; + @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 public Timestamp getTimestamp(int columnIndex) throws SQLException { - if (isClosed()) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); + checkAvailability(columnIndex, resultSet.get(pos).size()); - columnIndex = getTrueColumnIndex(columnIndex); - String strDate = resultSet.get(pos).get(columnIndex).toString(); -// strDate = strDate.substring(1, strDate.length() - 1); - return Timestamp.valueOf(strDate); + Object value = resultSet.get(pos).get(columnIndex - 1); + if (value == null) + return null; + if (value instanceof Timestamp) + return (Timestamp) value; + return Timestamp.valueOf(value.toString()); } - /*************************************************************************************************************/ @Override public ResultSetMetaData getMetaData() throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); - return this.metaData; } @Override - public Object getObject(String columnLabel) throws SQLException { - return getObject(findColumn(columnLabel)); + public Object getObject(int columnIndex) throws SQLException { + checkAvailability(columnIndex, resultSet.get(pos).size()); + + return resultSet.get(pos).get(columnIndex - 1); } @Override @@ -311,6 +335,23 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { 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 public boolean isBeforeFirst() throws SQLException { if (isClosed()) @@ -471,6 +512,12 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { return this.statement; } + @Override + public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { + //TODO:did not use the specified timezone in cal + return getTimestamp(columnIndex); + } + @Override public boolean isClosed() throws SQLException { return isClosed; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/OSUtils.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/OSUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..a67b4763f99164a58439df25d944cac913ab36d9 --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/OSUtils.java @@ -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; + } +} diff --git a/src/connector/jdbc/src/main/resources/META-INF/services/java.sql.Driver b/src/connector/jdbc/src/main/resources/META-INF/services/java.sql.Driver index e65b4e3b2215df049ef4a020f1aac3bb45d60b61..893f7cdf34c9934ffb9db91328967995d406b19b 100644 --- a/src/connector/jdbc/src/main/resources/META-INF/services/java.sql.Driver +++ b/src/connector/jdbc/src/main/resources/META-INF/services/java.sql.Driver @@ -1 +1,2 @@ com.taosdata.jdbc.TSDBDriver +com.taosdata.jdbc.rs.RestfulDriver diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/ResultSetTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/ResultSetTest.java deleted file mode 100644 index 87348f90261163eff650ecb225a168921c162f58..0000000000000000000000000000000000000000 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/ResultSetTest.java +++ /dev/null @@ -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(); - } - } -} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBConnectionTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBConnectionTest.java index 0a4ecb739cfd5a0abda01f7788d375ef95e0208a..ca7251bb0eac306d6a21872699918e18b2447e6e 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBConnectionTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBConnectionTest.java @@ -233,7 +233,7 @@ public class TSDBConnectionTest { int status = rs.getInt("server_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) diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBParameterMetaDataTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBParameterMetaDataTest.java new file mode 100644 index 0000000000000000000000000000000000000000..12bcc4391767e129289fae0a945d048570a18bc5 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBParameterMetaDataTest.java @@ -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(); + } + } +} \ No newline at end of file diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBPreparedStatementTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBPreparedStatementTest.java index 475cfef060e2769d3390c19bfebc521ada7c0b46..434095efa284b8bae0fafef2795714573e2f76e0 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBPreparedStatementTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBPreparedStatementTest.java @@ -5,14 +5,16 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import java.io.IOException; +import java.io.Serializable; import java.sql.*; public class TSDBPreparedStatementTest { 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 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 temperature >= ?"; + private static final String sql_select = "select * from t1 where ts > ? and ts <= ? and f1 >= ?"; private static PreparedStatement pstmt_select; @Test @@ -21,7 +23,7 @@ public class TSDBPreparedStatementTest { long start = end - 1000 * 60 * 60; pstmt_select.setTimestamp(1, new Timestamp(start)); pstmt_select.setTimestamp(2, new Timestamp(end)); - pstmt_select.setFloat(3, 0); + pstmt_select.setInt(3, 0); ResultSet rs = pstmt_select.executeQuery(); Assert.assertNotNull(rs); @@ -37,48 +39,73 @@ public class TSDBPreparedStatementTest { @Test public void executeUpdate() throws SQLException { 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(); Assert.assertEquals(1, result); } @Test 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 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 { - 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 - 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 - 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 - 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 - 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 - 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) @@ -87,12 +114,56 @@ public class TSDBPreparedStatementTest { } @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) - public void setBytes() throws SQLException { - pstmt_insert.setBytes(1, new byte[]{}); + class Person implements Serializable { + String name; + 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) @@ -106,8 +177,10 @@ public class TSDBPreparedStatementTest { } @Test - public void setTimestamp() { - //TODO + public void setTimestamp() throws SQLException { + pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis())); + int ret = pstmt_insert.executeUpdate(); + Assert.assertEquals(1, ret); } @Test(expected = SQLFeatureNotSupportedException.class) @@ -121,24 +194,69 @@ public class TSDBPreparedStatementTest { } @Test - public void clearParameters() { - //TODO + public void clearParameters() throws SQLException { + pstmt_insert.clearParameters(); } @Test public void setObject() throws SQLException { - pstmt_insert.setObject(1, System.currentTimeMillis()); - //TODO - } + pstmt_insert.setObject(1, new Timestamp(System.currentTimeMillis())); + int ret = pstmt_insert.executeUpdate(); + Assert.assertEquals(1, ret); - @Test - public void execute() { - //TODO + 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 - public void addBatch() { - //TODO: + public void execute() throws SQLException { + pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis())); + int ret = pstmt_insert.executeUpdate(); + Assert.assertEquals(1, ret); + + executeQuery(); } @Test(expected = SQLFeatureNotSupportedException.class) @@ -176,11 +294,11 @@ public class TSDBPreparedStatementTest { pstmt_insert.setURL(1, null); } - @Test(expected = SQLFeatureNotSupportedException.class) + @Test public void getParameterMetaData() throws SQLException { ParameterMetaData parameterMetaData = pstmt_insert.getParameterMetaData(); -// Assert.assertNotNull(parameterMetaData); - //TODO: + Assert.assertNotNull(parameterMetaData); + //TODO: modify the test case } @Test(expected = SQLFeatureNotSupportedException.class) @@ -215,10 +333,10 @@ public class TSDBPreparedStatementTest { 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, temperature float) tags(loc nchar(64))"); + stmt.execute("drop database if exists test_pstmt_jni"); + stmt.execute("create database if not exists test_pstmt_jni"); + stmt.execute("use test_pstmt_jni"); + 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); @@ -231,7 +349,10 @@ public class TSDBPreparedStatementTest { @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) { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBResultSetTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBResultSetTest.java new file mode 100644 index 0000000000000000000000000000000000000000..374b1335fc88e4eefcfd02f90ed5c2e36ede38e1 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBResultSetTest.java @@ -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(); + } + } + +} \ No newline at end of file diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DriverAutoloadTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DriverAutoloadTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9826e6ed764f8319c70a8a2c1edf7b2444b4f21d --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DriverAutoloadTest.java @@ -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"); + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertDbwithoutUseDbTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertDbwithoutUseDbTest.java index 54ee8fd6ebafbb18dfcfbab99503c1c30f148dc8..84149775c3d2bbda6a66930159e19eb27d95a6d1 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertDbwithoutUseDbTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertDbwithoutUseDbTest.java @@ -14,7 +14,6 @@ import java.util.Random; public class InsertDbwithoutUseDbTest { private static String host = "127.0.0.1"; - // private static String host = "master"; private static Properties properties; private static Random random = new Random(System.currentTimeMillis()); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetForJdbcRestfulTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetForJdbcRestfulTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f2ac94adc1b6e7d94e52650dcfbb5664c8f39760 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/NullValueInResultSetForJdbcRestfulTest.java @@ -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(); + } + } +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberRestfulTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberRestfulTest.java index d0e63067049d0cf739b4e9764af5d352f64f409c..4ae2f36fe95a37eba27dd78222f3120f5cbfaf3a 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberRestfulTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberRestfulTest.java @@ -10,8 +10,8 @@ import java.util.Properties; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class UnsignedNumberRestfulTest { + private static final String host = "127.0.0.1"; -// private static final String host = "master"; private static Connection conn; @Test diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/AuthenticationTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/AuthenticationTest.java index b0666989ba0e5aacfd6aa1110b4a57016a0937ee..a6fb6cfda044b4e88c5bd5509c51d114507d84f7 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/AuthenticationTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/AuthenticationTest.java @@ -8,7 +8,6 @@ import java.sql.*; public class AuthenticationTest { 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 password = "taos?data"; private Connection conn; diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulConnectionTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulConnectionTest.java index 4e005d129124ca480313f861a48af5fcfdbf25bc..abd60f5b63d46b406f19b6be9dcbbab6b786de12 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulConnectionTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulConnectionTest.java @@ -12,7 +12,6 @@ import java.util.Properties; public class RestfulConnectionTest { private static final String host = "127.0.0.1"; - // private static final String host = "master"; private static Connection conn; diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulDatabaseMetaDataTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulDatabaseMetaDataTest.java index 1991c17065a34c16fe7758486bd10b83f3241a07..a052fbbdcbc241a18cb7dd73b8b4ade053533541 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulDatabaseMetaDataTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulDatabaseMetaDataTest.java @@ -10,7 +10,6 @@ import java.sql.*; import java.util.Properties; public class RestfulDatabaseMetaDataTest { - // private static final String host = "master"; 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 Connection connection; diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulJDBCTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulJDBCTest.java index 451f5d49160a69b4786e806c51480236083eacac..c8bb69d82749e606f18d3298697ea0995029d064 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulJDBCTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulJDBCTest.java @@ -10,7 +10,6 @@ import java.util.Random; public class RestfulJDBCTest { private static final String host = "127.0.0.1"; -// private static final String host = "master"; private static Connection connection; private Random random = new Random(System.currentTimeMillis()); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulParameterMetaDataTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulParameterMetaDataTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8bb2532ce82e24e4015746e04b5b2dea18f530e4 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulParameterMetaDataTest.java @@ -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(); + } + } +} \ No newline at end of file diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulPreparedStatementTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulPreparedStatementTest.java index a3867c1b6e30d810dcea3001ee92eae698256341..094dff8c8de0667110e4911a32a8479e21d6fc71 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulPreparedStatementTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulPreparedStatementTest.java @@ -5,11 +5,12 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import java.io.IOException; +import java.io.Serializable; import java.sql.*; public class RestfulPreparedStatementTest { private static final String host = "127.0.0.1"; - // private static final String host = "master"; private static Connection conn; private static final String sql_insert = "insert into t1 values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; private static PreparedStatement pstmt_insert; @@ -38,48 +39,73 @@ public class RestfulPreparedStatementTest { @Test public void executeUpdate() throws SQLException { 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(); Assert.assertEquals(1, result); } @Test 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 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 { - 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 - 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 - 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 - 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 - 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 - 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) @@ -88,12 +114,56 @@ public class RestfulPreparedStatementTest { } @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) - public void setBytes() throws SQLException { - pstmt_insert.setBytes(1, new byte[]{}); + class Person implements Serializable { + String name; + 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) @@ -107,8 +177,10 @@ public class RestfulPreparedStatementTest { } @Test - public void setTimestamp() { - //TODO + public void setTimestamp() throws SQLException { + pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis())); + int ret = pstmt_insert.executeUpdate(); + Assert.assertEquals(1, ret); } @Test(expected = SQLFeatureNotSupportedException.class) @@ -122,24 +194,69 @@ public class RestfulPreparedStatementTest { } @Test - public void clearParameters() { - //TODO + public void clearParameters() throws SQLException { + pstmt_insert.clearParameters(); } @Test public void setObject() throws SQLException { - pstmt_insert.setObject(1, System.currentTimeMillis()); - //TODO - } + pstmt_insert.setObject(1, new Timestamp(System.currentTimeMillis())); + int ret = pstmt_insert.executeUpdate(); + Assert.assertEquals(1, ret); - @Test - public void execute() { - //TODO + 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 - public void addBatch() { - //TODO: + public void execute() throws SQLException { + pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis())); + int ret = pstmt_insert.executeUpdate(); + Assert.assertEquals(1, ret); + + executeQuery(); } @Test(expected = SQLFeatureNotSupportedException.class) @@ -180,8 +297,8 @@ public class RestfulPreparedStatementTest { @Test public void getParameterMetaData() throws SQLException { ParameterMetaData parameterMetaData = pstmt_insert.getParameterMetaData(); - Assert.assertNull(parameterMetaData); - //TODO: + Assert.assertNotNull(parameterMetaData); + //TODO: modify the test case } @Test(expected = SQLFeatureNotSupportedException.class) diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetMetaDataTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetMetaDataTest.java index 13973d8b6bf6c11ced27866724b91c0746a024d0..c7fc81297264f3cf38795d9d5a3b7eccc51574c9 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetMetaDataTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetMetaDataTest.java @@ -10,7 +10,6 @@ import java.sql.*; public class RestfulResultSetMetaDataTest { private static final String host = "127.0.0.1"; -// private static final String host = "master"; private static Connection conn; private static Statement stmt; diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetTest.java index a15b1964ea8301b5153a548b53c9fc8763cd65f5..d6b2a58127d0440cf1c3a730439ccbeb94a77bdd 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetTest.java @@ -1,5 +1,8 @@ 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.Assert; import org.junit.BeforeClass; @@ -9,11 +12,12 @@ 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 RestfulResultSetTest { private static final String host = "127.0.0.1"; -// private static final String host = "master"; private static Connection conn; private static Statement stmt; @@ -88,24 +92,75 @@ public class RestfulResultSetTest { Assert.assertEquals(3.1415926, f5, 0.0); } - @Test(expected = SQLFeatureNotSupportedException.class) + @Test 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 { - 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) - public void getDate() throws SQLException { - rs.getDate("f1"); + @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(expected = SQLFeatureNotSupportedException.class) + @Test public void getTime() throws SQLException { - rs.getTime("f1"); + Time f1 = rs.getTime("f1"); + Assert.assertEquals("00:00:00", f1.toString()); } @Test @@ -152,9 +207,49 @@ public class RestfulResultSetTest { Assert.assertNotNull(meta); } - @Test(expected = SQLFeatureNotSupportedException.class) - public void getObject() throws SQLException { - rs.getObject("f1"); + @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) diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulStatementTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulStatementTest.java index 653e480413189667ec57d836f9b503f4c96a79cb..1be32b502d3f8f7c1b94cd1a8940073520e11b12 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulStatementTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulStatementTest.java @@ -12,7 +12,6 @@ import java.util.UUID; public class RestfulStatementTest { private static final String host = "127.0.0.1"; - // private static final String host = "master"; private static Connection conn; private static Statement stmt; diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/SQLTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/SQLTest.java index fe4d04775da642bcf258e3680b0f5ba822e69684..4ad9826384a93e221b1181b72fa576bf72ebaff4 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/SQLTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/SQLTest.java @@ -12,7 +12,6 @@ import java.sql.*; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class SQLTest { private static final String host = "127.0.0.1"; -// private static final String host = "master"; private static Connection connection; @Test diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/OSUtilsTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/OSUtilsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fd6c83ad1cacfb351bcc1d35a5cf777213ad876d --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/OSUtilsTest.java @@ -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(); + } +} \ No newline at end of file diff --git a/src/dnode/src/dnodeMain.c b/src/dnode/src/dnodeMain.c index fb467094404a50b6817327c0bfc2127d94104a84..ea0ef4655d4cc98949012f125d9805ac20642d1a 100644 --- a/src/dnode/src/dnodeMain.c +++ b/src/dnode/src/dnodeMain.c @@ -70,13 +70,16 @@ static SStep tsDnodeSteps[] = { {"dnode-vread", dnodeInitVRead, dnodeCleanupVRead}, {"dnode-vwrite", dnodeInitVWrite, dnodeCleanupVWrite}, {"dnode-vmgmt", dnodeInitVMgmt, dnodeCleanupVMgmt}, - {"dnode-mread", dnodeInitMRead, dnodeCleanupMRead}, - {"dnode-mwrite", dnodeInitMWrite, dnodeCleanupMWrite}, - {"dnode-mpeer", dnodeInitMPeer, dnodeCleanupMPeer}, + {"dnode-mread", dnodeInitMRead, NULL}, + {"dnode-mwrite", dnodeInitMWrite, NULL}, + {"dnode-mpeer", dnodeInitMPeer, NULL}, {"dnode-client", dnodeInitClient, dnodeCleanupClient}, {"dnode-server", dnodeInitServer, dnodeCleanupServer}, {"dnode-vnodes", dnodeInitVnodes, dnodeCleanupVnodes}, {"dnode-modules", dnodeInitModules, dnodeCleanupModules}, + {"dnode-mread", NULL, dnodeCleanupMRead}, + {"dnode-mwrite", NULL, dnodeCleanupMWrite}, + {"dnode-mpeer", NULL, dnodeCleanupMPeer}, {"dnode-shell", dnodeInitShell, dnodeCleanupShell}, {"dnode-statustmr", dnodeInitStatusTimer,dnodeCleanupStatusTimer}, {"dnode-telemetry", dnodeInitTelemetry, dnodeCleanupTelemetry}, @@ -234,6 +237,18 @@ static int32_t dnodeInitStorage() { return -1; } + TDIR *tdir = tfsOpendir("vnode_bak/.staging"); + if (tfsReaddir(tdir) != NULL) { + dError("vnode_bak/.staging dir not empty, fix it first."); + tfsClosedir(tdir); + return -1; + } + + if (tfsMkdir("vnode_bak/.staging") < 0) { + dError("failed to create vnode_bak/.staging dir since %s", tstrerror(terrno)); + return -1; + } + dnodeCheckDataDirOpenned(tsDnodeDir); dInfo("dnode storage is initialized at %s", tsDnodeDir); diff --git a/src/dnode/src/dnodePeer.c b/src/dnode/src/dnodePeer.c index 79c60874f99cca535955246f9fc393b1a7cee638..b8ce1c802b2475a8aab76a6bb7f0264d2c9b39a0 100644 --- a/src/dnode/src/dnodePeer.c +++ b/src/dnode/src/dnodePeer.c @@ -43,6 +43,7 @@ int32_t dnodeInitServer() { dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_CREATE_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_ALTER_STREAM] = dnodeDispatchToVMgmtQueue; dnodeProcessReqMsgFp[TSDB_MSG_TYPE_MD_CONFIG_DNODE] = dnodeDispatchToVMgmtQueue; diff --git a/src/dnode/src/dnodeVMgmt.c b/src/dnode/src/dnodeVMgmt.c index 1e428fc8b13e2a476868738f043c90914c61f5fc..66c94bf6755850f4b731e425cd0da90f75c218f3 100644 --- a/src/dnode/src/dnodeVMgmt.c +++ b/src/dnode/src/dnodeVMgmt.c @@ -30,6 +30,7 @@ static taos_queue tsVMgmtQueue = NULL; static void * dnodeProcessMgmtQueue(void *param); static int32_t dnodeProcessCreateVnodeMsg(SRpcMsg *pMsg); static int32_t dnodeProcessAlterVnodeMsg(SRpcMsg *pMsg); +static int32_t dnodeProcessSyncVnodeMsg(SRpcMsg *pMsg); static int32_t dnodeProcessDropVnodeMsg(SRpcMsg *pMsg); static int32_t dnodeProcessAlterStreamMsg(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() { dnodeProcessMgmtMsgFp[TSDB_MSG_TYPE_MD_CREATE_VNODE] = dnodeProcessCreateVnodeMsg; 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_ALTER_STREAM] = dnodeProcessAlterStreamMsg; 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) { SDropVnodeMsg *pDrop = rpcMsg->pCont; pDrop->vgId = htonl(pDrop->vgId); diff --git a/src/dnode/src/dnodeVnodes.c b/src/dnode/src/dnodeVnodes.c index d00314fcbc806ab89b9f71a3a28880c7878f4579..d96251cebe1cbbcddeb48f1a09091e1c09caf630 100644 --- a/src/dnode/src/dnodeVnodes.c +++ b/src/dnode/src/dnodeVnodes.c @@ -202,10 +202,11 @@ static void dnodeProcessStatusRsp(SRpcMsg *pMsg) { char clusterId[TSDB_CLUSTER_ID_LEN]; dnodeGetClusterId(clusterId); if (clusterId[0] != '\0') { - dError("exit zombie dropped dnode"); - exit(EXIT_FAILURE); + dError("exit zombie dropped dnode"); + exit(EXIT_FAILURE); } } + taosTmrReset(dnodeSendStatusMsg, tsStatusInterval * 1000, NULL, tsDnodeTmr, &tsStatusTimer); return; } diff --git a/src/inc/taosdef.h b/src/inc/taosdef.h index 252e37a5d943d308af01174845a7c220de3b89ea..024bc198df80bd42f547cd89543c028403acccd3 100644 --- a/src/inc/taosdef.h +++ b/src/inc/taosdef.h @@ -259,7 +259,7 @@ do { \ #define TSDB_MIN_TABLES 4 #define TSDB_MAX_TABLES 10000000 #define TSDB_DEFAULT_TABLES 1000000 -#define TSDB_TABLES_STEP 100 +#define TSDB_TABLES_STEP 1000 #define TSDB_MIN_DAYS_PER_FILE 1 #define TSDB_MAX_DAYS_PER_FILE 3650 diff --git a/src/inc/taosmsg.h b/src/inc/taosmsg.h index ed9477ca3db5e34cfc2dbd201c95e3f5026cc561..e590fdbcbb06c3da4d1466744e5720b4f1b2ebf9 100644 --- a/src/inc/taosmsg.h +++ b/src/inc/taosmsg.h @@ -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_CONFIG_DNODE, "config-dnode" ) 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_DUMMY6, "dummy6" ) TAOS_DEFINE_MESSAGE_TYPE( TSDB_MSG_TYPE_DUMMY7, "dummy7" ) @@ -389,7 +390,7 @@ typedef struct { typedef struct { int32_t vgId; -} SDropVnodeMsg; +} SDropVnodeMsg, SSyncVnodeMsg; typedef struct SColIndex { int16_t colId; // column id diff --git a/src/inc/tsync.h b/src/inc/tsync.h index 99dfd3a6a30b1c7cf36e94a7d2485181f966f5fc..d1b68e3f5a1e27b63dd08a4d1d4862c7b1e68179 100644 --- a/src/inc/tsync.h +++ b/src/inc/tsync.h @@ -79,9 +79,6 @@ typedef void (*FStopSyncFile)(int32_t vgId, uint64_t fversion); // get file version 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 (*FRecvFile)(void *tsdb, SOCKET socketFd); @@ -99,7 +96,6 @@ typedef struct { FStartSyncFile startSyncFileFp; FStopSyncFile stopSyncFileFp; FGetVersion getVersionFp; - FResetVersion resetVersionFp; FSendFile sendFileFp; FRecvFile recvFileFp; } SSyncInfo; diff --git a/src/inc/vnode.h b/src/inc/vnode.h index dddec83da87f6cf7f25212dd1aa39373e6b613f7..39bd2f46c3e41927389ab4333e27a1cee717aaed 100644 --- a/src/inc/vnode.h +++ b/src/inc/vnode.h @@ -60,6 +60,7 @@ int32_t vnodeCreate(SCreateVnodeMsg *pVnodeCfg); int32_t vnodeDrop(int32_t vgId); int32_t vnodeOpen(int32_t vgId); int32_t vnodeAlter(void *pVnode, SCreateVnodeMsg *pVnodeCfg); +int32_t vnodeSync(int32_t vgId); int32_t vnodeClose(int32_t vgId); // vnodeMgmt @@ -89,4 +90,4 @@ int32_t vnodeProcessRead(void *pVnode, SVReadMsg *pRead); } #endif -#endif \ No newline at end of file +#endif diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index 1048d7b96922b57da2956d5682e40e49cf17b41d..d76185ca43c233c9ac0d4b6e46dc34f74a267670 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -37,10 +37,10 @@ #include #include #include -#else +#else #include #include -#endif +#endif #include #include @@ -69,7 +69,10 @@ enum TEST_MODE { #define MAX_SQL_SIZE 65536 #define BUFFER_SIZE (65536*2) +#define MAX_USERNAME_SIZE 64 +#define MAX_PASSWORD_SIZE 64 #define MAX_DB_NAME_SIZE 64 +#define MAX_HOSTNAME_SIZE 64 #define MAX_TB_NAME_SIZE 64 #define MAX_DATA_SIZE 16000 #define MAX_NUM_DATATYPE 10 @@ -82,7 +85,7 @@ enum TEST_MODE { #define MAX_NUM_DATATYPE 10 #define MAX_DB_COUNT 8 -#define MAX_SUPER_TABLE_COUNT 8 +#define MAX_SUPER_TABLE_COUNT 200 #define MAX_COLUMN_COUNT 1024 #define MAX_TAG_COUNT 128 @@ -100,7 +103,7 @@ typedef enum CREATE_SUB_TALBE_MOD_EN { AUTO_CREATE_SUBTBL, NO_CREATE_SUBTBL } CREATE_SUB_TALBE_MOD_EN; - + typedef enum TALBE_EXISTS_EN { TBL_NO_EXISTS, TBL_ALREADY_EXISTS, @@ -108,7 +111,7 @@ typedef enum TALBE_EXISTS_EN { } TALBE_EXISTS_EN; enum MODE { - SYNC, + SYNC, ASYNC, MODE_BUT }; @@ -121,7 +124,7 @@ typedef enum enum_INSERT_MODE { typedef enum enumQUERY_TYPE { NO_INSERT_TYPE, - INSERT_TYPE, + INSERT_TYPE, QUERY_TYPE_BUT } QUERY_TYPE; @@ -131,7 +134,7 @@ enum _show_db_index { TSDB_SHOW_DB_NTABLES_INDEX, TSDB_SHOW_DB_VGROUPS_INDEX, TSDB_SHOW_DB_REPLICA_INDEX, - TSDB_SHOW_DB_QUORUM_INDEX, + TSDB_SHOW_DB_QUORUM_INDEX, TSDB_SHOW_DB_DAYS_INDEX, TSDB_SHOW_DB_KEEP_INDEX, TSDB_SHOW_DB_CACHE_INDEX, @@ -153,10 +156,10 @@ enum _show_stables_index { TSDB_SHOW_STABLES_NAME_INDEX, TSDB_SHOW_STABLES_CREATED_TIME_INDEX, TSDB_SHOW_STABLES_COLUMNS_INDEX, - TSDB_SHOW_STABLES_METRIC_INDEX, - TSDB_SHOW_STABLES_UID_INDEX, + TSDB_SHOW_STABLES_METRIC_INDEX, + TSDB_SHOW_STABLES_UID_INDEX, TSDB_SHOW_STABLES_TID_INDEX, - TSDB_SHOW_STABLES_VGID_INDEX, + TSDB_SHOW_STABLES_VGID_INDEX, TSDB_MAX_SHOW_STABLES }; @@ -220,13 +223,13 @@ typedef struct SColumn_S { char field[TSDB_COL_NAME_LEN + 1]; char dataType[MAX_TB_NAME_SIZE]; int dataLen; - char note[128]; + char note[128]; } StrColumn; typedef struct SSuperTable_S { char sTblName[MAX_TB_NAME_SIZE+1]; int childTblCount; - bool childTblExists; // 0: no, 1: yes + bool childTblExists; // 0: no, 1: yes int batchCreateTableNum; // 0: no batch, > 0: batch table number in one sql int8_t autoCreateTable; // 0: create sub table, 1: auto create sub table char childTblPrefix[MAX_TB_NAME_SIZE]; @@ -236,15 +239,15 @@ typedef struct SSuperTable_S { int childTblOffset; int multiThreadWriteOneTbl; // 0: no, 1: yes - int interlaceRows; // + int interlaceRows; // int disorderRatio; // 0: no disorder, >0: x% int disorderRange; // ms or us by database precision - int maxSqlLen; // + int maxSqlLen; // int insertInterval; // insert interval, will override global insert interval int64_t insertRows; // 0: no limit int timeStampStep; - char startTimestamp[MAX_TB_NAME_SIZE]; // + char startTimestamp[MAX_TB_NAME_SIZE]; // char sampleFormat[MAX_TB_NAME_SIZE]; // csv, json char sampleFile[MAX_FILE_NAME_LEN+1]; char tagsFile[MAX_FILE_NAME_LEN+1]; @@ -269,7 +272,7 @@ typedef struct SSuperTable_S { int tagSampleCount; int tagUsePos; - // statistics + // statistics int64_t totalInsertRows; int64_t totalAffectedRows; } SSuperTable; @@ -278,10 +281,10 @@ typedef struct { char name[TSDB_DB_NAME_LEN + 1]; char create_time[32]; int32_t ntables; - int32_t vgroups; + int32_t vgroups; int16_t replica; int16_t quorum; - int16_t days; + int16_t days; char keeplist[32]; int32_t cache; //MB int32_t blocks; @@ -296,14 +299,14 @@ typedef struct { char status[16]; } SDbInfo; -typedef struct SDbCfg_S { +typedef struct SDbCfg_S { // int maxtablesPerVnode; - int minRows; + int minRows; int maxRows; int comp; int walLevel; int cacheLast; - int fsync; + int fsync; int replica; int update; int keep; @@ -311,7 +314,7 @@ typedef struct SDbCfg_S { int cache; int blocks; int quorum; - char precision[MAX_TB_NAME_SIZE]; + char precision[MAX_TB_NAME_SIZE]; } SDbCfg; typedef struct SDataBase_S { @@ -324,16 +327,16 @@ typedef struct SDataBase_S { typedef struct SDbs_S { char cfgDir[MAX_FILE_NAME_LEN+1]; - char host[MAX_DB_NAME_SIZE]; + char host[MAX_HOSTNAME_SIZE]; uint16_t port; - char user[MAX_DB_NAME_SIZE]; - char password[MAX_DB_NAME_SIZE]; + char user[MAX_USERNAME_SIZE]; + char password[MAX_PASSWORD_SIZE]; char resultFile[MAX_FILE_NAME_LEN+1]; bool use_metric; bool insert_only; bool do_aggreFunc; bool queryMode; - + int threadCount; int threadCountByCreateTbl; int dbCount; @@ -345,20 +348,21 @@ typedef struct SDbs_S { } SDbs; -typedef struct SuperQueryInfo_S { +typedef struct SpecifiedQueryInfo_S { int rate; // 0: unlimit > 0 loop/s int concurrent; int sqlCount; int subscribeMode; // 0: sync, 1: async int subscribeInterval; // ms + int queryTimes; int subscribeRestart; int subscribeKeepProgress; char sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1]; char result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1]; TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT]; -} SuperQueryInfo; +} SpecifiedQueryInfo; -typedef struct SubQueryInfo_S { +typedef struct SuperQueryInfo_S { char sTblName[MAX_TB_NAME_SIZE+1]; int rate; // 0: unlimit > 0 loop/s int threadCnt; @@ -366,33 +370,35 @@ typedef struct SubQueryInfo_S { int subscribeInterval; // ms int subscribeRestart; int subscribeKeepProgress; + int queryTimes; int childTblCount; char childTblPrefix[MAX_TB_NAME_SIZE]; int sqlCount; char sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1]; char result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1]; TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT]; - + char* childTblName; -} SubQueryInfo; +} SuperQueryInfo; typedef struct SQueryMetaInfo_S { char cfgDir[MAX_FILE_NAME_LEN+1]; - char host[MAX_DB_NAME_SIZE]; + char host[MAX_HOSTNAME_SIZE]; uint16_t port; - char user[MAX_DB_NAME_SIZE]; - char password[MAX_DB_NAME_SIZE]; + char user[MAX_USERNAME_SIZE]; + char password[MAX_PASSWORD_SIZE]; char dbName[MAX_DB_NAME_SIZE+1]; char queryMode[MAX_TB_NAME_SIZE]; // taosc, restful - SuperQueryInfo superQueryInfo; - SubQueryInfo subQueryInfo; + SpecifiedQueryInfo specifiedQueryInfo; + SuperQueryInfo superQueryInfo; } SQueryMetaInfo; typedef struct SThreadInfo_S { TAOS *taos; int threadID; char db_name[MAX_DB_NAME_SIZE+1]; + uint32_t time_precision; char fp[4096]; char tb_prefix[MAX_TB_NAME_SIZE]; int start_table_from; @@ -423,7 +429,7 @@ typedef struct SThreadInfo_S { int64_t avgDelay; int64_t maxDelay; int64_t minDelay; - + } threadInfo; #ifdef WINDOWS @@ -462,12 +468,12 @@ static void setupForAnsiEscape(void) { if(!SetConsoleMode(g_stdoutHandle, mode)) { exit(GetLastError()); - } + } } static void resetAfterAnsiEscape(void) { // Reset colors - printf("\x1b[0m"); + printf("\x1b[0m"); // Reset console mode if(!SetConsoleMode(g_stdoutHandle, g_consoleMode)) { @@ -490,9 +496,12 @@ static void resetAfterAnsiEscape(void) { printf("\x1b[0m"); } +#include + static int taosRandom() { - return random(); + srand(time(NULL)); + return rand(); } #endif @@ -507,7 +516,7 @@ int32_t randint[MAX_PREPARED_RAND]; int64_t randbigint[MAX_PREPARED_RAND]; float randfloat[MAX_PREPARED_RAND]; double randdouble[MAX_PREPARED_RAND]; -char *aggreFunc[] = {"*", "count(*)", "avg(col0)", "sum(col0)", +char *aggreFunc[] = {"*", "count(*)", "avg(col0)", "sum(col0)", "max(col0)", "min(col0)", "first(col0)", "last(col0)"}; SArguments g_args = { @@ -516,7 +525,7 @@ SArguments g_args = { "127.0.0.1", // host 6030, // port "root", // user - #ifdef _TD_POWER_ + #ifdef _TD_POWER_ "powerdb", // password #else "taosdata", // password @@ -530,7 +539,7 @@ SArguments g_args = { true, // insert_only false, // debug_print false, // verbose_print - false, // performance statistic print + false, // performance statistic print false, // answer_yes; "./output.txt", // output_file 0, // mode : sync or async @@ -598,7 +607,7 @@ static void ERROR_EXIT(const char *msg) { perror(msg); exit(-1); } #define TD_VERNUMBER "unknown" #endif -#ifndef TAOSDEMO_STATUS +#ifndef TAOSDEMO_STATUS #define TAOSDEMO_STATUS "unknown" #endif @@ -618,64 +627,64 @@ static void printVersion() { static void printHelp() { char indent[10] = " "; - printf("%s%s%s%s\n", indent, "-f", indent, + printf("%s%s%s%s\n", indent, "-f", indent, "The meta file to the execution procedure. Default is './meta.json'."); - printf("%s%s%s%s\n", indent, "-u", indent, + printf("%s%s%s%s\n", indent, "-u", indent, "The TDengine user name to use when connecting to the server. Default is 'root'."); #ifdef _TD_POWER_ - printf("%s%s%s%s\n", indent, "-P", indent, + printf("%s%s%s%s\n", indent, "-P", indent, "The password to use when connecting to the server. Default is 'powerdb'."); - printf("%s%s%s%s\n", indent, "-c", indent, + printf("%s%s%s%s\n", indent, "-c", indent, "Configuration directory. Default is '/etc/power/'."); #else - printf("%s%s%s%s\n", indent, "-P", indent, + printf("%s%s%s%s\n", indent, "-P", indent, "The password to use when connecting to the server. Default is 'taosdata'."); - printf("%s%s%s%s\n", indent, "-c", indent, + printf("%s%s%s%s\n", indent, "-c", indent, "Configuration directory. Default is '/etc/taos/'."); -#endif - printf("%s%s%s%s\n", indent, "-h", indent, +#endif + printf("%s%s%s%s\n", indent, "-h", indent, "The host to connect to TDengine. Default is localhost."); - printf("%s%s%s%s\n", indent, "-p", indent, + printf("%s%s%s%s\n", indent, "-p", indent, "The TCP/IP port number to use for the connection. Default is 0."); - printf("%s%s%s%s\n", indent, "-d", indent, + printf("%s%s%s%s\n", indent, "-d", indent, "Destination database. Default is 'test'."); - printf("%s%s%s%s\n", indent, "-a", indent, + printf("%s%s%s%s\n", indent, "-a", indent, "Set the replica parameters of the database, Default 1, min: 1, max: 3."); - printf("%s%s%s%s\n", indent, "-m", indent, + printf("%s%s%s%s\n", indent, "-m", indent, "Table prefix name. Default is 't'."); printf("%s%s%s%s\n", indent, "-s", indent, "The select sql file."); printf("%s%s%s%s\n", indent, "-N", indent, "Use normal table flag."); - printf("%s%s%s%s\n", indent, "-o", indent, + printf("%s%s%s%s\n", indent, "-o", indent, "Direct output to the named file. Default is './output.txt'."); - printf("%s%s%s%s\n", indent, "-q", indent, + printf("%s%s%s%s\n", indent, "-q", indent, "Query mode--0: SYNC, 1: ASYNC. Default is SYNC."); - printf("%s%s%s%s\n", indent, "-b", indent, + printf("%s%s%s%s\n", indent, "-b", indent, "The data_type of columns, default: TINYINT,SMALLINT,INT,BIGINT,FLOAT,DOUBLE,BINARY,NCHAR,BOOL,TIMESTAMP."); - printf("%s%s%s%s\n", indent, "-w", indent, + printf("%s%s%s%s\n", indent, "-w", indent, "The length of data_type 'BINARY' or 'NCHAR'. Default is 16"); - printf("%s%s%s%s\n", indent, "-l", indent, + printf("%s%s%s%s\n", indent, "-l", indent, "The number of columns per record. Default is 10."); - printf("%s%s%s%s\n", indent, "-T", indent, + printf("%s%s%s%s\n", indent, "-T", indent, "The number of threads. Default is 10."); - printf("%s%s%s%s\n", indent, "-i", indent, + printf("%s%s%s%s\n", indent, "-i", indent, "The sleep time (ms) between insertion. Default is 0."); - printf("%s%s%s%s\n", indent, "-r", indent, + printf("%s%s%s%s\n", indent, "-r", indent, "The number of records per request. Default is 100."); - printf("%s%s%s%s\n", indent, "-t", indent, + printf("%s%s%s%s\n", indent, "-t", indent, "The number of tables. Default is 10000."); - printf("%s%s%s%s\n", indent, "-n", indent, + printf("%s%s%s%s\n", indent, "-n", indent, "The number of records per table. Default is 10000."); printf("%s%s%s%s\n", indent, "-x", indent, "Not insert only flag."); printf("%s%s%s%s\n", indent, "-y", indent, "Default input yes for prompt."); - printf("%s%s%s%s\n", indent, "-O", indent, + printf("%s%s%s%s\n", indent, "-O", indent, "Insert mode--0: In order, > 0: disorder ratio. Default is in order."); - printf("%s%s%s%s\n", indent, "-R", indent, + printf("%s%s%s%s\n", indent, "-R", indent, "Out of order data's range, ms, default is 1000."); - printf("%s%s%s%s\n", indent, "-g", indent, + printf("%s%s%s%s\n", indent, "-g", indent, "Print debug info."); - printf("%s%s%s%s\n", indent, "-V, --version", indent, + printf("%s%s%s%s\n", indent, "-V, --version", indent, "Print version info."); -/* printf("%s%s%s%s\n", indent, "-D", indent, +/* printf("%s%s%s%s\n", indent, "-D", indent, "if elete database if exists. 0: no, 1: yes, default is 1"); */ } @@ -695,6 +704,7 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { } taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]); wordfree(&full_path); + } else if (strcmp(argv[i], "-h") == 0) { arguments->host = argv[++i]; } else if (strcmp(argv[i], "-p") == 0) { @@ -739,7 +749,7 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { && strcasecmp(argv[i], "SMALLINT") && strcasecmp(argv[i], "BIGINT") && strcasecmp(argv[i], "DOUBLE") - && strcasecmp(argv[i], "BINARY") + && strcasecmp(argv[i], "BINARY") && strcasecmp(argv[i], "NCHAR")) { printHelp(); ERROR_EXIT( "Invalid data_type!\n"); @@ -792,7 +802,7 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { strcpy(configDir, argv[++i]); } else if (strcmp(argv[i], "-O") == 0) { arguments->disorderRatio = atoi(argv[++i]); - if (arguments->disorderRatio > 1 + if (arguments->disorderRatio > 1 || arguments->disorderRatio < 0) { arguments->disorderRatio = 0; } else if (arguments->disorderRatio == 1) { @@ -800,8 +810,8 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { } } else if (strcmp(argv[i], "-R") == 0) { arguments->disorderRange = atoi(argv[++i]); - if (arguments->disorderRange == 1 - && (arguments->disorderRange > 50 + if (arguments->disorderRange == 1 + && (arguments->disorderRange > 50 || arguments->disorderRange <= 0)) { arguments->disorderRange = 10; } @@ -834,7 +844,7 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { || arguments->verbose_print) { printf("###################################################################\n"); printf("# meta file: %s\n", arguments->metaFile); - printf("# Server IP: %s:%hu\n", + printf("# Server IP: %s:%hu\n", arguments->host == NULL ? "localhost" : arguments->host, arguments->port ); printf("# User: %s\n", arguments->user); @@ -861,7 +871,7 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { if (arguments->disorderRatio) { printf("# Data order: %d\n", arguments->disorderRatio); printf("# Data out of order rate: %d\n", arguments->disorderRange); - + } printf("# Delete method: %d\n", arguments->method_of_delete); printf("# Answer yes when prompt: %d\n", arguments->answer_yes); @@ -929,7 +939,7 @@ static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) { return 0; } -static void getResult(TAOS_RES *res, char* resultFileName) { +static void getResult(TAOS_RES *res, char* resultFileName) { TAOS_ROW row = NULL; int num_rows = 0; int num_fields = taos_field_count(res); @@ -939,13 +949,15 @@ static void getResult(TAOS_RES *res, char* resultFileName) { if (resultFileName[0] != 0) { fp = fopen(resultFileName, "at"); if (fp == NULL) { - errorPrint("%s() LN%d, failed to open result file: %s, result will not save to file\n", __func__, __LINE__, resultFileName); + errorPrint("%s() LN%d, failed to open result file: %s, result will not save to file\n", + __func__, __LINE__, resultFileName); } } - + char* databuf = (char*) calloc(1, 100*1024*1024); if (databuf == NULL) { - errorPrint("%s() LN%d, failed to malloc, warning: save result to file slowly!\n", __func__, __LINE__); + errorPrint("%s() LN%d, failed to malloc, warning: save result to file slowly!\n", + __func__, __LINE__); if (fp) fclose(fp); return ; @@ -981,7 +993,7 @@ static void selectAndGetResult(TAOS *taos, char *command, char* resultFileName) taos_free_result(res); return; } - + getResult(res, resultFileName); taos_free_result(res); } @@ -1029,14 +1041,13 @@ static int64_t rand_bigint(){ cursor++; cursor = cursor % MAX_PREPARED_RAND; return randbigint[cursor]; - } static float rand_float(){ static int cursor; cursor++; cursor = cursor % MAX_PREPARED_RAND; - return randfloat[cursor]; + return randfloat[cursor]; } static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; @@ -1099,7 +1110,7 @@ static int printfInsertMeta() { printf("resultFile: \033[33m%s\033[0m\n", g_Dbs.resultFile); printf("thread num of insert data: \033[33m%d\033[0m\n", g_Dbs.threadCount); printf("thread num of create table: \033[33m%d\033[0m\n", g_Dbs.threadCountByCreateTbl); - printf("insert interval: \033[33m%d\033[0m\n", g_args.insert_interval); + printf("top insert interval: \033[33m%d\033[0m\n", g_args.insert_interval); printf("number of records per req: \033[33m%d\033[0m\n", g_args.num_of_RPR); printf("max sql length: \033[33m%d\033[0m\n", g_args.max_sql_len); @@ -1109,9 +1120,9 @@ static int printfInsertMeta() { printf("database[\033[33m%d\033[0m]:\n", i); printf(" database[%d] name: \033[33m%s\033[0m\n", i, g_Dbs.db[i].dbName); if (0 == g_Dbs.db[i].drop) { - printf(" drop: \033[33mno\033[0m\n"); - }else { - printf(" drop: \033[33myes\033[0m\n"); + printf(" drop: \033[33mno\033[0m\n"); + } else { + printf(" drop: \033[33myes\033[0m\n"); } if (g_Dbs.db[i].dbCfg.blocks > 0) { @@ -1164,8 +1175,8 @@ static int printfInsertMeta() { printf(" super table count: \033[33m%d\033[0m\n", g_Dbs.db[i].superTblCount); for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { printf(" super table[\033[33m%d\033[0m]:\n", j); - - printf(" stbName: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].sTblName); + + printf(" stbName: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].sTblName); if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) { printf(" autoCreateTable: \033[33m%s\033[0m\n", "no"); @@ -1174,7 +1185,7 @@ static int printfInsertMeta() { } else { printf(" autoCreateTable: \033[33m%s\033[0m\n", "error"); } - + if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) { printf(" childTblExists: \033[33m%s\033[0m\n", "no"); } else if (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) { @@ -1183,17 +1194,24 @@ static int printfInsertMeta() { printf(" childTblExists: \033[33m%s\033[0m\n", "error"); } - printf(" childTblCount: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].childTblCount); - printf(" childTblPrefix: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].childTblPrefix); - printf(" dataSource: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].dataSource); - printf(" insertMode: \033[33m%s\033[0m\n", g_Dbs.db[i].superTbls[j].insertMode); + printf(" childTblCount: \033[33m%d\033[0m\n", + g_Dbs.db[i].superTbls[j].childTblCount); + printf(" childTblPrefix: \033[33m%s\033[0m\n", + g_Dbs.db[i].superTbls[j].childTblPrefix); + printf(" dataSource: \033[33m%s\033[0m\n", + g_Dbs.db[i].superTbls[j].dataSource); + printf(" insertMode: \033[33m%s\033[0m\n", + g_Dbs.db[i].superTbls[j].insertMode); if (g_Dbs.db[i].superTbls[j].childTblLimit > 0) { - printf(" childTblLimit: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].childTblLimit); + printf(" childTblLimit: \033[33m%d\033[0m\n", + g_Dbs.db[i].superTbls[j].childTblLimit); } if (g_Dbs.db[i].superTbls[j].childTblOffset >= 0) { - printf(" childTblOffset: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].childTblOffset); + printf(" childTblOffset: \033[33m%d\033[0m\n", + g_Dbs.db[i].superTbls[j].childTblOffset); } - printf(" insertRows: \033[33m%"PRId64"\033[0m\n", g_Dbs.db[i].superTbls[j].insertRows); + printf(" insertRows: \033[33m%"PRId64"\033[0m\n", + g_Dbs.db[i].superTbls[j].insertRows); if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) { printf(" multiThreadWriteOneTbl: \033[33mno\033[0m\n"); @@ -1202,6 +1220,12 @@ static int printfInsertMeta() { } printf(" interlaceRows: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].interlaceRows); + + if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) { + printf(" stable insert interval: \033[33m%d\033[0m\n", + g_Dbs.db[i].superTbls[j].insertInterval); + } + printf(" disorderRange: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].disorderRange); printf(" disorderRatio: \033[33m%d\033[0m\n", @@ -1240,8 +1264,10 @@ static int printfInsertMeta() { g_Dbs.db[i].superTbls[j].tagCount); for (int k = 0; k < g_Dbs.db[i].superTbls[j].tagCount; k++) { //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].tags[k].dataType, g_Dbs.db[i].superTbls[j].tags[k].dataLen); - if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, "binary", 6)) - || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, "nchar", 5))) { + if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, + "binary", strlen("binary"))) + || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, + "nchar", strlen("nchar")))) { printf("tag[%d]:\033[33m%s(%d)\033[0m ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType, g_Dbs.db[i].superTbls[j].tags[k].dataLen); @@ -1269,7 +1295,6 @@ static void printfInsertMetaToFile(FILE* fp) { fprintf(fp, "resultFile: %s\n", g_Dbs.resultFile); fprintf(fp, "thread num of insert data: %d\n", g_Dbs.threadCount); fprintf(fp, "thread num of create table: %d\n", g_Dbs.threadCountByCreateTbl); - fprintf(fp, "insert interval: %d\n", g_args.insert_interval); fprintf(fp, "number of records per req: %d\n", g_args.num_of_RPR); fprintf(fp, "max sql length: %d\n", g_args.max_sql_len); fprintf(fp, "database count: %d\n", g_Dbs.dbCount); @@ -1278,9 +1303,9 @@ static void printfInsertMetaToFile(FILE* fp) { fprintf(fp, "database[%d]:\n", i); fprintf(fp, " database[%d] name: %s\n", i, g_Dbs.db[i].dbName); if (0 == g_Dbs.db[i].drop) { - fprintf(fp, " drop: no\n"); + fprintf(fp, " drop: no\n"); }else { - fprintf(fp, " drop: yes\n"); + fprintf(fp, " drop: yes\n"); } if (g_Dbs.db[i].dbCfg.blocks > 0) { @@ -1331,8 +1356,8 @@ static void printfInsertMetaToFile(FILE* fp) { fprintf(fp, " super table count: %d\n", g_Dbs.db[i].superTblCount); for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { fprintf(fp, " super table[%d]:\n", j); - - fprintf(fp, " stbName: %s\n", g_Dbs.db[i].superTbls[j].sTblName); + + fprintf(fp, " stbName: %s\n", g_Dbs.db[i].superTbls[j].sTblName); if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) { fprintf(fp, " autoCreateTable: %s\n", "no"); @@ -1341,7 +1366,7 @@ static void printfInsertMetaToFile(FILE* fp) { } else { fprintf(fp, " autoCreateTable: %s\n", "error"); } - + if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) { fprintf(fp, " childTblExists: %s\n", "no"); } else if (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) { @@ -1349,30 +1374,41 @@ static void printfInsertMetaToFile(FILE* fp) { } else { fprintf(fp, " childTblExists: %s\n", "error"); } - - fprintf(fp, " childTblCount: %d\n", g_Dbs.db[i].superTbls[j].childTblCount); - fprintf(fp, " childTblPrefix: %s\n", g_Dbs.db[i].superTbls[j].childTblPrefix); - fprintf(fp, " dataSource: %s\n", g_Dbs.db[i].superTbls[j].dataSource); - fprintf(fp, " insertMode: %s\n", g_Dbs.db[i].superTbls[j].insertMode); - fprintf(fp, " insertRows: %"PRId64"\n", g_Dbs.db[i].superTbls[j].insertRows); - fprintf(fp, " insert interval: %d\n", g_Dbs.db[i].superTbls[j].insertInterval); + + fprintf(fp, " childTblCount: %d\n", + g_Dbs.db[i].superTbls[j].childTblCount); + fprintf(fp, " childTblPrefix: %s\n", + g_Dbs.db[i].superTbls[j].childTblPrefix); + fprintf(fp, " dataSource: %s\n", + g_Dbs.db[i].superTbls[j].dataSource); + fprintf(fp, " insertMode: %s\n", + g_Dbs.db[i].superTbls[j].insertMode); + fprintf(fp, " insertRows: %"PRId64"\n", + g_Dbs.db[i].superTbls[j].insertRows); + fprintf(fp, " interlace rows: %d\n", + g_Dbs.db[i].superTbls[j].interlaceRows); + if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) { + fprintf(fp, " stable insert interval: %d\n", + g_Dbs.db[i].superTbls[j].insertInterval); + } if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) { - fprintf(fp, " multiThreadWriteOneTbl: no\n"); + fprintf(fp, " multiThreadWriteOneTbl: no\n"); }else { - fprintf(fp, " multiThreadWriteOneTbl: yes\n"); + fprintf(fp, " multiThreadWriteOneTbl: yes\n"); } - fprintf(fp, " interlaceRows: %d\n", g_Dbs.db[i].superTbls[j].interlaceRows); - fprintf(fp, " disorderRange: %d\n", g_Dbs.db[i].superTbls[j].disorderRange); + fprintf(fp, " interlaceRows: %d\n", + g_Dbs.db[i].superTbls[j].interlaceRows); + fprintf(fp, " disorderRange: %d\n", g_Dbs.db[i].superTbls[j].disorderRange); fprintf(fp, " disorderRatio: %d\n", g_Dbs.db[i].superTbls[j].disorderRatio); - fprintf(fp, " maxSqlLen: %d\n", g_Dbs.db[i].superTbls[j].maxSqlLen); - - fprintf(fp, " timeStampStep: %d\n", g_Dbs.db[i].superTbls[j].timeStampStep); - fprintf(fp, " startTimestamp: %s\n", g_Dbs.db[i].superTbls[j].startTimestamp); + fprintf(fp, " maxSqlLen: %d\n", g_Dbs.db[i].superTbls[j].maxSqlLen); + + fprintf(fp, " timeStampStep: %d\n", g_Dbs.db[i].superTbls[j].timeStampStep); + fprintf(fp, " startTimestamp: %s\n", g_Dbs.db[i].superTbls[j].startTimestamp); fprintf(fp, " sampleFormat: %s\n", g_Dbs.db[i].superTbls[j].sampleFormat); - fprintf(fp, " sampleFile: %s\n", g_Dbs.db[i].superTbls[j].sampleFile); - fprintf(fp, " tagsFile: %s\n", g_Dbs.db[i].superTbls[j].tagsFile); - + fprintf(fp, " sampleFile: %s\n", g_Dbs.db[i].superTbls[j].sampleFile); + fprintf(fp, " tagsFile: %s\n", g_Dbs.db[i].superTbls[j].tagsFile); + fprintf(fp, " columnCount: %d\n ", g_Dbs.db[i].superTbls[j].columnCount); for (int k = 0; k < g_Dbs.db[i].superTbls[j].columnCount; k++) { //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen); @@ -1423,38 +1459,41 @@ static void printfQueryMeta() { printf("\n"); printf("specified table query info: \n"); - printf("query interval: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.rate); - printf("query times: \033[33m%d\033[0m\n", g_args.query_times); - printf("concurrent: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.concurrent); - printf("sqlCount: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.sqlCount); + printf("query interval: \033[33m%d\033[0m\n", g_queryInfo.specifiedQueryInfo.rate); + printf("top query times:\033[33m%d\033[0m\n", g_args.query_times); + printf("concurrent: \033[33m%d\033[0m\n", g_queryInfo.specifiedQueryInfo.concurrent); + printf("sqlCount: \033[33m%d\033[0m\n", g_queryInfo.specifiedQueryInfo.sqlCount); + printf("specified tbl query times:\n"); + printf(" \033[33m%d\033[0m\n", g_queryInfo.specifiedQueryInfo.queryTimes); if (SUBSCRIBE_TEST == g_args.test_mode) { - printf("mod: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeMode); - printf("interval: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeInterval); - printf("restart: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeRestart); - printf("keepProgress: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeKeepProgress); + printf("mod: \033[33m%d\033[0m\n", g_queryInfo.specifiedQueryInfo.subscribeMode); + printf("interval: \033[33m%d\033[0m\n", g_queryInfo.specifiedQueryInfo.subscribeInterval); + printf("restart: \033[33m%d\033[0m\n", g_queryInfo.specifiedQueryInfo.subscribeRestart); + printf("keepProgress: \033[33m%d\033[0m\n", g_queryInfo.specifiedQueryInfo.subscribeKeepProgress); } - for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { - printf(" sql[%d]: \033[33m%s\033[0m\n", i, g_queryInfo.superQueryInfo.sql[i]); + for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) { + printf(" sql[%d]: \033[33m%s\033[0m\n", i, g_queryInfo.specifiedQueryInfo.sql[i]); } printf("\n"); printf("super table query info: \n"); - printf("query interval: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.rate); - printf("threadCnt: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.threadCnt); - printf("childTblCount: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.childTblCount); - printf("stable name: \033[33m%s\033[0m\n", g_queryInfo.subQueryInfo.sTblName); + printf("query interval: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.rate); + printf("threadCnt: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.threadCnt); + printf("childTblCount: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.childTblCount); + printf("stable name: \033[33m%s\033[0m\n", g_queryInfo.superQueryInfo.sTblName); + printf("stb query times:\033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.queryTimes); if (SUBSCRIBE_TEST == g_args.test_mode) { - printf("mod: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeMode); - printf("interval: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeInterval); - printf("restart: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeRestart); - printf("keepProgress: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeKeepProgress); + printf("mod: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeMode); + printf("interval: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeInterval); + printf("restart: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeRestart); + printf("keepProgress: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeKeepProgress); } - printf("sqlCount: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.sqlCount); - for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) { - printf(" sql[%d]: \033[33m%s\033[0m\n", i, g_queryInfo.subQueryInfo.sql[i]); + printf("sqlCount: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.sqlCount); + for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { + printf(" sql[%d]: \033[33m%s\033[0m\n", i, g_queryInfo.superQueryInfo.sql[i]); } printf("\n"); @@ -1562,7 +1601,7 @@ static int xDumpResultToFile(const char* fname, TAOS_RES* tres) { fprintf(fp, "%s", fields[col].name); } fputc('\n', fp); - + int numOfRows = 0; do { int32_t* length = taos_fetch_lengths(tres); @@ -1583,14 +1622,14 @@ static int xDumpResultToFile(const char* fname, TAOS_RES* tres) { return numOfRows; } -static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) { - TAOS_RES * res; +static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) { + TAOS_RES * res; TAOS_ROW row = NULL; int count = 0; - - res = taos_query(taos, "show databases;"); + + res = taos_query(taos, "show databases;"); int32_t code = taos_errno(res); - + if (code != 0) { errorPrint( "failed to run , reason: %s\n", taos_errstr(res)); return -1; @@ -1600,7 +1639,10 @@ static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) { while ((row = taos_fetch_row(res)) != NULL) { // sys database name : 'log' - if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log", fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) continue; + if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log", + fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) { + continue; + } dbInfos[count] = (SDbInfo *)calloc(1, sizeof(SDbInfo)); if (dbInfos[count] == NULL) { @@ -1614,13 +1656,13 @@ static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) { *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX], TSDB_TIME_PRECISION_MILLI); dbInfos[count]->ntables = *((int32_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]); - dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]); + dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]); dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]); dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]); - dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]); + dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]); tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX], - fields[TSDB_SHOW_DB_KEEP_INDEX].bytes); + fields[TSDB_SHOW_DB_KEEP_INDEX].bytes); dbInfos[count]->cache = *((int32_t *)row[TSDB_SHOW_DB_CACHE_INDEX]); dbInfos[count]->blocks = *((int32_t *)row[TSDB_SHOW_DB_BLOCKS_INDEX]); dbInfos[count]->minrows = *((int32_t *)row[TSDB_SHOW_DB_MINROWS_INDEX]); @@ -1630,16 +1672,16 @@ static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) { dbInfos[count]->comp = (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_COMP_INDEX])); dbInfos[count]->cachelast = (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX])); - tstrncpy(dbInfos[count]->precision, + tstrncpy(dbInfos[count]->precision, (char *)row[TSDB_SHOW_DB_PRECISION_INDEX], - fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes); + fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes); dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]); tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX], - fields[TSDB_SHOW_DB_STATUS_INDEX].bytes); + fields[TSDB_SHOW_DB_STATUS_INDEX].bytes); count++; if (count > MAX_DATABASE_COUNT) { - errorPrint( "The database count overflow than %d\n", MAX_DATABASE_COUNT); + errorPrint( "The database count overflow than %d\n", MAX_DATABASE_COUNT); break; } } @@ -1647,7 +1689,8 @@ static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) { return count; } -static void printfDbInfoForQueryToFile(char* filename, SDbInfo* dbInfos, int index) { +static void printfDbInfoForQueryToFile( + char* filename, SDbInfo* dbInfos, int index) { if (filename[0] == 0) return; @@ -1661,11 +1704,11 @@ static void printfDbInfoForQueryToFile(char* filename, SDbInfo* dbInfos, int ind fprintf(fp, "name: %s\n", dbInfos->name); fprintf(fp, "created_time: %s\n", dbInfos->create_time); fprintf(fp, "ntables: %d\n", dbInfos->ntables); - fprintf(fp, "vgroups: %d\n", dbInfos->vgroups); + fprintf(fp, "vgroups: %d\n", dbInfos->vgroups); fprintf(fp, "replica: %d\n", dbInfos->replica); fprintf(fp, "quorum: %d\n", dbInfos->quorum); - fprintf(fp, "days: %d\n", dbInfos->days); - fprintf(fp, "keep0,keep1,keep(D): %s\n", dbInfos->keeplist); + fprintf(fp, "days: %d\n", dbInfos->days); + fprintf(fp, "keep0,keep1,keep(D): %s\n", dbInfos->keeplist); fprintf(fp, "cache(MB): %d\n", dbInfos->cache); fprintf(fp, "blocks: %d\n", dbInfos->blocks); fprintf(fp, "minrows: %d\n", dbInfos->minrows); @@ -1673,10 +1716,10 @@ static void printfDbInfoForQueryToFile(char* filename, SDbInfo* dbInfos, int ind fprintf(fp, "wallevel: %d\n", dbInfos->wallevel); fprintf(fp, "fsync: %d\n", dbInfos->fsync); fprintf(fp, "comp: %d\n", dbInfos->comp); - fprintf(fp, "cachelast: %d\n", dbInfos->cachelast); - fprintf(fp, "precision: %s\n", dbInfos->precision); + fprintf(fp, "cachelast: %d\n", dbInfos->cachelast); + fprintf(fp, "precision: %s\n", dbInfos->precision); fprintf(fp, "update: %d\n", dbInfos->update); - fprintf(fp, "status: %s\n", dbInfos->status); + fprintf(fp, "status: %s\n", dbInfos->status); fprintf(fp, "\n"); fclose(fp); @@ -1719,14 +1762,14 @@ static void printfQuerySystemInfo(TAOS * taos) { } for (int i = 0; i < dbCount; i++) { - // printf database info + // printf database info printfDbInfoForQueryToFile(filename, dbInfos[i], i); // show db.vgroups snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.vgroups;", dbInfos[i]->name); res = taos_query(taos, buffer); xDumpResultToFile(filename, res); - + // show db.stables snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.stables;", dbInfos[i]->name); res = taos_query(taos, buffer); @@ -1736,7 +1779,6 @@ static void printfQuerySystemInfo(TAOS * taos) { } free(dbInfos); - } static int postProceSql(char* host, uint16_t port, char* sqlstr) @@ -1840,7 +1882,8 @@ static int postProceSql(char* host, uint16_t port, char* sqlstr) for (int l = 0; l < mod_table[userpass_buf_len % 3]; l++) base64_buf[encoded_len - 1 - l] = '='; - debugPrint("%s() LN%d: auth string base64 encoded: %s\n", __func__, __LINE__, base64_buf); + debugPrint("%s() LN%d: auth string base64 encoded: %s\n", + __func__, __LINE__, base64_buf); char *auth = base64_buf; int r = snprintf(request_buf, @@ -1919,7 +1962,7 @@ static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) { return dataBuf; } -static char* generateTagVaulesForStb(SSuperTable* stbInfo) { +static char* generateTagVaulesForStb(SSuperTable* stbInfo, int32_t tableSeq) { char* dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1); if (NULL == dataBuf) { printf("calloc failed! size:%d\n", TSDB_MAX_SQL_LEN+1); @@ -1938,20 +1981,27 @@ static char* generateTagVaulesForStb(SSuperTable* stbInfo) { return NULL; } - char* buf = (char*)calloc(stbInfo->tags[i].dataLen+1, 1); + int tagBufLen = stbInfo->tags[i].dataLen + 1; + char* buf = (char*)calloc(tagBufLen, 1); if (NULL == buf) { printf("calloc failed! size:%d\n", stbInfo->tags[i].dataLen); tmfree(dataBuf); return NULL; } - rand_string(buf, stbInfo->tags[i].dataLen); + + if (tableSeq % 2) { + tstrncpy(buf, "beijing", tagBufLen); + } else { + tstrncpy(buf, "shanghai", tagBufLen); + } + //rand_string(buf, stbInfo->tags[i].dataLen); dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "\'%s\', ", buf); tmfree(buf); } else if (0 == strncasecmp(stbInfo->tags[i].dataType, "int", strlen("int"))) { dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, - "%d, ", rand_int()); + "%d, ", tableSeq); } else if (0 == strncasecmp(stbInfo->tags[i].dataType, "bigint", strlen("bigint"))) { dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, @@ -1988,17 +2038,17 @@ static char* generateTagVaulesForStb(SSuperTable* stbInfo) { } dataLen -= 2; - dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")"); + dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")"); return dataBuf; } -static int calcRowLen(SSuperTable* superTbls) { +static int calcRowLen(SSuperTable* superTbls) { int colIndex; int lenOfOneRow = 0; - + for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) { char* dataType = superTbls->columns[colIndex].dataType; - + if (strcasecmp(dataType, "BINARY") == 0) { lenOfOneRow += superTbls->columns[colIndex].dataLen + 3; } else if (strcasecmp(dataType, "NCHAR") == 0) { @@ -2015,9 +2065,9 @@ static int calcRowLen(SSuperTable* superTbls) { lenOfOneRow += 6; } else if (strcasecmp(dataType, "FLOAT") == 0) { lenOfOneRow += 22; - } else if (strcasecmp(dataType, "DOUBLE") == 0) { + } else if (strcasecmp(dataType, "DOUBLE") == 0) { lenOfOneRow += 42; - } else if (strcasecmp(dataType, "TIMESTAMP") == 0) { + } else if (strcasecmp(dataType, "TIMESTAMP") == 0) { lenOfOneRow += 21; } else { printf("get error data type : %s\n", dataType); @@ -2048,7 +2098,7 @@ static int calcRowLen(SSuperTable* superTbls) { lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 6; } else if (strcasecmp(dataType, "FLOAT") == 0) { lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 22; - } else if (strcasecmp(dataType, "DOUBLE") == 0) { + } else if (strcasecmp(dataType, "DOUBLE") == 0) { lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42; } else { printf("get error tag type : %s\n", dataType); @@ -2057,7 +2107,7 @@ static int calcRowLen(SSuperTable* superTbls) { } superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow; - + return 0; } @@ -2069,7 +2119,7 @@ static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos, char command[BUFFER_SIZE] = "\0"; char limitBuf[100] = "\0"; - TAOS_RES * res; + TAOS_RES * res; TAOS_ROW row = NULL; char* childTblName = *childTblNameOfSuperTbl; @@ -2078,10 +2128,11 @@ static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos, snprintf(limitBuf, 100, " limit %d offset %d", limit, offset); } - //get all child table name use cmd: select tbname from superTblName; - snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s", dbName, sTblName, limitBuf); + //get all child table name use cmd: select tbname from superTblName; + snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s", + dbName, sTblName, limitBuf); - res = taos_query(taos, command); + res = taos_query(taos, command); int32_t code = taos_errno(res); if (code != 0) { taos_free_result(res); @@ -2150,7 +2201,7 @@ static int getSuperTableFromServer(TAOS * taos, char* dbName, SSuperTable* superTbls) { char command[BUFFER_SIZE] = "\0"; - TAOS_RES * res; + TAOS_RES * res; TAOS_ROW row = NULL; int count = 0; @@ -2211,7 +2262,7 @@ static int getSuperTableFromServer(TAOS * taos, char* dbName, /* if (TBL_ALREADY_EXISTS == superTbls->childTblExists) { - //get all child table name use cmd: select tbname from superTblName; + //get all child table name use cmd: select tbname from superTblName; int childTblCount = 10000; superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN); if (superTbls->childTblName == NULL) { @@ -2227,7 +2278,8 @@ static int getSuperTableFromServer(TAOS * taos, char* dbName, return 0; } -static int createSuperTable(TAOS * taos, char* dbName, SSuperTable* superTbls, bool use_metric) { +static int createSuperTable(TAOS * taos, char* dbName, + SSuperTable* superTbls, bool use_metric) { char command[BUFFER_SIZE] = "\0"; char cols[STRING_LEN] = "\0"; @@ -2237,7 +2289,7 @@ static int createSuperTable(TAOS * taos, char* dbName, SSuperTable* superTbls, int lenOfOneRow = 0; for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) { char* dataType = superTbls->columns[colIndex].dataType; - + if (strcasecmp(dataType, "BINARY") == 0) { len += snprintf(cols + len, STRING_LEN - len, ", col%d %s(%d)", colIndex, "BINARY", @@ -2334,7 +2386,7 @@ static int createSuperTable(TAOS * taos, char* dbName, SSuperTable* superTbls, len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex, "FLOAT"); lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 22; - } else if (strcasecmp(dataType, "DOUBLE") == 0) { + } else if (strcasecmp(dataType, "DOUBLE") == 0) { len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex, "DOUBLE"); lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42; @@ -2471,7 +2523,7 @@ static int createDatabases() { if ((ret != 0) || (g_Dbs.db[i].drop)) { ret = createSuperTable(taos, g_Dbs.db[i].dbName, &g_Dbs.db[i].superTbls[j], g_Dbs.use_metric); - + if (0 != ret) { errorPrint("\ncreate super table %d failed!\n\n", j); taos_close(taos); @@ -2528,39 +2580,46 @@ static void* createTable(void *sarg) g_args.tb_prefix, i, winfo->cols); } else { - if (0 == len) { - batchNum = 0; - memset(buffer, 0, buff_len); - len += snprintf(buffer + len, - buff_len - len, "create table "); - } - - char* tagsValBuf = NULL; - if (0 == superTblInfo->tagSource) { - tagsValBuf = generateTagVaulesForStb(superTblInfo); - } else { - tagsValBuf = getTagValueFromTagSample( - superTblInfo, - i % superTblInfo->tagSampleCount); - } - if (NULL == tagsValBuf) { + if (superTblInfo == NULL) { + errorPrint("%s() LN%d, use metric, but super table info is NULL\n", + __func__, __LINE__); free(buffer); - return NULL; - } + exit(-1); + } else { + if (0 == len) { + batchNum = 0; + memset(buffer, 0, buff_len); + len += snprintf(buffer + len, + buff_len - len, "create table "); + } - len += snprintf(buffer + len, - superTblInfo->maxSqlLen - len, - "if not exists %s.%s%d using %s.%s tags %s ", - winfo->db_name, superTblInfo->childTblPrefix, - i, winfo->db_name, - superTblInfo->sTblName, tagsValBuf); - free(tagsValBuf); - batchNum++; - - if ((batchNum < superTblInfo->batchCreateTableNum) - && ((superTblInfo->maxSqlLen - len) - >= (superTblInfo->lenOfTagOfOneRow + 256))) { - continue; + char* tagsValBuf = NULL; + if (0 == superTblInfo->tagSource) { + tagsValBuf = generateTagVaulesForStb(superTblInfo, i); + } else { + tagsValBuf = getTagValueFromTagSample( + superTblInfo, + i % superTblInfo->tagSampleCount); + } + if (NULL == tagsValBuf) { + free(buffer); + return NULL; + } + + len += snprintf(buffer + len, + superTblInfo->maxSqlLen - len, + "if not exists %s.%s%d using %s.%s tags %s ", + winfo->db_name, superTblInfo->childTblPrefix, + i, winfo->db_name, + superTblInfo->sTblName, tagsValBuf); + free(tagsValBuf); + batchNum++; + + if ((batchNum < superTblInfo->batchCreateTableNum) + && ((superTblInfo->maxSqlLen - len) + >= (superTblInfo->lenOfTagOfOneRow + 256))) { + continue; + } } } @@ -2579,7 +2638,7 @@ static void* createTable(void *sarg) lastPrintTime = currentPrintTime; } } - + if (0 != len) { verbosePrint("%s() %d buffer: %s\n", __func__, __LINE__, buffer); if (0 != queryDbExec(winfo->taos, buffer, NO_INSERT_TYPE, false)) { @@ -2615,7 +2674,7 @@ static int startMultiThreadCreateChildTable( int b = 0; b = ntables % threads; - + for (int i = 0; i < threads; i++) { threadInfo *t_info = infos + i; t_info->threadID = i; @@ -2644,7 +2703,7 @@ static int startMultiThreadCreateChildTable( t_info->minDelay = INT16_MAX; pthread_create(pids + i, NULL, createTable, t_info); } - + for (int i = 0; i < threads; i++) { pthread_join(pids[i], NULL); } @@ -2695,10 +2754,10 @@ static void createChildTables() { if ((strncasecmp(g_args.datatype[j], "BINARY", strlen("BINARY")) == 0) || (strncasecmp(g_args.datatype[j], "NCHAR", strlen("NCHAR")) == 0)) { - len = snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, + snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ", COL%d %s(60)", j, g_args.datatype[j]); } else { - len = snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, + snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ", COL%d %s", j, g_args.datatype[j]); } len = strlen(tblColsBuf); @@ -2803,7 +2862,7 @@ static int readSampleFromCsvFileToMem( ssize_t readLen = 0; char * line = NULL; int getRows = 0; - + FILE* fp = fopen(superTblInfo->sampleFile, "r"); if (fp == NULL) { errorPrint( "Failed to open sample file: %s, reason:%s\n", @@ -2825,7 +2884,7 @@ static int readSampleFromCsvFileToMem( } continue; } - + if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) { line[--readLen] = 0; } @@ -2861,7 +2920,7 @@ static bool getColumnAndTagTypeFromInsertJsonFile( cJSON* stbInfo, SSuperTable* superTbls) { bool ret = false; - // columns + // columns cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns"); if (columns && columns->type != cJSON_Array) { printf("ERROR: failed to read json, columns not found\n"); @@ -2871,7 +2930,7 @@ static bool getColumnAndTagTypeFromInsertJsonFile( superTbls->tagCount = 0; return true; } - + int columnSize = cJSON_GetArraySize(columns); if (columnSize > MAX_COLUMN_COUNT) { errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n", @@ -2899,7 +2958,7 @@ static bool getColumnAndTagTypeFromInsertJsonFile( count = 1; } - // column info + // column info memset(&columnCase, 0, sizeof(StrColumn)); cJSON *dataType = cJSON_GetObjectItem(column, "type"); if (!dataType || dataType->type != cJSON_String || dataType->valuestring == NULL) { @@ -2927,16 +2986,16 @@ static bool getColumnAndTagTypeFromInsertJsonFile( } } superTbls->columnCount = index; - + count = 1; index = 0; - // tags + // tags cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags"); if (!tags || tags->type != cJSON_Array) { debugPrint("%s() LN%d, failed to read json, tags not found\n", __func__, __LINE__); goto PARSE_OVER; } - + int tagSize = cJSON_GetArraySize(tags); if (tagSize > MAX_TAG_COUNT) { debugPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n", __func__, __LINE__, MAX_TAG_COUNT); @@ -2959,7 +3018,7 @@ static bool getColumnAndTagTypeFromInsertJsonFile( count = 1; } - // column info + // column info memset(&columnCase, 0, sizeof(StrColumn)); cJSON *dataType = cJSON_GetObjectItem(tag, "type"); if (!dataType || dataType->type != cJSON_String || dataType->valuestring == NULL) { @@ -3005,9 +3064,9 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { cJSON* host = cJSON_GetObjectItem(root, "host"); if (host && host->type == cJSON_String && host->valuestring != NULL) { - tstrncpy(g_Dbs.host, host->valuestring, MAX_DB_NAME_SIZE); + tstrncpy(g_Dbs.host, host->valuestring, MAX_HOSTNAME_SIZE); } else if (!host) { - tstrncpy(g_Dbs.host, "127.0.0.1", MAX_DB_NAME_SIZE); + tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE); } else { printf("ERROR: failed to read json, host not found\n"); goto PARSE_OVER; @@ -3022,16 +3081,16 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { cJSON* user = cJSON_GetObjectItem(root, "user"); if (user && user->type == cJSON_String && user->valuestring != NULL) { - tstrncpy(g_Dbs.user, user->valuestring, MAX_DB_NAME_SIZE); + tstrncpy(g_Dbs.user, user->valuestring, MAX_USERNAME_SIZE); } else if (!user) { - tstrncpy(g_Dbs.user, "root", MAX_DB_NAME_SIZE); + tstrncpy(g_Dbs.user, "root", MAX_USERNAME_SIZE); } cJSON* password = cJSON_GetObjectItem(root, "password"); if (password && password->type == cJSON_String && password->valuestring != NULL) { - tstrncpy(g_Dbs.password, password->valuestring, MAX_DB_NAME_SIZE); + tstrncpy(g_Dbs.password, password->valuestring, MAX_PASSWORD_SIZE); } else if (!password) { - tstrncpy(g_Dbs.password, "taosdata", MAX_DB_NAME_SIZE); + tstrncpy(g_Dbs.password, "taosdata", MAX_PASSWORD_SIZE); } cJSON* resultfile = cJSON_GetObjectItem(root, "result_file"); @@ -3049,8 +3108,8 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else { printf("ERROR: failed to read json, threads not found\n"); goto PARSE_OVER; - } - + } + cJSON* threads2 = cJSON_GetObjectItem(root, "thread_count_create_tbl"); if (threads2 && threads2->type == cJSON_Number) { g_Dbs.threadCountByCreateTbl = threads2->valueint; @@ -3060,7 +3119,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { errorPrint("%s() LN%d, failed to read json, threads2 not found\n", __func__, __LINE__); goto PARSE_OVER; - } + } cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval"); if (gInsertInterval && gInsertInterval->type == cJSON_Number) { @@ -3072,25 +3131,26 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { goto PARSE_OVER; } - cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times"); - if (gQueryTimes && gQueryTimes->type == cJSON_Number) { - g_args.query_times = gQueryTimes->valueint; - } else if (!gQueryTimes) { - g_args.query_times = 1; - } else { - errorPrint("%s() LN%d, failed to read json, query_times input mistake\n", __func__, __LINE__); - goto PARSE_OVER; - } - cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows"); if (interlaceRows && interlaceRows->type == cJSON_Number) { g_args.interlace_rows = interlaceRows->valueint; + + // rows per table need be less than insert batch + if (g_args.interlace_rows > g_args.num_of_RPR) { + printf("NOTICE: interlace rows value %d > num_of_records_per_request %d\n\n", + g_args.interlace_rows, g_args.num_of_RPR); + printf(" interlace rows value will be set to num_of_records_per_request %d\n\n", + g_args.num_of_RPR); + printf(" press Enter key to continue or Ctrl-C to stop."); + (void)getchar(); + g_args.interlace_rows = g_args.num_of_RPR; + } } else if (!interlaceRows) { g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req } else { errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n", __func__, __LINE__); goto PARSE_OVER; - } + } cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len"); if (maxSqlLen && maxSqlLen->type == cJSON_Number) { @@ -3101,20 +3161,19 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n", __func__, __LINE__); goto PARSE_OVER; } - cJSON* numRecPerReq = cJSON_GetObjectItem(root, "num_of_records_per_req"); if (numRecPerReq && numRecPerReq->type == cJSON_Number) { g_args.num_of_RPR = numRecPerReq->valueint; } else if (!numRecPerReq) { - g_args.num_of_RPR = 100; + g_args.num_of_RPR = 0xffff; } else { errorPrint("%s() LN%d, failed to read json, num_of_records_per_req not found\n", __func__, __LINE__); goto PARSE_OVER; } cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no, - if (answerPrompt + if (answerPrompt && answerPrompt->type == cJSON_String && answerPrompt->valuestring != NULL) { if (0 == strncasecmp(answerPrompt->valuestring, "yes", 3)) { @@ -3129,7 +3188,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else { printf("ERROR: failed to read json, confirm_parameter_prompt not found\n"); goto PARSE_OVER; - } + } cJSON* dbs = cJSON_GetObjectItem(root, "databases"); if (!dbs || dbs->type != cJSON_Array) { @@ -3150,13 +3209,13 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { cJSON* dbinfos = cJSON_GetArrayItem(dbs, i); if (dbinfos == NULL) continue; - // dbinfo + // dbinfo cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo"); if (!dbinfo || dbinfo->type != cJSON_Object) { printf("ERROR: failed to read json, dbinfo not found\n"); goto PARSE_OVER; } - + cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name"); if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) { printf("ERROR: failed to read json, db name not found\n"); @@ -3170,7 +3229,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { g_Dbs.db[i].drop = true; } else { g_Dbs.db[i].drop = false; - } + } } else if (!drop) { g_Dbs.db[i].drop = g_args.drop_database; } else { @@ -3221,7 +3280,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { printf("ERROR: failed to read json, keep not found\n"); goto PARSE_OVER; } - + cJSON* days = cJSON_GetObjectItem(dbinfo, "days"); if (days && days->type == cJSON_Number) { g_Dbs.db[i].dbCfg.days = days->valueint; @@ -3231,7 +3290,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { printf("ERROR: failed to read json, days not found\n"); goto PARSE_OVER; } - + cJSON* cache = cJSON_GetObjectItem(dbinfo, "cache"); if (cache && cache->type == cJSON_Number) { g_Dbs.db[i].dbCfg.cache = cache->valueint; @@ -3241,7 +3300,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { printf("ERROR: failed to read json, cache not found\n"); goto PARSE_OVER; } - + cJSON* blocks= cJSON_GetObjectItem(dbinfo, "blocks"); if (blocks && blocks->type == cJSON_Number) { g_Dbs.db[i].dbCfg.blocks = blocks->valueint; @@ -3328,22 +3387,24 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!fsync) { g_Dbs.db[i].dbCfg.fsync = -1; } else { - printf("ERROR: failed to read json, fsync not found\n"); - goto PARSE_OVER; - } + errorPrint("%s() LN%d, failed to read json, fsync input mistake\n", + __func__, __LINE__); + goto PARSE_OVER; + } - // super_talbes + // super_talbes cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables"); if (!stables || stables->type != cJSON_Array) { - printf("ERROR: failed to read json, super_tables not found\n"); + errorPrint("%s() LN%d, failed to read json, super_tables not found\n", + __func__, __LINE__); goto PARSE_OVER; - } - + } + int stbSize = cJSON_GetArraySize(stables); if (stbSize > MAX_SUPER_TABLE_COUNT) { errorPrint( - "ERROR: failed to read json, databases size overflow, max database is %d\n", - MAX_SUPER_TABLE_COUNT); + "%s() LN%d, failed to read json, supertable size overflow, max supertable is %d\n", + __func__, __LINE__, MAX_SUPER_TABLE_COUNT); goto PARSE_OVER; } @@ -3351,15 +3412,16 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { for (int j = 0; j < stbSize; ++j) { cJSON* stbInfo = cJSON_GetArrayItem(stables, j); if (stbInfo == NULL) continue; - - // dbinfo + + // dbinfo cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name"); if (!stbName || stbName->type != cJSON_String || stbName->valuestring == NULL) { - printf("ERROR: failed to read json, stb name not found\n"); + errorPrint("%s() LN%d, failed to read json, stb name not found\n", + __func__, __LINE__); goto PARSE_OVER; } tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, MAX_TB_NAME_SIZE); - + cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix"); if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) { printf("ERROR: failed to read json, childtable_prefix not found\n"); @@ -3384,7 +3446,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { printf("ERROR: failed to read json, auto_create_table not found\n"); goto PARSE_OVER; } - + cJSON* batchCreateTbl = cJSON_GetObjectItem(stbInfo, "batch_create_tbl_num"); if (batchCreateTbl && batchCreateTbl->type == cJSON_Number) { g_Dbs.db[i].superTbls[j].batchCreateTableNum = batchCreateTbl->valueint; @@ -3393,7 +3455,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else { printf("ERROR: failed to read json, batch_create_tbl_num not found\n"); goto PARSE_OVER; - } + } cJSON *childTblExists = cJSON_GetObjectItem(stbInfo, "child_table_exists"); // yes, no if (childTblExists @@ -3409,13 +3471,15 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!childTblExists) { g_Dbs.db[i].superTbls[j].childTblExists = TBL_NO_EXISTS; } else { - errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n", __func__, __LINE__); + errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n", + __func__, __LINE__); goto PARSE_OVER; } - + cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count"); if (!count || count->type != cJSON_Number || 0 >= count->valueint) { - errorPrint("%s() LN%d, failed to read json, childtable_count not found\n", __func__, __LINE__); + errorPrint("%s() LN%d, failed to read json, childtable_count not found\n", + __func__, __LINE__); goto PARSE_OVER; } g_Dbs.db[i].superTbls[j].childTblCount = count->valueint; @@ -3499,10 +3563,11 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else { printf("ERROR: failed to read json, sample_buf_size not found\n"); goto PARSE_OVER; - } + } cJSON *sampleFormat = cJSON_GetObjectItem(stbInfo, "sample_format"); - if (sampleFormat && sampleFormat->type == cJSON_String && sampleFormat->valuestring != NULL) { + if (sampleFormat && sampleFormat->type + == cJSON_String && sampleFormat->valuestring != NULL) { tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat, sampleFormat->valuestring, MAX_DB_NAME_SIZE); } else if (!sampleFormat) { @@ -3510,7 +3575,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else { printf("ERROR: failed to read json, sample_format not found\n"); goto PARSE_OVER; - } + } cJSON *sampleFile = cJSON_GetObjectItem(stbInfo, "sample_file"); if (sampleFile && sampleFile->type == cJSON_String && sampleFile->valuestring != NULL) { @@ -3521,7 +3586,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else { printf("ERROR: failed to read json, sample_file not found\n"); goto PARSE_OVER; - } + } cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file"); if (tagsFile && tagsFile->type == cJSON_String && tagsFile->valuestring != NULL) { @@ -3547,14 +3612,14 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { len = TSDB_MAX_ALLOWED_SQL_LEN; } else if (len < TSDB_MAX_SQL_LEN) { len = TSDB_MAX_SQL_LEN; - } + } g_Dbs.db[i].superTbls[j].maxSqlLen = len; } else if (!maxSqlLen) { - g_Dbs.db[i].superTbls[j].maxSqlLen = TSDB_MAX_SQL_LEN; + g_Dbs.db[i].superTbls[j].maxSqlLen = g_args.max_sql_len; } else { printf("ERROR: failed to read json, maxSqlLen not found\n"); goto PARSE_OVER; - } + } cJSON *multiThreadWriteOneTbl = cJSON_GetObjectItem(stbInfo, "multi_thread_write_one_tbl"); // no , yes @@ -3565,7 +3630,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 1; } else { g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0; - } + } } else if (!multiThreadWriteOneTbl) { g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0; } else { @@ -3576,6 +3641,16 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { cJSON* interlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows"); if (interlaceRows && interlaceRows->type == cJSON_Number) { g_Dbs.db[i].superTbls[j].interlaceRows = interlaceRows->valueint; + // rows per table need be less than insert batch + if (g_Dbs.db[i].superTbls[j].interlaceRows > g_args.num_of_RPR) { + printf("NOTICE: db[%d].superTbl[%d]'s interlace rows value %d > num_of_records_per_request %d\n\n", + i, j, g_Dbs.db[i].superTbls[j].interlaceRows, g_args.num_of_RPR); + printf(" interlace rows value will be set to num_of_records_per_request %d\n\n", + g_args.num_of_RPR); + printf(" press Enter key to continue or Ctrl-C to stop."); + (void)getchar(); + g_Dbs.db[i].superTbls[j].interlaceRows = g_args.num_of_RPR; + } } else if (!interlaceRows) { g_Dbs.db[i].superTbls[j].interlaceRows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req } else { @@ -3583,7 +3658,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { "%s() LN%d, failed to read json, interlace rows input mistake\n", __func__, __LINE__); goto PARSE_OVER; - } + } cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio"); if (disorderRatio && disorderRatio->type == cJSON_Number) { @@ -3593,7 +3668,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else { printf("ERROR: failed to read json, disorderRatio not found\n"); goto PARSE_OVER; - } + } cJSON* disorderRange = cJSON_GetObjectItem(stbInfo, "disorder_range"); if (disorderRange && disorderRange->type == cJSON_Number) { @@ -3620,7 +3695,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { if (insertInterval && insertInterval->type == cJSON_Number) { g_Dbs.db[i].superTbls[j].insertInterval = insertInterval->valueint; } else if (!insertInterval) { - debugPrint("%s() LN%d: stable insert interval be overrided by global %d.\n", + verbosePrint("%s() LN%d: stable insert interval be overrided by global %d.\n", __func__, __LINE__, g_args.insert_interval); g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval; } else { @@ -3633,8 +3708,8 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { stbInfo, &g_Dbs.db[i].superTbls[j]); if (false == retVal) { goto PARSE_OVER; - } - } + } + } } ret = true; @@ -3656,9 +3731,9 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { cJSON* host = cJSON_GetObjectItem(root, "host"); if (host && host->type == cJSON_String && host->valuestring != NULL) { - tstrncpy(g_queryInfo.host, host->valuestring, MAX_DB_NAME_SIZE); + tstrncpy(g_queryInfo.host, host->valuestring, MAX_HOSTNAME_SIZE); } else if (!host) { - tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_DB_NAME_SIZE); + tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE); } else { printf("ERROR: failed to read json, host not found\n"); goto PARSE_OVER; @@ -3673,16 +3748,16 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { cJSON* user = cJSON_GetObjectItem(root, "user"); if (user && user->type == cJSON_String && user->valuestring != NULL) { - tstrncpy(g_queryInfo.user, user->valuestring, MAX_DB_NAME_SIZE); + tstrncpy(g_queryInfo.user, user->valuestring, MAX_USERNAME_SIZE); } else if (!user) { - tstrncpy(g_queryInfo.user, "root", MAX_DB_NAME_SIZE); ; + tstrncpy(g_queryInfo.user, "root", MAX_USERNAME_SIZE); ; } cJSON* password = cJSON_GetObjectItem(root, "password"); if (password && password->type == cJSON_String && password->valuestring != NULL) { - tstrncpy(g_queryInfo.password, password->valuestring, MAX_DB_NAME_SIZE); + tstrncpy(g_queryInfo.password, password->valuestring, MAX_PASSWORD_SIZE); } else if (!password) { - tstrncpy(g_queryInfo.password, "taosdata", MAX_DB_NAME_SIZE);; + tstrncpy(g_queryInfo.password, "taosdata", MAX_PASSWORD_SIZE);; } cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no, @@ -3700,7 +3775,17 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { } else { printf("ERROR: failed to read json, confirm_parameter_prompt not found\n"); goto PARSE_OVER; - } + } + + cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times"); + if (gQueryTimes && gQueryTimes->type == cJSON_Number) { + g_args.query_times = gQueryTimes->valueint; + } else if (!gQueryTimes) { + g_args.query_times = 1; + } else { + errorPrint("%s() LN%d, failed to read json, query_times input mistake\n", __func__, __LINE__); + goto PARSE_OVER; + } cJSON* dbs = cJSON_GetObjectItem(root, "databases"); if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) { @@ -3719,249 +3804,269 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { printf("ERROR: failed to read json, query_mode not found\n"); goto PARSE_OVER; } - - // super_table_query - cJSON *superQuery = cJSON_GetObjectItem(root, "specified_table_query"); - if (!superQuery) { - g_queryInfo.superQueryInfo.concurrent = 0; - g_queryInfo.superQueryInfo.sqlCount = 0; - } else if (superQuery->type != cJSON_Object) { + + // super_table_query + cJSON *specifiedQuery = cJSON_GetObjectItem(root, "specified_table_query"); + if (!specifiedQuery) { + g_queryInfo.specifiedQueryInfo.concurrent = 0; + g_queryInfo.specifiedQueryInfo.sqlCount = 0; + } else if (specifiedQuery->type != cJSON_Object) { printf("ERROR: failed to read json, super_table_query not found\n"); goto PARSE_OVER; - } else { - cJSON* rate = cJSON_GetObjectItem(superQuery, "query_interval"); + } else { + cJSON* rate = cJSON_GetObjectItem(specifiedQuery, "query_interval"); if (rate && rate->type == cJSON_Number) { - g_queryInfo.superQueryInfo.rate = rate->valueint; + g_queryInfo.specifiedQueryInfo.rate = rate->valueint; } else if (!rate) { - g_queryInfo.superQueryInfo.rate = 0; + g_queryInfo.specifiedQueryInfo.rate = 0; } - - cJSON* concurrent = cJSON_GetObjectItem(superQuery, "concurrent"); + + cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery, "query_times"); + if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) { + g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint; + } else if (!specifiedQueryTimes) { + g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times; + } else { + errorPrint("%s() LN%d, failed to read json, query_times input mistake\n", __func__, __LINE__); + goto PARSE_OVER; + } + + cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent"); if (concurrent && concurrent->type == cJSON_Number) { - g_queryInfo.superQueryInfo.concurrent = concurrent->valueint; + g_queryInfo.specifiedQueryInfo.concurrent = concurrent->valueint; } else if (!concurrent) { - g_queryInfo.superQueryInfo.concurrent = 1; + g_queryInfo.specifiedQueryInfo.concurrent = 1; } - - cJSON* mode = cJSON_GetObjectItem(superQuery, "mode"); + + cJSON* mode = cJSON_GetObjectItem(specifiedQuery, "mode"); if (mode && mode->type == cJSON_String && mode->valuestring != NULL) { - if (0 == strcmp("sync", mode->valuestring)) { - g_queryInfo.superQueryInfo.subscribeMode = 0; - } else if (0 == strcmp("async", mode->valuestring)) { - g_queryInfo.superQueryInfo.subscribeMode = 1; + if (0 == strcmp("sync", mode->valuestring)) { + g_queryInfo.specifiedQueryInfo.subscribeMode = 0; + } else if (0 == strcmp("async", mode->valuestring)) { + g_queryInfo.specifiedQueryInfo.subscribeMode = 1; } else { printf("ERROR: failed to read json, subscribe mod error\n"); goto PARSE_OVER; } } else { - g_queryInfo.superQueryInfo.subscribeMode = 0; + g_queryInfo.specifiedQueryInfo.subscribeMode = 0; } - - cJSON* interval = cJSON_GetObjectItem(superQuery, "interval"); + + cJSON* interval = cJSON_GetObjectItem(specifiedQuery, "interval"); if (interval && interval->type == cJSON_Number) { - g_queryInfo.superQueryInfo.subscribeInterval = interval->valueint; - } else if (!interval) { + g_queryInfo.specifiedQueryInfo.subscribeInterval = interval->valueint; + } else if (!interval) { //printf("failed to read json, subscribe interval no found\n"); //goto PARSE_OVER; - g_queryInfo.superQueryInfo.subscribeInterval = 10000; + g_queryInfo.specifiedQueryInfo.subscribeInterval = 10000; } - - cJSON* restart = cJSON_GetObjectItem(superQuery, "restart"); + + cJSON* restart = cJSON_GetObjectItem(specifiedQuery, "restart"); if (restart && restart->type == cJSON_String && restart->valuestring != NULL) { - if (0 == strcmp("yes", restart->valuestring)) { - g_queryInfo.superQueryInfo.subscribeRestart = 1; - } else if (0 == strcmp("no", restart->valuestring)) { - g_queryInfo.superQueryInfo.subscribeRestart = 0; + if (0 == strcmp("yes", restart->valuestring)) { + g_queryInfo.specifiedQueryInfo.subscribeRestart = 1; + } else if (0 == strcmp("no", restart->valuestring)) { + g_queryInfo.specifiedQueryInfo.subscribeRestart = 0; } else { printf("ERROR: failed to read json, subscribe restart error\n"); goto PARSE_OVER; } } else { - g_queryInfo.superQueryInfo.subscribeRestart = 1; + g_queryInfo.specifiedQueryInfo.subscribeRestart = 1; } - - cJSON* keepProgress = cJSON_GetObjectItem(superQuery, "keepProgress"); + + cJSON* keepProgress = cJSON_GetObjectItem(specifiedQuery, "keepProgress"); if (keepProgress && keepProgress->type == cJSON_String && keepProgress->valuestring != NULL) { - if (0 == strcmp("yes", keepProgress->valuestring)) { - g_queryInfo.superQueryInfo.subscribeKeepProgress = 1; - } else if (0 == strcmp("no", keepProgress->valuestring)) { - g_queryInfo.superQueryInfo.subscribeKeepProgress = 0; + if (0 == strcmp("yes", keepProgress->valuestring)) { + g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 1; + } else if (0 == strcmp("no", keepProgress->valuestring)) { + g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0; } else { printf("ERROR: failed to read json, subscribe keepProgress error\n"); goto PARSE_OVER; } } else { - g_queryInfo.superQueryInfo.subscribeKeepProgress = 0; + g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0; } - // sqls - cJSON* superSqls = cJSON_GetObjectItem(superQuery, "sqls"); + // sqls + cJSON* superSqls = cJSON_GetObjectItem(specifiedQuery, "sqls"); if (!superSqls) { - g_queryInfo.superQueryInfo.sqlCount = 0; + g_queryInfo.specifiedQueryInfo.sqlCount = 0; } else if (superSqls->type != cJSON_Array) { printf("ERROR: failed to read json, super sqls not found\n"); goto PARSE_OVER; - } else { + } else { int superSqlSize = cJSON_GetArraySize(superSqls); if (superSqlSize > MAX_QUERY_SQL_COUNT) { printf("ERROR: failed to read json, query sql size overflow, max is %d\n", MAX_QUERY_SQL_COUNT); goto PARSE_OVER; } - g_queryInfo.superQueryInfo.sqlCount = superSqlSize; + g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize; for (int j = 0; j < superSqlSize; ++j) { cJSON* sql = cJSON_GetArrayItem(superSqls, j); if (sql == NULL) continue; - + cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql"); if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) { printf("ERROR: failed to read json, sql not found\n"); goto PARSE_OVER; } - tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH); + tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH); cJSON *result = cJSON_GetObjectItem(sql, "result"); if (NULL != result && result->type == cJSON_String && result->valuestring != NULL) { - tstrncpy(g_queryInfo.superQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN); + tstrncpy(g_queryInfo.specifiedQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN); } else if (NULL == result) { - memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN); + memset(g_queryInfo.specifiedQueryInfo.result[j], 0, MAX_FILE_NAME_LEN); } else { printf("ERROR: failed to read json, super query result file not found\n"); goto PARSE_OVER; - } + } } } } - // sub_table_query - cJSON *subQuery = cJSON_GetObjectItem(root, "super_table_query"); - if (!subQuery) { - g_queryInfo.subQueryInfo.threadCnt = 0; - g_queryInfo.subQueryInfo.sqlCount = 0; - } else if (subQuery->type != cJSON_Object) { + // sub_table_query + cJSON *superQuery = cJSON_GetObjectItem(root, "super_table_query"); + if (!superQuery) { + g_queryInfo.superQueryInfo.threadCnt = 0; + g_queryInfo.superQueryInfo.sqlCount = 0; + } else if (superQuery->type != cJSON_Object) { printf("ERROR: failed to read json, sub_table_query not found\n"); ret = true; goto PARSE_OVER; } else { - cJSON* subrate = cJSON_GetObjectItem(subQuery, "query_interval"); + cJSON* subrate = cJSON_GetObjectItem(superQuery, "query_interval"); if (subrate && subrate->type == cJSON_Number) { - g_queryInfo.subQueryInfo.rate = subrate->valueint; + g_queryInfo.superQueryInfo.rate = subrate->valueint; } else if (!subrate) { - g_queryInfo.subQueryInfo.rate = 0; + g_queryInfo.superQueryInfo.rate = 0; } - cJSON* threads = cJSON_GetObjectItem(subQuery, "threads"); + cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times"); + if (superQueryTimes && superQueryTimes->type == cJSON_Number) { + g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint; + } else if (!superQueryTimes) { + g_queryInfo.superQueryInfo.queryTimes = g_args.query_times; + } else { + errorPrint("%s() LN%d, failed to read json, query_times input mistake\n", __func__, __LINE__); + goto PARSE_OVER; + } + + cJSON* threads = cJSON_GetObjectItem(superQuery, "threads"); if (threads && threads->type == cJSON_Number) { - g_queryInfo.subQueryInfo.threadCnt = threads->valueint; + g_queryInfo.superQueryInfo.threadCnt = threads->valueint; } else if (!threads) { - g_queryInfo.subQueryInfo.threadCnt = 1; + g_queryInfo.superQueryInfo.threadCnt = 1; } - //cJSON* subTblCnt = cJSON_GetObjectItem(subQuery, "childtable_count"); + //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count"); //if (subTblCnt && subTblCnt->type == cJSON_Number) { - // g_queryInfo.subQueryInfo.childTblCount = subTblCnt->valueint; + // g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint; //} else if (!subTblCnt) { - // g_queryInfo.subQueryInfo.childTblCount = 0; + // g_queryInfo.superQueryInfo.childTblCount = 0; //} - cJSON* stblname = cJSON_GetObjectItem(subQuery, "stblname"); + cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname"); if (stblname && stblname->type == cJSON_String && stblname->valuestring != NULL) { - tstrncpy(g_queryInfo.subQueryInfo.sTblName, stblname->valuestring, MAX_TB_NAME_SIZE); + tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring, MAX_TB_NAME_SIZE); } else { printf("ERROR: failed to read json, super table name not found\n"); goto PARSE_OVER; } - cJSON* submode = cJSON_GetObjectItem(subQuery, "mode"); + cJSON* submode = cJSON_GetObjectItem(superQuery, "mode"); if (submode && submode->type == cJSON_String && submode->valuestring != NULL) { - if (0 == strcmp("sync", submode->valuestring)) { - g_queryInfo.subQueryInfo.subscribeMode = 0; - } else if (0 == strcmp("async", submode->valuestring)) { - g_queryInfo.subQueryInfo.subscribeMode = 1; + if (0 == strcmp("sync", submode->valuestring)) { + g_queryInfo.superQueryInfo.subscribeMode = 0; + } else if (0 == strcmp("async", submode->valuestring)) { + g_queryInfo.superQueryInfo.subscribeMode = 1; } else { printf("ERROR: failed to read json, subscribe mod error\n"); goto PARSE_OVER; } } else { - g_queryInfo.subQueryInfo.subscribeMode = 0; + g_queryInfo.superQueryInfo.subscribeMode = 0; } - cJSON* subinterval = cJSON_GetObjectItem(subQuery, "interval"); + cJSON* subinterval = cJSON_GetObjectItem(superQuery, "interval"); if (subinterval && subinterval->type == cJSON_Number) { - g_queryInfo.subQueryInfo.subscribeInterval = subinterval->valueint; - } else if (!subinterval) { + g_queryInfo.superQueryInfo.subscribeInterval = subinterval->valueint; + } else if (!subinterval) { //printf("failed to read json, subscribe interval no found\n"); //goto PARSE_OVER; - g_queryInfo.subQueryInfo.subscribeInterval = 10000; + g_queryInfo.superQueryInfo.subscribeInterval = 10000; } - - cJSON* subrestart = cJSON_GetObjectItem(subQuery, "restart"); + + cJSON* subrestart = cJSON_GetObjectItem(superQuery, "restart"); if (subrestart && subrestart->type == cJSON_String && subrestart->valuestring != NULL) { - if (0 == strcmp("yes", subrestart->valuestring)) { - g_queryInfo.subQueryInfo.subscribeRestart = 1; - } else if (0 == strcmp("no", subrestart->valuestring)) { - g_queryInfo.subQueryInfo.subscribeRestart = 0; + if (0 == strcmp("yes", subrestart->valuestring)) { + g_queryInfo.superQueryInfo.subscribeRestart = 1; + } else if (0 == strcmp("no", subrestart->valuestring)) { + g_queryInfo.superQueryInfo.subscribeRestart = 0; } else { printf("ERROR: failed to read json, subscribe restart error\n"); goto PARSE_OVER; } } else { - g_queryInfo.subQueryInfo.subscribeRestart = 1; + g_queryInfo.superQueryInfo.subscribeRestart = 1; } - - cJSON* subkeepProgress = cJSON_GetObjectItem(subQuery, "keepProgress"); + + cJSON* subkeepProgress = cJSON_GetObjectItem(superQuery, "keepProgress"); if (subkeepProgress && subkeepProgress->type == cJSON_String && subkeepProgress->valuestring != NULL) { - if (0 == strcmp("yes", subkeepProgress->valuestring)) { - g_queryInfo.subQueryInfo.subscribeKeepProgress = 1; - } else if (0 == strcmp("no", subkeepProgress->valuestring)) { - g_queryInfo.subQueryInfo.subscribeKeepProgress = 0; + if (0 == strcmp("yes", subkeepProgress->valuestring)) { + g_queryInfo.superQueryInfo.subscribeKeepProgress = 1; + } else if (0 == strcmp("no", subkeepProgress->valuestring)) { + g_queryInfo.superQueryInfo.subscribeKeepProgress = 0; } else { printf("ERROR: failed to read json, subscribe keepProgress error\n"); goto PARSE_OVER; } } else { - g_queryInfo.subQueryInfo.subscribeKeepProgress = 0; - } + g_queryInfo.superQueryInfo.subscribeKeepProgress = 0; + } - // sqls - cJSON* subsqls = cJSON_GetObjectItem(subQuery, "sqls"); + // sqls + cJSON* subsqls = cJSON_GetObjectItem(superQuery, "sqls"); if (!subsqls) { - g_queryInfo.subQueryInfo.sqlCount = 0; + g_queryInfo.superQueryInfo.sqlCount = 0; } else if (subsqls->type != cJSON_Array) { printf("ERROR: failed to read json, super sqls not found\n"); goto PARSE_OVER; - } else { + } else { int superSqlSize = cJSON_GetArraySize(subsqls); if (superSqlSize > MAX_QUERY_SQL_COUNT) { printf("ERROR: failed to read json, query sql size overflow, max is %d\n", MAX_QUERY_SQL_COUNT); goto PARSE_OVER; } - - g_queryInfo.subQueryInfo.sqlCount = superSqlSize; - for (int j = 0; j < superSqlSize; ++j) { + + g_queryInfo.superQueryInfo.sqlCount = superSqlSize; + for (int j = 0; j < superSqlSize; ++j) { cJSON* sql = cJSON_GetArrayItem(subsqls, j); if (sql == NULL) continue; - + cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql"); if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) { printf("ERROR: failed to read json, sql not found\n"); goto PARSE_OVER; } - tstrncpy(g_queryInfo.subQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH); + tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH); cJSON *result = cJSON_GetObjectItem(sql, "result"); if (result != NULL && result->type == cJSON_String && result->valuestring != NULL){ - tstrncpy(g_queryInfo.subQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN); + tstrncpy(g_queryInfo.superQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN); } else if (NULL == result) { - memset(g_queryInfo.subQueryInfo.result[j], 0, MAX_FILE_NAME_LEN); + memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN); } else { printf("ERROR: failed to read json, sub query result file not found\n"); goto PARSE_OVER; - } + } } } } @@ -3985,7 +4090,7 @@ static bool getInfoFromJsonFile(char* file) { } bool ret = false; - int maxLen = 64000; + int maxLen = 6400000; char *content = calloc(1, maxLen + 1); int len = fread(content, 1, maxLen, fp); if (len <= 0) { @@ -4023,14 +4128,14 @@ static bool getInfoFromJsonFile(char* file) { if (INSERT_TEST == g_args.test_mode) { ret = getMetaFromInsertJsonFile(root); - } else if (QUERY_TEST == g_args.test_mode) { - ret = getMetaFromQueryJsonFile(root); - } else if (SUBSCRIBE_TEST == g_args.test_mode) { + } else if ((QUERY_TEST == g_args.test_mode) + || (SUBSCRIBE_TEST == g_args.test_mode)) { ret = getMetaFromQueryJsonFile(root); } else { - errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n", __func__, __LINE__); + errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n", + __func__, __LINE__); goto PARSE_OVER; - } + } PARSE_OVER: free(content); @@ -4040,7 +4145,7 @@ PARSE_OVER: } static void prepareSampleData() { - for (int i = 0; i < g_Dbs.dbCount; i++) { + for (int i = 0; i < g_Dbs.dbCount; i++) { for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { if (g_Dbs.db[i].superTbls[j].tagsFile[0] != 0) { (void)readTagFromCsvFileToMem(&g_Dbs.db[i].superTbls[j]); @@ -4051,7 +4156,7 @@ static void prepareSampleData() { static void postFreeResource() { tmfclose(g_fpOfInsertResult); - for (int i = 0; i < g_Dbs.dbCount; i++) { + for (int i = 0; i < g_Dbs.dbCount; i++) { for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { if (0 != g_Dbs.db[i].superTbls[j].colsOfCreateChildTable) { free(g_Dbs.db[i].superTbls[j].colsOfCreateChildTable); @@ -4095,71 +4200,77 @@ static int getRowDataFromSample(char* dataBuf, int maxLen, int64_t timestamp, dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")"); (*sampleUsePos)++; - + return dataLen; } -static int generateRowData(char* dataBuf, int maxLen, int64_t timestamp, SSuperTable* stbInfo) { - int dataLen = 0; - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "(%" PRId64 ", ", timestamp); - for (int i = 0; i < stbInfo->columnCount; i++) { +static int generateRowData(char* recBuf, int64_t timestamp, SSuperTable* stbInfo) { + int dataLen = 0; + char *pstr = recBuf; + int maxLen = MAX_DATA_SIZE; + + dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "(%" PRId64 ", ", timestamp); + + for (int i = 0; i < stbInfo->columnCount; i++) { if ((0 == strncasecmp(stbInfo->columns[i].dataType, "binary", 6)) || (0 == strncasecmp(stbInfo->columns[i].dataType, "nchar", 5))) { if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) { errorPrint( "binary or nchar length overflow, max size:%u\n", (uint32_t)TSDB_MAX_BINARY_LEN); - return (-1); + return -1; } char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1); if (NULL == buf) { errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen); - return (-1); + return -1; } rand_string(buf, stbInfo->columns[i].dataLen); - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "\'%s\', ", buf); + dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "\'%s\', ", buf); tmfree(buf); } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "int", 3)) { - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, + dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "%d, ", rand_int()); } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "bigint", 6)) { - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, + dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "%"PRId64", ", rand_bigint()); } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "float", 5)) { - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, + dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "%f, ", rand_float()); } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "double", 6)) { - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, + dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "%f, ", rand_double()); } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "smallint", 8)) { - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_smallint()); + dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "%d, ", rand_smallint()); } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "tinyint", 7)) { - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_tinyint()); + dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "%d, ", rand_tinyint()); } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "bool", 4)) { - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_bool()); + dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "%d, ", rand_bool()); } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "timestamp", 9)) { - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%"PRId64", ", rand_bigint()); + dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "%"PRId64", ", rand_bigint()); } else { errorPrint( "No support data type: %s\n", stbInfo->columns[i].dataType); - return (-1); + return -1; } } dataLen -= 2; - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")"); + dataLen += snprintf(pstr + dataLen, maxLen - dataLen, ")"); - return dataLen; + verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf); + + return strlen(recBuf); } -static int32_t generateData(char *res, char **data_type, +static int32_t generateData(char *recBuf, char **data_type, int num_of_cols, int64_t timestamp, int lenOfBinary) { - memset(res, 0, MAX_DATA_SIZE); - char *pstr = res; + memset(recBuf, 0, MAX_DATA_SIZE); + char *pstr = recBuf; pstr += sprintf(pstr, "(%" PRId64, timestamp); int c = 0; @@ -4180,7 +4291,7 @@ static int32_t generateData(char *res, char **data_type, } else if (strcasecmp(data_type[i % c], "smallint") == 0) { pstr += sprintf(pstr, ", %d", rand_smallint()); } else if (strcasecmp(data_type[i % c], "int") == 0) { - pstr += sprintf(pstr, ", %d", rand_int()); + pstr += sprintf(pstr, ", %d", rand_int()); } else if (strcasecmp(data_type[i % c], "bigint") == 0) { pstr += sprintf(pstr, ", %" PRId64, rand_bigint()); } else if (strcasecmp(data_type[i % c], "float") == 0) { @@ -4203,7 +4314,7 @@ static int32_t generateData(char *res, char **data_type, free(s); } - if (pstr - res > MAX_DATA_SIZE) { + if (strlen(recBuf) > MAX_DATA_SIZE) { perror("column length too long, abort"); exit(-1); } @@ -4211,7 +4322,7 @@ static int32_t generateData(char *res, char **data_type, pstr += sprintf(pstr, ")"); - return (int32_t)(pstr - res); + return (int32_t)strlen(recBuf); } static int prepareSampleDataForSTable(SSuperTable *superTblInfo) { @@ -4220,9 +4331,9 @@ static int prepareSampleDataForSTable(SSuperTable *superTblInfo) { sampleDataBuf = calloc( superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1); if (sampleDataBuf == NULL) { - errorPrint("%s() LN%d, Failed to calloc %d Bytes, reason:%s\n", + errorPrint("%s() LN%d, Failed to calloc %d Bytes, reason:%s\n", __func__, __LINE__, - superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, + superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, strerror(errno)); return -1; } @@ -4272,7 +4383,8 @@ static void getTableName(char *pTblName, threadInfo* pThreadInfo, int tableSeq) if ((superTblInfo->childTblOffset >= 0) && (superTblInfo->childTblLimit > 0)) { snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s", - superTblInfo->childTblName + (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN); + superTblInfo->childTblName + + (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN); } else { verbosePrint("[%d] %s() LN%d: from=%d count=%d seq=%d\n", @@ -4290,7 +4402,7 @@ static void getTableName(char *pTblName, threadInfo* pThreadInfo, int tableSeq) static int generateDataTail(char *tableName, int32_t tableSeq, threadInfo* pThreadInfo, SSuperTable* superTblInfo, - int batch, char* buffer, int64_t insertRows, + int batch, char* buffer, int remainderBufLen, int64_t insertRows, int64_t startFrom, uint64_t startTime, int *pSamplePos, int *dataLen) { int len = 0; int ncols_per_record = 1; // count first col ts @@ -4307,80 +4419,77 @@ static int generateDataTail(char *tableName, int32_t tableSeq, int k = 0; for (k = 0; k < batch;) { - if (superTblInfo) { - int retLen = 0; + char data[MAX_DATA_SIZE]; + int retLen = 0; - if (0 == strncasecmp(superTblInfo->dataSource, + if (superTblInfo) { + if (0 == strncasecmp(superTblInfo->dataSource, "sample", strlen("sample"))) { retLen = getRowDataFromSample( - buffer + len, - superTblInfo->maxSqlLen - len, + data, + remainderBufLen, startTime + superTblInfo->timeStampStep * k, - superTblInfo, + superTblInfo, pSamplePos); - } else if (0 == strncasecmp(superTblInfo->dataSource, + } else if (0 == strncasecmp(superTblInfo->dataSource, "rand", strlen("rand"))) { int rand_num = rand_tinyint() % 100; - if (0 != superTblInfo->disorderRatio + if (0 != superTblInfo->disorderRatio && rand_num < superTblInfo->disorderRatio) { int64_t d = startTime + superTblInfo->timeStampStep * k - taosRandom() % superTblInfo->disorderRange; retLen = generateRowData( - buffer + len, - superTblInfo->maxSqlLen - len, - d, + data, + d, superTblInfo); } else { retLen = generateRowData( - buffer + len, - superTblInfo->maxSqlLen - len, + data, startTime + superTblInfo->timeStampStep * k, superTblInfo); - } - } - - if (retLen < 0) { - return -1; - } + } + } - len += retLen; + if (retLen > remainderBufLen) { + break; + } - if (len >= (superTblInfo->maxSqlLen - 256)) { // reserve for overwrite - k++; - break; - } + buffer += sprintf(buffer, " %s", data); + k++; + len += retLen; + remainderBufLen -= retLen; } else { int rand_num = taosRandom() % 100; - char data[MAX_DATA_SIZE]; - char **data_type = g_args.datatype; - int lenOfBinary = g_args.len_of_binary; + char **data_type = g_args.datatype; + int lenOfBinary = g_args.len_of_binary; if ((g_args.disorderRatio != 0) && (rand_num < g_args.disorderRange)) { - - int64_t d = startTime + DEFAULT_TIMESTAMP_STEP * k + + int64_t d = startTime + DEFAULT_TIMESTAMP_STEP * k - taosRandom() % 1000000 + rand_num; - len = generateData(data, data_type, + retLen = generateData(data, data_type, ncols_per_record, d, lenOfBinary); } else { - len = generateData(data, data_type, + retLen = generateData(data, data_type, ncols_per_record, startTime + DEFAULT_TIMESTAMP_STEP * k, lenOfBinary); } + if (len > remainderBufLen) + break; + buffer += sprintf(buffer, " %s", data); - if (strlen(buffer) >= (g_args.max_sql_len - 256)) { // too long - k++; - break; - } + k++; + len += retLen; + remainderBufLen -= retLen; } verbosePrint("%s() LN%d len=%d k=%d \nbuffer=%s\n", __func__, __LINE__, len, k, buffer); - k++; startFrom ++; if (startFrom >= insertRows) { @@ -4400,7 +4509,7 @@ static int generateSQLHead(char *tableName, int32_t tableSeq, if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) { char* tagsValBuf = NULL; if (0 == superTblInfo->tagSource) { - tagsValBuf = generateTagVaulesForStb(superTblInfo); + tagsValBuf = generateTagVaulesForStb(superTblInfo, tableSeq); } else { tagsValBuf = getTagValueFromTagSample( superTblInfo, @@ -4444,7 +4553,7 @@ static int generateSQLHead(char *tableName, int32_t tableSeq, return len; } -static int generateDataBuffer(char *pTblName, +static int generateProgressiveDataBuffer(char *pTblName, int32_t tableSeq, threadInfo *pThreadInfo, char *buffer, int64_t insertRows, @@ -4464,20 +4573,25 @@ static int generateDataBuffer(char *pTblName, assert(buffer != NULL); - memset(buffer, 0, superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len); + int maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len; + int remainderBufLen = maxSqlLen; + + memset(buffer, 0, maxSqlLen); char *pstr = buffer; int headLen = generateSQLHead(pTblName, tableSeq, pThreadInfo, superTblInfo, buffer); pstr += headLen; + remainderBufLen -= headLen; int k; int dataLen; k = generateDataTail(pTblName, tableSeq, pThreadInfo, superTblInfo, - g_args.num_of_RPR, pstr, insertRows, startFrom, + g_args.num_of_RPR, pstr, remainderBufLen, insertRows, startFrom, startTime, pSamplePos, &dataLen); + return k; } @@ -4486,6 +4600,18 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { pThreadInfo->threadID, __func__, __LINE__); SSuperTable* superTblInfo = pThreadInfo->superTblInfo; + int interlaceRows = superTblInfo?superTblInfo->interlaceRows:g_args.interlace_rows; + + int insertMode; + + if (interlaceRows > 0) { + insertMode = INTERLACE_INSERT_MODE; + } else { + insertMode = PROGRESSIVE_INSERT_MODE; + } + + // TODO: prompt tbl count multple interlace rows and batch + // char* buffer = calloc(superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len, 1); if (NULL == buffer) { @@ -4494,21 +4620,9 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { strerror(errno)); return NULL; } - - int insertMode; - char tableName[TSDB_TABLE_NAME_LEN]; - - int interlaceRows = superTblInfo?superTblInfo->interlaceRows:g_args.interlace_rows; - if (interlaceRows > 0) { - insertMode = INTERLACE_INSERT_MODE; - } else { - insertMode = PROGRESSIVE_INSERT_MODE; - } - // rows per table need be less than insert batch - if (interlaceRows > g_args.num_of_RPR) - interlaceRows = g_args.num_of_RPR; + char tableName[TSDB_TABLE_NAME_LEN]; pThreadInfo->totalInsertRows = 0; pThreadInfo->totalAffectedRows = 0; @@ -4550,13 +4664,18 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { int generatedRecPerTbl = 0; bool flagSleep = true; int sleepTimeTotal = 0; + + int maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len; + int remainderBufLen; + while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) { if ((flagSleep) && (insert_interval)) { st = taosGetTimestampUs(); flagSleep = false; } // generate data - memset(buffer, 0, superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len); + memset(buffer, 0, maxSqlLen); + remainderBufLen = maxSqlLen; char *pstr = buffer; int recOfBatch = 0; @@ -4579,18 +4698,35 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { pThreadInfo->threadID, __func__, __LINE__, i, buffer); pstr += headLen; + remainderBufLen -= headLen; + int dataLen = 0; verbosePrint("[%d] %s() LN%d i=%d batchPerTblTimes=%d batchPerTbl = %d\n", pThreadInfo->threadID, __func__, __LINE__, i, batchPerTblTimes, batchPerTbl); - generateDataTail( + + if (superTblInfo) { + if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) { + startTime = taosGetTimestamp(pThreadInfo->time_precision); + } + } else { + startTime = 1500000000000; + } + int generated = generateDataTail( tableName, tableSeq, pThreadInfo, superTblInfo, - batchPerTbl, pstr, insertRows, 0, + batchPerTbl, pstr, remainderBufLen, insertRows, 0, startTime, &(pThreadInfo->samplePos), &dataLen); + if (generated < 0) { + debugPrint("[%d] %s() LN%d, generated data is %d\n", + pThreadInfo->threadID, __func__, __LINE__, generated); + goto free_and_statistics_interlace; + } pstr += dataLen; + remainderBufLen -= dataLen; + recOfBatch += batchPerTbl; startTime += batchPerTbl * superTblInfo->timeStampStep; pThreadInfo->totalInsertRows += batchPerTbl; @@ -4682,9 +4818,9 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { free_and_statistics_interlace: tmfree(buffer); - printf("====thread[%d] completed total inserted rows: %"PRId64 ", total affected rows: %"PRId64 "====\n", - pThreadInfo->threadID, - pThreadInfo->totalInsertRows, + printf("====thread[%d] completed total inserted rows: %"PRId64 ", total affected rows: %"PRId64 "====\n", + pThreadInfo->threadID, + pThreadInfo->totalInsertRows, pThreadInfo->totalAffectedRows); return NULL; } @@ -4709,17 +4845,18 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { strerror(errno)); return NULL; } - + int64_t lastPrintTime = taosGetTimestampMs(); int64_t startTs = taosGetTimestampUs(); int64_t endTs; int timeStampStep = superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP; - int insert_interval = +/* int insert_interval = superTblInfo?superTblInfo->insertInterval:g_args.insert_interval; uint64_t st = 0; uint64_t et = 0xffffffff; + */ pThreadInfo->totalInsertRows = 0; pThreadInfo->totalAffectedRows = 0; @@ -4735,9 +4872,11 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { verbosePrint("%s() LN%d insertRows=%"PRId64"\n", __func__, __LINE__, insertRows); for (int64_t i = 0; i < insertRows;) { + /* if (insert_interval) { st = taosGetTimestampUs(); } + */ char tableName[TSDB_TABLE_NAME_LEN]; getTableName(tableName, pThreadInfo, tableSeq); @@ -4745,7 +4884,7 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { __func__, __LINE__, pThreadInfo->threadID, tableSeq, tableName); - int generated = generateDataBuffer( + int generated = generateProgressiveDataBuffer( tableName, tableSeq, pThreadInfo, buffer, insertRows, i, start_time, &(pThreadInfo->samplePos)); @@ -4787,7 +4926,7 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { if (i >= insertRows) break; - +/* if (insert_interval) { et = taosGetTimestampUs(); @@ -4798,6 +4937,7 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { taosMsleep(sleep_time); // ms } } + */ } // num_of_DPT if ((tableSeq == pThreadInfo->ntables - 1) && superTblInfo && @@ -4811,16 +4951,16 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { free_and_statistics_2: tmfree(buffer); - printf("====thread[%d] completed total inserted rows: %"PRId64 ", total affected rows: %"PRId64 "====\n", - pThreadInfo->threadID, - pThreadInfo->totalInsertRows, + printf("====thread[%d] completed total inserted rows: %"PRId64 ", total affected rows: %"PRId64 "====\n", + pThreadInfo->threadID, + pThreadInfo->totalInsertRows, pThreadInfo->totalAffectedRows); return NULL; } static void* syncWrite(void *sarg) { - threadInfo *winfo = (threadInfo *)sarg; + threadInfo *winfo = (threadInfo *)sarg; SSuperTable* superTblInfo = winfo->superTblInfo; int interlaceRows = superTblInfo?superTblInfo->interlaceRows:g_args.interlace_rows; @@ -4835,7 +4975,7 @@ static void* syncWrite(void *sarg) { } static void callBack(void *param, TAOS_RES *res, int code) { - threadInfo* winfo = (threadInfo*)param; + threadInfo* winfo = (threadInfo*)param; SSuperTable* superTblInfo = winfo->superTblInfo; int insert_interval = @@ -4846,9 +4986,9 @@ static void callBack(void *param, TAOS_RES *res, int code) { taosMsleep(insert_interval - (winfo->et - winfo->st)/1000); // ms } } - + char *buffer = calloc(1, winfo->superTblInfo->maxSqlLen); - char *data = calloc(1, MAX_DATA_SIZE); + char data[MAX_DATA_SIZE]; char *pstr = buffer; pstr += sprintf(pstr, "insert into %s.%s%d values", winfo->db_name, winfo->tb_prefix, winfo->start_table_from); @@ -4860,21 +5000,18 @@ static void callBack(void *param, TAOS_RES *res, int code) { if (winfo->start_table_from > winfo->end_table_to) { tsem_post(&winfo->lock_sem); free(buffer); - free(data); taos_free_result(res); return; } - + for (int i = 0; i < g_args.num_of_RPR; i++) { int rand_num = taosRandom() % 100; if (0 != winfo->superTblInfo->disorderRatio && rand_num < winfo->superTblInfo->disorderRatio) { int64_t d = winfo->lastTs - taosRandom() % 1000000 + rand_num; - //generateData(data, datatype, ncols_per_record, d, len_of_binary); - generateRowData(data, MAX_DATA_SIZE, d, winfo->superTblInfo); + generateRowData(data, d, winfo->superTblInfo); } else { - //generateData(data, datatype, ncols_per_record, start_time += 1000, len_of_binary); - generateRowData(data, MAX_DATA_SIZE, winfo->lastTs += 1000, winfo->superTblInfo); + generateRowData(data, winfo->lastTs += 1000, winfo->superTblInfo); } pstr += sprintf(pstr, "%s", data); winfo->counter++; @@ -4889,7 +5026,6 @@ static void callBack(void *param, TAOS_RES *res, int code) { } taos_query_a(winfo->taos, buffer, callBack, winfo); free(buffer); - free(data); taos_free_result(res); } @@ -4901,7 +5037,7 @@ static void *asyncWrite(void *sarg) { winfo->st = 0; winfo->et = 0; winfo->lastTs = winfo->start_time; - + int insert_interval = superTblInfo?superTblInfo->insertInterval:g_args.insert_interval; if (insert_interval) { @@ -4917,39 +5053,14 @@ static void *asyncWrite(void *sarg) { static void startMultiThreadInsertData(int threads, char* db_name, char* precision,SSuperTable* superTblInfo) { - pthread_t *pids = malloc(threads * sizeof(pthread_t)); - assert(pids != NULL); - - threadInfo *infos = malloc(threads * sizeof(threadInfo)); - assert(infos != NULL); - - memset(pids, 0, threads * sizeof(pthread_t)); - memset(infos, 0, threads * sizeof(threadInfo)); - - int ntables = 0; - if (superTblInfo) { - - if ((superTblInfo->childTblOffset >= 0) - && (superTblInfo->childTblLimit > 0)) { - - ntables = superTblInfo->childTblLimit; - } else { - ntables = superTblInfo->childTblCount; - } - } else { - ntables = g_args.num_of_tables; - } + pthread_t *pids = malloc(threads * sizeof(pthread_t)); + assert(pids != NULL); - int a = ntables / threads; - if (a < 1) { - threads = ntables; - a = 1; - } + threadInfo *infos = malloc(threads * sizeof(threadInfo)); + assert(infos != NULL); - int b = 0; - if (threads != 0) { - b = ntables % threads; - } + memset(pids, 0, threads * sizeof(pthread_t)); + memset(infos, 0, threads * sizeof(threadInfo)); //TAOS* taos; //if (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5)) { @@ -4990,13 +5101,6 @@ static void startMultiThreadInsertData(int threads, char* db_name, } double start = getCurrentTime(); - - int startFrom; - - if ((superTblInfo) && (superTblInfo->childTblOffset >= 0)) - startFrom = superTblInfo->childTblOffset; - else - startFrom = 0; // read sample data from file first if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource, @@ -5027,18 +5131,36 @@ static void startMultiThreadInsertData(int threads, char* db_name, exit(-1); } - if (superTblInfo) { + int ntables = 0; + int startFrom; + if (superTblInfo) { int limit, offset; - if (superTblInfo && (superTblInfo->childTblOffset >= 0) - && (superTblInfo->childTblLimit > 0)) { - limit = superTblInfo->childTblLimit; - offset = superTblInfo->childTblOffset; + + if (superTblInfo->childTblOffset >= superTblInfo->childTblCount) { + printf("WARNING: specified offset >= child table count! \n"); + if (!g_args.answer_yes) { + printf(" Press enter key to continue or Ctrl-C to stop\n\n"); + (void)getchar(); + } + } + + if (superTblInfo->childTblOffset >= 0) { + if (superTblInfo->childTblLimit <= 0) { + superTblInfo->childTblLimit = + superTblInfo->childTblCount - superTblInfo->childTblOffset; + } + + offset = superTblInfo->childTblOffset; + limit = superTblInfo->childTblLimit; } else { limit = superTblInfo->childTblCount; offset = 0; } + ntables = limit; + startFrom = offset; + superTblInfo->childTblName = (char*)calloc(1, limit * TSDB_TABLE_NAME_LEN); if (superTblInfo->childTblName == NULL) { @@ -5054,13 +5176,29 @@ static void startMultiThreadInsertData(int threads, char* db_name, &superTblInfo->childTblName, &childTblCount, limit, offset); + } else { + ntables = g_args.num_of_tables; + startFrom = 0; } + taos_close(taos); + int a = ntables / threads; + if (a < 1) { + threads = ntables; + a = 1; + } + + int b = 0; + if (threads != 0) { + b = ntables % threads; + } + for (int i = 0; i < threads; i++) { threadInfo *t_info = infos + i; t_info->threadID = i; tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE); + t_info->time_precision = timePrec; t_info->superTblInfo = superTblInfo; t_info->start_time = start_time; @@ -5181,7 +5319,7 @@ static void startMultiThreadInsertData(int threads, char* db_name, } static void *readTable(void *sarg) { -#if 1 +#if 1 threadInfo *rinfo = (threadInfo *)sarg; TAOS *taos = rinfo->taos; char command[BUFFER_SIZE] = "\0"; @@ -5253,7 +5391,7 @@ static void *readTable(void *sarg) { } static void *readMetric(void *sarg) { -#if 1 +#if 1 threadInfo *rinfo = (threadInfo *)sarg; TAOS *taos = rinfo->taos; char command[BUFFER_SIZE] = "\0"; @@ -5348,7 +5486,7 @@ static int insertTestProcess() { printf("Press enter key to continue\n\n"); (void)getchar(); } - + init_rand_data(); // create database and super tables @@ -5404,7 +5542,7 @@ static int insertTestProcess() { //int64_t totalInsertRows = 0; //int64_t totalAffectedRows = 0; - //for (int i = 0; i < g_Dbs.dbCount; i++) { + //for (int i = 0; i < g_Dbs.dbCount; i++) { // for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { // totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows; // totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows; @@ -5418,39 +5556,60 @@ static int insertTestProcess() { static void *superQueryProcess(void *sarg) { threadInfo *winfo = (threadInfo *)sarg; - //char sqlStr[MAX_TB_NAME_SIZE*2]; - //sprintf(sqlStr, "use %s", g_queryInfo.dbName); - //queryDB(winfo->taos, sqlStr); - + if (winfo->taos == NULL) { + TAOS * taos = NULL; + taos = taos_connect(g_queryInfo.host, + g_queryInfo.user, + g_queryInfo.password, + NULL, + g_queryInfo.port); + if (taos == NULL) { + errorPrint("[%d] Failed to connect to TDengine, reason:%s\n", + winfo->threadID, taos_errstr(NULL)); + return NULL; + } else { + winfo->taos = taos; + } + } + + char sqlStr[MAX_DB_NAME_SIZE + 5]; + sprintf(sqlStr, "use %s", g_queryInfo.dbName); + if (0 != queryDbExec(winfo->taos, sqlStr, NO_INSERT_TYPE, false)) { + taos_close(winfo->taos); + errorPrint( "use database %s failed!\n\n", + g_queryInfo.dbName); + return NULL; + } + int64_t st = 0; int64_t et = 0; - int queryTimes = g_args.query_times; + int queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes; while(queryTimes --) { - if (g_queryInfo.superQueryInfo.rate && (et - st) < - (int64_t)g_queryInfo.superQueryInfo.rate*1000) { - taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms + if (g_queryInfo.specifiedQueryInfo.rate && (et - st) < + (int64_t)g_queryInfo.specifiedQueryInfo.rate*1000) { + taosMsleep(g_queryInfo.specifiedQueryInfo.rate*1000 - (et - st)); // ms //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to); } st = taosGetTimestampUs(); - for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { + for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) { if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", 5)) { int64_t t1 = taosGetTimestampUs(); char tmpFile[MAX_FILE_NAME_LEN*2] = {0}; - if (g_queryInfo.superQueryInfo.result[i][0] != 0) { + if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) { sprintf(tmpFile, "%s-%d", - g_queryInfo.superQueryInfo.result[i], winfo->threadID); + g_queryInfo.specifiedQueryInfo.result[i], winfo->threadID); } - selectAndGetResult(winfo->taos, g_queryInfo.superQueryInfo.sql[i], tmpFile); + selectAndGetResult(winfo->taos, g_queryInfo.specifiedQueryInfo.sql[i], tmpFile); int64_t t2 = taosGetTimestampUs(); printf("=[taosc] thread[%"PRId64"] complete one sql, Spent %f s\n", taosGetSelfPthreadId(), (t2 - t1)/1000000.0); } else { int64_t t1 = taosGetTimestampUs(); int retCode = postProceSql(g_queryInfo.host, - g_queryInfo.port, g_queryInfo.superQueryInfo.sql[i]); + g_queryInfo.port, g_queryInfo.specifiedQueryInfo.sql[i]); int64_t t2 = taosGetTimestampUs(); printf("=[restful] thread[%"PRId64"] complete one sql, Spent %f s\n", taosGetSelfPthreadId(), (t2 - t1)/1000000.0); @@ -5473,7 +5632,7 @@ static void replaceSubTblName(char* inSql, char* outSql, int tblIndex) { char subTblName[MAX_TB_NAME_SIZE*3]; sprintf(subTblName, "%s.%s", g_queryInfo.dbName, - g_queryInfo.subQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN); + g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN); //printf("inSql: %s\n", inSql); @@ -5493,26 +5652,44 @@ static void replaceSubTblName(char* inSql, char* outSql, int tblIndex) { static void *subQueryProcess(void *sarg) { char sqlstr[1024]; threadInfo *winfo = (threadInfo *)sarg; + + if (winfo->taos == NULL) { + TAOS * taos = NULL; + taos = taos_connect(g_queryInfo.host, + g_queryInfo.user, + g_queryInfo.password, + NULL, + g_queryInfo.port); + if (taos == NULL) { + errorPrint("[%d] Failed to connect to TDengine, reason:%s\n", + winfo->threadID, taos_errstr(NULL)); + return NULL; + } else { + winfo->taos = taos; + } + } + int64_t st = 0; - int64_t et = (int64_t)g_queryInfo.subQueryInfo.rate*1000; - int queryTimes = g_args.query_times; + int64_t et = (int64_t)g_queryInfo.superQueryInfo.rate*1000; + + int queryTimes = g_queryInfo.superQueryInfo.queryTimes; while(queryTimes --) { - if (g_queryInfo.subQueryInfo.rate - && (et - st) < (int64_t)g_queryInfo.subQueryInfo.rate*1000) { - taosMsleep(g_queryInfo.subQueryInfo.rate*1000 - (et - st)); // ms + if (g_queryInfo.superQueryInfo.rate + && (et - st) < (int64_t)g_queryInfo.superQueryInfo.rate*1000) { + taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to); } st = taosGetTimestampUs(); for (int i = winfo->start_table_from; i <= winfo->end_table_to; i++) { - for (int j = 0; j < g_queryInfo.subQueryInfo.sqlCount; j++) { + for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) { memset(sqlstr,0,sizeof(sqlstr)); - replaceSubTblName(g_queryInfo.subQueryInfo.sql[j], sqlstr, i); + replaceSubTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i); char tmpFile[MAX_FILE_NAME_LEN*2] = {0}; - if (g_queryInfo.subQueryInfo.result[i][0] != 0) { + if (g_queryInfo.superQueryInfo.result[j][0] != 0) { sprintf(tmpFile, "%s-%d", - g_queryInfo.subQueryInfo.result[i], + g_queryInfo.superQueryInfo.result[j], winfo->threadID); } selectAndGetResult(winfo->taos, sqlstr, tmpFile); @@ -5534,12 +5711,12 @@ static int queryTestProcess() { setupForAnsiEscape(); printfQueryMeta(); resetAfterAnsiEscape(); - - TAOS * taos = NULL; - taos = taos_connect(g_queryInfo.host, - g_queryInfo.user, - g_queryInfo.password, - NULL, + + TAOS * taos = NULL; + taos = taos_connect(g_queryInfo.host, + g_queryInfo.user, + g_queryInfo.password, + NULL, g_queryInfo.port); if (taos == NULL) { errorPrint( "Failed to connect to TDengine, reason:%s\n", @@ -5547,105 +5724,105 @@ static int queryTestProcess() { exit(-1); } - if (0 != g_queryInfo.subQueryInfo.sqlCount) { + if (0 != g_queryInfo.superQueryInfo.sqlCount) { getAllChildNameOfSuperTable(taos, g_queryInfo.dbName, - g_queryInfo.subQueryInfo.sTblName, - &g_queryInfo.subQueryInfo.childTblName, - &g_queryInfo.subQueryInfo.childTblCount); + g_queryInfo.superQueryInfo.sTblName, + &g_queryInfo.superQueryInfo.childTblName, + &g_queryInfo.superQueryInfo.childTblCount); } - + if (!g_args.answer_yes) { printf("Press enter key to continue\n\n"); (void)getchar(); } - + printfQuerySystemInfo(taos); - + pthread_t *pids = NULL; threadInfo *infos = NULL; //==== create sub threads for query from specify table - if (g_queryInfo.superQueryInfo.sqlCount > 0 - && g_queryInfo.superQueryInfo.concurrent > 0) { + if (g_queryInfo.specifiedQueryInfo.sqlCount > 0 + && g_queryInfo.specifiedQueryInfo.concurrent > 0) { - pids = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(pthread_t)); + pids = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(pthread_t)); if (NULL == pids) { taos_close(taos); ERROR_EXIT("memory allocation failed\n"); } - infos = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(threadInfo)); + infos = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(threadInfo)); if (NULL == infos) { taos_close(taos); free(pids); ERROR_EXIT("memory allocation failed for create threads\n"); } - for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) { + for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) { threadInfo *t_info = infos + i; t_info->threadID = i; if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", 5)) { - t_info->taos = taos; char sqlStr[MAX_TB_NAME_SIZE*2]; sprintf(sqlStr, "use %s", g_queryInfo.dbName); verbosePrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr); - if (0 != queryDbExec(t_info->taos, sqlStr, NO_INSERT_TYPE, false)) { + if (0 != queryDbExec(taos, sqlStr, NO_INSERT_TYPE, false)) { + taos_close(taos); free(infos); free(pids); errorPrint( "use database %s failed!\n\n", g_queryInfo.dbName); return -1; } - } else { - t_info->taos = NULL; } + t_info->taos = NULL;// TODO: workaround to use separate taos connection; + pthread_create(pids + i, NULL, superQueryProcess, t_info); } - }else { - g_queryInfo.superQueryInfo.concurrent = 0; + } else { + g_queryInfo.specifiedQueryInfo.concurrent = 0; } + taos_close(taos); + pthread_t *pidsOfSub = NULL; threadInfo *infosOfSub = NULL; //==== create sub threads for query from all sub table of the super table - if ((g_queryInfo.subQueryInfo.sqlCount > 0) - && (g_queryInfo.subQueryInfo.threadCnt > 0)) { - pidsOfSub = malloc(g_queryInfo.subQueryInfo.threadCnt * sizeof(pthread_t)); + if ((g_queryInfo.superQueryInfo.sqlCount > 0) + && (g_queryInfo.superQueryInfo.threadCnt > 0)) { + pidsOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt * sizeof(pthread_t)); if (NULL == pidsOfSub) { - taos_close(taos); free(infos); free(pids); ERROR_EXIT("memory allocation failed for create threads\n"); } - infosOfSub = malloc(g_queryInfo.subQueryInfo.threadCnt * sizeof(threadInfo)); + infosOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt * sizeof(threadInfo)); if (NULL == infosOfSub) { - taos_close(taos); free(pidsOfSub); free(infos); free(pids); ERROR_EXIT("memory allocation failed for create threads\n"); } - int ntables = g_queryInfo.subQueryInfo.childTblCount; - int threads = g_queryInfo.subQueryInfo.threadCnt; - + int ntables = g_queryInfo.superQueryInfo.childTblCount; + int threads = g_queryInfo.superQueryInfo.threadCnt; + int a = ntables / threads; if (a < 1) { threads = ntables; a = 1; } - + int b = 0; if (threads != 0) { b = ntables % threads; } int startFrom = 0; - for (int i = 0; i < threads; i++) { + for (int i = 0; i < threads; i++) { threadInfo *t_info = infosOfSub + i; t_info->threadID = i; @@ -5653,30 +5830,30 @@ static int queryTestProcess() { t_info->ntables = iend_table_to = i < b ? startFrom + a : startFrom + a - 1; startFrom = t_info->end_table_to + 1; - t_info->taos = taos; + t_info->taos = NULL; // TODO: workaround to use separate taos connection; pthread_create(pidsOfSub + i, NULL, subQueryProcess, t_info); } - g_queryInfo.subQueryInfo.threadCnt = threads; + g_queryInfo.superQueryInfo.threadCnt = threads; } else { - g_queryInfo.subQueryInfo.threadCnt = 0; + g_queryInfo.superQueryInfo.threadCnt = 0; } - - for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) { + + for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) { pthread_join(pids[i], NULL); } tmfree((char*)pids); tmfree((char*)infos); - - for (int i = 0; i < g_queryInfo.subQueryInfo.threadCnt; i++) { + + for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) { pthread_join(pidsOfSub[i], NULL); } tmfree((char*)pidsOfSub); tmfree((char*)infosOfSub); - - taos_close(taos); + +// taos_close(taos);// TODO: workaround to use separate taos connection; return 0; } @@ -5694,14 +5871,14 @@ static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int c static TAOS_SUB* subscribeImpl(TAOS *taos, char *sql, char* topic, char* resultFileName) { TAOS_SUB* tsub = NULL; - if (g_queryInfo.superQueryInfo.subscribeMode) { + if (g_queryInfo.specifiedQueryInfo.subscribeMode) { tsub = taos_subscribe(taos, - g_queryInfo.superQueryInfo.subscribeRestart, + g_queryInfo.specifiedQueryInfo.subscribeRestart, topic, sql, subscribe_callback, (void*)resultFileName, - g_queryInfo.superQueryInfo.subscribeInterval); + g_queryInfo.specifiedQueryInfo.subscribeInterval); } else { tsub = taos_subscribe(taos, - g_queryInfo.superQueryInfo.subscribeRestart, + g_queryInfo.specifiedQueryInfo.subscribeRestart, topic, sql, NULL, NULL, 0); } @@ -5716,34 +5893,55 @@ static TAOS_SUB* subscribeImpl(TAOS *taos, char *sql, char* topic, char* resultF static void *subSubscribeProcess(void *sarg) { threadInfo *winfo = (threadInfo *)sarg; char subSqlstr[1024]; + TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT] = {0}; + + if (winfo->taos == NULL) { + TAOS * taos = NULL; + taos = taos_connect(g_queryInfo.host, + g_queryInfo.user, + g_queryInfo.password, + g_queryInfo.dbName, + g_queryInfo.port); + if (taos == NULL) { + errorPrint("[%d] Failed to connect to TDengine, reason:%s\n", + winfo->threadID, taos_errstr(NULL)); + return NULL; + } else { + winfo->taos = taos; + } + } char sqlStr[MAX_TB_NAME_SIZE*2]; sprintf(sqlStr, "use %s", g_queryInfo.dbName); - debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr); - if (0 != queryDbExec(winfo->taos, sqlStr, NO_INSERT_TYPE, false)){ + if (0 != queryDbExec(winfo->taos, sqlStr, NO_INSERT_TYPE, false)) { + taos_close(winfo->taos); + errorPrint( "use database %s failed!\n\n", + g_queryInfo.dbName); return NULL; } - + //int64_t st = 0; //int64_t et = 0; do { - //if (g_queryInfo.superQueryInfo.rate && (et - st) < g_queryInfo.superQueryInfo.rate*1000) { - // taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms + //if (g_queryInfo.specifiedQueryInfo.rate && (et - st) < g_queryInfo.specifiedQueryInfo.rate*1000) { + // taosMsleep(g_queryInfo.specifiedQueryInfo.rate*1000 - (et - st)); // ms // //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to); //} //st = taosGetTimestampMs(); char topic[32] = {0}; - for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) { + for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { sprintf(topic, "taosdemo-subscribe-%d", i); memset(subSqlstr,0,sizeof(subSqlstr)); - replaceSubTblName(g_queryInfo.subQueryInfo.sql[i], subSqlstr, i); + replaceSubTblName(g_queryInfo.superQueryInfo.sql[i], subSqlstr, i); char tmpFile[MAX_FILE_NAME_LEN*2] = {0}; - if (g_queryInfo.subQueryInfo.result[i][0] != 0) { - sprintf(tmpFile, "%s-%d", g_queryInfo.subQueryInfo.result[i], winfo->threadID); + if (g_queryInfo.superQueryInfo.result[i][0] != 0) { + sprintf(tmpFile, "%s-%d", + g_queryInfo.superQueryInfo.result[i], winfo->threadID); } - g_queryInfo.subQueryInfo.tsub[i] = subscribeImpl(winfo->taos, subSqlstr, topic, tmpFile); - if (NULL == g_queryInfo.subQueryInfo.tsub[i]) { + tsub[i] = subscribeImpl(winfo->taos, subSqlstr, topic, tmpFile); + if (NULL == tsub[i]) { + taos_close(winfo->taos); return NULL; } } @@ -5754,17 +5952,17 @@ static void *subSubscribeProcess(void *sarg) { // start loop to consume result TAOS_RES* res = NULL; while (1) { - for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) { - if (1 == g_queryInfo.subQueryInfo.subscribeMode) { + for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { + if (1 == g_queryInfo.superQueryInfo.subscribeMode) { continue; } - res = taos_consume(g_queryInfo.subQueryInfo.tsub[i]); + res = taos_consume(tsub[i]); if (res) { char tmpFile[MAX_FILE_NAME_LEN*2] = {0}; - if (g_queryInfo.subQueryInfo.result[i][0] != 0) { + if (g_queryInfo.superQueryInfo.result[i][0] != 0) { sprintf(tmpFile, "%s-%d", - g_queryInfo.subQueryInfo.result[i], + g_queryInfo.superQueryInfo.result[i], winfo->threadID); } getResult(res, tmpFile); @@ -5773,45 +5971,62 @@ static void *subSubscribeProcess(void *sarg) { } taos_free_result(res); - for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) { - taos_unsubscribe(g_queryInfo.subQueryInfo.tsub[i], - g_queryInfo.subQueryInfo.subscribeKeepProgress); + for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { + taos_unsubscribe(tsub[i], g_queryInfo.superQueryInfo.subscribeKeepProgress); } + + taos_close(winfo->taos); return NULL; } static void *superSubscribeProcess(void *sarg) { threadInfo *winfo = (threadInfo *)sarg; + TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT] = {0}; + + if (winfo->taos == NULL) { + TAOS * taos = NULL; + taos = taos_connect(g_queryInfo.host, + g_queryInfo.user, + g_queryInfo.password, + g_queryInfo.dbName, + g_queryInfo.port); + if (taos == NULL) { + errorPrint("[%d] Failed to connect to TDengine, reason:%s\n", + winfo->threadID, taos_errstr(NULL)); + return NULL; + } else { + winfo->taos = taos; + } + } char sqlStr[MAX_TB_NAME_SIZE*2]; sprintf(sqlStr, "use %s", g_queryInfo.dbName); debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr); if (0 != queryDbExec(winfo->taos, sqlStr, NO_INSERT_TYPE, false)) { + taos_close(winfo->taos); return NULL; } - + //int64_t st = 0; //int64_t et = 0; do { - //if (g_queryInfo.superQueryInfo.rate && (et - st) < g_queryInfo.superQueryInfo.rate*1000) { - // taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms + //if (g_queryInfo.specifiedQueryInfo.rate && (et - st) < g_queryInfo.specifiedQueryInfo.rate*1000) { + // taosMsleep(g_queryInfo.specifiedQueryInfo.rate*1000 - (et - st)); // ms // //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to); //} //st = taosGetTimestampMs(); char topic[32] = {0}; - for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { + for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) { sprintf(topic, "taosdemo-subscribe-%d", i); char tmpFile[MAX_FILE_NAME_LEN*2] = {0}; - if (g_queryInfo.subQueryInfo.result[i][0] != 0) { + if (g_queryInfo.superQueryInfo.result[i][0] != 0) { sprintf(tmpFile, "%s-%d", - g_queryInfo.superQueryInfo.result[i], winfo->threadID); + g_queryInfo.specifiedQueryInfo.result[i], winfo->threadID); } - g_queryInfo.superQueryInfo.tsub[i] = - subscribeImpl(winfo->taos, - g_queryInfo.superQueryInfo.sql[i], - topic, tmpFile); - if (NULL == g_queryInfo.superQueryInfo.tsub[i]) { + tsub[i] = subscribeImpl(winfo->taos, g_queryInfo.specifiedQueryInfo.sql[i], topic, tmpFile); + if (NULL == g_queryInfo.specifiedQueryInfo.tsub[i]) { + taos_close(winfo->taos); return NULL; } } @@ -5822,17 +6037,17 @@ static void *superSubscribeProcess(void *sarg) { // start loop to consume result TAOS_RES* res = NULL; while (1) { - for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { - if (1 == g_queryInfo.superQueryInfo.subscribeMode) { + for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) { + if (1 == g_queryInfo.specifiedQueryInfo.subscribeMode) { continue; } - res = taos_consume(g_queryInfo.superQueryInfo.tsub[i]); + res = taos_consume(tsub[i]); if (res) { char tmpFile[MAX_FILE_NAME_LEN*2] = {0}; - if (g_queryInfo.superQueryInfo.result[i][0] != 0) { + if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) { sprintf(tmpFile, "%s-%d", - g_queryInfo.superQueryInfo.result[i], winfo->threadID); + g_queryInfo.specifiedQueryInfo.result[i], winfo->threadID); } getResult(res, tmpFile); } @@ -5840,10 +6055,11 @@ static void *superSubscribeProcess(void *sarg) { } taos_free_result(res); - for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { - taos_unsubscribe(g_queryInfo.superQueryInfo.tsub[i], - g_queryInfo.superQueryInfo.subscribeKeepProgress); + for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) { + taos_unsubscribe(tsub[i], g_queryInfo.specifiedQueryInfo.subscribeKeepProgress); } + + taos_close(winfo->taos); return NULL; } @@ -5851,10 +6067,10 @@ static int subscribeTestProcess() { setupForAnsiEscape(); printfQueryMeta(); resetAfterAnsiEscape(); - + if (!g_args.answer_yes) { printf("Press enter key to continue\n\n"); - (void)getchar(); + (void) getchar(); } TAOS * taos = NULL; @@ -5869,69 +6085,71 @@ static int subscribeTestProcess() { exit(-1); } - if (0 != g_queryInfo.subQueryInfo.sqlCount) { + if (0 != g_queryInfo.superQueryInfo.sqlCount) { getAllChildNameOfSuperTable(taos, g_queryInfo.dbName, - g_queryInfo.subQueryInfo.sTblName, - &g_queryInfo.subQueryInfo.childTblName, - &g_queryInfo.subQueryInfo.childTblCount); + g_queryInfo.superQueryInfo.sTblName, + &g_queryInfo.superQueryInfo.childTblName, + &g_queryInfo.superQueryInfo.childTblCount); } + taos_close(taos); // TODO: workaround to use separate taos connection; + pthread_t *pids = NULL; threadInfo *infos = NULL; //==== create sub threads for query from super table - if ((g_queryInfo.superQueryInfo.sqlCount <= 0) || - (g_queryInfo.superQueryInfo.concurrent <= 0)) { + if ((g_queryInfo.specifiedQueryInfo.sqlCount <= 0) || + (g_queryInfo.specifiedQueryInfo.concurrent <= 0)) { errorPrint("%s() LN%d, query sqlCount %d or concurrent %d is not correct.\n", - __func__, __LINE__, g_queryInfo.superQueryInfo.sqlCount, - g_queryInfo.superQueryInfo.concurrent); + __func__, __LINE__, g_queryInfo.specifiedQueryInfo.sqlCount, + g_queryInfo.specifiedQueryInfo.concurrent); exit(-1); } - pids = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(pthread_t)); - infos = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(threadInfo)); + pids = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(pthread_t)); + infos = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(threadInfo)); if ((NULL == pids) || (NULL == infos)) { errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__); - taos_close(taos); exit(-1); } - for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) { + for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) { threadInfo *t_info = infos + i; t_info->threadID = i; - t_info->taos = taos; + t_info->taos = NULL; // TODO: workaround to use separate taos connection; pthread_create(pids + i, NULL, superSubscribeProcess, t_info); } - - //==== create sub threads for query from sub table + + //==== create sub threads for query from sub table pthread_t *pidsOfSub = NULL; threadInfo *infosOfSub = NULL; - if ((g_queryInfo.subQueryInfo.sqlCount > 0) - && (g_queryInfo.subQueryInfo.threadCnt > 0)) { - pidsOfSub = malloc(g_queryInfo.subQueryInfo.threadCnt * + if ((g_queryInfo.superQueryInfo.sqlCount > 0) + && (g_queryInfo.superQueryInfo.threadCnt > 0)) { + pidsOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt * sizeof(pthread_t)); - infosOfSub = malloc(g_queryInfo.subQueryInfo.threadCnt * + infosOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt * sizeof(threadInfo)); if ((NULL == pidsOfSub) || (NULL == infosOfSub)) { - printf("malloc failed for create threads\n"); - taos_close(taos); + errorPrint("%s() LN%d, malloc failed for create threads\n", + __func__, __LINE__); + // taos_close(taos); exit(-1); } - int ntables = g_queryInfo.subQueryInfo.childTblCount; - int threads = g_queryInfo.subQueryInfo.threadCnt; - + int ntables = g_queryInfo.superQueryInfo.childTblCount; + int threads = g_queryInfo.superQueryInfo.threadCnt; + int a = ntables / threads; if (a < 1) { threads = ntables; a = 1; } - + int b = 0; if (threads != 0) { b = ntables % threads; } - + int startFrom = 0; for (int i = 0; i < threads; i++) { threadInfo *t_info = infosOfSub + i; @@ -5941,26 +6159,27 @@ static int subscribeTestProcess() { t_info->ntables = iend_table_to = i < b ? startFrom + a : startFrom + a - 1; startFrom = t_info->end_table_to + 1; - t_info->taos = taos; + t_info->taos = NULL; // TODO: workaround to use separate taos connection; pthread_create(pidsOfSub + i, NULL, subSubscribeProcess, t_info); } - g_queryInfo.subQueryInfo.threadCnt = threads; + + g_queryInfo.superQueryInfo.threadCnt = threads; + + for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) { + pthread_join(pidsOfSub[i], NULL); + } } - - for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) { + + for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) { pthread_join(pids[i], NULL); - } + } tmfree((char*)pids); tmfree((char*)infos); - for (int i = 0; i < g_queryInfo.subQueryInfo.threadCnt; i++) { - pthread_join(pidsOfSub[i], NULL); - } - tmfree((char*)pidsOfSub); tmfree((char*)infosOfSub); - taos_close(taos); +// taos_close(taos); return 0; } @@ -5968,10 +6187,10 @@ static void initOfInsertMeta() { memset(&g_Dbs, 0, sizeof(SDbs)); // set default values - tstrncpy(g_Dbs.host, "127.0.0.1", MAX_DB_NAME_SIZE); + tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE); g_Dbs.port = 6030; - tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_DB_NAME_SIZE); - tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_DB_NAME_SIZE); + tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE); + tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE); g_Dbs.threadCount = 2; g_Dbs.use_metric = g_args.use_metric; @@ -5981,25 +6200,25 @@ static void initOfQueryMeta() { memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo)); // set default values - tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_DB_NAME_SIZE); + tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE); g_queryInfo.port = 6030; - tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_DB_NAME_SIZE); - tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_DB_NAME_SIZE); + tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE); + tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE); } static void setParaFromArg(){ if (g_args.host) { - strcpy(g_Dbs.host, g_args.host); + tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE); } else { - tstrncpy(g_Dbs.host, "127.0.0.1", MAX_DB_NAME_SIZE); + tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE); } if (g_args.user) { - strcpy(g_Dbs.user, g_args.user); + tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE); } if (g_args.password) { - strcpy(g_Dbs.password, g_args.password); + tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE); } if (g_args.port) { @@ -6041,7 +6260,7 @@ static void setParaFromArg(){ g_Dbs.threadCount = g_args.num_of_threads; g_Dbs.threadCountByCreateTbl = g_args.num_of_threads; g_Dbs.queryMode = g_args.mode; - + g_Dbs.db[0].superTbls[0].autoCreateTable = PRE_CREATE_SUBTBL; g_Dbs.db[0].superTbls[0].childTblExists = TBL_NO_EXISTS; g_Dbs.db[0].superTbls[0].disorderRange = g_args.disorderRange; @@ -6055,14 +6274,14 @@ static void setParaFromArg(){ g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP; g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT; - g_Dbs.db[0].superTbls[0].maxSqlLen = TSDB_PAYLOAD_SIZE; + g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len; g_Dbs.db[0].superTbls[0].columnCount = 0; for (int i = 0; i < MAX_NUM_DATATYPE; i++) { if (data_type[i] == NULL) { break; } - + tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType, data_type[i], MAX_TB_NAME_SIZE); g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary; @@ -6081,7 +6300,7 @@ static void setParaFromArg(){ tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType, "INT", MAX_TB_NAME_SIZE); g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0; - + tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType, "BINARY", MAX_TB_NAME_SIZE); g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary; g_Dbs.db[0].superTbls[0].tagCount = 2; @@ -6219,12 +6438,12 @@ static void queryResult() { rInfo->ntables = g_Dbs.db[0].superTbls[0].childTblCount; rInfo->end_table_to = g_Dbs.db[0].superTbls[0].childTblCount - 1; rInfo->superTblInfo = &g_Dbs.db[0].superTbls[0]; - strcpy(rInfo->tb_prefix, - g_Dbs.db[0].superTbls[0].childTblPrefix); + tstrncpy(rInfo->tb_prefix, + g_Dbs.db[0].superTbls[0].childTblPrefix, MAX_TB_NAME_SIZE); } else { rInfo->ntables = g_args.num_of_tables; rInfo->end_table_to = g_args.num_of_tables -1; - strcpy(rInfo->tb_prefix, g_args.tb_prefix); + tstrncpy(rInfo->tb_prefix, g_args.tb_prefix, MAX_TB_NAME_SIZE); } rInfo->taos = taos_connect( @@ -6240,7 +6459,7 @@ static void queryResult() { exit(-1); } - strcpy(rInfo->fp, g_Dbs.resultFile); + tstrncpy(rInfo->fp, g_Dbs.resultFile, MAX_FILE_NAME_LEN); if (!g_Dbs.use_metric) { pthread_create(&read_id, NULL, readTable, rInfo); diff --git a/src/mnode/inc/mnodeVgroup.h b/src/mnode/inc/mnodeVgroup.h index e052cdb83cbbffa0ceb1119bc49da52a23e02e2b..7b798c23f8b3414d40e504990bb75812d829102a 100644 --- a/src/mnode/inc/mnodeVgroup.h +++ b/src/mnode/inc/mnodeVgroup.h @@ -49,6 +49,7 @@ void mnodeRemoveTableFromVgroup(SVgObj *pVgroup, SCTableObj *pTable); void mnodeSendDropVnodeMsg(int32_t vgId, SRpcEpSet *epSet, void *ahandle); void mnodeSendCreateVgroupMsg(SVgObj *pVgroup, void *ahandle); void mnodeSendAlterVgroupMsg(SVgObj *pVgroup); +void mnodeSendSyncVgroupMsg(SVgObj *pVgroup); SRpcEpSet mnodeGetEpSetFromVgroup(SVgObj *pVgroup); SRpcEpSet mnodeGetEpSetFromIp(char *ep); diff --git a/src/mnode/src/mnodeDb.c b/src/mnode/src/mnodeDb.c index 0a82b8f27cf8cd1e0b88fc7f40674769affaefe1..909ca7cac6ec04af7d6c624a8d7fea06e7cad702 100644 --- a/src/mnode/src/mnodeDb.c +++ b/src/mnode/src/mnodeDb.c @@ -1186,8 +1186,44 @@ static int32_t mnodeProcessDropDbMsg(SMnodeMsg *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) { - return 0; + SSyncDbMsg *pSyncDb = pMsg->rpcMsg.pCont; + mDebug("db:%s, syncdb is received from thandle:%p, ignore:%d", pSyncDb->db, pMsg->rpcMsg.handle, pSyncDb->ignoreNotExists); + + if (pMsg->pDb == NULL) pMsg->pDb = mnodeGetDb(pSyncDb->db); + if (pMsg->pDb == NULL) { + if (pSyncDb->ignoreNotExists) { + mDebug("db:%s, db is not exist, treat as success", pSyncDb->db); + return TSDB_CODE_SUCCESS; + } else { + mError("db:%s, failed to sync, invalid db", pSyncDb->db); + return TSDB_CODE_MND_INVALID_DB; + } + } + + if (pMsg->pDb->status != TSDB_DB_STATUS_READY) { + mError("db:%s, status:%d, in dropping", pSyncDb->db, pMsg->pDb->status); + return TSDB_CODE_MND_DB_IN_DROPPING; + } + + return mnodeSyncDb(pMsg->pDb, pMsg); } void mnodeDropAllDbs(SAcctObj *pAcct) { diff --git a/src/mnode/src/mnodeDnode.c b/src/mnode/src/mnodeDnode.c index 304096f3ae6178bdb5b7ce0620d81cf29bef11d0..db03da4fe1752bb0d2c4a380530c205d3a953339 100644 --- a/src/mnode/src/mnodeDnode.c +++ b/src/mnode/src/mnodeDnode.c @@ -722,6 +722,10 @@ int32_t mnodeDropDnode(SDnodeObj *pDnode, void *pMsg) { static int32_t mnodeDropDnodeByEp(char *ep, SMnodeMsg *pMsg) { SDnodeObj *pDnode = mnodeGetDnodeByEp(ep); 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); pDnode = mnodeGetDnode(dnodeId); if (pDnode == NULL) { diff --git a/src/mnode/src/mnodeVgroup.c b/src/mnode/src/mnodeVgroup.c index fdbf7ae398e10d754b82d01a002f79130071d3c7..7eb3122d83032ed9759236bf999210008cdb908c 100644 --- a/src/mnode/src/mnodeVgroup.c +++ b/src/mnode/src/mnodeVgroup.c @@ -60,6 +60,7 @@ static int32_t mnodeGetVgroupMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *p static int32_t mnodeRetrieveVgroups(SShowObj *pShow, char *data, int32_t rows, void *pConn); static void mnodeProcessCreateVnodeRsp(SRpcMsg *rpcMsg); static void mnodeProcessAlterVnodeRsp(SRpcMsg *rpcMsg); +static void mnodeProcessSyncVnodeRsp(SRpcMsg *rpcMsg); static void mnodeProcessDropVnodeRsp(SRpcMsg *rpcMsg); static int32_t mnodeProcessVnodeCfgMsg(SMnodeMsg *pMsg) ; static void mnodeSendDropVgroupMsg(SVgObj *pVgroup, void *ahandle); @@ -236,6 +237,7 @@ int32_t mnodeInitVgroups() { mnodeAddShowFreeIterHandle(TSDB_MGMT_TABLE_VGROUP, mnodeCancelGetNextVgroup); mnodeAddPeerRspHandle(TSDB_MSG_TYPE_MD_CREATE_VNODE_RSP, mnodeProcessCreateVnodeRsp); mnodeAddPeerRspHandle(TSDB_MSG_TYPE_MD_ALTER_VNODE_RSP, mnodeProcessAlterVnodeRsp); + mnodeAddPeerRspHandle(TSDB_MSG_TYPE_MD_ALTER_VNODE_RSP, mnodeProcessSyncVnodeRsp); mnodeAddPeerRspHandle(TSDB_MSG_TYPE_MD_DROP_VNODE_RSP, mnodeProcessDropVnodeRsp); mnodeAddPeerMsgHandle(TSDB_MSG_TYPE_DM_CONFIG_VNODE, mnodeProcessVnodeCfgMsg); @@ -967,6 +969,38 @@ void mnodeSendAlterVgroupMsg(SVgObj *pVgroup) { } } +static SSyncVnodeMsg *mnodeBuildSyncVnodeMsg(int32_t vgId) { + SSyncVnodeMsg *pSyncVnode = rpcMallocCont(sizeof(SSyncVnodeMsg)); + if (pSyncVnode == NULL) return NULL; + + pSyncVnode->vgId = htonl(vgId); + return pSyncVnode; +} + +static void mnodeSendSyncVnodeMsg(SVgObj *pVgroup, SRpcEpSet *epSet) { + SSyncVnodeMsg *pSyncVnode = mnodeBuildSyncVnodeMsg(pVgroup->vgId); + SRpcMsg rpcMsg = { + .ahandle = NULL, + .pCont = pSyncVnode, + .contLen = pSyncVnode ? sizeof(SSyncVnodeMsg) : 0, + .code = 0, + .msgType = TSDB_MSG_TYPE_MD_SYNC_VNODE + }; + + dnodeSendMsgToDnode(epSet, &rpcMsg); +} + +void mnodeSendSyncVgroupMsg(SVgObj *pVgroup) { + mDebug("vgId:%d, send sync all vnodes msg, numOfVnodes:%d db:%s", pVgroup->vgId, pVgroup->numOfVnodes, + pVgroup->dbName); + for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) { + SRpcEpSet epSet = mnodeGetEpSetFromIp(pVgroup->vnodeGid[i].pDnode->dnodeEp); + mDebug("vgId:%d, index:%d, send sync vnode msg to dnode %s", pVgroup->vgId, i, + pVgroup->vnodeGid[i].pDnode->dnodeEp); + mnodeSendSyncVnodeMsg(pVgroup, &epSet); + } +} + static void mnodeSendCreateVnodeMsg(SVgObj *pVgroup, SRpcEpSet *epSet, void *ahandle) { SCreateVnodeMsg *pCreate = mnodeBuildVnodeMsg(pVgroup); SRpcMsg rpcMsg = { @@ -994,6 +1028,10 @@ static void mnodeProcessAlterVnodeRsp(SRpcMsg *rpcMsg) { mDebug("alter vnode rsp received"); } +static void mnodeProcessSyncVnodeRsp(SRpcMsg *rpcMsg) { + mDebug("sync vnode rsp received"); +} + static void mnodeProcessCreateVnodeRsp(SRpcMsg *rpcMsg) { if (rpcMsg->ahandle == NULL) return; diff --git a/src/sync/inc/syncInt.h b/src/sync/inc/syncInt.h index 2b87938474d9385e5d093dcf524be777eb22db27..91613ae35107f0a667798e730f6021687e3ced5e 100644 --- a/src/sync/inc/syncInt.h +++ b/src/sync/inc/syncInt.h @@ -117,7 +117,6 @@ typedef struct SSyncNode { FStartSyncFile startSyncFileFp; FStopSyncFile stopSyncFileFp; FGetVersion getVersionFp; - FResetVersion resetVersionFp; FSendFile sendFileFp; FRecvFile recvFileFp; pthread_mutex_t mutex; diff --git a/src/sync/src/syncMain.c b/src/sync/src/syncMain.c index 264bbf6b925b2244e38915326f7b9eaf9e8831ad..d21743d40ab43b90a7654a8e0c10ca49e2d62cd8 100644 --- a/src/sync/src/syncMain.c +++ b/src/sync/src/syncMain.c @@ -182,7 +182,6 @@ int64_t syncStart(const SSyncInfo *pInfo) { pNode->startSyncFileFp = pInfo->startSyncFileFp; pNode->stopSyncFileFp = pInfo->stopSyncFileFp; pNode->getVersionFp = pInfo->getVersionFp; - pNode->resetVersionFp = pInfo->resetVersionFp; pNode->sendFileFp = pInfo->sendFileFp; pNode->recvFileFp = pInfo->recvFileFp; @@ -410,7 +409,7 @@ void syncConfirmForward(int64_t rid, uint64_t version, int32_t code, bool force) syncReleaseNode(pNode); } -#if 0 +#if 1 void syncRecover(int64_t rid) { SSyncPeer *pPeer; diff --git a/src/sync/src/syncRestore.c b/src/sync/src/syncRestore.c index 22d0a2758131f3880adc63f3777528c8e3d06ff9..c0d66316cd5b802ddcaddf1015d4ceca1aa3b2c5 100644 --- a/src/sync/src/syncRestore.c +++ b/src/sync/src/syncRestore.c @@ -238,7 +238,6 @@ static int32_t syncRestoreDataStepByStep(SSyncPeer *pPeer) { (*pNode->stopSyncFileFp)(pNode->vgId, fversion); nodeVersion = fversion; - if (pNode->resetVersionFp) (*pNode->resetVersionFp)(pNode->vgId, fversion); sInfo("%s, start to restore wal, fver:%" PRIu64, pPeer->id, nodeVersion); uint64_t wver = 0; diff --git a/src/tsdb/src/tsdbCommit.c b/src/tsdb/src/tsdbCommit.c index 7cbc681149258ffa632666eeae17085e6b18c2ce..4351cce51c09f86fc06cee59c94b800c44e60b1c 100644 --- a/src/tsdb/src/tsdbCommit.c +++ b/src/tsdb/src/tsdbCommit.c @@ -17,7 +17,7 @@ #define TSDB_MAX_SUBBLOCKS 8 static FORCE_INLINE int TSDB_KEY_FID(TSKEY key, int32_t days, int8_t precision) { if (key < 0) { - return (int)((key + 1) / tsMsPerDay[precision] / days + 1); + return (int)((key + 1) / tsMsPerDay[precision] / days - 1); } else { return (int)((key / tsMsPerDay[precision] / days)); } @@ -452,6 +452,14 @@ static int tsdbCommitToFile(SCommitH *pCommith, SDFileSet *pSet, int fid) { return -1; } + if (tsdbUpdateDFileSetHeader(&(pCommith->wSet)) < 0) { + tsdbError("vgId:%d failed to update FSET %d header since %s", REPO_ID(pRepo), fid, tstrerror(terrno)); + tsdbCloseCommitFile(pCommith, true); + // revert the file change + tsdbApplyDFileSetChange(TSDB_COMMIT_WRITE_FSET(pCommith), pSet); + return -1; + } + // Close commit file tsdbCloseCommitFile(pCommith, false); diff --git a/src/tsdb/src/tsdbFS.c b/src/tsdb/src/tsdbFS.c index a9e74cb229df24800bd920186113669164ca7dc7..c9f087a5cfe25967786b07c03217c89f1e1dd249 100644 --- a/src/tsdb/src/tsdbFS.c +++ b/src/tsdb/src/tsdbFS.c @@ -33,6 +33,7 @@ static int tsdbScanDataDir(STsdbRepo *pRepo); static bool tsdbIsTFileInFS(STsdbFS *pfs, const TFILE *pf); static int tsdbRestoreCurrent(STsdbRepo *pRepo); static int tsdbComparTFILE(const void *arg1, const void *arg2); +static void tsdbScanAndTryFixDFilesHeader(STsdbRepo *pRepo); // ================== CURRENT file header info static int tsdbEncodeFSHeader(void **buf, SFSHeader *pHeader) { @@ -246,6 +247,8 @@ int tsdbOpenFS(STsdbRepo *pRepo) { tsdbError("vgId:%d failed to open FS since %s", REPO_ID(pRepo), tstrerror(terrno)); return -1; } + + tsdbScanAndTryFixDFilesHeader(pRepo); } else { if (tsdbRestoreCurrent(pRepo) < 0) { tsdbError("vgId:%d failed to restore current file since %s", REPO_ID(pRepo), tstrerror(terrno)); @@ -1201,4 +1204,41 @@ static int tsdbComparTFILE(const void *arg1, const void *arg2) { return 0; } } +} + +static void tsdbScanAndTryFixDFilesHeader(STsdbRepo *pRepo) { + STsdbFS * pfs = REPO_FS(pRepo); + SFSStatus *pStatus = pfs->cstatus; + SDFInfo info; + + for (size_t i = 0; i < taosArrayGetSize(pStatus->df); i++) { + SDFileSet fset; + tsdbInitDFileSetEx(&fset, (SDFileSet *)taosArrayGet(pStatus->df, i)); + + tsdbDebug("vgId:%d scan DFileSet %d header", REPO_ID(pRepo), fset.fid); + + if (tsdbOpenDFileSet(&fset, O_RDWR) < 0) { + tsdbError("vgId:%d failed to open DFileSet %d since %s, continue", REPO_ID(pRepo), fset.fid, tstrerror(terrno)); + continue; + } + + for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) { + SDFile *pDFile = TSDB_DFILE_IN_SET(&fset, ftype); + + if ((tsdbLoadDFileHeader(pDFile, &info) < 0) || pDFile->info.size != info.size || + pDFile->info.magic != info.magic) { + if (tsdbUpdateDFileHeader(pDFile) < 0) { + tsdbError("vgId:%d failed to update DFile header of %s since %s, continue", REPO_ID(pRepo), + TSDB_FILE_FULL_NAME(pDFile), tstrerror(terrno)); + } else { + tsdbInfo("vgId:%d DFile header of %s is updated", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile)); + TSDB_FILE_FSYNC(pDFile); + } + } else { + tsdbDebug("vgId:%d DFile header of %s is correct", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile)); + } + } + + tsdbCloseDFileSet(&fset); + } } \ No newline at end of file diff --git a/src/tsdb/src/tsdbFile.c b/src/tsdb/src/tsdbFile.c index ac33096aaeb2536a70b5226ce1b5bdb8856903b8..5db993e46346dcbde81507faa774d431a1607781 100644 --- a/src/tsdb/src/tsdbFile.c +++ b/src/tsdb/src/tsdbFile.c @@ -134,14 +134,14 @@ int tsdbCreateMFile(SMFile *pMFile, bool updateHeader) { return 0; } + pMFile->info.size += TSDB_FILE_HEAD_SIZE; + if (tsdbUpdateMFileHeader(pMFile) < 0) { tsdbCloseMFile(pMFile); tsdbRemoveMFile(pMFile); return -1; } - pMFile->info.size += TSDB_FILE_HEAD_SIZE; - return 0; } @@ -378,14 +378,14 @@ int tsdbCreateDFile(SDFile *pDFile, bool updateHeader) { return 0; } + pDFile->info.size += TSDB_FILE_HEAD_SIZE; + if (tsdbUpdateDFileHeader(pDFile) < 0) { tsdbCloseDFile(pDFile); tsdbRemoveDFile(pDFile); return -1; } - pDFile->info.size += TSDB_FILE_HEAD_SIZE; - return 0; } @@ -567,6 +567,7 @@ void tsdbInitDFileSet(SDFileSet *pSet, SDiskID did, int vid, int fid, uint32_t v } void tsdbInitDFileSetEx(SDFileSet *pSet, SDFileSet *pOSet) { + pSet->fid = pOSet->fid; for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) { tsdbInitDFileEx(TSDB_DFILE_IN_SET(pSet, ftype), TSDB_DFILE_IN_SET(pOSet, ftype)); } diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 6c0137abf568c23363a88b679ff47180aeb6491f..ea72760568293043b0cb415ee1beb6c0866ab5f9 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -917,7 +917,9 @@ static int32_t loadBlockInfo(STsdbQueryHandle * pQueryHandle, int32_t index, int pCheckInfo->compSize = compIndex->len; } - tsdbLoadBlockInfo(&(pQueryHandle->rhelper), (void*)(pCheckInfo->pCompInfo)); + if (tsdbLoadBlockInfo(&(pQueryHandle->rhelper), (void*)(pCheckInfo->pCompInfo)) < 0) { + return terrno; + } SBlockInfo* pCompInfo = pCheckInfo->pCompInfo; TSKEY s = TSKEY_INITIAL_VAL, e = TSKEY_INITIAL_VAL; @@ -2832,7 +2834,9 @@ int32_t tsdbRetrieveDataBlockStatisInfo(TsdbQueryHandleT* pQueryHandle, SDataSta } int64_t stime = taosGetTimestampUs(); - tsdbLoadBlockStatis(&pHandle->rhelper, pBlockInfo->compBlock); + if (tsdbLoadBlockStatis(&pHandle->rhelper, pBlockInfo->compBlock) < 0) { + return terrno; + } int16_t* colIds = pHandle->defaultLoadColumn->pData; diff --git a/src/tsdb/src/tsdbSync.c b/src/tsdb/src/tsdbSync.c index cef561aebea002649e8458057882094a7e42d9b4..5a2756537e6a37c8b4a0e7c3e1f81199523df2eb 100644 --- a/src/tsdb/src/tsdbSync.c +++ b/src/tsdb/src/tsdbSync.c @@ -194,8 +194,8 @@ static int32_t tsdbSyncRecvMeta(SSyncH *pSynch) { return 0; } - if (pLMFile == NULL || memcmp(&(pSynch->pmf->info), &(pLMFile->info), sizeof(SMFInfo)) != 0 || - TSDB_FILE_IS_BAD(pLMFile)) { + if (pLMFile == NULL || pSynch->pmf->info.size != pLMFile->info.size || + pSynch->pmf->info.magic != pLMFile->info.magic || TSDB_FILE_IS_BAD(pLMFile)) { // Local has no meta file or has a different meta file, need to copy from remote pSynch->mfChanged = true; @@ -536,7 +536,7 @@ static bool tsdbIsTowFSetSame(SDFileSet *pSet1, SDFileSet *pSet2) { SDFile *pDFile1 = TSDB_DFILE_IN_SET(pSet1, ftype); SDFile *pDFile2 = TSDB_DFILE_IN_SET(pSet2, ftype); - if (memcmp((void *)(TSDB_FILE_INFO(pDFile1)), (void *)(TSDB_FILE_INFO(pDFile2)), sizeof(SDFInfo)) != 0) { + if (pDFile1->info.size != pDFile2->info.size || pDFile1->info.magic != pDFile2->info.magic) { return false; } } diff --git a/src/vnode/inc/vnodeBackup.h b/src/vnode/inc/vnodeBackup.h new file mode 100644 index 0000000000000000000000000000000000000000..0a6b26546c809fd27701bf8194243a2a79561fcb --- /dev/null +++ b/src/vnode/inc/vnodeBackup.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef TDENGINE_VNODE_BACKUP_H +#define TDENGINE_VNODE_BACKUP_H + +#ifdef __cplusplus +extern "C" { +#endif +#include "vnodeInt.h" + +int32_t vnodeInitBackup(); +void vnodeCleanupBackup(); +int32_t vnodeBackup(int32_t vgId); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/vnode/inc/vnodeMain.h b/src/vnode/inc/vnodeMain.h index 73591bc10d97dfbe519cf9e5c1f73a96c8fa0854..91a5d632cd64d7979b77dcf86472ddf3be2aa1b4 100644 --- a/src/vnode/inc/vnodeMain.h +++ b/src/vnode/inc/vnodeMain.h @@ -25,6 +25,7 @@ int32_t vnodeCreate(SCreateVnodeMsg *pVnodeCfg); int32_t vnodeDrop(int32_t vgId); int32_t vnodeOpen(int32_t vgId); int32_t vnodeAlter(void *pVnode, SCreateVnodeMsg *pVnodeCfg); +int32_t vnodeSync(int32_t vgId); int32_t vnodeClose(int32_t vgId); void vnodeCleanUp(SVnodeObj *pVnode); void vnodeDestroy(SVnodeObj *pVnode); @@ -33,4 +34,4 @@ void vnodeDestroy(SVnodeObj *pVnode); } #endif -#endif \ No newline at end of file +#endif diff --git a/src/vnode/inc/vnodeSync.h b/src/vnode/inc/vnodeSync.h index 75d7ffbabda514f3d280c712fbd531aedbc3e0d7..28fb63dd6a2db971b430b526b4304a37c3ece9a1 100644 --- a/src/vnode/inc/vnodeSync.h +++ b/src/vnode/inc/vnodeSync.h @@ -30,7 +30,6 @@ void vnodeStopSyncFile(int32_t vgId, uint64_t fversion); void vnodeConfirmForard(int32_t vgId, void *wparam, int32_t code); int32_t vnodeWriteToCache(int32_t vgId, void *wparam, int32_t qtype, void *rparam); int32_t vnodeGetVersion(int32_t vgId, uint64_t *fver, uint64_t *wver); -int32_t vnodeResetVersion(int32_t vgId, uint64_t fver); void vnodeConfirmForward(void *pVnode, uint64_t version, int32_t code, bool force); diff --git a/src/vnode/src/vnodeBackup.c b/src/vnode/src/vnodeBackup.c new file mode 100644 index 0000000000000000000000000000000000000000..a0a975be2bcfbb2c945a72adecbf47f9cf404b40 --- /dev/null +++ b/src/vnode/src/vnodeBackup.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#define _DEFAULT_SOURCE +#include "os.h" +#include "taoserror.h" +#include "taosmsg.h" +#include "tutil.h" +#include "tqueue.h" +#include "tglobal.h" +#include "tfs.h" +#include "vnodeBackup.h" +#include "vnodeMain.h" + +typedef struct { + int32_t vgId; +} SVBackupMsg; + +typedef struct { + pthread_t thread; + int32_t workerId; +} SVBackupWorker; + +typedef struct { + int32_t num; + SVBackupWorker *worker; +} SVBackupWorkerPool; + +static SVBackupWorkerPool tsVBackupPool; +static taos_qset tsVBackupQset; +static taos_queue tsVBackupQueue; + +static void vnodeProcessBackupMsg(SVBackupMsg *pMsg) { + int32_t vgId = pMsg->vgId; + char newDir[TSDB_FILENAME_LEN] = {0}; + char stagingDir[TSDB_FILENAME_LEN] = {0}; + + sprintf(newDir, "%s/vnode%d", "vnode_bak", vgId); + sprintf(stagingDir, "%s/.staging/vnode%d", "vnode_bak", vgId); + + if (tsEnableVnodeBak) { + tfsRmdir(newDir); + tfsRename(stagingDir, newDir); + } else { + vInfo("vgId:%d, vnode backup not enabled", vgId); + + tfsRmdir(stagingDir); + } +} + +static void *vnodeBackupFunc(void *param) { + while (1) { + SVBackupMsg *pMsg = NULL; + if (taosReadQitemFromQset(tsVBackupQset, NULL, (void **)&pMsg, NULL) == 0) { + vDebug("qset:%p, vbackup got no message from qset, exiting", tsVBackupQset); + break; + } + + vTrace("vgId:%d, will be processed in vbackup queue", pMsg->vgId); + vnodeProcessBackupMsg(pMsg); + + vTrace("vgId:%d, disposed in vbackup worker", pMsg->vgId); + taosFreeQitem(pMsg); + } + + return NULL; +} + +static int32_t vnodeStartBackup() { + tsVBackupQueue = taosOpenQueue(); + if (tsVBackupQueue == NULL) return TSDB_CODE_DND_OUT_OF_MEMORY; + + taosAddIntoQset(tsVBackupQset, tsVBackupQueue, NULL); + + for (int32_t i = 0; i < tsVBackupPool.num; ++i) { + SVBackupWorker *pWorker = tsVBackupPool.worker + i; + pWorker->workerId = i; + + pthread_attr_t thAttr; + pthread_attr_init(&thAttr); + pthread_attr_setdetachstate(&thAttr, PTHREAD_CREATE_JOINABLE); + + if (pthread_create(&pWorker->thread, &thAttr, vnodeBackupFunc, pWorker) != 0) { + vError("failed to create thread to process vbackup queue, reason:%s", strerror(errno)); + } + + pthread_attr_destroy(&thAttr); + + vDebug("vbackup:%d is launched, total:%d", pWorker->workerId, tsVBackupPool.num); + } + + vDebug("vbackup queue:%p is allocated", tsVBackupQueue); + + return TSDB_CODE_SUCCESS; +} + +static int32_t vnodeWriteIntoBackupWorker(int32_t vgId) { + SVBackupMsg *pMsg = taosAllocateQitem(sizeof(SVBackupMsg)); + if (pMsg == NULL) return TSDB_CODE_VND_OUT_OF_MEMORY; + + pMsg->vgId = vgId; + + int32_t code = taosWriteQitem(tsVBackupQueue, TAOS_QTYPE_RPC, pMsg); + if (code == 0) code = TSDB_CODE_DND_ACTION_IN_PROGRESS; + + return code; +} + +int32_t vnodeBackup(int32_t vgId) { + vTrace("vgId:%d, will backup", vgId); + return vnodeWriteIntoBackupWorker(vgId); +} + +int32_t vnodeInitBackup() { + tsVBackupQset = taosOpenQset(); + + tsVBackupPool.num = 1; + tsVBackupPool.worker = calloc(sizeof(SVBackupWorker), tsVBackupPool.num); + + if (tsVBackupPool.worker == NULL) return -1; + for (int32_t i = 0; i < tsVBackupPool.num; ++i) { + SVBackupWorker *pWorker = tsVBackupPool.worker + i; + pWorker->workerId = i; + vDebug("vbackup:%d is created", i); + } + + vDebug("vbackup is initialized, num:%d qset:%p", tsVBackupPool.num, tsVBackupQset); + + return vnodeStartBackup(); +} + +void vnodeCleanupBackup() { + for (int32_t i = 0; i < tsVBackupPool.num; ++i) { + SVBackupWorker *pWorker = tsVBackupPool.worker + i; + if (taosCheckPthreadValid(pWorker->thread)) { + taosQsetThreadResume(tsVBackupQset); + } + vDebug("vbackup:%d is closed", i); + } + + for (int32_t i = 0; i < tsVBackupPool.num; ++i) { + SVBackupWorker *pWorker = tsVBackupPool.worker + i; + vDebug("vbackup:%d start to join", i); + if (taosCheckPthreadValid(pWorker->thread)) { + pthread_join(pWorker->thread, NULL); + } + vDebug("vbackup:%d join success", i); + } + + vDebug("vbackup is closed, qset:%p", tsVBackupQset); + + taosCloseQset(tsVBackupQset); + tsVBackupQset = NULL; + + tfree(tsVBackupPool.worker); + + vDebug("vbackup queue:%p is freed", tsVBackupQueue); + taosCloseQueue(tsVBackupQueue); + tsVBackupQueue = NULL; +} diff --git a/src/vnode/src/vnodeMain.c b/src/vnode/src/vnodeMain.c index ded39e67cc37d7733f4e7aaa9998b4578e05c122..69d94aff87388a96664b40b7db1d1c1e906ca8b2 100644 --- a/src/vnode/src/vnodeMain.c +++ b/src/vnode/src/vnodeMain.c @@ -27,6 +27,7 @@ #include "vnodeVersion.h" #include "vnodeMgmt.h" #include "vnodeWorker.h" +#include "vnodeBackup.h" #include "vnodeMain.h" static int32_t vnodeProcessTsdbStatus(void *arg, int32_t status, int32_t eno); @@ -91,6 +92,23 @@ int32_t vnodeCreate(SCreateVnodeMsg *pVnodeCfg) { return code; } +int32_t vnodeSync(int32_t vgId) { + SVnodeObj *pVnode = vnodeAcquire(vgId); + if (pVnode == NULL) { + vDebug("vgId:%d, failed to sync, vnode not find", vgId); + return TSDB_CODE_VND_INVALID_VGROUP_ID; + } + + if (pVnode->role != TAOS_SYNC_ROLE_MASTER) { + vInfo("vgId:%d, vnode will sync, refCount:%d pVnode:%p", pVnode->vgId, pVnode->refCount, pVnode); + syncRecover(pVnode->sync); + } + + vnodeRelease(pVnode); + + return TSDB_CODE_SUCCESS; +} + int32_t vnodeDrop(int32_t vgId) { SVnodeObj *pVnode = vnodeAcquire(vgId); if (pVnode == NULL) { @@ -347,7 +365,6 @@ int32_t vnodeOpen(int32_t vgId) { syncInfo.startSyncFileFp = vnodeStartSyncFile; syncInfo.stopSyncFileFp = vnodeStopSyncFile; syncInfo.getVersionFp = vnodeGetVersion; - syncInfo.resetVersionFp = vnodeResetVersion; syncInfo.sendFileFp = tsdbSyncSend; syncInfo.recvFileFp = tsdbSyncRecv; syncInfo.pTsdb = pVnode->tsdb; @@ -431,18 +448,14 @@ void vnodeDestroy(SVnodeObj *pVnode) { if (pVnode->dropped) { char rootDir[TSDB_FILENAME_LEN] = {0}; - char newDir[TSDB_FILENAME_LEN] = {0}; + char stagingDir[TSDB_FILENAME_LEN] = {0}; sprintf(rootDir, "%s/vnode%d", "vnode", vgId); - sprintf(newDir, "%s/vnode%d", "vnode_bak", vgId); + sprintf(stagingDir, "%s/.staging/vnode%d", "vnode_bak", vgId); - if (0 == tsEnableVnodeBak) { - vInfo("vgId:%d, vnode backup not enabled", pVnode->vgId); - } else { - tfsRmdir(newDir); - tfsRename(rootDir, newDir); - } + tfsRename(rootDir, stagingDir); + + vnodeBackup(vgId); - tfsRmdir(rootDir); dnodeSendStatusMsgToMnode(); } diff --git a/src/vnode/src/vnodeMgmt.c b/src/vnode/src/vnodeMgmt.c index 71d9bc07f50b6a8cba06d68b9b06b24f4dadcf83..32f95321383981924c5b6496bd4302edca19da5e 100644 --- a/src/vnode/src/vnodeMgmt.c +++ b/src/vnode/src/vnodeMgmt.c @@ -17,6 +17,7 @@ #include "os.h" #include "dnode.h" #include "vnodeStatus.h" +#include "vnodeBackup.h" #include "vnodeWorker.h" #include "vnodeRead.h" #include "vnodeWrite.h" @@ -29,6 +30,7 @@ static void vnodeCleanupHash(void); static void vnodeIncRef(void *ptNode); static SStep tsVnodeSteps[] = { + {"vnode-backup", vnodeInitBackup, vnodeCleanupBackup}, {"vnode-worker", vnodeInitMWorker, vnodeCleanupMWorker}, {"vnode-write", vnodeInitWrite, vnodeCleanupWrite}, {"vnode-read", vnodeInitRead, vnodeCleanupRead}, diff --git a/src/vnode/src/vnodeSync.c b/src/vnode/src/vnodeSync.c index 929dd1592610b03a41027781d66470b13756174a..aa4cf0fc15bd9db749888699baf90a97bfbeb39f 100644 --- a/src/vnode/src/vnodeSync.c +++ b/src/vnode/src/vnodeSync.c @@ -107,8 +107,9 @@ void vnodeStopSyncFile(int32_t vgId, uint64_t fversion) { pVnode->fversion = fversion; pVnode->version = fversion; vnodeSaveVersion(pVnode); + walResetVersion(pVnode->wal, fversion); - vDebug("vgId:%d, datafile is synced, fver:%" PRIu64 " vver:%" PRIu64, vgId, fversion, fversion); + vInfo("vgId:%d, datafile is synced, fver:%" PRIu64 " vver:%" PRIu64, vgId, fversion, fversion); vnodeSetReadyStatus(pVnode); vnodeRelease(pVnode); @@ -158,22 +159,6 @@ int32_t vnodeGetVersion(int32_t vgId, uint64_t *fver, uint64_t *wver) { return code; } -int32_t vnodeResetVersion(int32_t vgId, uint64_t fver) { - SVnodeObj *pVnode = vnodeAcquire(vgId); - if (pVnode == NULL) { - vError("vgId:%d, vnode not found while reset version", vgId); - return -1; - } - - pVnode->fversion = fver; - pVnode->version = fver; - walResetVersion(pVnode->wal, fver); - vInfo("vgId:%d, version reset to %" PRIu64, vgId, fver); - - vnodeRelease(pVnode); - return 0; -} - void vnodeConfirmForward(void *vparam, uint64_t version, int32_t code, bool force) { SVnodeObj *pVnode = vparam; syncConfirmForward(pVnode->sync, version, code, force); diff --git a/tests/Jenkinsfile b/tests/Jenkinsfile index 6db6351442a5b67b4088216dc27990097f56618a..178a0446c387118b167ee98e0fb39d6466697e92 100644 --- a/tests/Jenkinsfile +++ b/tests/Jenkinsfile @@ -76,9 +76,20 @@ pipeline { catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { sh ''' cd ${WKC}/tests/pytest + rm -rf /var/lib/taos/* + rm -rf /var/log/taos/* ./handle_crash_gen_val_log.sh ''' } + catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { + sh ''' + cd ${WKC}/tests/pytest + rm -rf /var/lib/taos/* + rm -rf /var/log/taos/* + ./handle_taosd_val_log.sh + ''' + } + sh''' systemctl start taosd sleep 10 @@ -163,6 +174,11 @@ pipeline { cd ${WKC}/tests ./test-all.sh b3 date''' + sh ''' + date + cd ${WKC}/tests + ./test-all.sh full example + date''' } } diff --git a/tests/examples/JDBC/JDBCDemo/pom.xml b/tests/examples/JDBC/JDBCDemo/pom.xml index 167e7e37ae410dd865aa2e08c7f885961f9ddadd..66e866a2d3753b574ba6a4b180fc5740dd4aeef6 100644 --- a/tests/examples/JDBC/JDBCDemo/pom.xml +++ b/tests/examples/JDBC/JDBCDemo/pom.xml @@ -13,7 +13,7 @@ com.taosdata.jdbc taos-jdbcdriver - 2.0.20 + 2.0.22 diff --git a/tests/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JDBCDemo.java b/tests/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JDBCDemo.java index 07a21e79d1cd188528fbbc7548e35fac78c65600..da865b3ffde0fbd6af1b39e52a99ca5f190abda6 100644 --- a/tests/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JDBCDemo.java +++ b/tests/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JDBCDemo.java @@ -68,12 +68,12 @@ public class JDBCDemo { } private void insert() { - final String sql = "insert into test.weather (ts, temperature, humidity) values(now, 20.5, 34)"; + final String sql = "insert into " + dbName + "." + tbName + " (ts, temperature, humidity) values(now, 20.5, 34)"; exuete(sql); } private void select() { - final String sql = "select * from test.weather"; + final String sql = "select * from "+ dbName + "." + tbName; executeQuery(sql); } diff --git a/tests/perftest-scripts/perftest-query.sh b/tests/perftest-scripts/perftest-query.sh index e43a45ed5e87ec81fc86e1af4733c0e859af69f0..8b9fa1a546eedc955b4b902a20731a4736d8f60d 100755 --- a/tests/perftest-scripts/perftest-query.sh +++ b/tests/perftest-scripts/perftest-query.sh @@ -50,7 +50,7 @@ function buildTDengine { echo "repo up-to-date" else echo "repo need to pull" - git pull > /dev/null + git pull > /dev/null 2>&1 LOCAL_COMMIT=`git rev-parse --short @` cd debug @@ -71,27 +71,14 @@ function runQueryPerfTest { python3 query/queryPerformance.py -c $LOCAL_COMMIT | tee -a $PERFORMANCE_TEST_REPORT python3 insert/insertFromCSVPerformance.py -c $LOCAL_COMMIT | tee -a $PERFORMANCE_TEST_REPORT - - yes | taosdemo -c /etc/taosperf/ -d taosdemo_insert_test -x > taosdemoperf.txt - - CREATETABLETIME=`grep 'Spent' taosdemoperf.txt | awk 'NR==1{print $2}'` - INSERTRECORDSTIME=`grep 'Spent' taosdemoperf.txt | awk 'NR==2{print $2}'` - REQUESTSPERSECOND=`grep 'Spent' taosdemoperf.txt | awk 'NR==2{print $13}'` - delay=`grep 'delay' taosdemoperf.txt | awk '{print $4}'` - AVGDELAY=`echo ${delay:0:${#delay}-3}` - delay=`grep 'delay' taosdemoperf.txt | awk '{print $6}'` - MAXDELAY=`echo ${delay:0:${#delay}-3}` - delay=`grep 'delay' taosdemoperf.txt | awk '{print $8}'` - MINDELAY=`echo ${delay:0:${#delay}-2}` - python3 tools/taosdemoPerformance.py -c $LOCAL_COMMIT -t $CREATETABLETIME -i $INSERTRECORDSTIME -r $REQUESTSPERSECOND -avg $AVGDELAY -max $MAXDELAY -min $MINDELAY | tee -a $PERFORMANCE_TEST_REPORT - [ -f taosdemoperf.txt ] && rm taosdemoperf.txt + python3 tools/taosdemoPerformance.py -c $LOCAL_COMMIT | tee -a $PERFORMANCE_TEST_REPORT } function sendReport { echo "send report" - receiver="pxiao@taosdata.com" + receiver="develop@taosdata.com" mimebody="MIME-Version: 1.0\nContent-Type: text/html; charset=utf-8\n" cd $TDENGINE_DIR diff --git a/tests/pytest/fulltest.sh b/tests/pytest/fulltest.sh index fc86570bd249d60ebb719e2cf6866b3a273fe238..bda52ffe6c7ab6cafe8a66fe18cdf4e3072759b9 100755 --- a/tests/pytest/fulltest.sh +++ b/tests/pytest/fulltest.sh @@ -139,6 +139,18 @@ python3 ./test.py -f import_merge/importInsertThenImport.py python3 ./test.py -f import_merge/importCSV.py #======================p1-end=============== #======================p2-start=============== +# tools +python3 test.py -f tools/taosdumpTest.py + +python3 test.py -f tools/taosdemoTest.py +python3 test.py -f tools/taosdemoTestWithoutMetric.py +python3 test.py -f tools/taosdemoTestWithJson.py +python3 test.py -f tools/taosdemoTestLimitOffset.py +python3 test.py -f tools/taosdemoTestTblAlt.py +python3 test.py -f tools/taosdemoTestSampleData.py +python3 test.py -f tools/taosdemoTestInterlace.py +python3 test.py -f tools/taosdemoTestQuery.py + # update python3 ./test.py -f update/allow_update.py python3 ./test.py -f update/allow_update-0.py @@ -164,6 +176,11 @@ python3 ./test.py -f user/pass_len.py # stable python3 ./test.py -f stable/query_after_reset.py +# perfbenchmark +python3 ./test.py -f perfbenchmark/bug3433.py +python3 ./test.py -f perfbenchmark/bug3589.py + + #query python3 ./test.py -f query/filter.py python3 ./test.py -f query/filterCombo.py @@ -196,6 +213,8 @@ python3 ./test.py -f query/bug2119.py python3 ./test.py -f query/isNullTest.py python3 ./test.py -f query/queryWithTaosdKilled.py python3 ./test.py -f query/floatCompare.py +python3 ./test.py -f query/query1970YearsAf.py +python3 ./test.py -f query/bug3351.py python3 ./test.py -f query/bug3375.py @@ -242,18 +261,6 @@ python3 test.py -f subscribe/supertable.py #======================p3-end=============== #======================p4-start=============== -# tools -python3 test.py -f tools/taosdumpTest.py - -python3 test.py -f tools/taosdemoTest.py -python3 test.py -f tools/taosdemoTestWithoutMetric.py -python3 test.py -f tools/taosdemoTestWithJson.py -python3 test.py -f tools/taosdemoTestLimitOffset.py -python3 test.py -f tools/taosdemoTest2.py -python3 test.py -f tools/taosdemoTestSampleData.py -python3 test.py -f tools/taosdemoTestInterlace.py -python3 test.py -f tools/taosdemoTestQuery.py - python3 ./test.py -f update/merge_commit_data-0.py # wal python3 ./test.py -f wal/addOldWalTest.py diff --git a/tests/pytest/handle_taosd_val_log.sh b/tests/pytest/handle_taosd_val_log.sh new file mode 100755 index 0000000000000000000000000000000000000000..6b7f669efe3577945081f20d4c9c9e78f774a7b2 --- /dev/null +++ b/tests/pytest/handle_taosd_val_log.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# Color setting +RED='\033[0;31m' +GREEN='\033[1;32m' +GREEN_DARK='\033[0;32m' +GREEN_UNDERLINE='\033[4;32m' +NC='\033[0m' +IN_TDINTERNAL="community" +TDIR=`pwd` +if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]]; then + cd ../.. +else + cd ../../.. +fi +TOP_DIR=`pwd` +TAOSD_DIR=`find . -name "taosd"|grep -v community|grep debug|head -n1` +VALGRIND_OUT=taosd_valgrind.out +VALGRIND_ERR=taosd_valgrind.err +rm -rf /var/lib/taos/* +# nohup valgrind --tool=memcheck --leak-check=yes $TAOSD_DIR > $TDIR/$VALGRIND_OUT 2> $TDIR/$VALGRIND_ERR & +nohup valgrind --leak-check=yes $TAOSD_DIR > $TDIR/$VALGRIND_OUT 2> $TDIR/$VALGRIND_ERR & +sleep 20 +cd - +./crash_gen.sh -p -t 10 -s 200 +ps -ef |grep valgrind|grep -v grep|awk '{print $2}'|xargs kill -term +while true +do + monitoring=` ps -ef|grep valgrind |grep -v grep| wc -l` + if [ $monitoring -eq 0 ] + then + echo "Manipulator is not running " + break + else + sleep 1 + fi +done + +grep 'start to execute\|ERROR SUMMARY' $VALGRIND_ERR | grep -v 'grep' | uniq | tee taosd_mem_err.log + +for memError in `grep 'ERROR SUMMARY' taosd_mem_err.log | awk '{print $4}'` +do +memError=(${memError//,/}) +if [ -n "$memError" ]; then + if [ "$memError" -gt 12 ]; then + echo -e "${RED} ## Memory errors number valgrind reports is $memError.\ + More than our threshold! ## ${NC}" + fi +fi +done + +grep 'start to execute\|definitely lost:' $VALGRIND_ERR|grep -v 'grep'|uniq|tee taosd-definitely-lost-out.log +for defiMemError in `grep 'definitely lost:' taosd-definitely-lost-out.log | awk '{print $7}'` +do +defiMemError=(${defiMemError//,/}) +if [ -n "$defiMemError" ]; then + if [ "$defiMemError" -gt 0 -a "$defiMemError" -lt 1013 ]; then + cat $VALGRIND_ERR + echo -e "${RED} ## Memory errors number valgrind reports \ + Definitely lost is $defiMemError. More than our threshold! ## ${NC}" + exit 8 + elif [ "$defiMemError" -gt 1013 ];then #add for azure + cat $VALGRIND_ERR + echo -e "${RED} ## Memory errors number valgrind reports \ + Definitely lost is $defiMemError. More than our threshold! ## ${NC}" + exit 8 + fi +fi +done diff --git a/tests/pytest/insert/metadataUpdate.py b/tests/pytest/insert/metadataUpdate.py index 76b9a3ae8f818e3bf3784eb99974ce56b1071af5..4c32b0e39ac87bbb5741c77a90f94374fc0e8f5e 100644 --- a/tests/pytest/insert/metadataUpdate.py +++ b/tests/pytest/insert/metadataUpdate.py @@ -25,6 +25,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) self.ts = 1538548685000 + self.tables = 10 + self.rows = 1000 def updateMetadata(self): self.host = "127.0.0.1" @@ -37,6 +39,29 @@ class TDTestCase: self.cursor.execute("alter table db.tb add column col2 int") print("alter table done") + def deleteTableAndRecreate(self): + self.host = "127.0.0.1" + self.user = "root" + self.password = "taosdata" + self.config = tdDnodes.getSimCfgPath() + + self.conn = taos.connect(host = self.host, user = self.user, password = self.password, config = self.config) + self.cursor = self.conn.cursor() + + self.cursor.execute("use test") + print("drop table stb") + self.cursor.execute("drop table stb") + + print("create table stb") + self.cursor.execute("create table if not exists stb (ts timestamp, col1 int) tags(areaid int, city nchar(20))") + print("insert data") + for i in range(self.tables): + city = "beijing" if i % 2 == 0 else "shanghai" + self.cursor.execute("create table tb%d using stb tags(%d, '%s')" % (i, i, city)) + for j in range(self.rows): + self.cursor.execute("insert into tb%d values(%d, %d)" % (i, self.ts + j, j * 100000)) + + def run(self): tdSql.prepare() @@ -59,6 +84,36 @@ class TDTestCase: tdSql.query("select * from tb") tdSql.checkRows(2) + # Add test case: https://jira.taosdata.com:18080/browse/TD-3474 + + print("==============step1") + tdSql.execute("create database test") + tdSql.execute("use test") + tdSql.execute("create table if not exists stb (ts timestamp, col1 int) tags(areaid int, city nchar(20))") + + for i in range(self.tables): + city = "beijing" if i % 2 == 0 else "shanghai" + tdSql.execute("create table tb%d using stb tags(%d, '%s')" % (i, i, city)) + for j in range(self.rows): + tdSql.execute("insert into tb%d values(%d, %d)" % (i, self.ts + j, j * 100000)) + + tdSql.query("select count(*) from stb") + tdSql.checkData(0, 0, 10000) + + tdSql.query("select count(*) from tb1") + tdSql.checkData(0, 0, 1000) + + p = Process(target=self.deleteTableAndRecreate, args=()) + p.start() + p.join() + p.terminate() + + tdSql.query("select count(*) from stb") + tdSql.checkData(0, 0, 10000) + + tdSql.query("select count(*) from tb1") + tdSql.checkData(0, 0, 1000) + def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/pytest/perfbenchmark/bug3433.py b/tests/pytest/perfbenchmark/bug3433.py new file mode 100644 index 0000000000000000000000000000000000000000..80e9cce0dc60937b3eaf7c122a8ae5951fd1ad6b --- /dev/null +++ b/tests/pytest/perfbenchmark/bug3433.py @@ -0,0 +1,245 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import json + +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import * + + +class TDTestCase: + def __init__(self): + self.path = "" + + def init(self, conn, logSql): + tdLog.debug(f"start to execute {__file__}") + tdSql.init(conn.cursor(), logSql) + + def getBuildPath(self): + selfPath = os.path.dirname(os.path.realpath(__file__)) + + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] + else: + projPath = selfPath[:selfPath.find("tests")] + + for root, dirs, files in os.walk(projPath): + if ("taosd" in files): + rootRealPath = os.path.dirname(os.path.realpath(root)) + if ("packaging" not in rootRealPath): + buildPath = root[:len(root) - len("/build/bin")] + break + return buildPath + + def getcfgPath(self, path): + binPath = os.path.dirname(os.path.realpath(__file__)) + binPath = binPath + "/../../../debug/" + tdLog.debug(f"binPath {binPath}") + binPath = os.path.realpath(binPath) + tdLog.debug(f"binPath real path {binPath}") + if path == "": + self.path = os.path.abspath(binPath + "../../") + else: + self.path = os.path.realpath(path) + return self.path + + def getCfgDir(self): + self.getcfgPath(self.path) + self.cfgDir = f"{self.path}/sim/psim/cfg" + return self.cfgDir + + def creatcfg(self): + dbinfo = { + "name": "db", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 16, + "blocks": 8, + "precision": "ms", + "keep": 3650, + "minRows": 100, + "maxRows": 4096, + "comp": 2, + "walLevel": 1, + "cachelast": 0, + "quorum": 1, + "fsync": 3000, + "update": 0 + } + + # set stable schema + stable1 = { + "name": "stb1", + "child_table_exists": "no", + "childtable_count": 1000, + "childtable_prefix": "t1", + "auto_create_table": "no", + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 1, + "multi_thread_write_one_tbl": "no", + "number_of_tbl_in_one_sql": 0, + "rows_per_tbl": 1, + "max_sql_len": 65480, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 20000, + "start_timestamp": "2020-12-31 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [ + {"type": "INT", "count": 2}, + {"type": "DOUBLE", "count": 2}, + {"type": "BIGINT", "count": 2}, + {"type": "FLOAT", "count": 2}, + {"type": "SMALLINT", "count": 2}, + {"type": "TINYINT", "count": 2}, + {"type": "BOOL", "count": 2}, + {"type": "NCHAR", "len": 3, "count": 1}, + {"type": "BINARY", "len": 8, "count": 1} + + ], + "tags": [ + {"type": "INT", "count": 2}, + {"type": "DOUBLE", "count": 2}, + {"type": "BIGINT", "count": 2}, + {"type": "FLOAT", "count": 2}, + {"type": "SMALLINT", "count": 2}, + {"type": "TINYINT", "count": 2}, + {"type": "BOOL", "count": 2}, + {"type": "NCHAR", "len": 3, "count": 1}, + {"type": "BINARY", "len": 8, "count": 1} + ] + } + stable2 = { + "name": "stb2", + "child_table_exists": "no", + "childtable_count": 1000, + "childtable_prefix": "t2", + "auto_create_table": "no", + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 1, + "multi_thread_write_one_tbl": "no", + "number_of_tbl_in_one_sql": 0, + "rows_per_tbl": 1, + "max_sql_len": 65480, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 20000, + "start_timestamp": "2020-12-31 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [ + {"type": "INT", "count": 2}, + {"type": "DOUBLE", "count": 2}, + {"type": "BIGINT", "count": 2}, + {"type": "FLOAT", "count": 2}, + {"type": "SMALLINT", "count": 2}, + {"type": "TINYINT", "count": 2}, + {"type": "BOOL", "count": 2}, + {"type": "NCHAR", "len": 3, "count": 1}, + {"type": "BINARY", "len": 8, "count": 1} + + ], + "tags": [ + {"type": "INT", "count": 2}, + {"type": "DOUBLE", "count": 2}, + {"type": "BIGINT", "count": 2}, + {"type": "FLOAT", "count": 2}, + {"type": "SMALLINT", "count": 2}, + {"type": "TINYINT", "count": 2}, + {"type": "BOOL", "count": 2}, + {"type": "NCHAR", "len": 3, "count": 1}, + {"type": "BINARY", "len": 8, "count": 1} + ] + } + + # create different stables like stable1 and add to list super_tables + super_tables = [] + super_tables.append(stable1) + super_tables.append(stable2) + database = { + "dbinfo": dbinfo, + "super_tables": super_tables + } + + cfgdir = self.getCfgDir() + create_table = { + "filetype": "insert", + "cfgdir": cfgdir, + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "/tmp/insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "num_of_records_per_req": 100, + "databases": [database] + } + return create_table + + def createinsertfile(self): + create_table = self.creatcfg() + date = datetime.datetime.now().strftime("%Y%m%d%H%M") + file_create_table = f"/tmp/insert_{date}.json" + + with open(file_create_table, 'w') as f: + json.dump(create_table, f) + return file_create_table + + def inserttable(self, filepath): + buildPath = self.getBuildPath() + if (buildPath == ""): + tdLog.exit("taosd not found!") + else: + tdLog.info(f"taosd found in {buildPath}") + binPath = buildPath + "/build/bin/" + + create_table_cmd = f"{binPath}taosdemo -f {filepath} > /dev/null 2>&1" + _ = subprocess.check_output(create_table_cmd, shell=True).decode("utf-8") + + def droptmpfile(self): + drop_file_cmd = "rm -f /tmp/insert_* " + _ = subprocess.check_output(drop_file_cmd, shell=True).decode("utf-8") + + def run(self): + tdLog.printNoPrefix("==========step1:create database and insert records") + file_create_table = self.createinsertfile() + self.inserttable(file_create_table) + + tdLog.printNoPrefix("==========step2:check database and stable records") + tdSql.query("show databases") + tdSql.checkData(0, 2, 2000) + tdSql.execute("use db") + tdSql.query("show stables") + tdSql.checkData(0, 4, 1000) + tdSql.checkData(1, 4, 1000) + + self.droptmpfile() + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/pytest/perfbenchmark/bug3589.py b/tests/pytest/perfbenchmark/bug3589.py new file mode 100644 index 0000000000000000000000000000000000000000..c54ef8595d0bea1c4984b3f90e282f09659576c3 --- /dev/null +++ b/tests/pytest/perfbenchmark/bug3589.py @@ -0,0 +1,156 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import json + +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import * + + +class TDTestCase: + def __init__(self): + self.path = "" + + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + def getBuildPath(self): + selfPath = os.path.dirname(os.path.realpath(__file__)) + + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] + else: + projPath = selfPath[:selfPath.find("tests")] + + for root, dirs, files in os.walk(projPath): + if ("taosd" in files): + rootRealPath = os.path.dirname(os.path.realpath(root)) + if ("packaging" not in rootRealPath): + buildPath = root[:len(root) - len("/debug/build/bin")] + break + return buildPath + + def getCfgDir(self): + return self.getBuildPath() + "/sim/psim/cfg" + + def querycfg(self): + cfgdir = self.getCfgDir() + querycfg={ + "filetype": "query", + "cfgdir": cfgdir, + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "confirm_parameter_prompt": "yes", + "databases": "db", + "specified_table_query": { + "query_interval": 0, + "concurrent": 1, + "sqls": [ + { + "sql": "select * from t10, t11 where t10.ts=t11.ts" + } + ] + } + } + + return querycfg + + def querycfgfile(self): + querycfg = self.querycfg() + date = datetime.datetime.now().strftime("%Y%m%d%H%M") + querycfg.get("specified_table_query").get("sqls")[0]["result"] = f"/tmp/query_{date}.log" + file_query_table = f"/tmp/query_{date}.json" + with open(file_query_table, "w") as f: + json.dump(querycfg, f) + + return [file_query_table, querycfg] + + def querytable(self, filepath): + buildPath = self.getBuildPath() + if (buildPath == ""): + tdLog.exit("taosd not found!") + else: + tdLog.info(f"taosd found in {buildPath}") + binPath = buildPath + "/debug/build/bin/" + + query_table_cmd = f"yes | {binPath}taosdemo -f {filepath}" + _ = subprocess.check_output(query_table_cmd, shell=True).decode("utf-8") + + def checkqueryresult(self, expectrows): + querycfg = self.querycfgfile()[1] + result_file = querycfg.get("specified_table_query").get("sqls")[0].get("result") + "-0" + if result_file: + check_cmd = f"wc -l {result_file}" + check_data_init = subprocess.check_output(check_cmd, shell=True).decode("utf-8") + check_data = int(check_data_init[0]) + if check_data == expectrows: + tdLog.info(f"queryResultRows:{check_data} == expect:{expectrows}") + else: + caller = inspect.getframeinfo(inspect.stack()[1][0]) + args = (caller.filename, caller.lineno, check_data, expectrows) + tdLog.exit(f"{args[0]}({args[1]}) failed: result:{args[2]} != expect:{args[3]}") + + def droptmpfile(self): + drop_file_cmd = "rm -f /tmp/query_* " + _ = subprocess.check_output(drop_file_cmd, shell=True).decode("utf-8") + drop_file_cmd = "rm -f querySystemInfo-*" + _ = subprocess.check_output(drop_file_cmd, shell=True).decode("utf-8") + + def run(self): + tdSql.prepare() + + tdLog.printNoPrefix("==========step1:create table && insert data") + tdSql.execute("alter database db keep 36500") + tdSql.execute( + "create table stb1 (ts timestamp, c1 int) TAGS(t1 int)" + ) + tdSql.execute("create table t10 using stb1 tags(1)") + tdSql.execute("create table t11 using stb1 tags(2)") + + tdSql.execute("insert into t10 values (-865000000, 1)") + tdSql.execute("insert into t11 values (-865000000, 2)") + tdSql.execute("insert into t10 values ('1969-12-31 23:59:59.000', 2)") + tdSql.execute("insert into t11 values ('1969-12-31 23:59:59.000', 3)") + tdSql.execute("insert into t10 values ('1970-01-01 00:00:00.000', 3)") + tdSql.execute("insert into t11 values ('1970-01-01 00:00:00.000', 4)") + tdSql.execute("insert into t10 values (-15230000, 4)") + tdSql.execute("insert into t11 values (-15230000, 5)") + tdSql.execute("insert into t10 values (-15220000, 5)") + tdSql.execute("insert into t11 values (-15220000, 6)") + tdSql.execute("insert into t10 values (-15210000, 6)") + tdSql.execute("insert into t11 values (-15210000, 7)") + tdSql.execute("insert into t10 values (0, 7)") + tdSql.execute("insert into t11 values (0, 8)") + tdSql.execute("insert into t10 values ('2020-10-01 00:00:00.000', 8)") + tdSql.execute("insert into t11 values ('2020-10-01 00:00:00.000', 9)") + + tdLog.printNoPrefix("==========step2:query") + query_file = self.querycfgfile()[0] + self.querytable(query_file) + self.checkqueryresult(8) + + self.droptmpfile() + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) \ No newline at end of file diff --git a/tests/pytest/query/bug3351.py b/tests/pytest/query/bug3351.py new file mode 100644 index 0000000000000000000000000000000000000000..288d071a69cac30e9e5666b4d39a8de5c29f91d9 --- /dev/null +++ b/tests/pytest/query/bug3351.py @@ -0,0 +1,74 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import * + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + def run(self): + tdSql.prepare() + tdSql.execute("drop database if exists db") + tdSql.execute("create database if not exists db keep 36500") + tdSql.execute("use db") + tdLog.printNoPrefix("==========step1:create table && insert data") + + tdSql.execute( + "create table stb1 (ts timestamp, c1 int) TAGS(t1 int)" + ) + tdSql.execute("create table t0 using stb1 tags(1)") + tdSql.execute("insert into t0 values (-865000000, 1)") + tdSql.execute("insert into t0 values (-864000000, 2)") + tdSql.execute("insert into t0 values (-863000000, 3)") + tdSql.execute("insert into t0 values (-15230000, 4)") + tdSql.execute("insert into t0 values (-15220000, 5)") + tdSql.execute("insert into t0 values (-15210000, 6)") + + tdLog.printNoPrefix("==========step2:query") + # bug1:when ts > -864000000, return 0 rows; + # bug2:when ts = -15220000, return 0 rows. + tdSql.query('select * from t0 where ts < -864000000') + tdSql.checkRows(1) + tdSql.query('select * from t0 where ts <= -864000000') + tdSql.checkRows(2) + tdSql.query('select * from t0 where ts = -864000000') + tdSql.checkRows(1) + tdSql.query('select * from t0 where ts > -864000000') + tdSql.checkRows(4) + tdSql.query('select * from t0 where ts >= -864000000') + tdSql.checkRows(5) + tdSql.query('select * from t0 where ts < -15220000') + tdSql.checkRows(4) + tdSql.query('select * from t0 where ts <= -15220000') + tdSql.checkRows(5) + tdSql.query('select * from t0 where ts = -15220000') + tdSql.checkRows(1) + tdSql.query('select * from t0 where ts > -15220000') + tdSql.checkRows(1) + tdSql.query('select * from t0 where ts >= -15220000') + tdSql.checkRows(2) + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) \ No newline at end of file diff --git a/tests/pytest/query/query1970YearsAf.py b/tests/pytest/query/query1970YearsAf.py index 9794973325b428ce185d6b9f7f5974293ad938f6..e66a79f5e6d4938bef62eccc93f4cec3de6fe712 100644 --- a/tests/pytest/query/query1970YearsAf.py +++ b/tests/pytest/query/query1970YearsAf.py @@ -22,25 +22,34 @@ import datetime from util.log import * from util.sql import * from util.cases import * +from util.dnodes import * +from util.dnodes import TDDnode class TDTestCase: + def __init__(self): + self.path = "" + def init(self, conn, logSql): tdLog.debug(f"start to excute {__file__}") tdSql.init(conn.cursor()) - def getCfgDir(self, path): + def getcfgPath(self, path): binPath = os.path.dirname(os.path.realpath(__file__)) binPath = binPath + "/../../../debug/" - tdLog.debug("binPath %s" % (binPath)) + tdLog.debug(f"binPath {binPath}") binPath = os.path.realpath(binPath) - tdLog.debug("binPath real path %s" % (binPath)) + tdLog.debug(f"binPath real path {binPath}") + if path == "": self.path = os.path.abspath(binPath + "../../") else: self.path = os.path.realpath(path) + return self.path - self.cfgDir = "%s/sim/psim/cfg" % (self.path) + def getCfgDir(self): + self.getcfgPath(self.path) + self.cfgDir = f"{self.path}/sim/psim/cfg" return self.cfgDir def creatcfg(self): @@ -63,7 +72,7 @@ class TDTestCase: "update": 0 } - # 设置创建的超级表格式 + # set stable schema stable1 = { "name": "stb2", "child_table_exists": "no", @@ -75,35 +84,49 @@ class TDTestCase: "insert_rows": 5000, "multi_thread_write_one_tbl": "no", "number_of_tbl_in_one_sql": 0, - "rows_per_tbl": 1000, + "rows_per_tbl": 1, "max_sql_len": 65480, "disorder_ratio": 0, "disorder_range": 1000, - "timestamp_step": 19000000, - "start_timestamp": "1969-01-01 00:00:00.000", + "timestamp_step": 20000, + "start_timestamp": "1969-12-31 00:00:00.000", "sample_format": "csv", "sample_file": "./sample.csv", "tags_file": "", "columns": [ - {"type": "INT"}, - {"type": "DOUBLE", "count": 10}, - {"type": "BINARY", "len": 16, "count": 3}, - {"type": "BINARY", "len": 32, "count": 6} + {"type": "INT", "count": 2}, + {"type": "DOUBLE", "count": 2}, + {"type": "BIGINT", "count": 2}, + {"type": "FLOAT", "count": 2}, + {"type": "SMALLINT", "count": 2}, + {"type": "TINYINT", "count": 2}, + {"type": "BOOL", "count": 2}, + {"type": "NCHAR", "len": 3, "count": 1}, + {"type": "BINARY", "len": 8, "count": 1} + ], "tags": [ + {"type": "INT", "count": 2}, + {"type": "DOUBLE", "count": 2}, + {"type": "BIGINT", "count": 2}, + {"type": "FLOAT", "count": 2}, + {"type": "SMALLINT", "count": 2}, {"type": "TINYINT", "count": 2}, - {"type": "BINARY", "len": 16, "count": 5} + {"type": "BOOL", "count": 2}, + {"type": "NCHAR", "len": 3, "count": 1}, + {"type": "BINARY", "len": 8, "count": 1} ] } - # 需要创建多个超级表时,只需创建不同的超级表格式并添加至super_tables - super_tables = [stable1] + # create different stables like stable1 and add to list super_tables + super_tables = [] + super_tables.append(stable1) database = { "dbinfo": dbinfo, "super_tables": super_tables } - cfgdir = self.getCfgDir("") + cfgdir = self.getCfgDir() create_table = { "filetype": "insert", "cfgdir": cfgdir, @@ -121,105 +144,110 @@ class TDTestCase: } return create_table - def inserttable(self): + def createinsertfile(self): create_table = self.creatcfg() date = datetime.datetime.now().strftime("%Y%m%d%H%M") file_create_table = f"/tmp/insert_{date}.json" with open(file_create_table, 'w') as f: json.dump(create_table, f) + return file_create_table - create_table_cmd = f"taosdemo -f {file_create_table}" + def inserttable(self, filepath): + create_table_cmd = f"taosdemo -f {filepath} > /dev/null 2>&1" _ = subprocess.check_output(create_table_cmd, shell=True).decode("utf-8") - - def run(self): - s = 'reset query cache' - tdSql.execute(s) - s = 'create database if not exists db' - tdSql.execute(s) - s = 'use db' - tdSql.execute(s) - - tdLog.info("==========step1:create table stable and child table,then insert data automatically") - self.inserttable() - # tdSql.execute( - # '''create table if not exists supt - # (ts timestamp, c1 int, c2 float, c3 bigint, c4 double, c5 smallint, c6 tinyint) - # tags(location binary(64), type int, isused bool , family nchar(64))''' - # ) - # tdSql.execute("create table t1 using supt tags('beijing', 1, 1, '自行车')") - # tdSql.execute("create table t2 using supt tags('shanghai', 2, 0, '拖拉机')") - # tdSql.execute( - # f"insert into t1 values (-31564800000, 6, 5, 4, 3, 2, 1)" - # ) - - - - tdLog.info("==========step2:query join") - + def sqlsquery(self): # stable query tdSql.query( "select * from stb2 where stb2.ts < '1970-01-01 00:00:00.000' " ) - tdSql.checkRows(16600) + tdSql.checkRows(43200) tdSql.query( "select * from stb2 where stb2.ts >= '1970-01-01 00:00:00.000' " ) - tdSql.checkRows(33400) + tdSql.checkRows(6800) tdSql.query( - "select * from stb2 where stb2.ts > '1969-12-01 00:00:00.000' and stb2.ts <'1970-01-31 00:00:00.000' " + "select * from stb2 where stb2.ts > '1969-12-31 23:00:00.000' and stb2.ts <'1970-01-01 01:00:00.000' " ) - tdSql.checkRows(2780) + tdSql.checkRows(3590) - # child-table query + # child-tables query tdSql.query( "select * from t0 where t0.ts < '1970-01-01 00:00:00.000' " ) - tdSql.checkRows(1660) + tdSql.checkRows(4320) tdSql.query( "select * from t1 where t1.ts >= '1970-01-01 00:00:00.000' " ) - tdSql.checkRows(3340) + tdSql.checkRows(680) tdSql.query( - "select * from t9 where t9.ts > '1969-12-01 00:00:00.000' and t9.ts <'1970-01-31 00:00:00.000' " + "select * from t9 where t9.ts > '1969-12-31 22:00:00.000' and t9.ts <'1970-01-01 02:00:00.000' " ) - tdSql.checkRows(278) - + tdSql.checkRows(719) + tdSql.query( "select * from t0,t1 where t0.ts=t1.ts and t1.ts >= '1970-01-01 00:00:00.000' " ) - tdSql.checkRows(3340) - + tdSql.checkRows(680) + tdSql.query( "select diff(col1) from t0 where t0.ts >= '1970-01-01 00:00:00.000' " ) - tdSql.checkRows(3339) + tdSql.checkRows(679) tdSql.query( "select t0,col1 from stb2 where stb2.ts < '1970-01-01 00:00:00.000' order by ts" ) - tdSql.checkRows(16600) + tdSql.checkRows(43200) # query with timestamp in 'where ...' tdSql.query( "select * from stb2 where stb2.ts > -28800000 " ) - tdSql.checkRows(33400) + tdSql.checkRows(6790) tdSql.query( "select * from stb2 where stb2.ts > -28800000 and stb2.ts < '1970-01-01 08:00:00.000' " ) - tdSql.checkRows(20) + tdSql.checkRows(6790) tdSql.query( - "select * from stb2 where stb2.ts < -28800000 and stb2.ts > '1969-12-31 16:00:00.000' " + "select * from stb2 where stb2.ts < -28800000 and stb2.ts > '1969-12-31 22:00:00.000' " ) + tdSql.checkRows(3590) + + def run(self): + s = 'reset query cache' + tdSql.execute(s) + s = 'create database if not exists db' + tdSql.execute(s) + s = 'use db' + tdSql.execute(s) + + tdLog.info("==========step1:create table stable and child table,then insert data automatically") + insertfile = self.createinsertfile() + self.inserttable(insertfile) + + tdLog.info("==========step2:query join") + self.sqlsquery() + + # after wal and sync, check again + tdSql.query("show dnodes") + index = tdSql.getData(0, 0) + tdDnodes.stop(index) + tdDnodes.start(index) + + tdLog.info("==========step3: query join again") + self.sqlsquery() + # delete temporary file + rm_cmd = f"rm -f /tmp/insert* > /dev/null 2>&1" + _ = subprocess.check_output(rm_cmd, shell=True).decode("utf-8") def stop(self): tdSql.close() diff --git a/tests/pytest/tools/taosdemoPerformance.py b/tests/pytest/tools/taosdemoPerformance.py index 28f451b6a08a43508352c75b0c498251c9afca54..1156cc2484799429f7f5fc689faee03453dad2ed 100644 --- a/tests/pytest/tools/taosdemoPerformance.py +++ b/tests/pytest/tools/taosdemoPerformance.py @@ -11,26 +11,16 @@ # -*- coding: utf-8 -*- -import sys import taos -import time -import datetime -import csv -import random import pandas as pd import argparse import os.path +import json class taosdemoPerformace: - def __init__(self, commitID, dbName, createTableTime, insertRecordsTime, recordsPerSecond, avgDelay, maxDelay, minDelay): + def __init__(self, commitID, dbName): self.commitID = commitID - self.dbName = dbName - self.createTableTime = createTableTime - self.insertRecordsTime = insertRecordsTime - self.recordsPerSecond = recordsPerSecond - self.avgDelay = avgDelay - self.maxDelay = maxDelay - self.minDelay = minDelay + self.dbName = dbName self.host = "127.0.0.1" self.user = "root" self.password = "taosdata" @@ -39,8 +29,97 @@ class taosdemoPerformace: self.host, self.user, self.password, - self.config) + self.config) + self.insertDB = "insertDB"; + def generateJson(self): + db = { + "name": "%s" % self.insertDB, + "drop": "yes", + "replica": 1 + } + + stb = { + "name": "meters", + "child_table_exists":"no", + "childtable_count": 10000, + "childtable_prefix": "stb_", + "auto_create_table": "no", + "data_source": "rand", + "batch_create_tbl_num": 10, + "insert_mode": "taosc", + "insert_rows": 100000, + "multi_thread_write_one_tbl": "no", + "number_of_tbl_in_one_sql": 0, + "rows_per_tbl": 100, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [ + {"type": "INT", "count": 4} + ], + "tags": [ + {"type": "INT", "count":1}, + {"type": "BINARY", "len": 16} + ] + } + + stables = [] + stables.append(stb) + + db = { + "dbinfo": db, + "super_tables": stables + } + + insert_data = { + "filetype": "insert", + "cfgdir": "/etc/taosperf", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 10, + "thread_count_create_tbl": 10, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "num_of_records_per_req": 30000, + "databases": [db] + } + + insert_json_file = f"/tmp/insert.json" + + with open(insert_json_file, 'w') as f: + json.dump(insert_data, f) + return insert_json_file + + def getCMDOutput(self, cmd): + cmd = os.popen(cmd) + output = cmd.read() + cmd.close() + return output + + def insertData(self): + os.system("taosdemo -f %s > taosdemoperf.txt" % self.generateJson()) + self.createTableTime = self.getCMDOutput("grep 'Spent' taosdemoperf.txt | awk 'NR==1{print $2}'") + self.insertRecordsTime = self.getCMDOutput("grep 'Spent' taosdemoperf.txt | awk 'NR==2{print $2}'") + self.recordsPerSecond = self.getCMDOutput("grep 'Spent' taosdemoperf.txt | awk 'NR==2{print $16}'") + self.commitID = self.getCMDOutput("git rev-parse --short HEAD") + delay = self.getCMDOutput("grep 'delay' taosdemoperf.txt | awk '{print $4}'") + self.avgDelay = delay[:-4] + delay = self.getCMDOutput("grep 'delay' taosdemoperf.txt | awk '{print $6}'") + self.maxDelay = delay[:-4] + delay = self.getCMDOutput("grep 'delay' taosdemoperf.txt | awk '{print $8}'") + self.minDelay = delay[:-3] + + os.system("[ -f taosdemoperf.txt ] && rm taosdemoperf.txt") + def createTablesAndStoreData(self): cursor = self.conn.cursor() @@ -48,14 +127,15 @@ class taosdemoPerformace: cursor.execute("use %s" % self.dbName) cursor.execute("create table if not exists taosdemo_perf (ts timestamp, create_table_time float, insert_records_time float, records_per_second float, commit_id binary(50), avg_delay float, max_delay float, min_delay float)") print("==================== taosdemo performance ====================") - print("create tables time: %f" % self.createTableTime) - print("insert records time: %f" % self.insertRecordsTime) - print("records per second: %f" % self.recordsPerSecond) - print("avg delay: %f" % self.avgDelay) - print("max delay: %f" % self.maxDelay) - print("min delay: %f" % self.minDelay) - cursor.execute("insert into taosdemo_perf values(now, %f, %f, %f, '%s', %f, %f, %f)" % (self.createTableTime, self.insertRecordsTime, self.recordsPerSecond, self.commitID, self.avgDelay, self.maxDelay, self.minDelay)) - cursor.execute("drop database if exists taosdemo_insert_test") + print("create tables time: %f" % float(self.createTableTime)) + print("insert records time: %f" % float(self.insertRecordsTime)) + print("records per second: %f" % float(self.recordsPerSecond)) + print("avg delay: %f" % float(self.avgDelay)) + print("max delay: %f" % float(self.maxDelay)) + print("min delay: %f" % float(self.minDelay)) + cursor.execute("insert into taosdemo_perf values(now, %f, %f, %f, '%s', %f, %f, %f)" % + (float(self.createTableTime), float(self.insertRecordsTime), float(self.recordsPerSecond), self.commitID, float(self.avgDelay), float(self.maxDelay), float(self.minDelay))) + cursor.execute("drop database if exists %s" % self.insertDB) cursor.close() @@ -64,7 +144,7 @@ if __name__ == '__main__': parser.add_argument( '-c', '--commit-id', - action='store', + action='store', type=str, help='git commit id (default: null)') parser.add_argument( @@ -74,46 +154,9 @@ if __name__ == '__main__': default='perf', type=str, help='Database name to be created (default: perf)') - parser.add_argument( - '-t', - '--create-table', - action='store', - type=float, - help='create table time') - parser.add_argument( - '-i', - '--insert-records', - action='store', - type=float, - help='insert records time') - parser.add_argument( - '-r', - '---records-per-second', - action='store', - type=float, - help='records per request') - parser.add_argument( - '-avg', - '---avg-delay', - action='store', - type=float, - help='avg delay') - parser.add_argument( - '-max', - '---max-delay', - action='store', - type=float, - help='max delay') - parser.add_argument( - '-min', - '---min-delay', - action='store', - type=float, - help='min delay') - args = parser.parse_args() - perftest = taosdemoPerformace(args.commit_id, args.database_name, args.create_table, args.insert_records, args.records_per_second, - args.avg_delay, args.max_delay, args.min_delay) + perftest = taosdemoPerformace(args.commit_id, args.database_name) + perftest.insertData() perftest.createTablesAndStoreData() \ No newline at end of file diff --git a/tests/pytest/tools/taosdemoTest2.py b/tests/pytest/tools/taosdemoTestTblAlt.py similarity index 57% rename from tests/pytest/tools/taosdemoTest2.py rename to tests/pytest/tools/taosdemoTestTblAlt.py index 92f6fa12657c4976bd975ffaa5358a510ae8f3f0..bb367817cf082a4a4b75f2deac6883d72d7ba145 100644 --- a/tests/pytest/tools/taosdemoTest2.py +++ b/tests/pytest/tools/taosdemoTestTblAlt.py @@ -29,17 +29,54 @@ class TDTestCase: self.numberOfTables = 10 self.numberOfRecords = 1000000 + def getBuildPath(self): + selfPath = os.path.dirname(os.path.realpath(__file__)) + + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] + else: + projPath = selfPath[:selfPath.find("tests")] + + for root, dirs, files in os.walk(projPath): + if ("taosd" in files): + rootRealPath = os.path.dirname(os.path.realpath(root)) + if ("packaging" not in rootRealPath): + buildPath = root[:len(root) - len("/build/bin")] + break + return buildPath + def insertDataAndAlterTable(self, threadID): + buildPath = self.getBuildPath() + if (buildPath == ""): + tdLog.exit("taosd not found!") + else: + tdLog.info("taosd found in %s" % buildPath) + binPath = buildPath + "/build/bin/" + if(threadID == 0): - os.system("taosdemo -y -t %d -n %d" % - (self.numberOfTables, self.numberOfRecords)) + os.system("%staosdemo -y -t %d -n %d" % + (binPath, self.numberOfTables, self.numberOfRecords)) if(threadID == 1): time.sleep(2) print("use test") - tdSql.execute("use test") + while True: + try: + tdSql.execute("use test") + break + except Exception as e: + tdLog.info("use database test failed") + time.sleep(1) + continue + # check if all the tables have heen created while True: - tdSql.query("show tables") + try: + tdSql.query("show tables") + except Exception as e: + tdLog.info("show tables test failed") + time.sleep(1) + continue + rows = tdSql.queryRows print("number of tables: %d" % rows) if(rows == self.numberOfTables): @@ -48,16 +85,23 @@ class TDTestCase: # check if there are any records in the last created table while True: print("query started") - tdSql.query("select * from test.t9") + try: + tdSql.query("select * from test.t9") + except Exception as e: + tdLog.info("select * test failed") + time.sleep(2) + continue + rows = tdSql.queryRows print("number of records: %d" % rows) if(rows > 0): break time.sleep(1) + print("alter table test.meters add column col10 int") tdSql.execute("alter table test.meters add column col10 int") - print("insert into test.t0 values (now, 1, 2, 3, 4, 0.1, 0.01,'test', '测试', TRUE, 1610000000000, 0)") - tdSql.execute("insert into test.t0 values (now, 1, 2, 3, 4, 0.1, 0.01,'test', '测试', TRUE, 1610000000000, 0)") + print("insert into test.t9 values (now, 1, 2, 3, 4, 0.1, 0.01,'test', '测试', TRUE, 1610000000000, 0)") + tdSql.execute("insert into test.t9 values (now, 1, 2, 3, 4, 0.1, 0.01,'test', '测试', TRUE, 1610000000000, 0)") def run(self): tdSql.prepare() @@ -70,6 +114,8 @@ class TDTestCase: t1.join() t2.join() + time.sleep(3) + tdSql.query("select count(*) from test.meters") tdSql.checkData(0, 0, self.numberOfRecords * self.numberOfTables + 1) diff --git a/tests/script/general/db/topic1.sim b/tests/script/general/db/topic1.sim index e17a4996f569450116a8050cc4e32905463cea4d..42613405afda7580003f58ae82f950880d60de62 100644 --- a/tests/script/general/db/topic1.sim +++ b/tests/script/general/db/topic1.sim @@ -878,5 +878,7 @@ if $rows != 0 then endi sql drop topic t2 +sql_error drop topic abc +sql drop topic if exists abc; system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/unique/dnode/remove2.sim b/tests/script/unique/dnode/remove2.sim index f97e55164b14bc62237513a057cff21c36073179..ff92ff7eb05e87cc88a76af2d40502b36f0d0e4f 100644 --- a/tests/script/unique/dnode/remove2.sim +++ b/tests/script/unique/dnode/remove2.sim @@ -120,7 +120,8 @@ sql show dnodes print dnode1 openVnodes $data2_1 print dnode2 openVnodes $data2_2 print dnode3 openVnodes $data2_3 -if $data2_3 != 0 then +# wait dnode3 create first vgroup in dnode-status msg +if $data2_3 != 1 then goto step4 endi @@ -181,4 +182,4 @@ system sh/exec.sh -n dnode4 -s stop -x SIGINT system sh/exec.sh -n dnode5 -s stop -x SIGINT system sh/exec.sh -n dnode6 -s stop -x SIGINT system sh/exec.sh -n dnode7 -s stop -x SIGINT -system sh/exec.sh -n dnode8 -s stop -x SIGINT \ No newline at end of file +system sh/exec.sh -n dnode8 -s stop -x SIGINT diff --git a/tests/test-all.sh b/tests/test-all.sh index ad3ad5fc94d0d5a4da5a9792085f2456ded0ade4..3c8aed7d186aab0038103fe50d57137d79db08e2 100755 --- a/tests/test-all.sh +++ b/tests/test-all.sh @@ -25,27 +25,24 @@ function stopTaosd { function dohavecore(){ corefile=`find $corepath -mmin 1` core_file=`echo $corefile|cut -d " " -f2` - echo $core_file proc=`echo $corefile|cut -d "_" -f3` if [ -n "$corefile" ];then echo 'taosd or taos has generated core' + rm case.log if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]] && [[ $1 == 1 ]]; then cd ../../../ tar -zcPf $corepath'taos_'`date "+%Y_%m_%d_%H_%M_%S"`.tar.gz debug/build/bin/taosd debug/build/bin/tsim debug/build/lib/libtaos*so* if [[ $2 == 1 ]];then cp -r sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S"` - rm -rf sim/case.log else cd community cp -r sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S" ` - rm -rf sim/case.log fi else cd ../../ if [[ $1 == 1 ]];then tar -zcPf $corepath'taos_'`date "+%Y_%m_%d_%H_%M_%S"`.tar.gz debug/build/bin/taosd debug/build/bin/tsim debug/build/lib/libtaos*so* cp -r sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S" ` - rm -rf sim/case.log fi fi if [[ $1 == 1 ]];then @@ -80,7 +77,6 @@ function runSimCaseOneByOne { # fi end_time=`date +%s` echo execution time of $case was `expr $end_time - $start_time`s. | tee -a out.log - dohavecore 0 fi done < $1 } @@ -97,26 +93,25 @@ function runSimCaseOneByOnefq { date +%F\ %T | tee -a out.log if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]]; then echo -n $case - ./test.sh -f $case > ../../../sim/case.log 2>&1 && \ + ./test.sh -f $case > case.log 2>&1 && \ ( grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \ ( grep -q 'script.*success.*m$' ../../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \ - ( echo -e "${RED} failed${NC}" | tee -a out.log && echo '=====================log=====================' && cat ../../../sim/case.log ) + ( echo -e "${RED} failed${NC}" | tee -a out.log && echo '=====================log=====================' && cat case.log ) else echo -n $case ./test.sh -f $case > ../../sim/case.log 2>&1 && \ ( grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \ ( grep -q 'script.*success.*m$' ../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \ - ( echo -e "${RED} failed${NC}" | tee -a out.log && echo '=====================log=====================' && cat ../../sim/case.log ) + ( echo -e "${RED} failed${NC}" | tee -a out.log && echo '=====================log=====================' && cat case.log ) fi out_log=`tail -1 out.log ` if [[ $out_log =~ 'failed' ]];then + rm case.log if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]]; then cp -r ../../../sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S"` - rm -rf ../../../sim/case.log else cp -r ../../sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S" ` - rm -rf ../../sim/case.log fi dohavecore $2 1 if [[ $2 == 1 ]];then @@ -157,7 +152,6 @@ function runPyCaseOneByOne { else $line > /dev/null 2>&1 fi - dohavecore 0 fi done < $1 } @@ -183,7 +177,7 @@ function runPyCaseOneByOnefq() { start_time=`date +%s` date +%F\ %T | tee -a pytest-out.log echo -n $case - $line > ../../sim/case.log 2>&1 && \ + $line > case.log 2>&1 && \ echo -e "${GREEN} success${NC}" | tee -a pytest-out.log || \ echo -e "${RED} failed${NC}" | tee -a pytest-out.log end_time=`date +%s` @@ -191,8 +185,8 @@ function runPyCaseOneByOnefq() { if [[ $out_log =~ 'failed' ]];then cp -r ../../sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S" ` echo '=====================log===================== ' - cat ../../sim/case.log - rm -rf ../../sim/case.log + cat case.log + rm -rf case.log dohavecore $2 2 if [[ $2 == 1 ]];then exit 8 @@ -212,9 +206,10 @@ totalFailed=0 totalPyFailed=0 totalJDBCFailed=0 totalUnitFailed=0 +totalExampleFailed=0 corepath=`grep -oP '.*(?=core_)' /proc/sys/kernel/core_pattern||grep -oP '.*(?=core-)' /proc/sys/kernel/core_pattern` -if [ "$2" != "jdbc" ] && [ "$2" != "python" ] && [ "$2" != "unit" ]; then +if [ "$2" != "jdbc" ] && [ "$2" != "python" ] && [ "$2" != "unit" ] && [ "$2" != "example" ]; then echo "### run TSIM test case ###" cd $tests_dir/script @@ -283,7 +278,7 @@ if [ "$2" != "jdbc" ] && [ "$2" != "python" ] && [ "$2" != "unit" ]; then fi fi -if [ "$2" != "sim" ] && [ "$2" != "jdbc" ] && [ "$2" != "unit" ]; then +if [ "$2" != "sim" ] && [ "$2" != "jdbc" ] && [ "$2" != "unit" ] && [ "$2" != "example" ]; then echo "### run Python test case ###" cd $tests_dir @@ -352,7 +347,7 @@ if [ "$2" != "sim" ] && [ "$2" != "jdbc" ] && [ "$2" != "unit" ]; then fi -if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "unit" ] && [ "$1" == "full" ]; then +if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "unit" ] && [ "$2" != "example" ] && [ "$1" == "full" ]; then echo "### run JDBC test cases ###" cd $tests_dir @@ -396,7 +391,7 @@ if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "unit" ] && [ "$1" == dohavecore 1 fi -if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$1" == "full" ]; then +if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$2" != "example" ] && [ "$1" == "full" ]; then echo "### run Unit tests ###" stopTaosd @@ -432,5 +427,80 @@ if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$1" == dohavecore 1 fi +if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$2" != "unit" ] && [ "$1" == "full" ]; then + echo "### run Example tests ###" -exit $(($totalFailed + $totalPyFailed + $totalJDBCFailed + $totalUnitFailed)) + stopTaosd + cd $tests_dir + + if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]]; then + cd ../../ + else + cd ../ + fi + + pwd + cd debug/build/bin + rm -rf /var/lib/taos/* + nohup ./taosd -c /etc/taos/ > /dev/null 2>&1 & + echo "sleeping for 30 seconds" + #sleep 30 + + cd $tests_dir + echo "current dir: " + pwd + cd examples/c + echo "building applications" + make > /dev/null + totalExamplePass=0 + + echo "Running tests" + ./apitest > /dev/null 2>&1 + if [ $? != "0" ]; then + echo "apitest failed" + totalExampleFailed=`expr $totalExampleFailed + 1` + else + echo "apitest pass" + totalExamplePass=`expr $totalExamplePass + 1` + fi + + ./prepare 127.0.0.1 > /dev/null 2>&1 + if [ $? != "0" ]; then + echo "prepare failed" + totalExampleFailed=`expr $totalExampleFailed + 1` + else + echo "prepare pass" + totalExamplePass=`expr $totalExamplePass + 1` + fi + + ./subscribe -test > /dev/null 2>&1 + if [ $? != "0" ]; then + echo "subscribe failed" + totalExampleFailed=`expr $totalExampleFailed + 1` + else + echo "subscribe pass" + totalExamplePass=`expr $totalExamplePass + 1` + fi + + yes |./asyncdemo 127.0.0.1 test 1000 10 > /dev/null 2>&1 + if [ $? != "0" ]; then + echo "asyncdemo failed" + totalExampleFailed=`expr $totalExampleFailed + 1` + else + echo "asyncdemo pass" + totalExamplePass=`expr $totalExamplePass + 1` + fi + + if [ "$totalExamplePass" -gt "0" ]; then + echo -e "\n${GREEN} ### Total $totalExamplePass examples succeed! ### ${NC}" + fi + + if [ "$totalExampleFailed" -ne "0" ]; then + echo -e "\n${RED} ### Total $totalExampleFailed examples failed! ### ${NC}" + fi + + dohavecore 1 +fi + + +exit $(($totalFailed + $totalPyFailed + $totalJDBCFailed + $totalUnitFailed + $totalExampleFailed))