Merge branch 'develop' into hotfix/test

This commit is contained in:
Hui Li 2021-01-08 13:43:01 +08:00
commit 117aa3032d
167 changed files with 5367 additions and 4335 deletions

View File

@ -146,7 +146,7 @@ matrix:
branch_pattern: coverity_scan branch_pattern: coverity_scan
- os: linux - os: linux
dist: xenial dist: trusty
language: c language: c
git: git:
- depth: 1 - depth: 1
@ -156,8 +156,9 @@ matrix:
packages: packages:
- build-essential - build-essential
- cmake - cmake
- binutils-2.26
env: env:
- DESC="xenial build" - DESC="trusty/gcc-4.8/bintuils-2.26 build"
before_script: before_script:
- export TZ=Asia/Harbin - export TZ=Asia/Harbin
@ -168,7 +169,7 @@ matrix:
script: script:
- cmake .. > /dev/null - cmake .. > /dev/null
- make - export PATH=/usr/lib/binutils-2.26/bin:$PATH && make
- os: linux - os: linux
dist: bionic dist: bionic
@ -200,7 +201,7 @@ matrix:
dist: bionic dist: bionic
language: c language: c
compiler: clang compiler: clang
env: DESC="linux/clang build" env: DESC="arm64 linux/clang build"
git: git:
- depth: 1 - depth: 1
@ -238,7 +239,7 @@ matrix:
- build-essential - build-essential
- cmake - cmake
env: env:
- DESC="xenial build" - DESC="arm64 xenial build"
before_script: before_script:
- export TZ=Asia/Harbin - export TZ=Asia/Harbin

4
Jenkinsfile vendored
View File

@ -104,6 +104,10 @@ pipeline {
find pytest -name '*'sql|xargs rm -rf find pytest -name '*'sql|xargs rm -rf
./test-all.sh p2 ./test-all.sh p2
date''' date'''
sh '''
cd ${WKC}/tests
./test-all.sh b4fq
'''
} }
} }
stage('test_b1') { stage('test_b1') {

View File

@ -33,11 +33,17 @@ To build TDengine, use [CMake](https://cmake.org/) 3.5 or higher versions in the
## Install tools ## Install tools
### Ubuntu & Debian: ### Ubuntu 16.04 and above & Debian:
```bash ```bash
sudo apt-get install -y gcc cmake build-essential git sudo apt-get install -y gcc cmake build-essential git
``` ```
### Ubuntu 14.04:
```bash
sudo apt-get install -y gcc cmake3 build-essential git binutils-2.26
export PATH=/usr/lib/binutils-2.26/bin:$PATH
```
To compile and package the JDBC driver source code, you should have a Java jdk-8 or higher and Apache Maven 2.7 or higher installed. To compile and package the JDBC driver source code, you should have a Java jdk-8 or higher and Apache Maven 2.7 or higher installed.
To install openjdk-8: To install openjdk-8:
```bash ```bash

View File

@ -4,7 +4,7 @@ PROJECT(TDengine)
IF (DEFINED VERNUMBER) IF (DEFINED VERNUMBER)
SET(TD_VER_NUMBER ${VERNUMBER}) SET(TD_VER_NUMBER ${VERNUMBER})
ELSE () ELSE ()
SET(TD_VER_NUMBER "2.0.12.0") SET(TD_VER_NUMBER "2.0.13.0")
ENDIF () ENDIF ()
IF (DEFINED VERCOMPATIBLE) IF (DEFINED VERCOMPATIBLE)

View File

@ -4,6 +4,8 @@
TDengine采用关系型数据模型需要建库、建表。因此对于一个具体的应用场景需要考虑库的设计超级表和普通表的设计。本节不讨论细致的语法规则只介绍概念。 TDengine采用关系型数据模型需要建库、建表。因此对于一个具体的应用场景需要考虑库的设计超级表和普通表的设计。本节不讨论细致的语法规则只介绍概念。
关于数据建模请参考<a href="https://www.taosdata.com/blog/2020/11/11/1945.html">视频教程</a>
## 创建库 ## 创建库
不同类型的数据采集点往往具有不同的数据特征包括数据采集频率的高低数据保留时间的长短副本的数目数据块的大小是否允许更新数据等等。为让各种场景下TDengine都能最大效率的工作TDengine建议将不同数据特征的表创建在不同的库里因为每个库可以配置不同的存储策略。创建一个库时除SQL标准的选项外应用还可以指定保留时长、副本数、内存块个数、时间精度、文件块里最大最小记录条数、是否压缩、一个数据文件覆盖的天数等多种参数。比如 不同类型的数据采集点往往具有不同的数据特征包括数据采集频率的高低数据保留时间的长短副本的数目数据块的大小是否允许更新数据等等。为让各种场景下TDengine都能最大效率的工作TDengine建议将不同数据特征的表创建在不同的库里因为每个库可以配置不同的存储策略。创建一个库时除SQL标准的选项外应用还可以指定保留时长、副本数、内存块个数、时间精度、文件块里最大最小记录条数、是否压缩、一个数据文件覆盖的天数等多种参数。比如
@ -60,4 +62,3 @@ TDengine支持多列模型只要物理量是一个数据采集点同时采集
TDengine建议尽可能采用多列模型因为插入效率以及存储效率更高。但对于有些场景一个采集点的采集量的种类经常变化这个时候如果采用多列模型就需要频繁修改超级表的结构定义让应用变的复杂这个时候采用单列模型会显得简单。 TDengine建议尽可能采用多列模型因为插入效率以及存储效率更高。但对于有些场景一个采集点的采集量的种类经常变化这个时候如果采用多列模型就需要频繁修改超级表的结构定义让应用变的复杂这个时候采用单列模型会显得简单。
关于数据建模请参考<a href="https://www.taosdata.com/blog/2020/11/11/1945.html">视频教程</a>

View File

@ -148,7 +148,7 @@ TDengine缺省的时间戳是毫秒精度但通过修改配置参数enableMic
SHOW TABLES [LIKE tb_name_wildcar]; SHOW TABLES [LIKE tb_name_wildcar];
``` ```
显示当前数据库下的所有数据表信息。说明可在like中使用通配符进行名称的匹配。 通配符匹配1% (百分号)匹配0到任意个字符2_下划线匹配一个字符。 显示当前数据库下的所有数据表信息。说明:可在 like 中使用通配符进行名称的匹配。 通配符匹配1“%”(百分号)匹配 0 到任意个字符2“\_”下划线匹配一个字符。
- **在线修改显示字符宽度** - **在线修改显示字符宽度**
@ -263,33 +263,33 @@ TDengine缺省的时间戳是毫秒精度但通过修改配置参数enableMic
- **插入一条记录,数据对应到指定的列** - **插入一条记录,数据对应到指定的列**
```mysql ```mysql
INSERT INTO tb_name (field1_name, ...) VALUES(field1_value, ...) INSERT INTO tb_name (field1_name, ...) VALUES (field1_value, ...)
``` ```
向表tb_name中插入一条记录数据对应到指定的列。SQL语句中没有出现的列数据库将自动填充为NULL。主键时间戳不能为NULL。 向表tb_name中插入一条记录数据对应到指定的列。SQL语句中没有出现的列数据库将自动填充为NULL。主键时间戳不能为NULL。
- **插入多条记录** - **插入多条记录**
```mysql ```mysql
INSERT INTO tb_name VALUES (field1_value1, ...) (field1_value2, ...)...; INSERT INTO tb_name VALUES (field1_value1, ...) (field1_value2, ...) ...;
``` ```
向表tb_name中插入多条记录 向表tb_name中插入多条记录
- **按指定的列插入多条记录** - **按指定的列插入多条记录**
```mysql ```mysql
INSERT INTO tb_name (field1_name, ...) VALUES(field1_value1, ...) (field1_value2, ...) INSERT INTO tb_name (field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...) ...;
``` ```
向表tb_name中按指定的列插入多条记录 向表tb_name中按指定的列插入多条记录
- **向多个表插入多条记录** - **向多个表插入多条记录**
```mysql ```mysql
INSERT INTO tb1_name VALUES (field1_value1, ...)(field1_value2, ...)... INSERT INTO tb1_name VALUES (field1_value1, ...) (field1_value2, ...) ...
tb2_name VALUES (field1_value1, ...)(field1_value2, ...)...; tb2_name VALUES (field1_value1, ...) (field1_value2, ...) ...;
``` ```
同时向表tb1_name和tb2_name中分别插入多条记录 同时向表tb1_name和tb2_name中分别插入多条记录
- **同时向多个表按列插入多条记录** - **同时向多个表按列插入多条记录**
```mysql ```mysql
INSERT INTO tb1_name (tb1_field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...) INSERT INTO tb1_name (tb1_field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...) ...
tb2_name (tb2_field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...); tb2_name (tb2_field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...) ...;
``` ```
同时向表tb1_name和tb2_name中按列分别插入多条记录 同时向表tb1_name和tb2_name中按列分别插入多条记录
@ -318,23 +318,23 @@ SELECT select_expr [, select_expr ...]
``` ```
说明:针对 insert 类型的 SQL 语句我们采用的流式解析策略在发现后面的错误之前前面正确的部分SQL仍会执行。下面的sql中insert语句是无效的但是d1001仍会被创建。 说明:针对 insert 类型的 SQL 语句我们采用的流式解析策略在发现后面的错误之前前面正确的部分SQL仍会执行。下面的sql中insert语句是无效的但是d1001仍会被创建。
```mysql ```mysql
taos> create table meters(ts timestamp, current float, voltage int, phase float) tags(location binary(30), groupId int); taos> CREATE TABLE meters(ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS(location BINARY(30), groupId INT);
Query OK, 0 row(s) affected (0.008245s) Query OK, 0 row(s) affected (0.008245s)
taos> show stables; taos> SHOW STABLES;
name | created_time | columns | tags | tables | name | created_time | columns | tags | tables |
============================================================================================ ============================================================================================
meters | 2020-08-06 17:50:27.831 | 4 | 2 | 0 | meters | 2020-08-06 17:50:27.831 | 4 | 2 | 0 |
Query OK, 1 row(s) in set (0.001029s) Query OK, 1 row(s) in set (0.001029s)
taos> show tables; taos> SHOW TABLES;
Query OK, 0 row(s) in set (0.000946s) Query OK, 0 row(s) in set (0.000946s)
taos> insert into d1001 using meters tags('Beijing.Chaoyang', 2); taos> INSERT INTO d1001 USING meters TAGS('Beijing.Chaoyang', 2);
DB error: invalid SQL: keyword VALUES or FILE required DB error: invalid SQL: keyword VALUES or FILE required
taos> show tables; taos> SHOW TABLES;
table_name | created_time | columns | stable_name | table_name | created_time | columns | stable_name |
====================================================================================================== ======================================================================================================
d1001 | 2020-08-06 17:52:02.097 | 4 | meters | d1001 | 2020-08-06 17:52:02.097 | 4 | meters |
@ -397,27 +397,41 @@ Query OK, 1 row(s) in set (0.020443s)
在使用SQL函数来进行查询过程中部分SQL函数支持通配符操作。其中的区别在于 在使用SQL函数来进行查询过程中部分SQL函数支持通配符操作。其中的区别在于
```count(\*)```函数只返回一列。```first```、```last```、```last_row```函数则是返回全部列。 ```count(\*)```函数只返回一列。```first```、```last```、```last_row```函数则是返回全部列。
``` ```mysql
taos> select count(*) from d1001; taos> SELECT COUNT(*) FROM d1001;
count(*) | count(*) |
======================== ========================
3 | 3 |
Query OK, 1 row(s) in set (0.001035s) Query OK, 1 row(s) in set (0.001035s)
``` ```
``` ```mysql
taos> select first(*) from d1001; taos> SELECT FIRST(*) FROM d1001;
first(ts) | first(current) | first(voltage) | first(phase) | first(ts) | first(current) | first(voltage) | first(phase) |
========================================================================================= =========================================================================================
2018-10-03 14:38:05.000 | 10.30000 | 219 | 0.31000 | 2018-10-03 14:38:05.000 | 10.30000 | 219 | 0.31000 |
Query OK, 1 row(s) in set (0.000849s) Query OK, 1 row(s) in set (0.000849s)
``` ```
##### 标签列
从 2.0.14 版本开始,支持在普通表的查询中指定 _标签列_,且标签列的值会与普通列的数据一起返回。
```mysql
taos> SELECT location, groupid, current FROM d1001 LIMIT 2;
location | groupid | current |
======================================================================
Beijing.Chaoyang | 2 | 10.30000 |
Beijing.Chaoyang | 2 | 12.60000 |
Query OK, 2 row(s) in set (0.003112s)
```
注意:普通表的通配符 * 中并不包含 _标签列_
#### 结果集列名 #### 结果集列名
```SELECT```子句中,如果不指定返回结果集合的列名,结果集列名称默认使用```SELECT```子句中的表达式名称作为列名称。此外,用户可使用```AS```来重命名返回结果集合中列的名称。例如: ```SELECT```子句中,如果不指定返回结果集合的列名,结果集列名称默认使用```SELECT```子句中的表达式名称作为列名称。此外,用户可使用```AS```来重命名返回结果集合中列的名称。例如:
``` ```mysql
taos> select ts, ts as primary_key_ts from d1001; taos> SELECT ts, ts AS primary_key_ts FROM d1001;
ts | primary_key_ts | ts | primary_key_ts |
==================================================== ====================================================
2018-10-03 14:38:05.000 | 2018-10-03 14:38:05.000 | 2018-10-03 14:38:05.000 | 2018-10-03 14:38:05.000 |
@ -434,53 +448,53 @@ Query OK, 3 row(s) in set (0.001191s)
FROM关键字后面可以是若干个表超级表列表也可以是子查询的结果。 FROM关键字后面可以是若干个表超级表列表也可以是子查询的结果。
如果没有指定用户的当前数据库,可以在表名称之前使用数据库的名称来指定表所属的数据库。例如:```power.d1001``` 方式来跨库使用表。 如果没有指定用户的当前数据库,可以在表名称之前使用数据库的名称来指定表所属的数据库。例如:```power.d1001``` 方式来跨库使用表。
``` ```mysql
SELECT * FROM power.d1001; SELECT * FROM power.d1001;
------------------------------ ------------------------------
use power; USE power;
SELECT * FROM d1001; SELECT * FROM d1001;
``` ```
#### 特殊功能 #### 特殊功能
部分特殊的查询功能可以不使用FROM子句执行。获取当前所在的数据库 database() 部分特殊的查询功能可以不使用FROM子句执行。获取当前所在的数据库 database()
``` ```mysql
taos> SELECT database(); taos> SELECT DATABASE();
database() | database() |
================================= =================================
power | power |
Query OK, 1 row(s) in set (0.000079s) Query OK, 1 row(s) in set (0.000079s)
``` ```
如果登录的时候没有指定默认数据库,且没有使用```use```命令切换数据则返回NULL。 如果登录的时候没有指定默认数据库,且没有使用```use```命令切换数据则返回NULL。
``` ```mysql
taos> SELECT database(); taos> SELECT DATABASE();
database() | database() |
================================= =================================
NULL | NULL |
Query OK, 1 row(s) in set (0.000184s) Query OK, 1 row(s) in set (0.000184s)
``` ```
获取服务器和客户端版本号: 获取服务器和客户端版本号:
``` ```mysql
taos> SELECT client_version(); taos> SELECT CLIENT_VERSION();
client_version() | client_version() |
=================== ===================
2.0.0.0 | 2.0.0.0 |
Query OK, 1 row(s) in set (0.000070s) Query OK, 1 row(s) in set (0.000070s)
taos> SELECT server_version(); taos> SELECT SERVER_VERSION();
server_version() | server_version() |
=================== ===================
2.0.0.0 | 2.0.0.0 |
Query OK, 1 row(s) in set (0.000077s) Query OK, 1 row(s) in set (0.000077s)
``` ```
服务器状态检测语句。如果服务器正常,返回一个数字(例如 1。如果服务器异常返回error code。该SQL语法能兼容连接池对于TDengine状态的检查及第三方工具对于数据库服务器状态的检查。并可以避免出现使用了错误的心跳检测SQL语句导致的连接池连接丢失的问题。 服务器状态检测语句。如果服务器正常,返回一个数字(例如 1。如果服务器异常返回error code。该SQL语法能兼容连接池对于TDengine状态的检查及第三方工具对于数据库服务器状态的检查。并可以避免出现使用了错误的心跳检测SQL语句导致的连接池连接丢失的问题。
``` ```mysql
taos> SELECT server_status(); taos> SELECT SERVER_STATUS();
server_status() | server_status() |
================== ==================
1 | 1 |
Query OK, 1 row(s) in set (0.000074s) Query OK, 1 row(s) in set (0.000074s)
taos> SELECT server_status() as status; taos> SELECT SERVER_STATUS() AS status;
status | status |
============== ==============
1 | 1 |
@ -493,15 +507,15 @@ Query OK, 1 row(s) in set (0.000081s)
#### 小技巧 #### 小技巧
获取一个超级表所有的子表名及相关的标签信息: 获取一个超级表所有的子表名及相关的标签信息:
``` ```mysql
SELECT TBNAME, location FROM meters; SELECT TBNAME, location FROM meters;
``` ```
统计超级表下辖子表数量: 统计超级表下辖子表数量:
``` ```mysql
SELECT COUNT(TBNAME) FROM meters; SELECT COUNT(TBNAME) FROM meters;
``` ```
以上两个查询均只支持在Where条件子句中添加针对标签TAGS的过滤条件。例如 以上两个查询均只支持在Where条件子句中添加针对标签TAGS的过滤条件。例如
``` ```mysql
taos> SELECT TBNAME, location FROM meters; taos> SELECT TBNAME, location FROM meters;
tbname | location | tbname | location |
================================================================== ==================================================================
@ -511,7 +525,7 @@ taos> SELECT TBNAME, location FROM meters;
d1001 | Beijing.Chaoyang | d1001 | Beijing.Chaoyang |
Query OK, 4 row(s) in set (0.000881s) Query OK, 4 row(s) in set (0.000881s)
taos> SELECT count(tbname) FROM meters WHERE groupId > 2; taos> SELECT COUNT(tbname) FROM meters WHERE groupId > 2;
count(tbname) | count(tbname) |
======================== ========================
2 | 2 |
@ -545,7 +559,7 @@ Query OK, 1 row(s) in set (0.001091s)
- 对于下面的例子表tb1用以下语句创建 - 对于下面的例子表tb1用以下语句创建
```mysql ```mysql
CREATE TABLE tb1 (ts timestamp, col1 int, col2 float, col3 binary(50)); CREATE TABLE tb1 (ts TIMESTAMP, col1 INT, col2 FLOAT, col3 BINARY(50));
``` ```
- 查询tb1刚过去的一个小时的所有记录 - 查询tb1刚过去的一个小时的所有记录
@ -563,7 +577,7 @@ Query OK, 1 row(s) in set (0.001091s)
- 查询col1与col2的和并取名complex, 时间大于2018-06-01 08:00:00.000, col2大于1.2结果输出仅仅10条记录从第5条开始 - 查询col1与col2的和并取名complex, 时间大于2018-06-01 08:00:00.000, col2大于1.2结果输出仅仅10条记录从第5条开始
```mysql ```mysql
SELECT (col1 + col2) AS 'complex' FROM tb1 WHERE ts > '2018-06-01 08:00:00.000' and col2 > 1.2 LIMIT 10 OFFSET 5; SELECT (col1 + col2) AS 'complex' FROM tb1 WHERE ts > '2018-06-01 08:00:00.000' AND col2 > 1.2 LIMIT 10 OFFSET 5;
``` ```
- 查询过去10分钟的记录col2的值大于3.14,并且将结果输出到文件 `/home/testoutpu.csv`. - 查询过去10分钟的记录col2的值大于3.14,并且将结果输出到文件 `/home/testoutpu.csv`.
@ -590,13 +604,13 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
示例: 示例:
```mysql ```mysql
taos> SELECT COUNT(*), COUNT(VOLTAGE) FROM meters; taos> SELECT COUNT(*), COUNT(voltage) FROM meters;
count(*) | count(voltage) | count(*) | count(voltage) |
================================================ ================================================
9 | 9 | 9 | 9 |
Query OK, 1 row(s) in set (0.004475s) Query OK, 1 row(s) in set (0.004475s)
taos> SELECT COUNT(*), COUNT(VOLTAGE) FROM d1001; taos> SELECT COUNT(*), COUNT(voltage) FROM d1001;
count(*) | count(voltage) | count(*) | count(voltage) |
================================================ ================================================
3 | 3 | 3 | 3 |
@ -620,7 +634,7 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
11.466666751 | 220.444444444 | 0.293333333 | 11.466666751 | 220.444444444 | 0.293333333 |
Query OK, 1 row(s) in set (0.004135s) Query OK, 1 row(s) in set (0.004135s)
taos> SELECT AVG(current), AVG(voltage), AVG(phase) from d1001; taos> SELECT AVG(current), AVG(voltage), AVG(phase) FROM d1001;
avg(current) | avg(voltage) | avg(phase) | avg(current) | avg(voltage) | avg(phase) |
==================================================================================== ====================================================================================
11.733333588 | 219.333333333 | 0.316666673 | 11.733333588 | 219.333333333 | 0.316666673 |
@ -648,13 +662,13 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
示例: 示例:
```mysql ```mysql
taos> SELECT SUM(current), SUM(voltage), SUM(phase) from meters; taos> SELECT SUM(current), SUM(voltage), SUM(phase) FROM meters;
sum(current) | sum(voltage) | sum(phase) | sum(current) | sum(voltage) | sum(phase) |
================================================================================ ================================================================================
103.200000763 | 1984 | 2.640000001 | 103.200000763 | 1984 | 2.640000001 |
Query OK, 1 row(s) in set (0.001702s) Query OK, 1 row(s) in set (0.001702s)
taos> SELECT SUM(current), SUM(voltage), SUM(phase) from d1001; taos> SELECT SUM(current), SUM(voltage), SUM(phase) FROM d1001;
sum(current) | sum(voltage) | sum(phase) | sum(current) | sum(voltage) | sum(phase) |
================================================================================ ================================================================================
35.200000763 | 658 | 0.950000018 | 35.200000763 | 658 | 0.950000018 |
@ -753,7 +767,7 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
功能说明:统计表/超级表中某列的值最先写入的非NULL值。 功能说明:统计表/超级表中某列的值最先写入的非NULL值。
返回结果数据类型:同应用的字段。 返回结果数据类型:同应用的字段。
应用字段:所有字段。 应用字段:所有字段。
说明1如果要返回各个列的首个时间戳最小非NULL值可以使用FIRST(*)2) 如果结果集中的某列全部为NULL值则该列的返回结果也是NULL3) 如果结果集中所有列全部为NULL值则不返回结果。 说明1如果要返回各个列的首个时间戳最小非NULL值可以使用FIRST(\*)2) 如果结果集中的某列全部为NULL值则该列的返回结果也是NULL3) 如果结果集中所有列全部为NULL值则不返回结果。
示例: 示例:
```mysql ```mysql
@ -777,7 +791,7 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
功能说明:统计表/超级表中某列的值最后写入的非NULL值。 功能说明:统计表/超级表中某列的值最后写入的非NULL值。
返回结果数据类型:同应用的字段。 返回结果数据类型:同应用的字段。
应用字段:所有字段。 应用字段:所有字段。
说明1如果要返回各个列的最后时间戳最大一个非NULL值可以使用LAST(*)2如果结果集中的某列全部为NULL值则该列的返回结果也是NULL如果结果集中所有列全部为NULL值则不返回结果。 说明1如果要返回各个列的最后时间戳最大一个非NULL值可以使用LAST(\*)2如果结果集中的某列全部为NULL值则该列的返回结果也是NULL如果结果集中所有列全部为NULL值则不返回结果。
示例: 示例:
```mysql ```mysql
@ -1004,15 +1018,15 @@ SELECT function_list FROM stb_name
**示例:** 智能电表的建表语句如下: **示例:** 智能电表的建表语句如下:
```mysql ```mysql
CREATE TABLE meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int); CREATE TABLE meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT);
``` ```
针对智能电表采集的数据以10分钟为一个阶段计算过去24小时的电流数据的平均值、最大值、电流的中位数、以及随着时间变化的电流走势拟合直线。如果没有计算值用前一个非NULL值填充。 针对智能电表采集的数据以10分钟为一个阶段计算过去24小时的电流数据的平均值、最大值、电流的中位数、以及随着时间变化的电流走势拟合直线。如果没有计算值用前一个非NULL值填充。
使用的查询语句如下: 使用的查询语句如下:
```mysql ```mysql
SELECT AVG(current),MAX(current),LEASTSQUARES(current, start_val, step_val), PERCENTILE(current, 50) FROM meters SELECT AVG(current), MAX(current), LEASTSQUARES(current, start_val, step_val), PERCENTILE(current, 50) FROM meters
WHERE TS>=NOW-1d WHERE ts>=NOW-1d
INTERVAL(10m) INTERVAL(10m)
FILL(PREV); FILL(PREV);
``` ```

View File

@ -6,6 +6,8 @@
TDengine的集群管理极其简单除添加和删除节点需要人工干预之外其他全部是自动完成最大程度的降低了运维的工作量。本章对集群管理的操作做详细的描述。 TDengine的集群管理极其简单除添加和删除节点需要人工干预之外其他全部是自动完成最大程度的降低了运维的工作量。本章对集群管理的操作做详细的描述。
关于集群搭建请参考<a href="https://www.taosdata.com/blog/2020/11/11/1961.html">视频教程</a>
## 准备工作 ## 准备工作
**第零步**规划集群所有物理节点的FQDN将规划好的FQDN分别添加到每个物理节点的/etc/hostname修改每个物理节点的/etc/hosts将所有集群物理节点的IP与FQDN的对应添加好。【如部署了DNS请联系网络管理员在DNS上做好相关配置】 **第零步**规划集群所有物理节点的FQDN将规划好的FQDN分别添加到每个物理节点的/etc/hostname修改每个物理节点的/etc/hosts将所有集群物理节点的IP与FQDN的对应添加好。【如部署了DNS请联系网络管理员在DNS上做好相关配置】
@ -227,4 +229,3 @@ SHOW MNODES;
TDengine提供一个执行程序tarbitrator, 找任何一台Linux服务器运行它即可。请点击[安装包下载](https://www.taosdata.com/cn/all-downloads/)在TDengine Arbitrator Linux一节中选择适合的版本下载并安装。该程序对系统资源几乎没有要求只需要保证有网络连接即可。该应用的命令行参数`-p`可以指定其对外服务的端口号缺省是6042。配置每个taosd实例时可以在配置文件taos.cfg里将参数arbitrator设置为arbitrator的End Point。如果该参数配置了当副本数为偶数数系统将自动连接配置的arbitrator。如果副本数为奇数即使配置了arbitrator, 系统也不会去建立连接。 TDengine提供一个执行程序tarbitrator, 找任何一台Linux服务器运行它即可。请点击[安装包下载](https://www.taosdata.com/cn/all-downloads/)在TDengine Arbitrator Linux一节中选择适合的版本下载并安装。该程序对系统资源几乎没有要求只需要保证有网络连接即可。该应用的命令行参数`-p`可以指定其对外服务的端口号缺省是6042。配置每个taosd实例时可以在配置文件taos.cfg里将参数arbitrator设置为arbitrator的End Point。如果该参数配置了当副本数为偶数数系统将自动连接配置的arbitrator。如果副本数为奇数即使配置了arbitrator, 系统也不会去建立连接。
关于集群搭建请参考<a href="https://www.taosdata.com/blog/2020/11/11/1961.html">视频教程</a>

View File

@ -1,6 +1,6 @@
name: tdengine name: tdengine
base: core18 base: core18
version: '2.0.12.0' version: '2.0.13.0'
icon: snap/gui/t-dengine.svg icon: snap/gui/t-dengine.svg
summary: an open-source big data platform designed and optimized for IoT. summary: an open-source big data platform designed and optimized for IoT.
description: | description: |
@ -72,7 +72,7 @@ parts:
- usr/bin/taosd - usr/bin/taosd
- usr/bin/taos - usr/bin/taos
- usr/bin/taosdemo - usr/bin/taosdemo
- usr/lib/libtaos.so.2.0.12.0 - usr/lib/libtaos.so.2.0.13.0
- usr/lib/libtaos.so.1 - usr/lib/libtaos.so.1
- usr/lib/libtaos.so - usr/lib/libtaos.so

View File

@ -421,7 +421,7 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex); SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
// check if it is a sub-query of super table query first, if true, enter another routine // check if it is a sub-query of super table query first, if true, enter another routine
if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, (TSDB_QUERY_TYPE_STABLE_SUBQUERY|TSDB_QUERY_TYPE_TAG_FILTER_QUERY))) { if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, (TSDB_QUERY_TYPE_STABLE_SUBQUERY|TSDB_QUERY_TYPE_SUBQUERY|TSDB_QUERY_TYPE_TAG_FILTER_QUERY))) {
tscDebug("%p update local table meta, continue to process sql and send the corresponding query", pSql); tscDebug("%p update local table meta, continue to process sql and send the corresponding query", pSql);
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);

View File

@ -75,11 +75,11 @@ static int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SC
static int32_t convertFunctionId(int32_t optr, int16_t* functionId); static int32_t convertFunctionId(int32_t optr, int16_t* functionId);
static uint8_t convertOptr(SStrToken *pToken); static uint8_t convertOptr(SStrToken *pToken);
static int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery); static int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery, bool intervalQuery);
static bool validateIpAddress(const char* ip, size_t size); static bool validateIpAddress(const char* ip, size_t size);
static bool hasUnsupportFunctionsForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo); static bool hasUnsupportFunctionsForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo);
static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery); static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery, bool intervalQuery);
static int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd); static int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd);
@ -1475,7 +1475,7 @@ static void addPrimaryTsColIntoResult(SQueryInfo* pQueryInfo) {
pQueryInfo->type |= TSDB_QUERY_TYPE_PROJECTION_QUERY; pQueryInfo->type |= TSDB_QUERY_TYPE_PROJECTION_QUERY;
} }
int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery) { int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery, bool intervalQuery) {
assert(pSelection != NULL && pCmd != NULL); assert(pSelection != NULL && pCmd != NULL);
const char* msg2 = "functions can not be mixed up"; const char* msg2 = "functions can not be mixed up";
@ -1531,7 +1531,7 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
addPrimaryTsColIntoResult(pQueryInfo); addPrimaryTsColIntoResult(pQueryInfo);
} }
if (!functionCompatibleCheck(pQueryInfo, joinQuery)) { if (!functionCompatibleCheck(pQueryInfo, joinQuery, intervalQuery)) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
} }
@ -2810,7 +2810,7 @@ bool hasUnsupportFunctionsForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo)
return false; return false;
} }
static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery) { static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery, bool intervalQuery) {
int32_t startIdx = 0; int32_t startIdx = 0;
size_t numOfExpr = tscSqlExprNumOfExprs(pQueryInfo); size_t numOfExpr = tscSqlExprNumOfExprs(pQueryInfo);
@ -2826,6 +2826,10 @@ static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery) {
int32_t factor = functionCompatList[tscSqlExprGet(pQueryInfo, startIdx)->functionId]; int32_t factor = functionCompatList[tscSqlExprGet(pQueryInfo, startIdx)->functionId];
if (tscSqlExprGet(pQueryInfo, 0)->functionId == TSDB_FUNC_LAST_ROW && (joinQuery || intervalQuery)) {
return false;
}
// diff function cannot be executed with other function // diff function cannot be executed with other function
// arithmetic function can be executed with other arithmetic functions // arithmetic function can be executed with other arithmetic functions
size_t size = tscSqlExprNumOfExprs(pQueryInfo); size_t size = tscSqlExprNumOfExprs(pQueryInfo);
@ -2850,7 +2854,7 @@ static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery) {
} }
} }
if (functionId == TSDB_FUNC_LAST_ROW && joinQuery) { if (functionId == TSDB_FUNC_LAST_ROW && (joinQuery || intervalQuery)) {
return false; return false;
} }
} }
@ -4594,8 +4598,8 @@ static void setDefaultOrderInfo(SQueryInfo* pQueryInfo) {
int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql, SSchema* pSchema) { int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql, SSchema* pSchema) {
const char* msg0 = "only support order by primary timestamp"; const char* msg0 = "only support order by primary timestamp";
const char* msg1 = "invalid column name"; const char* msg1 = "invalid column name";
const char* msg2 = "only support order by primary timestamp or queried column"; const char* msg2 = "only support order by primary timestamp or first tag in groupby clause allowed";
const char* msg3 = "only support order by primary timestamp or first tag in groupby clause"; const char* msg3 = "invalid column in order by clause, only primary timestamp or first tag in groupby clause allowed";
setDefaultOrderInfo(pQueryInfo); setDefaultOrderInfo(pQueryInfo);
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
@ -5275,8 +5279,7 @@ int32_t parseLimitClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t clauseIn
const char* msg0 = "soffset/offset can not be less than 0"; const char* msg0 = "soffset/offset can not be less than 0";
const char* msg1 = "slimit/soffset only available for STable query"; const char* msg1 = "slimit/soffset only available for STable query";
const char* msg2 = "functions mixed up in table query"; const char* msg2 = "slimit/soffset can not apply to projection query";
const char* msg3 = "slimit/soffset can not apply to projection query";
// handle the limit offset value, validate the limit // handle the limit offset value, validate the limit
pQueryInfo->limit = pQuerySql->limit; pQueryInfo->limit = pQuerySql->limit;
@ -5301,7 +5304,7 @@ int32_t parseLimitClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t clauseIn
if (!tscQueryTags(pQueryInfo)) { // local handle the super table tag query if (!tscQueryTags(pQueryInfo)) { // local handle the super table tag query
if (tscIsProjectionQueryOnSTable(pQueryInfo, 0)) { if (tscIsProjectionQueryOnSTable(pQueryInfo, 0)) {
if (pQueryInfo->slimit.limit > 0 || pQueryInfo->slimit.offset > 0) { if (pQueryInfo->slimit.limit > 0 || pQueryInfo->slimit.offset > 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
} }
// for projection query on super table, all queries are subqueries // for projection query on super table, all queries are subqueries
@ -5359,24 +5362,6 @@ int32_t parseLimitClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t clauseIn
if (pQueryInfo->slimit.limit != -1 || pQueryInfo->slimit.offset != 0) { if (pQueryInfo->slimit.limit != -1 || pQueryInfo->slimit.offset != 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
} }
size_t size = taosArrayGetSize(pQueryInfo->exprList);
bool hasTags = false;
bool hasOtherFunc = false;
// filter the query functions operating on "tbname" column that are not supported by normal columns.
for (int32_t i = 0; i < size; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
if (TSDB_COL_IS_TAG(pExpr->colInfo.flag)) {
hasTags = true;
} else {
hasOtherFunc = true;
}
}
if (hasTags && hasOtherFunc) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
} }
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
@ -5848,14 +5833,43 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
static int32_t doTagFunctionCheck(SQueryInfo* pQueryInfo) {
bool tagProjection = false;
bool tableCounting = false;
int32_t numOfCols = (int32_t) tscSqlExprNumOfExprs(pQueryInfo);
for (int32_t i = 0; i < numOfCols; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
int32_t functionId = pExpr->functionId;
if (functionId == TSDB_FUNC_TAGPRJ) {
tagProjection = true;
continue;
}
if (functionId == TSDB_FUNC_COUNT) {
assert(pExpr->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX);
tableCounting = true;
}
}
return (tableCounting && tagProjection)? -1:0;
}
int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) { int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
const char* msg1 = "functions/columns not allowed in group by query"; const char* msg1 = "functions/columns not allowed in group by query";
const char* msg2 = "projection query on columns not allowed"; const char* msg2 = "projection query on columns not allowed";
const char* msg3 = "group by not allowed on projection query"; const char* msg3 = "group by not allowed on projection query";
const char* msg4 = "retrieve tags not compatible with group by or interval query"; const char* msg4 = "retrieve tags not compatible with group by or interval query";
const char* msg5 = "functions can not be mixed up";
// only retrieve tags, group by is not supportted // only retrieve tags, group by is not supportted
if (tscQueryTags(pQueryInfo)) { if (tscQueryTags(pQueryInfo)) {
if (doTagFunctionCheck(pQueryInfo) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
if (pQueryInfo->groupbyExpr.numOfGroupCols > 0 || pQueryInfo->interval.interval > 0) { if (pQueryInfo->groupbyExpr.numOfGroupCols > 0 || pQueryInfo->interval.interval > 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
} else { } else {
@ -6278,10 +6292,12 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) { int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
const char* msg1 = "invalid table name"; const char* msg1 = "invalid table name";
const char* msg2 = "functions not allowed in CQ";
const char* msg3 = "fill only available for interval query"; const char* msg3 = "fill only available for interval query";
const char* msg4 = "fill option not supported in stream computing"; const char* msg4 = "fill option not supported in stream computing";
const char* msg5 = "sql too long"; // todo ADD support const char* msg5 = "sql too long"; // todo ADD support
const char* msg6 = "from missing in subclause"; const char* msg6 = "from missing in subclause";
const char* msg7 = "time interval is required";
SSqlCmd* pCmd = &pSql->cmd; SSqlCmd* pCmd = &pSql->cmd;
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0); SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
@ -6291,10 +6307,10 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
// if sql specifies db, use it, otherwise use default db // if sql specifies db, use it, otherwise use default db
SStrToken* pzTableName = &(pCreateTable->name); SStrToken* pName = &(pCreateTable->name);
SQuerySQL* pQuerySql = pCreateTable->pSelect; SQuerySQL* pQuerySql = pCreateTable->pSelect;
if (tscValidateName(pzTableName) != TSDB_CODE_SUCCESS) { if (tscValidateName(pName) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
} }
@ -6320,7 +6336,7 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
} }
bool isSTable = UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo); bool isSTable = UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo);
if (parseSelectClause(&pSql->cmd, 0, pQuerySql->pSelection, isSTable, false) != TSDB_CODE_SUCCESS) { if (parseSelectClause(&pSql->cmd, 0, pQuerySql->pSelection, isSTable, false, false) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL; return TSDB_CODE_TSC_INVALID_SQL;
} }
@ -6333,15 +6349,19 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
// set interval value // set interval value
if (parseIntervalClause(pSql, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) { if (parseIntervalClause(pSql, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL; return TSDB_CODE_TSC_INVALID_SQL;
} else { }
if ((pQueryInfo->interval.interval > 0) &&
(validateFunctionsInIntervalOrGroupbyQuery(pCmd, pQueryInfo) != TSDB_CODE_SUCCESS)) { if ((pQueryInfo->interval.interval > 0) &&
return TSDB_CODE_TSC_INVALID_SQL; (validateFunctionsInIntervalOrGroupbyQuery(pCmd, pQueryInfo) != TSDB_CODE_SUCCESS)) {
} return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
if (!tscIsProjectionQuery(pQueryInfo) && pQueryInfo->interval.interval == 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7);
} }
// set the created table[stream] name // set the created table[stream] name
code = tscSetTableFullName(pTableMetaInfo, pzTableName, pSql); code = tscSetTableFullName(pTableMetaInfo, pName, pSql);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
return code; return code;
} }
@ -6565,7 +6585,9 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
int32_t joinQuery = (pQuerySql->from != NULL && taosArrayGetSize(pQuerySql->from) > 2); int32_t joinQuery = (pQuerySql->from != NULL && taosArrayGetSize(pQuerySql->from) > 2);
if (parseSelectClause(pCmd, index, pQuerySql->pSelection, isSTable, joinQuery) != TSDB_CODE_SUCCESS) { int32_t intervalQuery = !(pQuerySql->interval.type == 0 || pQuerySql->interval.n == 0);
if (parseSelectClause(pCmd, index, pQuerySql->pSelection, isSTable, joinQuery, intervalQuery) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL; return TSDB_CODE_TSC_INVALID_SQL;
} }

View File

@ -65,44 +65,51 @@ static int64_t tscGetRetryDelayTime(SSqlStream* pStream, int64_t slidingTime, in
return retryDelta; return retryDelta;
} }
static void tscProcessStreamLaunchQuery(SSchedMsg *pMsg) { static void doLaunchQuery(void* param, TAOS_RES* tres, int32_t code) {
SSqlStream *pStream = (SSqlStream *)pMsg->ahandle; SSqlStream *pStream = (SSqlStream *)param;
SSqlObj * pSql = pStream->pSql; assert(pStream->pSql == tres && code == TSDB_CODE_SUCCESS);
pSql->fp = tscProcessStreamQueryCallback; SSqlObj* pSql = (SSqlObj*) tres;
pSql->fetchFp = tscProcessStreamQueryCallback; pSql->fp = doLaunchQuery;
pSql->param = pStream; pSql->fetchFp = doLaunchQuery;
pSql->res.completed = false; pSql->res.completed = false;
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0); SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
int code = tscGetTableMeta(pSql, pTableMetaInfo); code = tscGetTableMeta(pSql, pTableMetaInfo);
pSql->res.code = code;
if (code == 0 && UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { if (code == 0 && UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
code = tscGetSTableVgroupInfo(pSql, 0); code = tscGetSTableVgroupInfo(pSql, 0);
pSql->res.code = code;
} }
// failed to get meter/metric meta, retry in 10sec. // failed to get table Meta or vgroup list, retry in 10sec.
if (code != TSDB_CODE_SUCCESS) { if (code == TSDB_CODE_SUCCESS) {
int64_t retryDelayTime = tscGetRetryDelayTime(pStream, pStream->interval.sliding, pStream->precision);
tscDebug("%p stream:%p,get metermeta failed, retry in %" PRId64 "ms", pStream->pSql, pStream, retryDelayTime);
tscSetRetryTimer(pStream, pSql, retryDelayTime);
} else {
tscTansformSQLFuncForSTableQuery(pQueryInfo); tscTansformSQLFuncForSTableQuery(pQueryInfo);
tscDebug("%p stream:%p start stream query on:%s", pSql, pStream, pTableMetaInfo->name); tscDebug("%p stream:%p, start stream query on:%s", pSql, pStream, pTableMetaInfo->name);
tscDoQuery(pStream->pSql);
pSql->fp = tscProcessStreamQueryCallback;
pSql->fetchFp = tscProcessStreamQueryCallback;
tscDoQuery(pSql);
tscIncStreamExecutionCount(pStream); tscIncStreamExecutionCount(pStream);
} else if (code != TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
pSql->res.code = code;
int64_t retryDelayTime = tscGetRetryDelayTime(pStream, pStream->interval.sliding, pStream->precision);
tscDebug("%p stream:%p, get table Meta failed, retry in %" PRId64 "ms", pSql, pStream, retryDelayTime);
tscSetRetryTimer(pStream, pSql, retryDelayTime);
} }
} }
static void tscProcessStreamLaunchQuery(SSchedMsg *pMsg) {
SSqlStream *pStream = (SSqlStream *)pMsg->ahandle;
doLaunchQuery(pStream, pStream->pSql, 0);
}
static void tscProcessStreamTimer(void *handle, void *tmrId) { static void tscProcessStreamTimer(void *handle, void *tmrId) {
SSqlStream *pStream = (SSqlStream *)handle; SSqlStream *pStream = (SSqlStream *)handle;
if (pStream == NULL) return; if (pStream == NULL || pStream->pTimer != tmrId) {
if (pStream->pTimer != tmrId) return; return;
}
pStream->pTimer = NULL; pStream->pTimer = NULL;
pStream->numOfRes = 0; // reset the numOfRes. pStream->numOfRes = 0; // reset the numOfRes.
@ -392,11 +399,16 @@ static void tscSetNextLaunchTimer(SSqlStream *pStream, SSqlObj *pSql) {
tscSetRetryTimer(pStream, pSql, timer); tscSetRetryTimer(pStream, pSql, timer);
} }
static void tscSetSlidingWindowInfo(SSqlObj *pSql, SSqlStream *pStream) { static int32_t tscSetSlidingWindowInfo(SSqlObj *pSql, SSqlStream *pStream) {
int64_t minIntervalTime = int64_t minIntervalTime =
(pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsMinIntervalTime * 1000L : tsMinIntervalTime; (pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsMinIntervalTime * 1000L : tsMinIntervalTime;
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0); SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
if (!pStream->isProject && pQueryInfo->interval.interval == 0) {
sprintf(pSql->cmd.payload, "the interval value is 0");
return -1;
}
if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit!= 'y' && pQueryInfo->interval.interval < minIntervalTime) { if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit!= 'y' && pQueryInfo->interval.interval < minIntervalTime) {
tscWarn("%p stream:%p, original sample interval:%" PRId64 " too small, reset to:%" PRId64, pSql, pStream, tscWarn("%p stream:%p, original sample interval:%" PRId64 " too small, reset to:%" PRId64, pSql, pStream,
@ -436,6 +448,8 @@ static void tscSetSlidingWindowInfo(SSqlObj *pSql, SSqlStream *pStream) {
pQueryInfo->interval.interval = 0; // clear the interval value to avoid the force time window split by query processor pQueryInfo->interval.interval = 0; // clear the interval value to avoid the force time window split by query processor
pQueryInfo->interval.sliding = 0; pQueryInfo->interval.sliding = 0;
} }
return TSDB_CODE_SUCCESS;
} }
static int64_t tscGetStreamStartTimestamp(SSqlObj *pSql, SSqlStream *pStream, int64_t stime) { static int64_t tscGetStreamStartTimestamp(SSqlObj *pSql, SSqlStream *pStream, int64_t stime) {
@ -485,34 +499,19 @@ static int64_t tscGetLaunchTimestamp(const SSqlStream *pStream) {
return (pStream->precision == TSDB_TIME_PRECISION_MICRO) ? timer / 1000L : timer; return (pStream->precision == TSDB_TIME_PRECISION_MICRO) ? timer / 1000L : timer;
} }
static void setErrorInfo(SSqlObj* pSql, int32_t code, char* info) {
if (pSql == NULL) {
return;
}
SSqlCmd* pCmd = &pSql->cmd;
pSql->res.code = code;
if (info != NULL) {
strncpy(pCmd->payload, info, pCmd->payloadLen);
}
}
static void tscCreateStream(void *param, TAOS_RES *res, int code) { static void tscCreateStream(void *param, TAOS_RES *res, int code) {
SSqlStream* pStream = (SSqlStream*)param; SSqlStream* pStream = (SSqlStream*)param;
SSqlObj* pSql = pStream->pSql; SSqlObj* pSql = pStream->pSql;
SSqlCmd* pCmd = &pSql->cmd; SSqlCmd* pCmd = &pSql->cmd;
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
setErrorInfo(pSql, code, pCmd->payload); pSql->res.code = code;
tscError("%p open stream failed, sql:%s, reason:%s, code:0x%08x", pSql, pSql->sqlstr, pCmd->payload, code); tscError("%p open stream failed, sql:%s, reason:%s, code:%s", pSql, pSql->sqlstr, pCmd->payload, tstrerror(code));
pStream->fp(pStream->param, NULL, NULL); pStream->fp(pStream->param, NULL, NULL);
return; return;
} }
registerSqlObj(pSql);
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0); SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta); STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
@ -523,13 +522,22 @@ static void tscCreateStream(void *param, TAOS_RES *res, int code) {
pStream->ctime = taosGetTimestamp(pStream->precision); pStream->ctime = taosGetTimestamp(pStream->precision);
pStream->etime = pQueryInfo->window.ekey; pStream->etime = pQueryInfo->window.ekey;
tscAddIntoStreamList(pStream); if (tscSetSlidingWindowInfo(pSql, pStream) != TSDB_CODE_SUCCESS) {
pSql->res.code = code;
tscError("%p stream %p open failed, since the interval value is incorrect", pSql, pStream);
pStream->fp(pStream->param, NULL, NULL);
return;
}
tscSetSlidingWindowInfo(pSql, pStream);
pStream->stime = tscGetStreamStartTimestamp(pSql, pStream, pStream->stime); pStream->stime = tscGetStreamStartTimestamp(pSql, pStream, pStream->stime);
int64_t starttime = tscGetLaunchTimestamp(pStream); int64_t starttime = tscGetLaunchTimestamp(pStream);
pCmd->command = TSDB_SQL_SELECT; pCmd->command = TSDB_SQL_SELECT;
registerSqlObj(pSql);
tscAddIntoStreamList(pStream);
taosTmrReset(tscProcessStreamTimer, (int32_t)starttime, pStream, tscTmr, &pStream->pTimer); taosTmrReset(tscProcessStreamTimer, (int32_t)starttime, pStream, tscTmr, &pStream->pTimer);
tscDebug("%p stream:%p is opened, query on:%s, interval:%" PRId64 ", sliding:%" PRId64 ", first launched in:%" PRId64 ", sql:%s", pSql, tscDebug("%p stream:%p is opened, query on:%s, interval:%" PRId64 ", sliding:%" PRId64 ", first launched in:%" PRId64 ", sql:%s", pSql,

View File

@ -188,8 +188,10 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJ
tsBufFlush(output2); tsBufFlush(output2);
tsBufDestroy(pSupporter1->pTSBuf); tsBufDestroy(pSupporter1->pTSBuf);
pSupporter1->pTSBuf = NULL;
tsBufDestroy(pSupporter2->pTSBuf); tsBufDestroy(pSupporter2->pTSBuf);
pSupporter2->pTSBuf = NULL;
TSKEY et = taosGetTimestampUs(); TSKEY et = taosGetTimestampUs();
tscDebug("%p input1:%" PRId64 ", input2:%" PRId64 ", final:%" PRId64 " in %d vnodes for secondary query after ts blocks " tscDebug("%p input1:%" PRId64 ", input2:%" PRId64 ", final:%" PRId64 " in %d vnodes for secondary query after ts blocks "
"intersecting, skey:%" PRId64 ", ekey:%" PRId64 ", numOfVnode:%d, elapsed time:%" PRId64 " us", "intersecting, skey:%" PRId64 ", ekey:%" PRId64 ", numOfVnode:%d, elapsed time:%" PRId64 " us",
@ -219,12 +221,9 @@ SJoinSupporter* tscCreateJoinSupporter(SSqlObj* pSql, int32_t index) {
assert (pSupporter->uid != 0); assert (pSupporter->uid != 0);
taosGetTmpfilePath("join-", pSupporter->path); taosGetTmpfilePath("join-", pSupporter->path);
pSupporter->f = fopen(pSupporter->path, "w");
// todo handle error // do NOT create file here to reduce crash generated file left issue
if (pSupporter->f == NULL) { pSupporter->f = NULL;
tscError("%p failed to create tmp file:%s, reason:%s", pSql, pSupporter->path, strerror(errno));
}
return pSupporter; return pSupporter;
} }
@ -244,12 +243,19 @@ static void tscDestroyJoinSupporter(SJoinSupporter* pSupporter) {
tscFieldInfoClear(&pSupporter->fieldsInfo); tscFieldInfoClear(&pSupporter->fieldsInfo);
if (pSupporter->pTSBuf != NULL) {
tsBufDestroy(pSupporter->pTSBuf);
pSupporter->pTSBuf = NULL;
}
unlink(pSupporter->path);
if (pSupporter->f != NULL) { if (pSupporter->f != NULL) {
fclose(pSupporter->f); fclose(pSupporter->f);
unlink(pSupporter->path);
pSupporter->f = NULL; pSupporter->f = NULL;
} }
if (pSupporter->pVgroupTables != NULL) { if (pSupporter->pVgroupTables != NULL) {
taosArrayDestroy(pSupporter->pVgroupTables); taosArrayDestroy(pSupporter->pVgroupTables);
pSupporter->pVgroupTables = NULL; pSupporter->pVgroupTables = NULL;
@ -526,6 +532,8 @@ static void quitAllSubquery(SSqlObj* pSqlObj, SJoinSupporter* pSupporter) {
tscError("%p all subquery return and query failed, global code:%s", pSqlObj, tstrerror(pSqlObj->res.code)); tscError("%p all subquery return and query failed, global code:%s", pSqlObj, tstrerror(pSqlObj->res.code));
freeJoinSubqueryObj(pSqlObj); freeJoinSubqueryObj(pSqlObj);
} }
tscDestroyJoinSupporter(pSupporter);
} }
// update the query time range according to the join results on timestamp // update the query time range according to the join results on timestamp
@ -921,6 +929,22 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
} }
if (numOfRows > 0) { // write the compressed timestamp to disk file if (numOfRows > 0) { // write the compressed timestamp to disk file
if(pSupporter->f == NULL) {
pSupporter->f = fopen(pSupporter->path, "w");
if (pSupporter->f == NULL) {
tscError("%p failed to create tmp file:%s, reason:%s", pSql, pSupporter->path, strerror(errno));
pParentSql->res.code = TAOS_SYSTEM_ERROR(errno);
quitAllSubquery(pParentSql, pSupporter);
tscAsyncResultOnError(pParentSql);
return;
}
}
fwrite(pRes->data, (size_t)pRes->numOfRows, 1, pSupporter->f); fwrite(pRes->data, (size_t)pRes->numOfRows, 1, pSupporter->f);
fclose(pSupporter->f); fclose(pSupporter->f);
pSupporter->f = NULL; pSupporter->f = NULL;
@ -930,6 +954,9 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
tscError("%p invalid ts comp file from vnode, abort subquery, file size:%d", pSql, numOfRows); tscError("%p invalid ts comp file from vnode, abort subquery, file size:%d", pSql, numOfRows);
pParentSql->res.code = TAOS_SYSTEM_ERROR(errno); pParentSql->res.code = TAOS_SYSTEM_ERROR(errno);
quitAllSubquery(pParentSql, pSupporter);
tscAsyncResultOnError(pParentSql); tscAsyncResultOnError(pParentSql);
return; return;
@ -2094,6 +2121,13 @@ static SSqlObj *tscCreateSTableSubquery(SSqlObj *pSql, SRetrieveSupport *trsuppo
} }
void tscRetrieveDataRes(void *param, TAOS_RES *tres, int code) { void tscRetrieveDataRes(void *param, TAOS_RES *tres, int code) {
// the param may be null, since it may be done by other query threads. and the asyncOnError may enter in this
// function while kill query by a user.
if (param == NULL) {
assert(code != TSDB_CODE_SUCCESS);
return;
}
SRetrieveSupport *trsupport = (SRetrieveSupport *) param; SRetrieveSupport *trsupport = (SRetrieveSupport *) param;
SSqlObj* pParentSql = trsupport->pParentSql; SSqlObj* pParentSql = trsupport->pParentSql;

View File

@ -19,136 +19,137 @@ using System.Runtime.InteropServices;
namespace TDengineDriver namespace TDengineDriver
{ {
enum TDengineDataType { enum TDengineDataType
TSDB_DATA_TYPE_NULL = 0, // 1 bytes
TSDB_DATA_TYPE_BOOL = 1, // 1 bytes
TSDB_DATA_TYPE_TINYINT = 2, // 1 bytes
TSDB_DATA_TYPE_SMALLINT = 3, // 2 bytes
TSDB_DATA_TYPE_INT = 4, // 4 bytes
TSDB_DATA_TYPE_BIGINT = 5, // 8 bytes
TSDB_DATA_TYPE_FLOAT = 6, // 4 bytes
TSDB_DATA_TYPE_DOUBLE = 7, // 8 bytes
TSDB_DATA_TYPE_BINARY = 8, // string
TSDB_DATA_TYPE_TIMESTAMP = 9,// 8 bytes
TSDB_DATA_TYPE_NCHAR = 10 // unicode string
}
enum TDengineInitOption
{
TSDB_OPTION_LOCALE = 0,
TSDB_OPTION_CHARSET = 1,
TSDB_OPTION_TIMEZONE = 2,
TDDB_OPTION_CONFIGDIR = 3,
TDDB_OPTION_SHELL_ACTIVITY_TIMER = 4
}
class TDengineMeta
{
public string name;
public short size;
public byte type;
public string TypeName()
{ {
switch ((TDengineDataType)type) TSDB_DATA_TYPE_NULL = 0, // 1 bytes
{ TSDB_DATA_TYPE_BOOL = 1, // 1 bytes
case TDengineDataType.TSDB_DATA_TYPE_BOOL: TSDB_DATA_TYPE_TINYINT = 2, // 1 bytes
return "BOOLEAN"; TSDB_DATA_TYPE_SMALLINT = 3, // 2 bytes
case TDengineDataType.TSDB_DATA_TYPE_TINYINT: TSDB_DATA_TYPE_INT = 4, // 4 bytes
return "BYTE"; TSDB_DATA_TYPE_BIGINT = 5, // 8 bytes
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT: TSDB_DATA_TYPE_FLOAT = 6, // 4 bytes
return "SHORT"; TSDB_DATA_TYPE_DOUBLE = 7, // 8 bytes
case TDengineDataType.TSDB_DATA_TYPE_INT: TSDB_DATA_TYPE_BINARY = 8, // string
return "INT"; TSDB_DATA_TYPE_TIMESTAMP = 9,// 8 bytes
case TDengineDataType.TSDB_DATA_TYPE_BIGINT: TSDB_DATA_TYPE_NCHAR = 10 // unicode string
return "LONG";
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
return "FLOAT";
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
return "DOUBLE";
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
return "STRING";
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
return "TIMESTAMP";
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
return "NCHAR";
default:
return "undefine";
}
}
}
class TDengine
{
public const int TSDB_CODE_SUCCESS = 0;
[DllImport("taos.dll", EntryPoint = "taos_init", CallingConvention = CallingConvention.Cdecl)]
static extern public void Init();
[DllImport("taos.dll", EntryPoint = "taos_cleanup", CallingConvention = CallingConvention.Cdecl)]
static extern public void Cleanup();
[DllImport("taos.dll", EntryPoint = "taos_options", CallingConvention = CallingConvention.Cdecl)]
static extern public void Options(int option, string value);
[DllImport("taos.dll", EntryPoint = "taos_connect", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr Connect(string ip, string user, string password, string db, short port);
[DllImport("taos.dll", EntryPoint = "taos_errstr", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr taos_errstr(IntPtr res);
static public string Error(IntPtr res)
{
IntPtr errPtr = taos_errstr(res);
return Marshal.PtrToStringAnsi(errPtr);
} }
[DllImport("taos.dll", EntryPoint = "taos_errno", CallingConvention = CallingConvention.Cdecl)] enum TDengineInitOption
static extern public int ErrorNo(IntPtr res);
[DllImport("taos.dll", EntryPoint = "taos_query", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr Query(IntPtr conn, string sqlstr);
[DllImport("taos.dll", EntryPoint = "taos_affected_rows", CallingConvention = CallingConvention.Cdecl)]
static extern public int AffectRows(IntPtr res);
[DllImport("taos.dll", EntryPoint = "taos_field_count", CallingConvention = CallingConvention.Cdecl)]
static extern public int FieldCount(IntPtr res);
[DllImport("taos.dll", EntryPoint = "taos_fetch_fields", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr taos_fetch_fields(IntPtr res);
static public List<TDengineMeta> FetchFields(IntPtr res)
{ {
const int fieldSize = 68; TSDB_OPTION_LOCALE = 0,
TSDB_OPTION_CHARSET = 1,
List<TDengineMeta> metas = new List<TDengineMeta>(); TSDB_OPTION_TIMEZONE = 2,
if (res == IntPtr.Zero) TDDB_OPTION_CONFIGDIR = 3,
{ TDDB_OPTION_SHELL_ACTIVITY_TIMER = 4
return metas;
}
int fieldCount = FieldCount(res);
IntPtr fieldsPtr = taos_fetch_fields(res);
for (int i = 0; i < fieldCount; ++i)
{
int offset = i * fieldSize;
TDengineMeta meta = new TDengineMeta();
meta.name = Marshal.PtrToStringAnsi(fieldsPtr + offset);
meta.type = Marshal.ReadByte(fieldsPtr + offset + 65);
meta.size = Marshal.ReadInt16(fieldsPtr + offset + 66);
metas.Add(meta);
}
return metas;
} }
[DllImport("taos.dll", EntryPoint = "taos_fetch_row", CallingConvention = CallingConvention.Cdecl)] class TDengineMeta
static extern public IntPtr FetchRows(IntPtr res); {
public string name;
public short size;
public byte type;
public string TypeName()
{
switch ((TDengineDataType)type)
{
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
return "BOOLEAN";
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
return "BYTE";
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
return "SHORT";
case TDengineDataType.TSDB_DATA_TYPE_INT:
return "INT";
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
return "LONG";
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
return "FLOAT";
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
return "DOUBLE";
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
return "STRING";
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
return "TIMESTAMP";
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
return "NCHAR";
default:
return "undefine";
}
}
}
[DllImport("taos.dll", EntryPoint = "taos_free_result", CallingConvention = CallingConvention.Cdecl)] class TDengine
static extern public IntPtr FreeResult(IntPtr res); {
public const int TSDB_CODE_SUCCESS = 0;
[DllImport("taos.dll", EntryPoint = "taos_close", CallingConvention = CallingConvention.Cdecl)] [DllImport("taos", EntryPoint = "taos_init", CallingConvention = CallingConvention.Cdecl)]
static extern public int Close(IntPtr taos); static extern public void Init();
}
} [DllImport("taos", EntryPoint = "taos_cleanup", CallingConvention = CallingConvention.Cdecl)]
static extern public void Cleanup();
[DllImport("taos", EntryPoint = "taos_options", CallingConvention = CallingConvention.Cdecl)]
static extern public void Options(int option, string value);
[DllImport("taos", EntryPoint = "taos_connect", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr Connect(string ip, string user, string password, string db, short port);
[DllImport("taos", EntryPoint = "taos_errstr", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr taos_errstr(IntPtr res);
static public string Error(IntPtr res)
{
IntPtr errPtr = taos_errstr(res);
return Marshal.PtrToStringAnsi(errPtr);
}
[DllImport("taos", EntryPoint = "taos_errno", CallingConvention = CallingConvention.Cdecl)]
static extern public int ErrorNo(IntPtr res);
[DllImport("taos", EntryPoint = "taos_query", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr Query(IntPtr conn, string sqlstr);
[DllImport("taos", EntryPoint = "taos_affected_rows", CallingConvention = CallingConvention.Cdecl)]
static extern public int AffectRows(IntPtr res);
[DllImport("taos", EntryPoint = "taos_field_count", CallingConvention = CallingConvention.Cdecl)]
static extern public int FieldCount(IntPtr res);
[DllImport("taos", EntryPoint = "taos_fetch_fields", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr taos_fetch_fields(IntPtr res);
static public List<TDengineMeta> FetchFields(IntPtr res)
{
const int fieldSize = 68;
List<TDengineMeta> metas = new List<TDengineMeta>();
if (res == IntPtr.Zero)
{
return metas;
}
int fieldCount = FieldCount(res);
IntPtr fieldsPtr = taos_fetch_fields(res);
for (int i = 0; i < fieldCount; ++i)
{
int offset = i * fieldSize;
TDengineMeta meta = new TDengineMeta();
meta.name = Marshal.PtrToStringAnsi(fieldsPtr + offset);
meta.type = Marshal.ReadByte(fieldsPtr + offset + 65);
meta.size = Marshal.ReadInt16(fieldsPtr + offset + 66);
metas.Add(meta);
}
return metas;
}
[DllImport("taos", EntryPoint = "taos_fetch_row", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr FetchRows(IntPtr res);
[DllImport("taos", EntryPoint = "taos_free_result", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr FreeResult(IntPtr res);
[DllImport("taos", EntryPoint = "taos_close", CallingConvention = CallingConvention.Cdecl)]
static extern public int Close(IntPtr taos);
}
}

View File

@ -56,6 +56,12 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- for restful --> <!-- for restful -->
<dependency> <dependency>
<groupId>org.apache.httpcomponents</groupId> <groupId>org.apache.httpcomponents</groupId>
@ -73,7 +79,14 @@
<version>1.2.58</version> <version>1.2.58</version>
</dependency> </dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>

View File

@ -0,0 +1,808 @@
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
private final static String PRODUCT_NAME = "TDengine";
private final static String PRODUCT_VESION = "2.0.x.x";
private final static String DRIVER_NAME = "taos-jdbcdriver";
private final static String DRIVER_VERSION = "2.0.x";
private final static int DRIVER_MAJAR_VERSION = 2;
private final static int DRIVER_MINOR_VERSION = 0;
public boolean allProceduresAreCallable() throws SQLException {
return false;
}
public boolean allTablesAreSelectable() throws SQLException {
return false;
}
public abstract String getURL() throws SQLException;
public abstract String getUserName() throws SQLException;
public boolean isReadOnly() throws SQLException {
return false;
}
public boolean nullsAreSortedHigh() throws SQLException {
return false;
}
public boolean nullsAreSortedLow() throws SQLException {
return !nullsAreSortedHigh();
}
public boolean nullsAreSortedAtStart() throws SQLException {
return true;
}
public boolean nullsAreSortedAtEnd() throws SQLException {
return !nullsAreSortedAtStart();
}
public String getDatabaseProductName() throws SQLException {
return PRODUCT_NAME;
}
public String getDatabaseProductVersion() throws SQLException {
return PRODUCT_VESION;
}
public String getDriverName() throws SQLException {
return DRIVER_NAME;
}
public String getDriverVersion() throws SQLException {
return DRIVER_VERSION;
}
public int getDriverMajorVersion() {
return DRIVER_MAJAR_VERSION;
}
public int getDriverMinorVersion() {
return DRIVER_MINOR_VERSION;
}
public boolean usesLocalFiles() throws SQLException {
return false;
}
public boolean usesLocalFilePerTable() throws SQLException {
return false;
}
public boolean supportsMixedCaseIdentifiers() throws SQLException {
return false;
}
public boolean storesUpperCaseIdentifiers() throws SQLException {
return false;
}
public boolean storesLowerCaseIdentifiers() throws SQLException {
return false;
}
public boolean storesMixedCaseIdentifiers() throws SQLException {
return false;
}
public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
return false;
}
public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
return false;
}
public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
return false;
}
public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
return false;
}
public String getIdentifierQuoteString() throws SQLException {
return " ";
}
public String getSQLKeywords() throws SQLException {
return null;
}
public String getNumericFunctions() throws SQLException {
return null;
}
public String getStringFunctions() throws SQLException {
return null;
}
public String getSystemFunctions() throws SQLException {
return null;
}
public String getTimeDateFunctions() throws SQLException {
return null;
}
public String getSearchStringEscape() throws SQLException {
return null;
}
public String getExtraNameCharacters() throws SQLException {
return null;
}
public boolean supportsAlterTableWithAddColumn() throws SQLException {
return true;
}
public boolean supportsAlterTableWithDropColumn() throws SQLException {
return true;
}
public boolean supportsColumnAliasing() throws SQLException {
return true;
}
public boolean nullPlusNonNullIsNull() throws SQLException {
return false;
}
public boolean supportsConvert() throws SQLException {
return false;
}
public boolean supportsConvert(int fromType, int toType) throws SQLException {
return false;
}
public boolean supportsTableCorrelationNames() throws SQLException {
return false;
}
public boolean supportsDifferentTableCorrelationNames() throws SQLException {
return false;
}
public boolean supportsExpressionsInOrderBy() throws SQLException {
return false;
}
public boolean supportsOrderByUnrelated() throws SQLException {
return false;
}
public boolean supportsGroupBy() throws SQLException {
return false;
}
public boolean supportsGroupByUnrelated() throws SQLException {
return false;
}
public boolean supportsGroupByBeyondSelect() throws SQLException {
return false;
}
public boolean supportsLikeEscapeClause() throws SQLException {
return false;
}
public boolean supportsMultipleResultSets() throws SQLException {
return false;
}
public boolean supportsMultipleTransactions() throws SQLException {
return false;
}
public boolean supportsNonNullableColumns() throws SQLException {
return false;
}
public boolean supportsMinimumSQLGrammar() throws SQLException {
return false;
}
public boolean supportsCoreSQLGrammar() throws SQLException {
return false;
}
public boolean supportsExtendedSQLGrammar() throws SQLException {
return false;
}
public boolean supportsANSI92EntryLevelSQL() throws SQLException {
return false;
}
public boolean supportsANSI92IntermediateSQL() throws SQLException {
return false;
}
public boolean supportsANSI92FullSQL() throws SQLException {
return false;
}
public boolean supportsIntegrityEnhancementFacility() throws SQLException {
return false;
}
public boolean supportsOuterJoins() throws SQLException {
return false;
}
public boolean supportsFullOuterJoins() throws SQLException {
return false;
}
public boolean supportsLimitedOuterJoins() throws SQLException {
return false;
}
public String getSchemaTerm() throws SQLException {
return null;
}
public String getProcedureTerm() throws SQLException {
return null;
}
public String getCatalogTerm() throws SQLException {
return "database";
}
public boolean isCatalogAtStart() throws SQLException {
return true;
}
public String getCatalogSeparator() throws SQLException {
return ".";
}
public boolean supportsSchemasInDataManipulation() throws SQLException {
return false;
}
public boolean supportsSchemasInProcedureCalls() throws SQLException {
return false;
}
public boolean supportsSchemasInTableDefinitions() throws SQLException {
return false;
}
public boolean supportsSchemasInIndexDefinitions() throws SQLException {
return false;
}
public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {
return false;
}
public boolean supportsCatalogsInDataManipulation() throws SQLException {
return true;
}
public boolean supportsCatalogsInProcedureCalls() throws SQLException {
return false;
}
public boolean supportsCatalogsInTableDefinitions() throws SQLException {
return false;
}
public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
return false;
}
public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {
return false;
}
public boolean supportsPositionedDelete() throws SQLException {
return false;
}
public boolean supportsPositionedUpdate() throws SQLException {
return false;
}
public boolean supportsSelectForUpdate() throws SQLException {
return false;
}
public boolean supportsStoredProcedures() throws SQLException {
return false;
}
public boolean supportsSubqueriesInComparisons() throws SQLException {
return false;
}
public boolean supportsSubqueriesInExists() throws SQLException {
return false;
}
public boolean supportsSubqueriesInIns() throws SQLException {
return false;
}
public boolean supportsSubqueriesInQuantifieds() throws SQLException {
return false;
}
public boolean supportsCorrelatedSubqueries() throws SQLException {
return false;
}
public boolean supportsUnion() throws SQLException {
return false;
}
public boolean supportsUnionAll() throws SQLException {
return false;
}
public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
return false;
}
public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
return false;
}
public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
return false;
}
public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
return false;
}
public int getMaxBinaryLiteralLength() throws SQLException {
return 0;
}
public int getMaxCharLiteralLength() throws SQLException {
return 0;
}
public int getMaxColumnNameLength() throws SQLException {
return 0;
}
public int getMaxColumnsInGroupBy() throws SQLException {
return 0;
}
public int getMaxColumnsInIndex() throws SQLException {
return 0;
}
public int getMaxColumnsInOrderBy() throws SQLException {
return 0;
}
public int getMaxColumnsInSelect() throws SQLException {
return 0;
}
public int getMaxColumnsInTable() throws SQLException {
return 0;
}
public int getMaxConnections() throws SQLException {
return 0;
}
public int getMaxCursorNameLength() throws SQLException {
return 0;
}
public int getMaxIndexLength() throws SQLException {
return 0;
}
public int getMaxSchemaNameLength() throws SQLException {
return 0;
}
public int getMaxProcedureNameLength() throws SQLException {
return 0;
}
public int getMaxCatalogNameLength() throws SQLException {
return 0;
}
public int getMaxRowSize() throws SQLException {
return 0;
}
public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
return false;
}
public int getMaxStatementLength() throws SQLException {
return 0;
}
public int getMaxStatements() throws SQLException {
return 0;
}
public int getMaxTableNameLength() throws SQLException {
return 0;
}
public int getMaxTablesInSelect() throws SQLException {
return 0;
}
public int getMaxUserNameLength() throws SQLException {
return 0;
}
public int getDefaultTransactionIsolation() throws SQLException {
return 0;
}
public boolean supportsTransactions() throws SQLException {
return false;
}
public boolean supportsTransactionIsolationLevel(int level) throws SQLException {
return false;
}
public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {
return false;
}
public boolean supportsDataManipulationTransactionsOnly() throws SQLException {
return false;
}
public boolean dataDefinitionCausesTransactionCommit() throws SQLException {
return false;
}
public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
return false;
}
public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern)
throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern,
String columnNamePattern) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public abstract ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types)
throws SQLException;
public ResultSet getSchemas() throws SQLException {
return getEmptyResultSet();
}
public abstract ResultSet getCatalogs() throws SQLException;
public ResultSet getTableTypes() throws SQLException {
DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
// set up ColumnMetaDataList
List<ColumnMetaData> columnMetaDataList = new ArrayList<ColumnMetaData>(1);
ColumnMetaData colMetaData = new ColumnMetaData();
colMetaData.setColIndex(0);
colMetaData.setColName("TABLE_TYPE");
colMetaData.setColSize(10);
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
columnMetaDataList.add(colMetaData);
// set up rowDataList
List<TSDBResultSetRowData> rowDataList = new ArrayList<TSDBResultSetRowData>(2);
TSDBResultSetRowData rowData = new TSDBResultSetRowData();
rowData.setString(0, "TABLE");
rowDataList.add(rowData);
rowData = new TSDBResultSetRowData();
rowData.setString(0, "STABLE");
rowDataList.add(rowData);
resultSet.setColumnMetaDataList(columnMetaDataList);
resultSet.setRowDataList(rowDataList);
return resultSet;
}
public abstract ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException;
protected int getNullable(int index, String typeName) {
if (index == 0 && "TIMESTAMP".equals(typeName))
return DatabaseMetaData.columnNoNulls;
return DatabaseMetaData.columnNullable;
}
protected int getColumnSize(String typeName, int length) {
switch (typeName) {
case "TIMESTAMP":
return 23;
default:
return 0;
}
}
protected int getDecimalDigits(String typeName) {
switch (typeName) {
case "FLOAT":
return 5;
case "DOUBLE":
return 9;
default:
return 0;
}
}
protected int getDataType(String typeName) {
switch (typeName) {
case "TIMESTAMP":
return Types.TIMESTAMP;
case "INT":
return Types.INTEGER;
case "BIGINT":
return Types.BIGINT;
case "FLOAT":
return Types.FLOAT;
case "DOUBLE":
return Types.DOUBLE;
case "BINARY":
return Types.BINARY;
case "SMALLINT":
return Types.SMALLINT;
case "TINYINT":
return Types.TINYINT;
case "BOOL":
return Types.BOOLEAN;
case "NCHAR":
return Types.NCHAR;
default:
return Types.NULL;
}
}
public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern)
throws SQLException {
return getEmptyResultSet();
}
public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern)
throws SQLException {
return getEmptyResultSet();
}
public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable)
throws SQLException {
return getEmptyResultSet();
}
public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable,
String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getTypeInfo() throws SQLException {
return getEmptyResultSet();
}
public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate)
throws SQLException {
return getEmptyResultSet();
}
public boolean supportsResultSetType(int type) throws SQLException {
return false;
}
public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {
return false;
}
public boolean ownUpdatesAreVisible(int type) throws SQLException {
return false;
}
public boolean ownDeletesAreVisible(int type) throws SQLException {
return false;
}
public boolean ownInsertsAreVisible(int type) throws SQLException {
return false;
}
public boolean othersUpdatesAreVisible(int type) throws SQLException {
return false;
}
public boolean othersDeletesAreVisible(int type) throws SQLException {
return false;
}
public boolean othersInsertsAreVisible(int type) throws SQLException {
return false;
}
public boolean updatesAreDetected(int type) throws SQLException {
return false;
}
public boolean deletesAreDetected(int type) throws SQLException {
return false;
}
public boolean insertsAreDetected(int type) throws SQLException {
return false;
}
public boolean supportsBatchUpdates() throws SQLException {
return false;
}
public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types)
throws SQLException {
return getEmptyResultSet();
}
public Connection getConnection() throws SQLException {
return null;
}
public boolean supportsSavepoints() throws SQLException {
return false;
}
public boolean supportsNamedParameters() throws SQLException {
return false;
}
public boolean supportsMultipleOpenResults() throws SQLException {
return false;
}
public boolean supportsGetGeneratedKeys() throws SQLException {
return false;
}
public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern,
String attributeNamePattern) throws SQLException {
return getEmptyResultSet();
}
public boolean supportsResultSetHoldability(int holdability) throws SQLException {
return false;
}
public int getResultSetHoldability() throws SQLException {
return 0;
}
public int getDatabaseMajorVersion() throws SQLException {
return 0;
}
public int getDatabaseMinorVersion() throws SQLException {
return 0;
}
public int getJDBCMajorVersion() throws SQLException {
return 0;
}
public int getJDBCMinorVersion() throws SQLException {
return 0;
}
public int getSQLStateType() throws SQLException {
return 0;
}
public boolean locatorsUpdateCopy() throws SQLException {
return false;
}
public boolean supportsStatementPooling() throws SQLException {
return false;
}
public RowIdLifetime getRowIdLifetime() throws SQLException {
return null;
}
public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
return null;
}
public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
return false;
}
public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
return false;
}
public ResultSet getClientInfoProperties() throws SQLException {
return getEmptyResultSet();
}
public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern)
throws SQLException {
return getEmptyResultSet();
}
public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern,
String columnNamePattern) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern,
String columnNamePattern) throws SQLException {
return getEmptyResultSet();
}
public boolean generatedKeyAlwaysReturned() throws SQLException {
return false;
}
private ResultSet getEmptyResultSet() {
return new EmptyResultSet();
}
}

View File

@ -19,68 +19,71 @@ import java.util.Map;
public abstract class TSDBConstants { public abstract class TSDBConstants {
public static final String DEFAULT_PORT = "6200"; public static final String DEFAULT_PORT = "6200";
public static final String UNSUPPORT_METHOD_EXCEPTIONZ_MSG = "this operation is NOT supported currently!"; public static final String UNSUPPORT_METHOD_EXCEPTIONZ_MSG = "this operation is NOT supported currently!";
public static final String INVALID_VARIABLES = "invalid variables"; public static final String INVALID_VARIABLES = "invalid variables";
public static Map<Integer, String> DATATYPE_MAP = null; public static Map<Integer, String> DATATYPE_MAP = null;
public static final long JNI_NULL_POINTER = 0L; public static final long JNI_NULL_POINTER = 0L;
public static final int JNI_SUCCESS = 0; public static final int JNI_SUCCESS = 0;
public static final int JNI_TDENGINE_ERROR = -1; public static final int JNI_TDENGINE_ERROR = -1;
public static final int JNI_CONNECTION_NULL = -2; public static final int JNI_CONNECTION_NULL = -2;
public static final int JNI_RESULT_SET_NULL = -3; public static final int JNI_RESULT_SET_NULL = -3;
public static final int JNI_NUM_OF_FIELDS_0 = -4; public static final int JNI_NUM_OF_FIELDS_0 = -4;
public static final int JNI_SQL_NULL = -5; public static final int JNI_SQL_NULL = -5;
public static final int JNI_FETCH_END = -6; public static final int JNI_FETCH_END = -6;
public static final int TSDB_DATA_TYPE_NULL = 0;
public static final int TSDB_DATA_TYPE_BOOL = 1;
public static final int TSDB_DATA_TYPE_TINYINT = 2;
public static final int TSDB_DATA_TYPE_SMALLINT = 3;
public static final int TSDB_DATA_TYPE_INT = 4;
public static final int TSDB_DATA_TYPE_BIGINT = 5;
public static final int TSDB_DATA_TYPE_FLOAT = 6;
public static final int TSDB_DATA_TYPE_DOUBLE = 7;
public static final int TSDB_DATA_TYPE_BINARY = 8;
public static final int TSDB_DATA_TYPE_TIMESTAMP = 9;
public static final int TSDB_DATA_TYPE_NCHAR = 10;
public static String WrapErrMsg(String msg) {
return "TDengine Error: " + msg;
}
public static String FixErrMsg(int code) { public static final int TSDB_DATA_TYPE_NULL = 0;
switch (code) { public static final int TSDB_DATA_TYPE_BOOL = 1;
case JNI_TDENGINE_ERROR: public static final int TSDB_DATA_TYPE_TINYINT = 2;
return WrapErrMsg("internal error of database!"); public static final int TSDB_DATA_TYPE_SMALLINT = 3;
case JNI_CONNECTION_NULL: public static final int TSDB_DATA_TYPE_INT = 4;
return WrapErrMsg("invalid tdengine connection!"); public static final int TSDB_DATA_TYPE_BIGINT = 5;
case JNI_RESULT_SET_NULL: public static final int TSDB_DATA_TYPE_FLOAT = 6;
return WrapErrMsg("invalid resultset pointer!"); public static final int TSDB_DATA_TYPE_DOUBLE = 7;
case JNI_NUM_OF_FIELDS_0: public static final int TSDB_DATA_TYPE_BINARY = 8;
return WrapErrMsg("invalid num of fields!"); public static final int TSDB_DATA_TYPE_TIMESTAMP = 9;
case JNI_SQL_NULL: public static final int TSDB_DATA_TYPE_NCHAR = 10;
return WrapErrMsg("can't execute empty sql!");
case JNI_FETCH_END:
return WrapErrMsg("fetch to the end of resultset");
default:
break;
}
return WrapErrMsg("unkown error!");
}
static { // nchar field's max length
DATATYPE_MAP = new HashMap<Integer, String>(); public static final int maxFieldSize = 16 * 1024;
DATATYPE_MAP.put(1, "BOOL");
DATATYPE_MAP.put(2, "TINYINT"); public static String WrapErrMsg(String msg) {
DATATYPE_MAP.put(3, "SMALLINT"); return "TDengine Error: " + msg;
DATATYPE_MAP.put(4, "INT"); }
DATATYPE_MAP.put(5, "BIGINT");
DATATYPE_MAP.put(6, "FLOAT"); public static String FixErrMsg(int code) {
DATATYPE_MAP.put(7, "DOUBLE"); switch (code) {
DATATYPE_MAP.put(8, "BINARY"); case JNI_TDENGINE_ERROR:
DATATYPE_MAP.put(9, "TIMESTAMP"); return WrapErrMsg("internal error of database!");
DATATYPE_MAP.put(10, "NCHAR"); case JNI_CONNECTION_NULL:
} return WrapErrMsg("invalid tdengine connection!");
case JNI_RESULT_SET_NULL:
return WrapErrMsg("invalid resultset pointer!");
case JNI_NUM_OF_FIELDS_0:
return WrapErrMsg("invalid num of fields!");
case JNI_SQL_NULL:
return WrapErrMsg("can't execute empty sql!");
case JNI_FETCH_END:
return WrapErrMsg("fetch to the end of resultset");
default:
break;
}
return WrapErrMsg("unkown error!");
}
static {
DATATYPE_MAP = new HashMap<Integer, String>();
DATATYPE_MAP.put(1, "BOOL");
DATATYPE_MAP.put(2, "TINYINT");
DATATYPE_MAP.put(3, "SMALLINT");
DATATYPE_MAP.put(4, "INT");
DATATYPE_MAP.put(5, "BIGINT");
DATATYPE_MAP.put(6, "FLOAT");
DATATYPE_MAP.put(7, "DOUBLE");
DATATYPE_MAP.put(8, "BINARY");
DATATYPE_MAP.put(9, "TIMESTAMP");
DATATYPE_MAP.put(10, "NCHAR");
}
} }

View File

@ -1,19 +1,29 @@
package com.taosdata.jdbc.rs; package com.taosdata.jdbc.rs;
import com.taosdata.jdbc.TSDBConstants; import com.taosdata.jdbc.TSDBConstants;
import com.taosdata.jdbc.TSDBDriver;
import java.sql.*; import java.sql.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
public class RestfulConnection implements Connection { public class RestfulConnection implements Connection {
private static final String CONNECTION_IS_CLOSED = "connection is closed.";
private static final String AUTO_COMMIT_IS_TRUE = "auto commit is true";
private final String host; private final String host;
private final int port; private final int port;
private final Properties props; private final Properties props;
private final String database; private volatile String database;
private final String url; private final String url;
/******************************************************/
private boolean isClosed;
private DatabaseMetaData metadata;
private Map<String, Class<?>> typeMap;
private Properties clientInfoProps = new Properties();
public RestfulConnection(String host, String port, Properties props, String database, String url) { public RestfulConnection(String host, String port, Properties props, String database, String url) {
this.host = host; this.host = host;
@ -21,280 +31,424 @@ public class RestfulConnection implements Connection {
this.props = props; this.props = props;
this.database = database; this.database = database;
this.url = url; this.url = url;
this.metadata = new RestfulDatabaseMetaData(url, props.getProperty(TSDBDriver.PROPERTY_KEY_USER), this);
} }
@Override @Override
public Statement createStatement() throws SQLException { public Statement createStatement() throws SQLException {
if (isClosed()) if (isClosed())
throw new SQLException(TSDBConstants.WrapErrMsg("restful TDengine connection is closed.")); throw new SQLException(CONNECTION_IS_CLOSED);
return new RestfulStatement(this, database); return new RestfulStatement(this, database);
} }
@Override @Override
public PreparedStatement prepareStatement(String sql) throws SQLException { public PreparedStatement prepareStatement(String sql) throws SQLException {
return null; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
//TODO: prepareStatement
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public CallableStatement prepareCall(String sql) throws SQLException { public CallableStatement prepareCall(String sql) throws SQLException {
return null; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public String nativeSQL(String sql) throws SQLException { public String nativeSQL(String sql) throws SQLException {
return null; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
//nothing did
return sql;
} }
@Override @Override
public void setAutoCommit(boolean autoCommit) throws SQLException { public void setAutoCommit(boolean autoCommit) throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
if (!autoCommit)
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public boolean getAutoCommit() throws SQLException { public boolean getAutoCommit() throws SQLException {
return false; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
return true;
} }
@Override @Override
public void commit() throws SQLException { public void commit() throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
if (getAutoCommit())
throw new SQLException(AUTO_COMMIT_IS_TRUE);
//nothing to do
} }
@Override @Override
public void rollback() throws SQLException { public void rollback() throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
if (getAutoCommit())
throw new SQLException(AUTO_COMMIT_IS_TRUE);
//nothing to do
} }
@Override @Override
public void close() throws SQLException { public void close() throws SQLException {
if (isClosed)
return;
//TODO: release all resources
isClosed = true;
} }
@Override @Override
public boolean isClosed() throws SQLException { public boolean isClosed() throws SQLException {
return false; return isClosed;
} }
@Override @Override
public DatabaseMetaData getMetaData() throws SQLException { public DatabaseMetaData getMetaData() throws SQLException {
//TODO: RestfulDatabaseMetaData is not implemented if (isClosed())
return new RestfulDatabaseMetaData(); throw new SQLException(CONNECTION_IS_CLOSED);
return this.metadata;
} }
@Override @Override
public void setReadOnly(boolean readOnly) throws SQLException { public void setReadOnly(boolean readOnly) throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
// nothing to do
} }
@Override @Override
public boolean isReadOnly() throws SQLException { public boolean isReadOnly() throws SQLException {
return false; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
return true;
} }
@Override @Override
public void setCatalog(String catalog) throws SQLException { public void setCatalog(String catalog) throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
synchronized (RestfulConnection.class) {
this.database = catalog;
}
} }
@Override @Override
public String getCatalog() throws SQLException { public String getCatalog() throws SQLException {
return null; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
return this.database;
} }
@Override @Override
public void setTransactionIsolation(int level) throws SQLException { public void setTransactionIsolation(int level) throws SQLException {
//transaction is not supported if (isClosed())
throw new SQLFeatureNotSupportedException("transactions are not supported"); throw new SQLException(CONNECTION_IS_CLOSED);
switch (level) {
case Connection.TRANSACTION_NONE:
break;
case Connection.TRANSACTION_READ_UNCOMMITTED:
case Connection.TRANSACTION_READ_COMMITTED:
case Connection.TRANSACTION_REPEATABLE_READ:
case Connection.TRANSACTION_SERIALIZABLE:
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
default:
throw new SQLException(TSDBConstants.INVALID_VARIABLES);
}
} }
/**
*
*/
@Override @Override
public int getTransactionIsolation() throws SQLException { public int getTransactionIsolation() throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
//Connection.TRANSACTION_NONE specifies that transactions are not supported. //Connection.TRANSACTION_NONE specifies that transactions are not supported.
return Connection.TRANSACTION_NONE; return Connection.TRANSACTION_NONE;
} }
@Override @Override
public SQLWarning getWarnings() throws SQLException { public SQLWarning getWarnings() throws SQLException {
//TODO: getWarnings not implemented if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
return null; return null;
} }
@Override @Override
public void clearWarnings() throws SQLException { public void clearWarnings() throws SQLException {
throw new SQLFeatureNotSupportedException("clearWarnings not supported."); if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
//nothing to do
} }
@Override @Override
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
return null; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
if (resultSetType != ResultSet.TYPE_FORWARD_ONLY) {
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY)
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
return createStatement();
} }
@Override @Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return null; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
if (resultSetType != ResultSet.TYPE_FORWARD_ONLY || resultSetConcurrency != ResultSet.CONCUR_READ_ONLY)
throw new SQLFeatureNotSupportedException(TSDBConstants.INVALID_VARIABLES);
return this.prepareStatement(sql);
} }
@Override @Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return null; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
if (resultSetType != ResultSet.TYPE_FORWARD_ONLY || resultSetConcurrency != ResultSet.CONCUR_READ_ONLY)
throw new SQLFeatureNotSupportedException(TSDBConstants.INVALID_VARIABLES);
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public Map<String, Class<?>> getTypeMap() throws SQLException { public Map<String, Class<?>> getTypeMap() throws SQLException {
return null; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
synchronized (RestfulConnection.class) {
if (this.typeMap == null) {
this.typeMap = new HashMap<>();
}
return this.typeMap;
}
} }
@Override @Override
public void setTypeMap(Map<String, Class<?>> map) throws SQLException { public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
synchronized (RestfulConnection.class) {
this.typeMap = map;
}
} }
@Override @Override
public void setHoldability(int holdability) throws SQLException { public void setHoldability(int holdability) throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
if (holdability != ResultSet.HOLD_CURSORS_OVER_COMMIT)
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public int getHoldability() throws SQLException { public int getHoldability() throws SQLException {
return 0; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
return ResultSet.HOLD_CURSORS_OVER_COMMIT;
} }
@Override @Override
public Savepoint setSavepoint() throws SQLException { public Savepoint setSavepoint() throws SQLException {
return null; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
if (getAutoCommit())
throw new SQLException(TSDBConstants.INVALID_VARIABLES);
//nothing to do
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public Savepoint setSavepoint(String name) throws SQLException { public Savepoint setSavepoint(String name) throws SQLException {
return null; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
if (getAutoCommit())
throw new SQLException(TSDBConstants.INVALID_VARIABLES);
//nothing to do
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public void rollback(Savepoint savepoint) throws SQLException { public void rollback(Savepoint savepoint) throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
if (getAutoCommit())
throw new SQLException(TSDBConstants.INVALID_VARIABLES);
//nothing to do
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException { public void releaseSavepoint(Savepoint savepoint) throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return null; if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT)
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
return createStatement(resultSetType, resultSetConcurrency);
} }
@Override @Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return null; if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT)
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
return prepareStatement(sql, resultSetType, resultSetConcurrency);
} }
@Override @Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return null; throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
return null; throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
return null; throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
return null; throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public Clob createClob() throws SQLException { public Clob createClob() throws SQLException {
//TODO: not supported throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
throw new SQLFeatureNotSupportedException();
} }
@Override @Override
public Blob createBlob() throws SQLException { public Blob createBlob() throws SQLException {
//TODO: not supported throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
throw new SQLFeatureNotSupportedException();
} }
@Override @Override
public NClob createNClob() throws SQLException { public NClob createNClob() throws SQLException {
//TODO: not supported throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
throw new SQLFeatureNotSupportedException();
} }
@Override @Override
public SQLXML createSQLXML() throws SQLException { public SQLXML createSQLXML() throws SQLException {
//TODO: not supported throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
throw new SQLFeatureNotSupportedException();
} }
@Override @Override
public boolean isValid(int timeout) throws SQLException { public boolean isValid(int timeout) throws SQLException {
return false; if (timeout < 0)
throw new SQLException(TSDBConstants.INVALID_VARIABLES);
// TODO:
/* The driver shall submit a query on the connection or use some other mechanism that positively verifies
the connection is still valid when this method is called.*/
return !isClosed();
} }
@Override @Override
public void setClientInfo(String name, String value) throws SQLClientInfoException { public void setClientInfo(String name, String value) throws SQLClientInfoException {
if (isClosed)
throw new SQLClientInfoException();
clientInfoProps.setProperty(name, value);
} }
@Override @Override
public void setClientInfo(Properties properties) throws SQLClientInfoException { public void setClientInfo(Properties properties) throws SQLClientInfoException {
if (isClosed)
throw new SQLClientInfoException();
for (Enumeration<Object> enumer = properties.keys(); enumer.hasMoreElements(); ) {
String name = (String) enumer.nextElement();
clientInfoProps.put(name, properties.getProperty(name));
}
} }
@Override @Override
public String getClientInfo(String name) throws SQLException { public String getClientInfo(String name) throws SQLException {
return null; if (isClosed)
throw new SQLClientInfoException();
return clientInfoProps.getProperty(name);
} }
@Override @Override
public Properties getClientInfo() throws SQLException { public Properties getClientInfo() throws SQLException {
return null; if (isClosed)
throw new SQLClientInfoException();
return clientInfoProps;
} }
@Override @Override
public Array createArrayOf(String typeName, Object[] elements) throws SQLException { public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
//TODO: not supported throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
throw new SQLFeatureNotSupportedException();
} }
@Override @Override
public Struct createStruct(String typeName, Object[] attributes) throws SQLException { public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
//TODO: not supported throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
throw new SQLFeatureNotSupportedException();
} }
@Override @Override
public void setSchema(String schema) throws SQLException { public void setSchema(String schema) throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
synchronized (RestfulConnection.class) {
this.database = schema;
}
} }
@Override @Override
public String getSchema() throws SQLException { public String getSchema() throws SQLException {
return null; if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
return this.database;
} }
@Override @Override
public void abort(Executor executor) throws SQLException { public void abort(Executor executor) throws SQLException {
if (executor == null) {
throw new SQLException("Executor can not be null");
}
executor.execute(() -> {
try {
close();
} catch (SQLException e) {
e.printStackTrace();
}
});
} }
@Override @Override
public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public int getNetworkTimeout() throws SQLException { public int getNetworkTimeout() throws SQLException {
if (isClosed())
throw new SQLException(CONNECTION_IS_CLOSED);
return 0; return 0;
} }

View File

@ -33,7 +33,7 @@ public class RestfulDriver extends AbstractTaosDriver {
return null; return null;
Properties props = parseURL(url, info); Properties props = parseURL(url, info);
String host = props.getProperty(TSDBDriver.PROPERTY_KEY_HOST, "localhost"); String host = props.getProperty(TSDBDriver.PROPERTY_KEY_HOST);
String port = props.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "6041"); String port = props.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "6041");
String database = props.containsKey(TSDBDriver.PROPERTY_KEY_DBNAME) ? props.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME) : null; String database = props.containsKey(TSDBDriver.PROPERTY_KEY_DBNAME) ? props.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME) : null;

View File

@ -2,13 +2,15 @@ package com.taosdata.jdbc.rs;
import java.sql.ResultSetMetaData; import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.ArrayList;
public class RestfulResultSetMetaData implements ResultSetMetaData { public class RestfulResultSetMetaData implements ResultSetMetaData {
private List<String> fields; private final String database;
private ArrayList<RestfulResultSet.Field> fields;
public RestfulResultSetMetaData(List<String> fields) { public RestfulResultSetMetaData(String database, ArrayList<RestfulResultSet.Field> fields) {
this.database = database;
this.fields = fields; this.fields = fields;
} }
@ -24,6 +26,7 @@ public class RestfulResultSetMetaData implements ResultSetMetaData {
@Override @Override
public boolean isCaseSensitive(int column) throws SQLException { public boolean isCaseSensitive(int column) throws SQLException {
//TODO
return false; return false;
} }
@ -39,7 +42,7 @@ public class RestfulResultSetMetaData implements ResultSetMetaData {
@Override @Override
public int isNullable(int column) throws SQLException { public int isNullable(int column) throws SQLException {
return 0; return ResultSetMetaData.columnNullable;
} }
@Override @Override
@ -54,7 +57,7 @@ public class RestfulResultSetMetaData implements ResultSetMetaData {
@Override @Override
public String getColumnLabel(int column) throws SQLException { public String getColumnLabel(int column) throws SQLException {
return fields.get(column - 1); return fields.get(column - 1).name;
} }
@Override @Override
@ -64,7 +67,7 @@ public class RestfulResultSetMetaData implements ResultSetMetaData {
@Override @Override
public String getSchemaName(int column) throws SQLException { public String getSchemaName(int column) throws SQLException {
return null; return this.database;
} }
@Override @Override
@ -84,7 +87,7 @@ public class RestfulResultSetMetaData implements ResultSetMetaData {
@Override @Override
public String getCatalogName(int column) throws SQLException { public String getCatalogName(int column) throws SQLException {
return null; return this.database;
} }
@Override @Override

View File

@ -7,20 +7,60 @@ import com.taosdata.jdbc.rs.util.HttpClientPoolUtil;
import com.taosdata.jdbc.utils.SqlSyntaxValidator; import com.taosdata.jdbc.utils.SqlSyntaxValidator;
import java.sql.*; import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
public class RestfulStatement implements Statement { public class RestfulStatement implements Statement {
private static final String STATEMENT_CLOSED = "Statement already closed.";
private boolean closed; private boolean closed;
private String database; private String database;
private final RestfulConnection conn; private final RestfulConnection conn;
public RestfulStatement(RestfulConnection c, String database) { private volatile RestfulResultSet resultSet;
this.conn = c; private volatile int affectedRows;
private volatile boolean closeOnCompletion;
public RestfulStatement(RestfulConnection conn, String database) {
this.conn = conn;
this.database = database; this.database = database;
} }
private String[] parseTableIdentifier(String sql) {
sql = sql.trim().toLowerCase();
String[] ret = null;
if (sql.contains("where"))
sql = sql.substring(0, sql.indexOf("where"));
if (sql.contains("interval"))
sql = sql.substring(0, sql.indexOf("interval"));
if (sql.contains("fill"))
sql = sql.substring(0, sql.indexOf("fill"));
if (sql.contains("sliding"))
sql = sql.substring(0, sql.indexOf("sliding"));
if (sql.contains("group by"))
sql = sql.substring(0, sql.indexOf("group by"));
if (sql.contains("order by"))
sql = sql.substring(0, sql.indexOf("order by"));
if (sql.contains("slimit"))
sql = sql.substring(0, sql.indexOf("slimit"));
if (sql.contains("limit"))
sql = sql.substring(0, sql.indexOf("limit"));
// parse
if (sql.contains("from")) {
sql = sql.substring(sql.indexOf("from") + 4).trim();
return Arrays.asList(sql.split(",")).stream()
.map(tableIdentifier -> {
tableIdentifier = tableIdentifier.trim();
if (tableIdentifier.contains(" "))
tableIdentifier = tableIdentifier.substring(0, tableIdentifier.indexOf(" "));
return tableIdentifier;
}).collect(Collectors.joining(",")).split(",");
}
return ret;
}
@Override @Override
public ResultSet executeQuery(String sql) throws SQLException { public ResultSet executeQuery(String sql) throws SQLException {
if (isClosed()) if (isClosed())
@ -29,43 +69,33 @@ public class RestfulStatement implements Statement {
throw new SQLException("not a select sql for executeQuery: " + sql); throw new SQLException("not a select sql for executeQuery: " + sql);
final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
// row data
String result = HttpClientPoolUtil.execute(url, sql); String result = HttpClientPoolUtil.execute(url, sql);
String fields = ""; JSONObject resultJson = JSON.parseObject(result);
List<String> words = Arrays.asList(sql.split(" ")); if (resultJson.getString("status").equals("error")) {
if (words.get(0).equalsIgnoreCase("select")) { throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " + resultJson.getString("desc") + "\n" + "error code: " + resultJson.getString("code")));
int index = 0; }
if (words.contains("from")) {
index = words.indexOf("from"); // parse table name from sql
String[] tableIdentifiers = parseTableIdentifier(sql);
if (tableIdentifiers != null) {
List<JSONObject> fieldJsonList = new ArrayList<>();
for (String tableIdentifier : tableIdentifiers) {
// field meta
String fields = HttpClientPoolUtil.execute(url, "DESCRIBE " + tableIdentifier);
JSONObject fieldJson = JSON.parseObject(fields);
if (fieldJson.getString("status").equals("error")) {
throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " + fieldJson.getString("desc") + "\n" + "error code: " + fieldJson.getString("code")));
}
fieldJsonList.add(fieldJson);
} }
if (words.contains("FROM")) { this.resultSet = new RestfulResultSet(database, this, resultJson, fieldJsonList);
index = words.indexOf("FROM"); } else {
} this.resultSet = new RestfulResultSet(database, this, resultJson);
fields = HttpClientPoolUtil.execute(url, "DESCRIBE " + words.get(index + 1));
} }
JSONObject jsonObject = JSON.parseObject(result); this.affectedRows = 0;
if (jsonObject.getString("status").equals("error")) { return resultSet;
throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " +
jsonObject.getString("desc") + "\n" +
"error code: " + jsonObject.getString("code")));
}
String dataStr = jsonObject.getString("data");
if ("use".equalsIgnoreCase(fields.split(" ")[0])) {
return new RestfulResultSet(dataStr, "");
}
JSONObject jsonField = JSON.parseObject(fields);
if (jsonField == null) {
return new RestfulResultSet(dataStr, "");
}
if (jsonField.getString("status").equals("error")) {
throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " +
jsonField.getString("desc") + "\n" +
"error code: " + jsonField.getString("code")));
}
String fieldData = jsonField.getString("data");
return new RestfulResultSet(dataStr, fieldData);
} }
@Override @Override
@ -78,77 +108,103 @@ public class RestfulStatement implements Statement {
if (this.database == null) if (this.database == null)
throw new SQLException("Database not specified or available"); throw new SQLException("Database not specified or available");
final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; final String url = "http://" + conn.getHost().trim() + ":" + conn.getPort() + "/rest/sql";
HttpClientPoolUtil.execute(url, "use " + conn.getDatabase()); // HttpClientPoolUtil.execute(url, "use " + conn.getDatabase());
String result = HttpClientPoolUtil.execute(url, sql); String result = HttpClientPoolUtil.execute(url, sql);
JSONObject jsonObject = JSON.parseObject(result); JSONObject jsonObject = JSON.parseObject(result);
if (jsonObject.getString("status").equals("error")) { if (jsonObject.getString("status").equals("error")) {
throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " + throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " + jsonObject.getString("desc") + "\n" + "error code: " + jsonObject.getString("code")));
jsonObject.getString("desc") + "\n" +
"error code: " + jsonObject.getString("code")));
} }
return Integer.parseInt(jsonObject.getString("rows")); this.resultSet = null;
this.affectedRows = Integer.parseInt(jsonObject.getString("rows"));
return this.affectedRows;
} }
@Override @Override
public void close() throws SQLException { public void close() throws SQLException {
this.closed = true; synchronized (RestfulStatement.class) {
if (!isClosed())
this.closed = true;
}
} }
@Override @Override
public int getMaxFieldSize() throws SQLException { public int getMaxFieldSize() throws SQLException {
return 0; if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
return TSDBConstants.maxFieldSize;
} }
@Override @Override
public void setMaxFieldSize(int max) throws SQLException { public void setMaxFieldSize(int max) throws SQLException {
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
if (max < 0)
throw new SQLException(TSDBConstants.INVALID_VARIABLES);
// nothing to do
} }
@Override @Override
public int getMaxRows() throws SQLException { public int getMaxRows() throws SQLException {
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
return 0; return 0;
} }
@Override @Override
public void setMaxRows(int max) throws SQLException { public void setMaxRows(int max) throws SQLException {
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
if (max < 0)
throw new SQLException(TSDBConstants.INVALID_VARIABLES);
// nothing to do
} }
@Override @Override
public void setEscapeProcessing(boolean enable) throws SQLException { public void setEscapeProcessing(boolean enable) throws SQLException {
if (isClosed())
throw new SQLException(RestfulStatement.STATEMENT_CLOSED);
} }
@Override @Override
public int getQueryTimeout() throws SQLException { public int getQueryTimeout() throws SQLException {
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
return 0; return 0;
} }
@Override @Override
public void setQueryTimeout(int seconds) throws SQLException { public void setQueryTimeout(int seconds) throws SQLException {
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
if (seconds < 0)
throw new SQLException(TSDBConstants.INVALID_VARIABLES);
} }
@Override @Override
public void cancel() throws SQLException { public void cancel() throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public SQLWarning getWarnings() throws SQLException { public SQLWarning getWarnings() throws SQLException {
//TODO: getWarnings not Implemented if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
return null; return null;
} }
@Override @Override
public void clearWarnings() throws SQLException { public void clearWarnings() throws SQLException {
// nothing to do
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
} }
@Override @Override
public void setCursorName(String name) throws SQLException { public void setCursorName(String name) throws SQLException {
if (isClosed())
throw new SQLException(RestfulStatement.STATEMENT_CLOSED);
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
@ -159,133 +215,181 @@ public class RestfulStatement implements Statement {
//如果执行了use操作应该将当前Statement的catalog设置为新的database //如果执行了use操作应该将当前Statement的catalog设置为新的database
if (SqlSyntaxValidator.isUseSql(sql)) { if (SqlSyntaxValidator.isUseSql(sql)) {
this.database = sql.trim().replace("use", "").trim(); this.database = sql.trim().replace("use", "").trim();
this.conn.setCatalog(this.database);
} }
if (this.database == null) if (this.database == null)
throw new SQLException("Database not specified or available"); throw new SQLException("Database not specified or available");
final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; if (SqlSyntaxValidator.isSelectSql(sql)) {
// use database executeQuery(sql);
HttpClientPoolUtil.execute(url, "use " + conn.getDatabase()); } else if (SqlSyntaxValidator.isShowSql(sql) || SqlSyntaxValidator.isDescribeSql(sql)) {
// execute sql final String url = "http://" + conn.getHost().trim() + ":" + conn.getPort() + "/rest/sql";
String result = HttpClientPoolUtil.execute(url, sql); if (!SqlSyntaxValidator.isShowDatabaseSql(sql)) {
// parse result HttpClientPoolUtil.execute(url, "use " + conn.getDatabase());
JSONObject jsonObject = JSON.parseObject(result); }
if (jsonObject.getString("status").equals("error")) { String result = HttpClientPoolUtil.execute(url, sql);
throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " + JSONObject resultJson = JSON.parseObject(result);
jsonObject.getString("desc") + "\n" + if (resultJson.getString("status").equals("error")) {
"error code: " + jsonObject.getString("code"))); throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " + resultJson.getString("desc") + "\n" + "error code: " + resultJson.getString("code")));
}
this.resultSet = new RestfulResultSet(database, this, resultJson);
} else {
executeUpdate(sql);
} }
return true; return true;
} }
@Override @Override
public ResultSet getResultSet() throws SQLException { public ResultSet getResultSet() throws SQLException {
return null; if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
return resultSet;
} }
@Override @Override
public int getUpdateCount() throws SQLException { public int getUpdateCount() throws SQLException {
return 0; if (isClosed()) {
throw new SQLException("Invalid method call on a closed statement.");
}
return this.affectedRows;
} }
@Override @Override
public boolean getMoreResults() throws SQLException { public boolean getMoreResults() throws SQLException {
return false; return getMoreResults(CLOSE_CURRENT_RESULT);
} }
@Override @Override
public void setFetchDirection(int direction) throws SQLException { public void setFetchDirection(int direction) throws SQLException {
if (direction != ResultSet.FETCH_FORWARD && direction != ResultSet.FETCH_REVERSE && direction != ResultSet.FETCH_UNKNOWN)
throw new SQLException(TSDBConstants.INVALID_VARIABLES);
this.resultSet.setFetchDirection(direction);
} }
@Override @Override
public int getFetchDirection() throws SQLException { public int getFetchDirection() throws SQLException {
return 0; return this.resultSet.getFetchDirection();
} }
@Override @Override
public void setFetchSize(int rows) throws SQLException { public void setFetchSize(int rows) throws SQLException {
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
if (rows < 0)
throw new SQLException(TSDBConstants.INVALID_VARIABLES);
//nothing to do
} }
@Override @Override
public int getFetchSize() throws SQLException { public int getFetchSize() throws SQLException {
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
return 0; return 0;
} }
@Override @Override
public int getResultSetConcurrency() throws SQLException { public int getResultSetConcurrency() throws SQLException {
return 0; if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
return this.resultSet.getConcurrency();
} }
@Override @Override
public int getResultSetType() throws SQLException { public int getResultSetType() throws SQLException {
return 0; if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
return this.resultSet.getType();
} }
@Override @Override
public void addBatch(String sql) throws SQLException { public void addBatch(String sql) throws SQLException {
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
//TODO:
} }
@Override @Override
public void clearBatch() throws SQLException { public void clearBatch() throws SQLException {
//TODO:
} }
@Override @Override
public int[] executeBatch() throws SQLException { public int[] executeBatch() throws SQLException {
//TODO:
return new int[0]; return new int[0];
} }
@Override @Override
public Connection getConnection() throws SQLException { public Connection getConnection() throws SQLException {
return null; if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
return this.conn;
} }
@Override @Override
public boolean getMoreResults(int current) throws SQLException { public boolean getMoreResults(int current) throws SQLException {
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
if (resultSet == null)
return false;
// switch (current) {
// case CLOSE_CURRENT_RESULT:
// resultSet.close();
// break;
// case KEEP_CURRENT_RESULT:
// break;
// case CLOSE_ALL_RESULTS:
// resultSet.close();
// break;
// default:
// throw new SQLException(TSDBConstants.INVALID_VARIABLES);
// }
// return next;
return false; return false;
} }
@Override @Override
public ResultSet getGeneratedKeys() throws SQLException { public ResultSet getGeneratedKeys() throws SQLException {
return null; throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
return 0; throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
return 0; throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public int executeUpdate(String sql, String[] columnNames) throws SQLException { public int executeUpdate(String sql, String[] columnNames) throws SQLException {
return 0; throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
return false; throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public boolean execute(String sql, int[] columnIndexes) throws SQLException { public boolean execute(String sql, int[] columnIndexes) throws SQLException {
return false; throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public boolean execute(String sql, String[] columnNames) throws SQLException { public boolean execute(String sql, String[] columnNames) throws SQLException {
return false; throw new SQLFeatureNotSupportedException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
} }
@Override @Override
public int getResultSetHoldability() throws SQLException { public int getResultSetHoldability() throws SQLException {
return 0; if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
return this.resultSet.getHoldability();
} }
@Override @Override
@ -295,22 +399,30 @@ public class RestfulStatement implements Statement {
@Override @Override
public void setPoolable(boolean poolable) throws SQLException { public void setPoolable(boolean poolable) throws SQLException {
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
//nothing to do
} }
@Override @Override
public boolean isPoolable() throws SQLException { public boolean isPoolable() throws SQLException {
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
return false; return false;
} }
@Override @Override
public void closeOnCompletion() throws SQLException { public void closeOnCompletion() throws SQLException {
if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
this.closeOnCompletion = true;
} }
@Override @Override
public boolean isCloseOnCompletion() throws SQLException { public boolean isCloseOnCompletion() throws SQLException {
return false; if (isClosed())
throw new SQLException(STATEMENT_CLOSED);
return this.closeOnCompletion;
} }
@Override @Override

View File

@ -17,6 +17,8 @@ import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import java.nio.charset.Charset;
public class HttpClientPoolUtil { public class HttpClientPoolUtil {
public static PoolingHttpClientConnectionManager cm = null; public static PoolingHttpClientConnectionManager cm = null;
@ -94,7 +96,9 @@ public class HttpClientPoolUtil {
initPools(); initPools();
} }
method = (HttpEntityEnclosingRequestBase) getRequest(uri, HttpPost.METHOD_NAME, DEFAULT_CONTENT_TYPE, 0); method = (HttpEntityEnclosingRequestBase) getRequest(uri, HttpPost.METHOD_NAME, DEFAULT_CONTENT_TYPE, 0);
method.setEntity(new StringEntity(data)); method.setHeader("Authorization", "Basic cm9vdDp0YW9zZGF0YQ==");
method.setHeader("Content-Type", "text/plain");
method.setEntity(new StringEntity(data, Charset.forName("UTF-8")));
HttpContext context = HttpClientContext.create(); HttpContext context = HttpClientContext.create();
CloseableHttpResponse httpResponse = httpClient.execute(method, context); CloseableHttpResponse httpResponse = httpClient.execute(method, context);
httpEntity = httpResponse.getEntity(); httpEntity = httpResponse.getEntity();
@ -105,26 +109,13 @@ public class HttpClientPoolUtil {
if (method != null) { if (method != null) {
method.abort(); method.abort();
} }
// e.printStackTrace(); new Exception("execute post request exception, url:" + uri + ", exception:" + e.toString() + ", cost time(ms):" + (System.currentTimeMillis() - startTime)).printStackTrace();
// logger.error("execute post request exception, url:" + uri + ", exception:" + e.toString()
// + ", cost time(ms):" + (System.currentTimeMillis() - startTime));
new Exception("execute post request exception, url:"
+ uri + ", exception:" + e.toString() +
", cost time(ms):" + (System.currentTimeMillis() - startTime))
.printStackTrace();
} finally { } finally {
if (httpEntity != null) { if (httpEntity != null) {
try { try {
EntityUtils.consumeQuietly(httpEntity); EntityUtils.consumeQuietly(httpEntity);
} catch (Exception e) { } catch (Exception e) {
// e.printStackTrace(); new Exception("close response exception, url:" + uri + ", exception:" + e.toString() + ", cost time(ms):" + (System.currentTimeMillis() - startTime)).printStackTrace();
// logger.error("close response exception, url:" + uri + ", exception:" + e.toString()
// + ", cost time(ms):" + (System.currentTimeMillis() - startTime));
new Exception(
"close response exception, url:" + uri +
", exception:" + e.toString()
+ ", cost time(ms):" + (System.currentTimeMillis() - startTime))
.printStackTrace();
} }
} }
} }

View File

@ -15,14 +15,12 @@
package com.taosdata.jdbc.utils; package com.taosdata.jdbc.utils;
import com.taosdata.jdbc.TSDBConnection; import com.taosdata.jdbc.TSDBConnection;
import com.taosdata.jdbc.TSDBJNIConnector;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException;
public class SqlSyntaxValidator { public class SqlSyntaxValidator {
private static final String[] updateSQL = {"insert", "update", "delete", "create", "alter", "drop", "show", "describe", "use"}; private static final String[] updateSQL = {"insert", "update", "delete", "create", "alter", "drop", "show", "describe", "use", "import"};
private static final String[] querySQL = {"select"}; private static final String[] querySQL = {"select"};
private TSDBConnection tsdbConnection; private TSDBConnection tsdbConnection;
@ -31,22 +29,6 @@ public class SqlSyntaxValidator {
this.tsdbConnection = (TSDBConnection) connection; this.tsdbConnection = (TSDBConnection) connection;
} }
public boolean validateSqlSyntax(String sql) throws SQLException {
boolean res = false;
if (tsdbConnection == null || tsdbConnection.isClosed()) {
throw new SQLException("invalid connection");
} else {
TSDBJNIConnector jniConnector = tsdbConnection.getConnection();
if (jniConnector == null) {
throw new SQLException("jniConnector is null");
} else {
res = jniConnector.validateCreateTableSql(sql);
}
}
return res;
}
public static boolean isValidForExecuteUpdate(String sql) { public static boolean isValidForExecuteUpdate(String sql) {
for (String prefix : updateSQL) { for (String prefix : updateSQL) {
if (sql.trim().toLowerCase().startsWith(prefix)) if (sql.trim().toLowerCase().startsWith(prefix))
@ -56,18 +38,28 @@ public class SqlSyntaxValidator {
} }
public static boolean isUseSql(String sql) { public static boolean isUseSql(String sql) {
return sql.trim().toLowerCase().startsWith(updateSQL[8]) || sql.trim().toLowerCase().matches("create\\s*database.*") || sql.toLowerCase().toLowerCase().matches("drop\\s*database.*"); return sql.trim().toLowerCase().startsWith("use") || sql.trim().toLowerCase().matches("create\\s*database.*") || sql.toLowerCase().toLowerCase().matches("drop\\s*database.*");
} }
public static boolean isUpdateSql(String sql) { public static boolean isShowSql(String sql) {
return sql.trim().toLowerCase().startsWith(updateSQL[1]); return sql.trim().toLowerCase().startsWith("show");
} }
public static boolean isDescribeSql(String sql) {
return sql.trim().toLowerCase().startsWith("describe");
}
public static boolean isInsertSql(String sql) { public static boolean isInsertSql(String sql) {
return sql.trim().toLowerCase().startsWith(updateSQL[0]); return sql.trim().toLowerCase().startsWith("insert") || sql.trim().toLowerCase().startsWith("import");
} }
public static boolean isSelectSql(String sql) { public static boolean isSelectSql(String sql) {
return sql.trim().toLowerCase().startsWith(querySQL[0]); return sql.trim().toLowerCase().startsWith("select");
}
public static boolean isShowDatabaseSql(String sql) {
return sql.trim().toLowerCase().matches("show\\s*databases");
} }
} }

View File

@ -7,7 +7,7 @@ import org.junit.Test;
import java.sql.*; import java.sql.*;
import java.util.Properties; import java.util.Properties;
public class DatabaseMetaDataTest extends BaseTest { public class DatabaseMetaDataTest {
static Connection connection = null; static Connection connection = null;
static PreparedStatement statement = null; static PreparedStatement statement = null;
static String dbName = "test"; static String dbName = "test";
@ -23,20 +23,21 @@ public class DatabaseMetaDataTest extends BaseTest {
} }
Properties properties = new Properties(); Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host); properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties); connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
String sql = "drop database if exists " + dbName; String sql = "drop database if exists " + dbName;
statement = (TSDBPreparedStatement) connection.prepareStatement(sql); statement = connection.prepareStatement(sql);
statement.executeUpdate("create database if not exists " + dbName); statement.executeUpdate("create database if not exists " + dbName);
statement.executeUpdate("create table if not exists " + dbName + "." + tName + " (ts timestamp, k int, v int)"); statement.executeUpdate("create table if not exists " + dbName + "." + tName + " (ts timestamp, k int, v int)");
} }
@Test @Test
public void testMetaDataTest() throws SQLException { public void testMetaDataTest() throws SQLException {
DatabaseMetaData databaseMetaData = connection.getMetaData(); DatabaseMetaData databaseMetaData = connection.getMetaData();
ResultSet resultSet = databaseMetaData.getTables(dbName, "t*", "t*", new String[]{"t"}); ResultSet resultSet = databaseMetaData.getTables(dbName, "t*", "t*", new String[]{"t"});
while (resultSet.next()) { while (resultSet.next()) {
@ -180,7 +181,7 @@ public class DatabaseMetaDataTest extends BaseTest {
databaseMetaData.getCatalogs(); databaseMetaData.getCatalogs();
// databaseMetaData.getTableTypes(); // databaseMetaData.getTableTypes();
databaseMetaData.getColumns("", "", "", ""); databaseMetaData.getColumns(dbName, "", tName, "");
databaseMetaData.getColumnPrivileges("", "", "", ""); databaseMetaData.getColumnPrivileges("", "", "", "");
databaseMetaData.getTablePrivileges("", "", ""); databaseMetaData.getTablePrivileges("", "", "");
databaseMetaData.getBestRowIdentifier("", "", "", 0, false); databaseMetaData.getBestRowIdentifier("", "", "", 0, false);

View File

@ -19,7 +19,7 @@ public class AppMemoryLeakTest {
} }
} }
@Test @Test(expected = Exception.class)
public void testCreateTooManyStatement() throws ClassNotFoundException, SQLException { public void testCreateTooManyStatement() throws ClassNotFoundException, SQLException {
Class.forName("com.taosdata.jdbc.TSDBDriver"); Class.forName("com.taosdata.jdbc.TSDBDriver");
int stmtCnt = 0; int stmtCnt = 0;
@ -30,15 +30,4 @@ public class AppMemoryLeakTest {
} }
} }
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.taosdata.jdbc.TSDBDriver");
int stmtCnt = 0;
Connection conn = DriverManager.getConnection("jdbc:TAOS://localhost:6030/?user=root&password=taosdata");
while (true) {
Statement stmt = conn.createStatement();
System.out.println(++stmtCnt + " : " + stmt);
}
}
} }

View File

@ -0,0 +1,24 @@
package com.taosdata.jdbc.cases;
import org.junit.Assert;
import org.junit.Test;
import java.sql.DriverManager;
import java.sql.SQLException;
public class ConnectWrongDatabaseTest {
@Test
public void connect() {
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
DriverManager.getConnection("jdbc:TAOS://localhost:6030/wrong_db?user=root&password=taosdata");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
System.out.println(e.getMessage());
Assert.assertEquals("TDengine Error: Invalid database name", e.getMessage());
}
}
}

View File

@ -1,5 +1,6 @@
package com.taosdata.jdbc.rs; package com.taosdata.jdbc.rs;
import org.junit.*; import org.junit.*;
import org.junit.runners.MethodSorters; import org.junit.runners.MethodSorters;

View File

@ -0,0 +1,399 @@
package com.taosdata.jdbc.rs;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import java.sql.*;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SQLTest {
private static final String host = "master";
private static Connection connection;
@Test
public void testCase001() {
String sql = "create database if not exists restful_test";
execute(sql);
}
@Test
public void testCase002() {
String sql = "use restful_test";
execute(sql);
}
@Test
public void testCase003() {
String sql = "show databases";
executeWithResult(sql);
}
@Test
public void testCase004() {
String sql = "show tables";
executeWithResult(sql);
}
@Test
public void testCase005() {
String sql = "show stables";
executeWithResult(sql);
}
@Test
public void testCase006() {
String sql = "show dnodes";
executeWithResult(sql);
}
@Test
public void testCase007() {
String sql = "show vgroups";
executeWithResult(sql);
}
@Test
public void testCase008() {
String sql = "drop table if exists restful_test.weather";
execute(sql);
}
@Test
public void testCase009() {
String sql = "create table if not exists restful_test.weather(ts timestamp, temperature float) tags(location nchar(64))";
execute(sql);
}
@Test
public void testCase010() {
String sql = "create table t1 using restful_test.weather tags('北京')";
execute(sql);
}
@Test
public void testCase011() {
String sql = "insert into restful_test.t1 values(now, 22.22)";
executeUpdate(sql);
}
@Test
public void testCase012() {
String sql = "insert into restful_test.t1 values('2020-01-01 00:00:00.000', 22.22)";
executeUpdate(sql);
}
@Test
public void testCase013() {
String sql = "insert into restful_test.t1 values('2020-01-01 00:01:00.000', 22.22),('2020-01-01 00:02:00.000', 22.22)";
executeUpdate(sql);
}
@Test
public void testCase014() {
String sql = "insert into restful_test.t2 using weather tags('上海') values('2020-01-01 00:03:00.000', 22.22)";
executeUpdate(sql);
}
@Test
public void testCase015() {
String sql = "insert into restful_test.t2 using weather tags('上海') values('2020-01-01 00:01:00.000', 22.22),('2020-01-01 00:02:00.000', 22.22)";
executeUpdate(sql);
}
@Test
public void testCase016() {
String sql = "insert into t1 values('2020-01-01 01:0:00.000', 22.22),('2020-01-01 02:00:00.000', 22.22) t2 values('2020-01-01 01:0:00.000', 33.33),('2020-01-01 02:00:00.000', 33.33)";
executeUpdate(sql);
}
@Test
public void testCase017() {
String sql = "Insert into t3 using weather tags('广东') values('2020-01-01 01:0:00.000', 22.22),('2020-01-01 02:00:00.000', 22.22) t4 using weather tags('天津') values('2020-01-01 01:0:00.000', 33.33),('2020-01-01 02:00:00.000', 33.33)";
executeUpdate(sql);
}
@Test
public void testCase018() {
String sql = "select * from restful_test.t1";
executeQuery(sql);
}
@Test
public void testCase019() {
String sql = "select * from restful_test.weather";
executeQuery(sql);
}
@Test
public void testCase020() {
String sql = "select ts, temperature from restful_test.t1";
executeQuery(sql);
}
@Test
public void testCase021() {
String sql = "select ts, temperature from restful_test.weather";
executeQuery(sql);
}
@Test
public void testCase022() {
String sql = "select temperature, ts from restful_test.t1";
executeQuery(sql);
}
@Test
public void testCase023() {
String sql = "select temperature, ts from restful_test.weather";
executeQuery(sql);
}
@Test
public void testCase024() {
String sql = "import into restful_test.t5 using weather tags('石家庄') values('2020-01-01 00:01:00.000', 22.22)";
executeUpdate(sql);
}
@Test
public void testCase025() {
String sql = "import into restful_test.t6 using weather tags('沈阳') values('2020-01-01 00:01:00.000', 22.22),('2020-01-01 00:02:00.000', 22.22)";
executeUpdate(sql);
}
@Test
public void testCase026() {
String sql = "import into restful_test.t7 using weather tags('长沙') values('2020-01-01 00:01:00.000', 22.22) restful_test.t8 using weather tags('吉林') values('2020-01-01 00:01:00.000', 22.22)";
executeUpdate(sql);
}
@Test
public void testCase027() {
String sql = "import into restful_test.t9 using weather tags('武汉') values('2020-01-01 00:01:00.000', 22.22) ,('2020-01-02 00:01:00.000', 22.22) restful_test.t10 using weather tags('哈尔滨') values('2020-01-01 00:01:00.000', 22.22),('2020-01-02 00:01:00.000', 22.22)";
executeUpdate(sql);
}
@Test
public void testCase028() {
String sql = "select location, temperature, ts from restful_test.weather where temperature > 1";
executeQuery(sql);
}
@Test
public void testCase029() {
String sql = "select location, temperature, ts from restful_test.weather where temperature < 1";
executeQuery(sql);
}
@Test
public void testCase030() {
String sql = "select location, temperature, ts from restful_test.weather where ts > now";
executeQuery(sql);
}
@Test
public void testCase031() {
String sql = "select location, temperature, ts from restful_test.weather where ts < now";
executeQuery(sql);
}
@Test
public void testCase032() {
String sql = "select count(*) from restful_test.weather";
executeQuery(sql);
}
@Test
public void testCase033() {
String sql = "select first(*) from restful_test.weather";
executeQuery(sql);
}
@Test
public void testCase034() {
String sql = "select last(*) from restful_test.weather";
executeQuery(sql);
}
@Test
public void testCase035() {
String sql = "select last_row(*) from restful_test.weather";
executeQuery(sql);
}
@Test
public void testCase036() {
String sql = "select ts, ts as primary_key from restful_test.weather";
executeQuery(sql);
}
@Test
public void testCase037() {
String sql = "select database()";
execute("use restful_test");
executeQuery(sql);
}
@Test
public void testCase038() {
String sql = "select client_version()";
executeQuery(sql);
}
@Test
public void testCase039() {
String sql = "select server_status()";
executeQuery(sql);
}
@Test
public void testCase040() {
String sql = "select server_status() as status";
executeQuery(sql);
}
@Test
public void testCase041() {
String sql = "select tbname, location from restful_test.weather";
executeQuery(sql);
}
@Test
public void testCase042() {
String sql = "select count(tbname) from restful_test.weather";
executeQuery(sql);
}
@Test
public void testCase043() {
String sql = "select * from restful_test.weather where ts < now - 1h";
executeQuery(sql);
}
@Test
public void testCase044() {
String sql = "select * from restful_test.weather where ts < now - 1h and location like '%'";
executeQuery(sql);
}
@Test
public void testCase045() {
String sql = "select * from restful_test.weather where ts < now - 1h order by ts";
executeQuery(sql);
}
@Test
public void testCase046() {
String sql = "select last(*) from restful_test.weather where ts < now - 1h group by tbname order by tbname";
executeQuery(sql);
}
@Test
public void testCase047() {
String sql = "select * from restful_test.weather limit 2";
executeQuery(sql);
}
@Test
public void testCase048() {
String sql = "select * from restful_test.weather limit 2 offset 5";
executeQuery(sql);
}
@Test
public void testCase049() {
String sql = "select * from restful_test.t1, restful_test.t3 where t1.ts = t3.ts ";
executeQuery(sql);
}
@Test
public void testCase050() {
String sql = "select * from restful_test.t1, restful_test.t3 where t1.ts = t3.ts and t1.location = t3.location";
executeQuery(sql);
}
@Test
public void testCase051() {
String sql = "select * from restful_test.t1 tt, restful_test.t3 yy where tt.ts = yy.ts";
executeQuery(sql);
}
private void executeUpdate(String sql) {
try (Statement statement = connection.createStatement()) {
long start = System.currentTimeMillis();
int affectedRows = statement.executeUpdate(sql);
long end = System.currentTimeMillis();
System.out.println("[ affected rows : " + affectedRows + " ] time cost: " + (end - start) + " ms, execute statement ====> " + sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
private void executeWithResult(String sql) {
try (Statement statement = connection.createStatement()) {
statement.execute(sql);
ResultSet resultSet = statement.getResultSet();
printResult(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
}
private void execute(String sql) {
try (Statement statement = connection.createStatement()) {
long start = System.currentTimeMillis();
boolean execute = statement.execute(sql);
long end = System.currentTimeMillis();
printSql(sql, execute, (end - start));
} catch (SQLException e) {
System.out.println("ERROR execute SQL ===> " + sql);
e.printStackTrace();
}
}
private static void printSql(String sql, boolean succeed, long cost) {
System.out.println("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql);
}
private void executeQuery(String sql) {
try (Statement statement = connection.createStatement()) {
long start = System.currentTimeMillis();
ResultSet resultSet = statement.executeQuery(sql);
long end = System.currentTimeMillis();
printSql(sql, true, (end - start));
printResult(resultSet);
} catch (SQLException e) {
System.out.println("ERROR execute SQL ===> " + sql);
e.printStackTrace();
}
}
private static void printResult(ResultSet resultSet) throws SQLException {
ResultSetMetaData metaData = resultSet.getMetaData();
while (resultSet.next()) {
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= metaData.getColumnCount(); i++) {
String columnLabel = metaData.getColumnLabel(i);
String value = resultSet.getString(i);
sb.append(columnLabel + ": " + value + "\t");
}
System.out.println(sb.toString());
}
}
@BeforeClass
public static void before() throws ClassNotFoundException, SQLException {
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=root&password=taosdata");
}
@AfterClass
public static void after() throws SQLException {
connection.close();
}
}

View File

@ -5,10 +5,6 @@ import org.junit.Test;
public class SqlSyntaxValidatorTest { public class SqlSyntaxValidatorTest {
@Test
public void validateSqlSyntax() {
}
@Test @Test
public void isSelectSQL() { public void isSelectSQL() {
Assert.assertTrue(SqlSyntaxValidator.isSelectSql("select * from test.weather")); Assert.assertTrue(SqlSyntaxValidator.isSelectSql("select * from test.weather"));

View File

@ -4,6 +4,7 @@
*/ */
const ref = require('ref'); const ref = require('ref');
const os = require('os');
const ffi = require('ffi'); const ffi = require('ffi');
const ArrayType = require('ref-array'); const ArrayType = require('ref-array');
const Struct = require('ref-struct'); const Struct = require('ref-struct');
@ -188,7 +189,13 @@ function CTaosInterface (config = null, pass = false) {
ref.types.void_ptr2 = ref.refType(ref.types.void_ptr); ref.types.void_ptr2 = ref.refType(ref.types.void_ptr);
/*Declare a bunch of functions first*/ /*Declare a bunch of functions first*/
/* Note, pointers to TAOS_RES, TAOS, are ref.types.void_ptr. The connection._conn buffer is supplied for pointers to TAOS * */ /* Note, pointers to TAOS_RES, TAOS, are ref.types.void_ptr. The connection._conn buffer is supplied for pointers to TAOS * */
this.libtaos = ffi.Library('libtaos', {
if ('win32' == os.platform()) {
taoslibname = 'taos';
} else {
taoslibname = 'libtaos';
}
this.libtaos = ffi.Library(taoslibname, {
'taos_options': [ ref.types.int, [ ref.types.int , ref.types.void_ptr ] ], 'taos_options': [ ref.types.int, [ ref.types.int , ref.types.void_ptr ] ],
'taos_init': [ ref.types.void, [ ] ], 'taos_init': [ ref.types.void, [ ] ],
//TAOS *taos_connect(char *ip, char *user, char *pass, char *db, int port) //TAOS *taos_connect(char *ip, char *user, char *pass, char *db, int port)

View File

@ -1,6 +1,6 @@
{ {
"name": "td2.0-connector", "name": "td2.0-connector",
"version": "2.0.4", "version": "2.0.5",
"description": "A Node.js connector for TDengine.", "description": "A Node.js connector for TDengine.",
"main": "tdengine.js", "main": "tdengine.js",
"scripts": { "scripts": {

View File

@ -23,8 +23,7 @@ extern "C" {
int32_t dnodeInitModules(); int32_t dnodeInitModules();
void dnodeCleanupModules(); void dnodeCleanupModules();
bool dnodeStartMnode(SMInfos *pMinfos); int32_t dnodeStartMnode(SMInfos *pMinfos);
void dnodeProcessModuleStatus(uint32_t moduleStatus);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -188,8 +188,8 @@ void dnodeReprocessMWriteMsg(void *pMsg) {
++pWrite->pBatchMasterMsg->received; ++pWrite->pBatchMasterMsg->received;
if (pWrite->pBatchMasterMsg->successed + pWrite->pBatchMasterMsg->received if (pWrite->pBatchMasterMsg->successed + pWrite->pBatchMasterMsg->received
>= pWrite->pBatchMasterMsg->expected) { >= pWrite->pBatchMasterMsg->expected) {
dnodeSendRedirectMsg(&pWrite->rpcMsg, true); dnodeSendRedirectMsg(&pWrite->pBatchMasterMsg->rpcMsg, true);
dnodeFreeMWriteMsg(pWrite); dnodeFreeMWriteMsg(pWrite->pBatchMasterMsg);
} }
mnodeDestroySubMsg(pWrite); mnodeDestroySubMsg(pWrite);

View File

@ -127,14 +127,16 @@ int32_t dnodeInitModules() {
return dnodeStartModules(); return dnodeStartModules();
} }
void dnodeProcessModuleStatus(uint32_t moduleStatus) { int32_t dnodeProcessModuleStatus(uint32_t moduleStatus) {
int32_t code = 0;
for (int32_t module = TSDB_MOD_MNODE; module < TSDB_MOD_HTTP; ++module) { for (int32_t module = TSDB_MOD_MNODE; module < TSDB_MOD_HTTP; ++module) {
bool enableModule = moduleStatus & (1 << module); bool enableModule = moduleStatus & (1 << module);
if (!tsModule[module].enable && enableModule) { if (!tsModule[module].enable && enableModule) {
dInfo("module status:%u is set, start %s module", moduleStatus, tsModule[module].name); dInfo("module status:%u is set, start %s module", moduleStatus, tsModule[module].name);
tsModule[module].enable = true; tsModule[module].enable = true;
dnodeSetModuleStatus(module); dnodeSetModuleStatus(module);
(*tsModule[module].startFp)(); code = (*tsModule[module].startFp)();
} }
if (tsModule[module].enable && !enableModule) { if (tsModule[module].enable && !enableModule) {
@ -144,21 +146,29 @@ void dnodeProcessModuleStatus(uint32_t moduleStatus) {
(*tsModule[module].stopFp)(); (*tsModule[module].stopFp)();
} }
} }
return code;
} }
bool dnodeStartMnode(SMInfos *pMinfos) { int32_t dnodeStartMnode(SMInfos *pMinfos) {
SMInfos *pMnodes = pMinfos;
if (tsModuleStatus & (1 << TSDB_MOD_MNODE)) { if (tsModuleStatus & (1 << TSDB_MOD_MNODE)) {
dDebug("mnode module is already started, module status:%d", tsModuleStatus); dDebug("mnode module is already started, module status:%d", tsModuleStatus);
return false; return 0;
} }
uint32_t moduleStatus = tsModuleStatus | (1 << TSDB_MOD_MNODE); uint32_t moduleStatus = tsModuleStatus | (1 << TSDB_MOD_MNODE);
dInfo("start mnode module, module status:%d, new status:%d", tsModuleStatus, moduleStatus); dInfo("start mnode module, module status:%d, new status:%d", tsModuleStatus, moduleStatus);
dnodeProcessModuleStatus(moduleStatus);
sdbUpdateSync(pMnodes); int32_t code = dnodeProcessModuleStatus(moduleStatus);
if (code == 0) {
code = sdbUpdateSync(pMinfos);
}
return true; if (code != 0) {
dError("failed to start mnode module since %s", tstrerror(code));
moduleStatus = tsModuleStatus & ~(1 << TSDB_MOD_MNODE);
dnodeProcessModuleStatus(moduleStatus);
}
return code;
} }

View File

@ -60,7 +60,7 @@ int32_t dnodeInitServer() {
rpcInit.label = "DND-S"; rpcInit.label = "DND-S";
rpcInit.numOfThreads = 1; rpcInit.numOfThreads = 1;
rpcInit.cfp = dnodeProcessReqMsgFromDnode; rpcInit.cfp = dnodeProcessReqMsgFromDnode;
rpcInit.sessions = TSDB_MAX_VNODES; rpcInit.sessions = TSDB_MAX_VNODES << 4;
rpcInit.connType = TAOS_CONN_SERVER; rpcInit.connType = TAOS_CONN_SERVER;
rpcInit.idleTime = tsShellActivityTimer * 1000; rpcInit.idleTime = tsShellActivityTimer * 1000;
@ -123,7 +123,7 @@ int32_t dnodeInitClient() {
rpcInit.label = "DND-C"; rpcInit.label = "DND-C";
rpcInit.numOfThreads = 1; rpcInit.numOfThreads = 1;
rpcInit.cfp = dnodeProcessRspFromDnode; rpcInit.cfp = dnodeProcessRspFromDnode;
rpcInit.sessions = TSDB_MAX_VNODES; rpcInit.sessions = TSDB_MAX_VNODES << 4;
rpcInit.connType = TAOS_CONN_CLIENT; rpcInit.connType = TAOS_CONN_CLIENT;
rpcInit.idleTime = tsShellActivityTimer * 1000; rpcInit.idleTime = tsShellActivityTimer * 1000;
rpcInit.user = "t"; rpcInit.user = "t";

View File

@ -214,7 +214,5 @@ static int32_t dnodeProcessCreateMnodeMsg(SRpcMsg *pMsg) {
dDebug("mnode index:%d, mnode:%d:%s", i, pCfg->mnodes.mnodeInfos[i].mnodeId, pCfg->mnodes.mnodeInfos[i].mnodeEp); dDebug("mnode index:%d, mnode:%d:%s", i, pCfg->mnodes.mnodeInfos[i].mnodeId, pCfg->mnodes.mnodeInfos[i].mnodeEp);
} }
dnodeStartMnode(&pCfg->mnodes); return dnodeStartMnode(&pCfg->mnodes);
return TSDB_CODE_SUCCESS;
} }

View File

@ -40,7 +40,7 @@ void dnodeGetClusterId(char *clusterId);
void dnodeUpdateEp(int32_t dnodeId, char *ep, char *fqdn, uint16_t *port); void dnodeUpdateEp(int32_t dnodeId, char *ep, char *fqdn, uint16_t *port);
bool dnodeCheckEpChanged(int32_t dnodeId, char *epstr); bool dnodeCheckEpChanged(int32_t dnodeId, char *epstr);
bool dnodeStartMnode(SMInfos *pMinfos); int32_t dnodeStartMnode(SMInfos *pMinfos);
void dnodeAddClientRspHandle(uint8_t msgType, void (*fp)(SRpcMsg *rpcMsg)); void dnodeAddClientRspHandle(uint8_t msgType, void (*fp)(SRpcMsg *rpcMsg));
void dnodeSendMsgToDnode(SRpcEpSet *epSet, SRpcMsg *rpcMsg); void dnodeSendMsgToDnode(SRpcEpSet *epSet, SRpcMsg *rpcMsg);

View File

@ -65,7 +65,7 @@ int32_t mnodeStartSystem();
void mnodeCleanupSystem(); void mnodeCleanupSystem();
void mnodeStopSystem(); void mnodeStopSystem();
void sdbUpdateAsync(); void sdbUpdateAsync();
void sdbUpdateSync(void *pMnodes); int32_t sdbUpdateSync(void *pMnodes);
bool mnodeIsRunning(); bool mnodeIsRunning();
int32_t mnodeProcessRead(SMnodeMsg *pMsg); int32_t mnodeProcessRead(SMnodeMsg *pMsg);
int32_t mnodeProcessWrite(SMnodeMsg *pMsg); int32_t mnodeProcessWrite(SMnodeMsg *pMsg);

View File

@ -86,6 +86,7 @@ void qDestroyQueryInfo(qinfo_t qHandle);
void* qOpenQueryMgmt(int32_t vgId); void* qOpenQueryMgmt(int32_t vgId);
void qQueryMgmtNotifyClosed(void* pExecutor); void qQueryMgmtNotifyClosed(void* pExecutor);
void qQueryMgmtReOpen(void *pExecutor);
void qCleanupQueryMgmt(void* pExecutor); void qCleanupQueryMgmt(void* pExecutor);
void** qRegisterQInfo(void* pMgmt, uint64_t qInfo); void** qRegisterQInfo(void* pMgmt, uint64_t qInfo);
void** qAcquireQInfo(void* pMgmt, uint64_t key); void** qAcquireQInfo(void* pMgmt, uint64_t key);

View File

@ -126,6 +126,11 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_SHOWOBJ, 0, 0x030B, "Data expir
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_QUERY_ID, 0, 0x030C, "Invalid query id") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_QUERY_ID, 0, 0x030C, "Invalid query id")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_STREAM_ID, 0, 0x030D, "Invalid stream id") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_STREAM_ID, 0, 0x030D, "Invalid stream id")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_CONN_ID, 0, 0x030E, "Invalid connection id") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_CONN_ID, 0, 0x030E, "Invalid connection id")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_MNODE_IS_RUNNING, 0, 0x0310, "mnode is alreay running")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_FAILED_TO_CONFIG_SYNC, 0, 0x0311, "failed to config sync")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_FAILED_TO_START_SYNC, 0, 0x0312, "failed to start sync")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_FAILED_TO_CREATE_DIR, 0, 0x0313, "failed to create mnode dir")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_FAILED_TO_INIT_STEP, 0, 0x0314, "failed to init components")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SDB_OBJ_ALREADY_THERE, 0, 0x0320, "Object already there") TAOS_DEFINE_ERROR(TSDB_CODE_MND_SDB_OBJ_ALREADY_THERE, 0, 0x0320, "Object already there")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SDB_ERROR, 0, 0x0321, "Unexpected generic error in sdb") TAOS_DEFINE_ERROR(TSDB_CODE_MND_SDB_ERROR, 0, 0x0321, "Unexpected generic error in sdb")

View File

@ -311,6 +311,11 @@ static int32_t mnodeCheckDbCfg(SDbCfg *pCfg) {
return TSDB_CODE_MND_INVALID_DB_OPTION; return TSDB_CODE_MND_INVALID_DB_OPTION;
} }
if (pCfg->replications > mnodeGetDnodesNum()) {
mError("no enough dnode to config replica: %d, #dnodes: %d", pCfg->replications, mnodeGetDnodesNum());
return TSDB_CODE_MND_INVALID_DB_OPTION;
}
if (pCfg->quorum < TSDB_MIN_DB_REPLICA_OPTION || pCfg->quorum > TSDB_MAX_DB_REPLICA_OPTION) { if (pCfg->quorum < TSDB_MIN_DB_REPLICA_OPTION || pCfg->quorum > TSDB_MAX_DB_REPLICA_OPTION) {
mError("invalid db option quorum:%d valid range: [%d, %d]", pCfg->quorum, TSDB_MIN_DB_REPLICA_OPTION, mError("invalid db option quorum:%d valid range: [%d, %d]", pCfg->quorum, TSDB_MIN_DB_REPLICA_OPTION,
TSDB_MAX_DB_REPLICA_OPTION); TSDB_MAX_DB_REPLICA_OPTION);

View File

@ -74,13 +74,13 @@ static int32_t mnodeInitComponents() {
int32_t mnodeStartSystem() { int32_t mnodeStartSystem() {
if (tsMgmtIsRunning) { if (tsMgmtIsRunning) {
mInfo("mnode module already started..."); mInfo("mnode module already started...");
return 0; return TSDB_CODE_SUCCESS;
} }
mInfo("starting to initialize mnode ..."); mInfo("starting to initialize mnode ...");
if (mkdir(tsMnodeDir, 0755) != 0 && errno != EEXIST) { if (mkdir(tsMnodeDir, 0755) != 0 && errno != EEXIST) {
mError("failed to init mnode dir:%s, reason:%s", tsMnodeDir, strerror(errno)); mError("failed to init mnode dir:%s, reason:%s", tsMnodeDir, strerror(errno));
return -1; return TSDB_CODE_MND_FAILED_TO_CREATE_DIR;
} }
dnodeAllocMWritequeue(); dnodeAllocMWritequeue();
@ -88,7 +88,7 @@ int32_t mnodeStartSystem() {
dnodeAllocateMPeerQueue(); dnodeAllocateMPeerQueue();
if (mnodeInitComponents() != 0) { if (mnodeInitComponents() != 0) {
return -1; return TSDB_CODE_MND_FAILED_TO_INIT_STEP;
} }
dnodeReportStep("mnode-grant", "start to set grant infomation", 0); dnodeReportStep("mnode-grant", "start to set grant infomation", 0);
@ -99,7 +99,7 @@ int32_t mnodeStartSystem() {
sdbUpdateSync(NULL); sdbUpdateSync(NULL);
return 0; return TSDB_CODE_SUCCESS;
} }
int32_t mnodeInitSystem() { int32_t mnodeInitSystem() {

View File

@ -318,11 +318,11 @@ void sdbUpdateAsync() {
taosTmrReset(sdbUpdateSyncTmrFp, 200, NULL, tsMnodeTmr, &tsSdbTmr); taosTmrReset(sdbUpdateSyncTmrFp, 200, NULL, tsMnodeTmr, &tsSdbTmr);
} }
void sdbUpdateSync(void *pMnodes) { int32_t sdbUpdateSync(void *pMnodes) {
SMInfos *pMinfos = pMnodes; SMInfos *pMinfos = pMnodes;
if (!mnodeIsRunning()) { if (!mnodeIsRunning()) {
mDebug("vgId:1, mnode not start yet, update sync config later"); mDebug("vgId:1, mnode not start yet, update sync config later");
return; return TSDB_CODE_MND_MNODE_IS_RUNNING;
} }
mDebug("vgId:1, update sync config, pMnodes:%p", pMnodes); mDebug("vgId:1, update sync config, pMnodes:%p", pMnodes);
@ -377,12 +377,12 @@ void sdbUpdateSync(void *pMnodes) {
if (!hasThisDnode) { if (!hasThisDnode) {
sdbDebug("vgId:1, update sync config, this dnode not exist"); sdbDebug("vgId:1, update sync config, this dnode not exist");
return; return TSDB_CODE_MND_FAILED_TO_CONFIG_SYNC;
} }
if (memcmp(&syncCfg, &tsSdbMgmt.cfg, sizeof(SSyncCfg)) == 0) { if (memcmp(&syncCfg, &tsSdbMgmt.cfg, sizeof(SSyncCfg)) == 0) {
sdbDebug("vgId:1, update sync config, info not changed"); sdbDebug("vgId:1, update sync config, info not changed");
return; return TSDB_CODE_SUCCESS;
} }
sdbInfo("vgId:1, work as mnode, replica:%d", syncCfg.replica); sdbInfo("vgId:1, work as mnode, replica:%d", syncCfg.replica);
@ -407,12 +407,15 @@ void sdbUpdateSync(void *pMnodes) {
tsSdbMgmt.cfg = syncCfg; tsSdbMgmt.cfg = syncCfg;
if (tsSdbMgmt.sync) { if (tsSdbMgmt.sync) {
syncReconfig(tsSdbMgmt.sync, &syncCfg); int32_t code = syncReconfig(tsSdbMgmt.sync, &syncCfg);
if (code != 0) return code;
} else { } else {
tsSdbMgmt.sync = syncStart(&syncInfo); tsSdbMgmt.sync = syncStart(&syncInfo);
if (tsSdbMgmt.sync <= 0) return TSDB_CODE_MND_FAILED_TO_START_SYNC;
} }
sdbUpdateMnodeRoles(); sdbUpdateMnodeRoles();
return TSDB_CODE_SUCCESS;
} }
int32_t sdbInitRef() { int32_t sdbInitRef() {
@ -1051,7 +1054,10 @@ static int32_t sdbWriteFwdToQueue(int32_t vgId, void *wparam, int32_t qtype, voi
memcpy(pRow->pHead, pHead, sizeof(SWalHead) + pHead->len); memcpy(pRow->pHead, pHead, sizeof(SWalHead) + pHead->len);
pRow->rowData = pRow->pHead->cont; pRow->rowData = pRow->pHead->cont;
return sdbWriteToQueue(pRow, qtype); int32_t code = sdbWriteToQueue(pRow, qtype);
if (code == TSDB_CODE_MND_ACTION_IN_PROGRESS) code = 0;
return code;
} }
static int32_t sdbWriteRowToQueue(SSdbRow *pInputRow, int32_t action) { static int32_t sdbWriteRowToQueue(SSdbRow *pInputRow, int32_t action) {

View File

@ -827,21 +827,21 @@ static int32_t mnodeProcessBatchCreateTableMsg(SMnodeMsg *pMsg) {
SCreateTableMsg *pCreateTable = (SCreateTableMsg*) ((char*) pCreate + sizeof(SCMCreateTableMsg)); SCreateTableMsg *pCreateTable = (SCreateTableMsg*) ((char*) pCreate + sizeof(SCMCreateTableMsg));
int32_t code = mnodeValidateCreateTableMsg(pCreateTable, pMsg); int32_t code = mnodeValidateCreateTableMsg(pCreateTable, pMsg);
if (code == TSDB_CODE_SUCCESS || code == TSDB_CODE_MND_TABLE_ALREADY_EXIST) { if (code == TSDB_CODE_SUCCESS || code == TSDB_CODE_MND_TABLE_ALREADY_EXIST) {
++pMsg->pBatchMasterMsg->successed; ++pMsg->pBatchMasterMsg->successed;
mnodeDestroySubMsg(pMsg); mnodeDestroySubMsg(pMsg);
} } else if (code == TSDB_CODE_MND_ACTION_NEED_REPROCESSED) {
return code;
if (code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { } else if (code != TSDB_CODE_MND_ACTION_IN_PROGRESS) {
mnodeDestroySubMsg(pMsg); ++pMsg->pBatchMasterMsg->received;
return code; mnodeDestroySubMsg(pMsg);
} }
if (pMsg->pBatchMasterMsg->successed + pMsg->pBatchMasterMsg->received if (pMsg->pBatchMasterMsg->successed + pMsg->pBatchMasterMsg->received
>= pMsg->pBatchMasterMsg->expected) { >= pMsg->pBatchMasterMsg->expected) {
return code; dnodeSendRpcMWriteRsp(pMsg->pBatchMasterMsg, TSDB_CODE_SUCCESS);
} else {
return TSDB_CODE_MND_ACTION_IN_PROGRESS;
} }
return TSDB_CODE_MND_ACTION_IN_PROGRESS;
} else { // batch master replay, reprocess the whole batch } else { // batch master replay, reprocess the whole batch
assert(0); assert(0);
} }

View File

@ -89,12 +89,17 @@ int taosInitTimer(void (*callback)(int), int ms) {
if (code != 0) { if (code != 0) {
uError("failed to create timer thread"); uError("failed to create timer thread");
return -1; return -1;
} else {
uDebug("timer thread:0x%08" PRIx64 " is created", taosGetPthreadId(timerThread));
} }
return 0; return 0;
} }
void taosUninitTimer() { void taosUninitTimer() {
stopTimer = true; stopTimer = true;
uDebug("join timer thread:0x%08" PRIx64, taosGetPthreadId(timerThread));
pthread_join(timerThread, NULL); pthread_join(timerThread, NULL);
} }

View File

@ -152,7 +152,7 @@ typedef struct SQuery {
int16_t precision; int16_t precision;
int16_t numOfOutput; int16_t numOfOutput;
int16_t fillType; int16_t fillType;
int16_t checkBuffer; // check if the buffer is full during scan each block int16_t checkResultBuf; // check if the buffer is full during scan each block
SLimitVal limit; SLimitVal limit;
int32_t rowSize; int32_t rowSize;
SSqlGroupbyExpr* pGroupbyExpr; SSqlGroupbyExpr* pGroupbyExpr;

View File

@ -88,6 +88,7 @@ typedef struct STSBuf {
STSList tsData; // uncompressed raw ts data STSList tsData; // uncompressed raw ts data
uint64_t numOfTotal; uint64_t numOfTotal;
bool autoDelete; bool autoDelete;
bool remainOpen;
int32_t tsOrder; // order of timestamp in ts comp buffer int32_t tsOrder; // order of timestamp in ts comp buffer
STSCursor cur; STSCursor cur;
} STSBuf; } STSBuf;

View File

@ -1268,12 +1268,14 @@ static void min_function_f(SQLFunctionCtx *pCtx, int32_t index) {
} }
static void stddev_function(SQLFunctionCtx *pCtx) { static void stddev_function(SQLFunctionCtx *pCtx) {
// the second stage to calculate standard deviation
SStddevInfo *pStd = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); SStddevInfo *pStd = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
if (pStd->stage == 0) { // the first stage is to calculate average value if (pStd->stage == 0) {
// the first stage is to calculate average value
avg_function(pCtx); avg_function(pCtx);
} else { } else if (pStd->num > 0) {
// the second stage to calculate standard deviation
// if pStd->num == 0, there are no numbers in the first round check. No need to do the second round
double *retVal = &pStd->res; double *retVal = &pStd->res;
double avg = pStd->avg; double avg = pStd->avg;
@ -1326,7 +1328,7 @@ static void stddev_function_f(SQLFunctionCtx *pCtx, int32_t index) {
/* the first stage is to calculate average value */ /* the first stage is to calculate average value */
if (pStd->stage == 0) { if (pStd->stage == 0) {
avg_function_f(pCtx, index); avg_function_f(pCtx, index);
} else { } else if (pStd->num > 0) {
double avg = pStd->avg; double avg = pStd->avg;
void * pData = GET_INPUT_DATA(pCtx, index); void * pData = GET_INPUT_DATA(pCtx, index);
@ -3836,8 +3838,10 @@ static void ts_comp_finalize(SQLFunctionCtx *pCtx) {
STSBuf * pTSbuf = pInfo->pTSBuf; STSBuf * pTSbuf = pInfo->pTSBuf;
tsBufFlush(pTSbuf); tsBufFlush(pTSbuf);
strcpy(pCtx->aOutputBuf, pTSbuf->path);
*(FILE **)pCtx->aOutputBuf = pTSbuf->f;
pTSbuf->remainOpen = true;
tsBufDestroy(pTSbuf); tsBufDestroy(pTSbuf);
doFinalizer(pCtx); doFinalizer(pCtx);
} }

View File

@ -548,7 +548,7 @@ static STimeWindow getActiveTimeWindow(SResultRowInfo *pWindowResInfo, int64_t t
if (pWindowResInfo->curIndex == -1) { // the first window, from the previous stored value if (pWindowResInfo->curIndex == -1) { // the first window, from the previous stored value
w.skey = pWindowResInfo->prevSKey; w.skey = pWindowResInfo->prevSKey;
if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') { if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') {
w.ekey = taosTimeAdd(w.skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision); w.ekey = taosTimeAdd(w.skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1;
} else { } else {
w.ekey = w.skey + pQuery->interval.interval - 1; w.ekey = w.skey + pQuery->interval.interval - 1;
} }
@ -758,7 +758,12 @@ static void doUpdateResultRowIndex(SResultRowInfo*pResultRowInfo, TSKEY lastKey,
} }
} }
pResultRowInfo->curIndex = i + 1; // current not closed result object if (i == pResultRowInfo->size - 1) {
pResultRowInfo->curIndex = i;
} else {
pResultRowInfo->curIndex = i + 1; // current not closed result object
}
pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->curIndex]->win.skey; pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->curIndex]->win.skey;
} }
} }
@ -1667,7 +1672,7 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS
_end: _end:
assert(offset >= 0 && tsCols != NULL); assert(offset >= 0 && tsCols != NULL);
if (prevTs != INT64_MIN) { if (prevTs != INT64_MIN && prevTs != *(int64_t*)pRuntimeEnv->prevRow[0]) {
assert(prevRowIndex >= 0); assert(prevRowIndex >= 0);
item->lastKey = prevTs + step; item->lastKey = prevTs + step;
} }
@ -1708,7 +1713,7 @@ static int32_t tableApplyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SDataBl
numOfRes = (int32_t) getNumOfResult(pRuntimeEnv); numOfRes = (int32_t) getNumOfResult(pRuntimeEnv);
// update the number of output result // update the number of output result
if (numOfRes > 0 && pQuery->checkBuffer == 1) { if (numOfRes > 0 && pQuery->checkResultBuf == 1) {
assert(numOfRes >= pQuery->rec.rows); assert(numOfRes >= pQuery->rec.rows);
pQuery->rec.rows = numOfRes; pQuery->rec.rows = numOfRes;
@ -2005,6 +2010,7 @@ static void doFreeQueryHandle(SQInfo* pQInfo) {
assert(pMemRef->ref == 0 && pMemRef->imem == NULL && pMemRef->mem == NULL); assert(pMemRef->ref == 0 && pMemRef->imem == NULL && pMemRef->mem == NULL);
} }
static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) { static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
if (pRuntimeEnv->pQuery == NULL) { if (pRuntimeEnv->pQuery == NULL) {
return; return;
@ -2016,6 +2022,16 @@ static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
qDebug("QInfo:%p teardown runtime env", pQInfo); qDebug("QInfo:%p teardown runtime env", pQInfo);
cleanupResultRowInfo(&pRuntimeEnv->windowResInfo); cleanupResultRowInfo(&pRuntimeEnv->windowResInfo);
if (isTSCompQuery(pQuery)) {
FILE *f = *(FILE **)pQuery->sdata[0]->data;
if (f) {
fclose(f);
*(FILE **)pQuery->sdata[0]->data = NULL;
}
}
if (pRuntimeEnv->pCtx != NULL) { if (pRuntimeEnv->pCtx != NULL) {
for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i]; SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i];
@ -2222,9 +2238,9 @@ void getAlignQueryTimeWindow(SQuery *pQuery, int64_t key, int64_t keyFirst, int6
static void setScanLimitationByResultBuffer(SQuery *pQuery) { static void setScanLimitationByResultBuffer(SQuery *pQuery) {
if (isTopBottomQuery(pQuery)) { if (isTopBottomQuery(pQuery)) {
pQuery->checkBuffer = 0; pQuery->checkResultBuf = 0;
} else if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) { } else if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) {
pQuery->checkBuffer = 0; pQuery->checkResultBuf = 0;
} else { } else {
bool hasMultioutput = false; bool hasMultioutput = false;
for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
@ -2239,7 +2255,7 @@ static void setScanLimitationByResultBuffer(SQuery *pQuery) {
} }
} }
pQuery->checkBuffer = hasMultioutput ? 1 : 0; pQuery->checkResultBuf = hasMultioutput ? 1 : 0;
} }
} }
@ -2911,7 +2927,7 @@ void setTagVal(SQueryRuntimeEnv *pRuntimeEnv, void *pTable, void *tsdb) {
SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv); SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv);
SExprInfo *pExprInfo = &pQuery->pExpr1[0]; SExprInfo *pExprInfo = &pQuery->pExpr1[0];
if (pQuery->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP) { if (pQuery->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP && pRuntimeEnv->stableQuery) {
assert(pExprInfo->base.numOfParams == 1); assert(pExprInfo->base.numOfParams == 1);
int16_t tagColId = (int16_t)pExprInfo->base.arg->argValue.i64; int16_t tagColId = (int16_t)pExprInfo->base.arg->argValue.i64;
@ -3674,6 +3690,10 @@ void scanOneTableDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) {
SQueryStatusInfo qstatus = getQueryStatusInfo(pRuntimeEnv, start); SQueryStatusInfo qstatus = getQueryStatusInfo(pRuntimeEnv, start);
SET_MASTER_SCAN_FLAG(pRuntimeEnv); SET_MASTER_SCAN_FLAG(pRuntimeEnv);
if (!pRuntimeEnv->groupbyColumn && pRuntimeEnv->hasTagResults) {
setTagVal(pRuntimeEnv, pTableQueryInfo->pTable, pQInfo->tsdb);
}
while (1) { while (1) {
doScanAllDataBlocks(pRuntimeEnv); doScanAllDataBlocks(pRuntimeEnv);
@ -4757,20 +4777,21 @@ static void enableExecutionForNextTable(SQueryRuntimeEnv *pRuntimeEnv) {
} }
} }
// TODO refactor: setAdditionalInfo
static FORCE_INLINE void setEnvForEachBlock(SQInfo* pQInfo, STableQueryInfo* pTableQueryInfo, SDataBlockInfo* pBlockInfo) { static FORCE_INLINE void setEnvForEachBlock(SQInfo* pQInfo, STableQueryInfo* pTableQueryInfo, SDataBlockInfo* pBlockInfo) {
SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
SQuery* pQuery = pQInfo->runtimeEnv.pQuery; SQuery* pQuery = pQInfo->runtimeEnv.pQuery;
int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
if (!QUERY_IS_INTERVAL_QUERY(pQuery)) { if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
setExecutionContext(pQInfo, pTableQueryInfo->groupIndex, pBlockInfo->window.ekey + step);
} else { // interval query
TSKEY nextKey = pBlockInfo->window.skey; TSKEY nextKey = pBlockInfo->window.skey;
setIntervalQueryRange(pQInfo, nextKey); setIntervalQueryRange(pQInfo, nextKey);
if (pRuntimeEnv->hasTagResults || pRuntimeEnv->pTsBuf != NULL) { if (pRuntimeEnv->hasTagResults || pRuntimeEnv->pTsBuf != NULL) {
setAdditionalInfo(pQInfo, pTableQueryInfo->pTable, pTableQueryInfo); setAdditionalInfo(pQInfo, pTableQueryInfo->pTable, pTableQueryInfo);
} }
} else { // non-interval query
setExecutionContext(pQInfo, pTableQueryInfo->groupIndex, pBlockInfo->window.ekey + step);
} }
} }
@ -5626,8 +5647,6 @@ static void tableAggregationProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo)
return; return;
} }
pQuery->current = pTableInfo; // set current query table info
scanOneTableDataBlocks(pRuntimeEnv, pTableInfo->lastKey); scanOneTableDataBlocks(pRuntimeEnv, pTableInfo->lastKey);
finalizeQueryResult(pRuntimeEnv); finalizeQueryResult(pRuntimeEnv);
@ -5646,10 +5665,8 @@ static void tableAggregationProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo)
static void tableProjectionProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) { static void tableProjectionProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) {
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
SQuery *pQuery = pRuntimeEnv->pQuery;
pQuery->current = pTableInfo;
// for ts_comp query, re-initialized is not allowed // for ts_comp query, re-initialized is not allowed
SQuery *pQuery = pRuntimeEnv->pQuery;
if (!isTSCompQuery(pQuery)) { if (!isTSCompQuery(pQuery)) {
resetDefaultResInfoOutputBuf(pRuntimeEnv); resetDefaultResInfoOutputBuf(pRuntimeEnv);
} }
@ -5701,9 +5718,7 @@ static void tableProjectionProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo)
// handle time interval query on table // handle time interval query on table
static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) { static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) {
SQueryRuntimeEnv *pRuntimeEnv = &(pQInfo->runtimeEnv); SQueryRuntimeEnv *pRuntimeEnv = &(pQInfo->runtimeEnv);
SQuery *pQuery = pRuntimeEnv->pQuery; SQuery *pQuery = pRuntimeEnv->pQuery;
pQuery->current = pTableInfo;
TSKEY newStartKey = QUERY_IS_ASC_QUERY(pQuery)? INT64_MIN:INT64_MAX; TSKEY newStartKey = QUERY_IS_ASC_QUERY(pQuery)? INT64_MIN:INT64_MAX;
@ -5773,7 +5788,6 @@ static void tableQueryImpl(SQInfo *pQInfo) {
} }
qDebug("QInfo:%p current:%" PRId64 " returned, total:%" PRId64, pQInfo, pQuery->rec.rows, pQuery->rec.total); qDebug("QInfo:%p current:%" PRId64 " returned, total:%" PRId64, pQInfo, pQuery->rec.rows, pQuery->rec.total);
return;
} else { } else {
pQuery->rec.rows = 0; pQuery->rec.rows = 0;
assert(pRuntimeEnv->windowResInfo.size > 0); assert(pRuntimeEnv->windowResInfo.size > 0);
@ -5791,9 +5805,9 @@ static void tableQueryImpl(SQInfo *pQInfo) {
if (pQuery->rec.rows <= 0 || pRuntimeEnv->windowResInfo.size <= pQInfo->groupIndex) { if (pQuery->rec.rows <= 0 || pRuntimeEnv->windowResInfo.size <= pQInfo->groupIndex) {
qDebug("QInfo:%p query over, %" PRId64 " rows are returned", pQInfo, pQuery->rec.total); qDebug("QInfo:%p query over, %" PRId64 " rows are returned", pQInfo, pQuery->rec.total);
} }
return;
} }
return;
} }
// number of points returned during this query // number of points returned during this query
@ -5802,7 +5816,9 @@ static void tableQueryImpl(SQInfo *pQInfo) {
assert(pQInfo->tableqinfoGroupInfo.numOfTables == 1); assert(pQInfo->tableqinfoGroupInfo.numOfTables == 1);
SArray* g = GET_TABLEGROUP(pQInfo, 0); SArray* g = GET_TABLEGROUP(pQInfo, 0);
STableQueryInfo* item = taosArrayGetP(g, 0); STableQueryInfo* item = taosArrayGetP(g, 0);
pQuery->current = item;
// group by normal column, sliding window query, interval query are handled by interval query processor // group by normal column, sliding window query, interval query are handled by interval query processor
if (QUERY_IS_INTERVAL_QUERY(pQuery) || pRuntimeEnv->groupbyColumn) { // interval (down sampling operation) if (QUERY_IS_INTERVAL_QUERY(pQuery) || pRuntimeEnv->groupbyColumn) { // interval (down sampling operation)
@ -5810,7 +5826,7 @@ static void tableQueryImpl(SQInfo *pQInfo) {
} else if (isFixedOutputQuery(pRuntimeEnv)) { } else if (isFixedOutputQuery(pRuntimeEnv)) {
tableAggregationProcess(pQInfo, item); tableAggregationProcess(pQInfo, item);
} else { // diff/add/multiply/subtract/division } else { // diff/add/multiply/subtract/division
assert(pQuery->checkBuffer == 1); assert(pQuery->checkResultBuf == 1);
tableProjectionProcess(pQInfo, item); tableProjectionProcess(pQInfo, item);
} }
@ -5830,7 +5846,7 @@ static void stableQueryImpl(SQInfo *pQInfo) {
(isFixedOutputQuery(pRuntimeEnv) && (!isPointInterpoQuery(pQuery)) && (!pRuntimeEnv->groupbyColumn))) { (isFixedOutputQuery(pRuntimeEnv) && (!isPointInterpoQuery(pQuery)) && (!pRuntimeEnv->groupbyColumn))) {
multiTableQueryProcess(pQInfo); multiTableQueryProcess(pQInfo);
} else { } else {
assert((pQuery->checkBuffer == 1 && pQuery->interval.interval == 0) || isPointInterpoQuery(pQuery) || assert((pQuery->checkResultBuf == 1 && pQuery->interval.interval == 0) || isPointInterpoQuery(pQuery) ||
pRuntimeEnv->groupbyColumn); pRuntimeEnv->groupbyColumn);
sequentialTableProcess(pQInfo); sequentialTableProcess(pQInfo);
@ -6944,10 +6960,10 @@ static size_t getResultSize(SQInfo *pQInfo, int64_t *numOfRows) {
* TODO handle the case that the file is too large to send back one time * TODO handle the case that the file is too large to send back one time
*/ */
if (isTSCompQuery(pQuery) && (*numOfRows) > 0) { if (isTSCompQuery(pQuery) && (*numOfRows) > 0) {
struct stat fstat; struct stat fStat;
if (stat(pQuery->sdata[0]->data, &fstat) == 0) { if (fstat(fileno(*(FILE **)pQuery->sdata[0]->data), &fStat) == 0) {
*numOfRows = fstat.st_size; *numOfRows = fStat.st_size;
return fstat.st_size; return fStat.st_size;
} else { } else {
qError("QInfo:%p failed to get file info, path:%s, reason:%s", pQInfo, pQuery->sdata[0]->data, strerror(errno)); qError("QInfo:%p failed to get file info, path:%s, reason:%s", pQInfo, pQuery->sdata[0]->data, strerror(errno));
return 0; return 0;
@ -6963,15 +6979,16 @@ static int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
// load data from file to msg buffer // load data from file to msg buffer
if (isTSCompQuery(pQuery)) { if (isTSCompQuery(pQuery)) {
int32_t fd = open(pQuery->sdata[0]->data, O_RDONLY, 0666);
FILE *f = *(FILE **)pQuery->sdata[0]->data;
// make sure file exist // make sure file exist
if (FD_VALID(fd)) { if (f) {
uint64_t s = lseek(fd, 0, SEEK_END); off_t s = lseek(fileno(f), 0, SEEK_END);
qDebug("QInfo:%p ts comp data return, file:%s, size:%"PRId64, pQInfo, pQuery->sdata[0]->data, s); qDebug("QInfo:%p ts comp data return, file:%p, size:%"PRId64, pQInfo, f, s);
if (lseek(fd, 0, SEEK_SET) >= 0) { if (fseek(f, 0, SEEK_SET) >= 0) {
size_t sz = read(fd, data, (uint32_t) s); size_t sz = fread(data, 1, s, f);
if(sz < s) { // todo handle error if(sz < s) { // todo handle error
assert(0); assert(0);
} }
@ -6979,15 +6996,8 @@ static int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
UNUSED(s); UNUSED(s);
} }
close(fd); fclose(f);
unlink(pQuery->sdata[0]->data); *(FILE **)pQuery->sdata[0]->data = NULL;
} else {
// todo return the error code to client and handle invalid fd
qError("QInfo:%p failed to open tmp file to send ts-comp data to client, path:%s, reason:%s", pQInfo,
pQuery->sdata[0]->data, strerror(errno));
if (fd != -1) {
close(fd);
}
} }
// all data returned, set query over // all data returned, set query over
@ -7635,6 +7645,19 @@ void qQueryMgmtNotifyClosed(void* pQMgmt) {
taosCacheRefresh(pQueryMgmt->qinfoPool, queryMgmtKillQueryFn); taosCacheRefresh(pQueryMgmt->qinfoPool, queryMgmtKillQueryFn);
} }
void qQueryMgmtReOpen(void *pQMgmt) {
if (pQMgmt == NULL) {
return;
}
SQueryMgmt *pQueryMgmt = pQMgmt;
qDebug("vgId:%d, set querymgmt reopen", pQueryMgmt->vgId);
pthread_mutex_lock(&pQueryMgmt->lock);
pQueryMgmt->closed = false;
pthread_mutex_unlock(&pQueryMgmt->lock);
}
void qCleanupQueryMgmt(void* pQMgmt) { void qCleanupQueryMgmt(void* pQMgmt) {
if (pQMgmt == NULL) { if (pQMgmt == NULL) {
return; return;
@ -7715,4 +7738,4 @@ void** qReleaseQInfo(void* pMgmt, void* pQInfo, bool freeHandle) {
taosCacheRelease(pQueryMgmt->qinfoPool, pQInfo, freeHandle); taosCacheRelease(pQueryMgmt->qinfoPool, pQInfo, freeHandle);
return 0; return 0;
} }

View File

@ -143,6 +143,9 @@ SHistogramInfo* tHistogramCreateFrom(void* pBuf, int32_t numOfBins) {
SHistogramInfo* pHisto = (SHistogramInfo*)pBuf; SHistogramInfo* pHisto = (SHistogramInfo*)pBuf;
pHisto->elems = (SHistBin*)((char*)pBuf + sizeof(SHistogramInfo)); pHisto->elems = (SHistBin*)((char*)pBuf + sizeof(SHistogramInfo));
for(int32_t i = 0; i < numOfBins; ++i) {
pHisto->elems[i].val = -DBL_MAX;
}
pHisto->maxEntries = numOfBins; pHisto->maxEntries = numOfBins;

View File

@ -19,6 +19,8 @@ STSBuf* tsBufCreate(bool autoDelete, int32_t order) {
if (pTSBuf == NULL) { if (pTSBuf == NULL) {
return NULL; return NULL;
} }
pTSBuf->autoDelete = autoDelete;
taosGetTmpfilePath("join", pTSBuf->path); taosGetTmpfilePath("join", pTSBuf->path);
pTSBuf->f = fopen(pTSBuf->path, "w+"); pTSBuf->f = fopen(pTSBuf->path, "w+");
@ -26,6 +28,10 @@ STSBuf* tsBufCreate(bool autoDelete, int32_t order) {
free(pTSBuf); free(pTSBuf);
return NULL; return NULL;
} }
if (!autoDelete) {
unlink(pTSBuf->path);
}
if (NULL == allocResForTSBuf(pTSBuf)) { if (NULL == allocResForTSBuf(pTSBuf)) {
return NULL; return NULL;
@ -37,8 +43,7 @@ STSBuf* tsBufCreate(bool autoDelete, int32_t order) {
tsBufResetPos(pTSBuf); tsBufResetPos(pTSBuf);
pTSBuf->cur.order = TSDB_ORDER_ASC; pTSBuf->cur.order = TSDB_ORDER_ASC;
pTSBuf->autoDelete = autoDelete;
pTSBuf->tsOrder = order; pTSBuf->tsOrder = order;
return pTSBuf; return pTSBuf;
@ -49,6 +54,8 @@ STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete) {
if (pTSBuf == NULL) { if (pTSBuf == NULL) {
return NULL; return NULL;
} }
pTSBuf->autoDelete = autoDelete;
tstrncpy(pTSBuf->path, path, sizeof(pTSBuf->path)); tstrncpy(pTSBuf->path, path, sizeof(pTSBuf->path));
@ -129,7 +136,6 @@ STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete) {
// ascending by default // ascending by default
pTSBuf->cur.order = TSDB_ORDER_ASC; pTSBuf->cur.order = TSDB_ORDER_ASC;
pTSBuf->autoDelete = autoDelete;
// tscDebug("create tsBuf from file:%s, fd:%d, size:%d, numOfGroups:%d, autoDelete:%d", pTSBuf->path, fileno(pTSBuf->f), // tscDebug("create tsBuf from file:%s, fd:%d, size:%d, numOfGroups:%d, autoDelete:%d", pTSBuf->path, fileno(pTSBuf->f),
// pTSBuf->fileSize, pTSBuf->numOfGroups, pTSBuf->autoDelete); // pTSBuf->fileSize, pTSBuf->numOfGroups, pTSBuf->autoDelete);
@ -147,8 +153,10 @@ void* tsBufDestroy(STSBuf* pTSBuf) {
tfree(pTSBuf->pData); tfree(pTSBuf->pData);
tfree(pTSBuf->block.payload); tfree(pTSBuf->block.payload);
fclose(pTSBuf->f); if (!pTSBuf->remainOpen) {
fclose(pTSBuf->f);
}
if (pTSBuf->autoDelete) { if (pTSBuf->autoDelete) {
// ("tsBuf %p destroyed, delete tmp file:%s", pTSBuf, pTSBuf->path); // ("tsBuf %p destroyed, delete tmp file:%s", pTSBuf, pTSBuf->path);

View File

@ -4,42 +4,9 @@
#include <iostream> #include <iostream>
#include "taos.h" #include "taos.h"
#include "tsdb.h"
#include "tstoken.h"
#include "tutil.h"
#include "qHistogram.h" #include "qHistogram.h"
namespace {
/* test validate the names for table/database */ void doHistogramAddTest() {
TEST(testCase, histogram_binary_search) {
SHistogramInfo* pHisto = tHistogramCreate(MAX_HISTOGRAM_BIN);
pHisto->numOfEntries = 10;
for (int32_t i = 0; i < 10; ++i) {
pHisto->elems[i].num = 1;
pHisto->elems[i].val = i;
}
int32_t idx = histoBinarySearch(pHisto->elems, pHisto->numOfEntries, 1);
assert(idx == 1);
idx = histoBinarySearch(pHisto->elems, pHisto->numOfEntries, 9);
assert(idx == 9);
idx = histoBinarySearch(pHisto->elems, pHisto->numOfEntries, 20);
assert(idx == 10);
idx = histoBinarySearch(pHisto->elems, pHisto->numOfEntries, -1);
assert(idx == 0);
idx = histoBinarySearch(pHisto->elems, pHisto->numOfEntries, 3.9);
assert(idx == 4);
free(pHisto);
}
TEST(testCase, histogram_add) {
SHistogramInfo* pHisto = NULL; SHistogramInfo* pHisto = NULL;
/** /**
@ -99,6 +66,56 @@ TEST(testCase, histogram_add) {
tHistogramDestroy(&pRes); tHistogramDestroy(&pRes);
free(res); free(res);
} }
void doHistogramRepeatTest() {
SHistogramInfo* pHisto = NULL;
struct timeval systemTime;
gettimeofday(&systemTime, NULL);
int64_t st =
(int64_t)systemTime.tv_sec * 1000L + (uint64_t)systemTime.tv_usec / 1000;
for (int32_t i = 0; i < 1000; ++i) {
tHistogramAdd(&pHisto, -24 + i);
// tHistogramPrint(pHisto);
}
tHistogramDestroy(&pHisto);
}
}
/* test validate the names for table/database */
TEST(testCase, histogram_binary_search) {
SHistogramInfo* pHisto = tHistogramCreate(MAX_HISTOGRAM_BIN);
pHisto->numOfEntries = 10;
for (int32_t i = 0; i < 10; ++i) {
pHisto->elems[i].num = 1;
pHisto->elems[i].val = i;
}
int32_t idx = histoBinarySearch(pHisto->elems, pHisto->numOfEntries, 1);
assert(idx == 1);
idx = histoBinarySearch(pHisto->elems, pHisto->numOfEntries, 9);
assert(idx == 9);
idx = histoBinarySearch(pHisto->elems, pHisto->numOfEntries, 20);
assert(idx == 10);
idx = histoBinarySearch(pHisto->elems, pHisto->numOfEntries, -1);
assert(idx == 0);
idx = histoBinarySearch(pHisto->elems, pHisto->numOfEntries, 3.9);
assert(idx == 4);
free(pHisto);
}
TEST(testCase, histogram_add) {
doHistogramAddTest();
doHistogramRepeatTest();
}
TEST(testCase, heapsort) { TEST(testCase, heapsort) {
// int32_t num = 20; // int32_t num = 20;

View File

@ -1567,6 +1567,7 @@ static int rpcCheckAuthentication(SRpcConn *pConn, char *msg, int msgLen) {
// for response, if code is auth failure, it shall bypass the auth process // for response, if code is auth failure, it shall bypass the auth process
code = htonl(pHead->code); code = htonl(pHead->code);
if (code == TSDB_CODE_RPC_INVALID_TIME_STAMP || code == TSDB_CODE_RPC_AUTH_FAILURE || if (code == TSDB_CODE_RPC_INVALID_TIME_STAMP || code == TSDB_CODE_RPC_AUTH_FAILURE ||
code == TSDB_CODE_RPC_INVALID_VERSION ||
code == TSDB_CODE_RPC_AUTH_REQUIRED || code == TSDB_CODE_MND_INVALID_USER || code == TSDB_CODE_RPC_NOT_READY) { code == TSDB_CODE_RPC_AUTH_REQUIRED || code == TSDB_CODE_MND_INVALID_USER || code == TSDB_CODE_RPC_NOT_READY) {
pHead->msgLen = (int32_t)htonl((uint32_t)pHead->msgLen); pHead->msgLen = (int32_t)htonl((uint32_t)pHead->msgLen);
// tTrace("%s, dont check authentication since code is:0x%x", pConn->info, code); // tTrace("%s, dont check authentication since code is:0x%x", pConn->info, code);

View File

@ -375,6 +375,8 @@ int32_t syncReconfig(int64_t rid, const SSyncCfg *pNewCfg) {
} }
int32_t syncForwardToPeer(int64_t rid, void *data, void *mhandle, int32_t qtype) { int32_t syncForwardToPeer(int64_t rid, void *data, void *mhandle, int32_t qtype) {
if (rid <= 0) return 0;
SSyncNode *pNode = syncAcquireNode(rid); SSyncNode *pNode = syncAcquireNode(rid);
if (pNode == NULL) return 0; if (pNode == NULL) return 0;

View File

@ -90,7 +90,7 @@ static int32_t syncRestoreFile(SSyncPeer *pPeer, uint64_t *fversion) {
break; break;
} }
sDebug("%s, file:%s info is received from master, index:%d size:%" PRId64 " fver:%" PRIu64 " magic:%d", pPeer->id, sDebug("%s, file:%s info is received from master, index:%d size:%" PRId64 " fver:%" PRIu64 " magic:%u", pPeer->id,
minfo.name, minfo.index, minfo.size, minfo.fversion, minfo.magic); minfo.name, minfo.index, minfo.size, minfo.fversion, minfo.magic);
// remove extra files on slave between the current and last index // remove extra files on slave between the current and last index
@ -100,13 +100,13 @@ static int32_t syncRestoreFile(SSyncPeer *pPeer, uint64_t *fversion) {
// check the file info // check the file info
sinfo = minfo; sinfo = minfo;
sinfo.magic = (*pNode->getFileInfo)(pNode->vgId, sinfo.name, &sinfo.index, TAOS_SYNC_MAX_INDEX, &sinfo.size, &sinfo.fversion); sinfo.magic = (*pNode->getFileInfo)(pNode->vgId, sinfo.name, &sinfo.index, TAOS_SYNC_MAX_INDEX, &sinfo.size, &sinfo.fversion);
sDebug("%s, local file:%s info, index:%d size:%" PRId64 " fver:%" PRIu64 " magic:%d", pPeer->id, sinfo.name, sDebug("%s, local file:%s info, index:%d size:%" PRId64 " fver:%" PRIu64 " magic:%u", pPeer->id, sinfo.name,
sinfo.index, sinfo.size, sinfo.fversion, sinfo.magic); sinfo.index, sinfo.size, sinfo.fversion, sinfo.magic);
// if file not there or magic is not the same, file shall be synced // if file not there or magic is not the same, file shall be synced
memset(&fileAck, 0, sizeof(SFileAck)); memset(&fileAck, 0, sizeof(SFileAck));
syncBuildFileAck(&fileAck, pNode->vgId); syncBuildFileAck(&fileAck, pNode->vgId);
fileAck.sync = (sinfo.magic != minfo.magic || sinfo.name[0] == 0) ? 1 : 0; fileAck.sync = (sinfo.magic != minfo.magic || sinfo.size != minfo.size || sinfo.name[0] == 0) ? 1 : 0;
// send file ack // send file ack
ret = taosWriteMsg(pPeer->syncFd, &fileAck, sizeof(SFileAck)); ret = taosWriteMsg(pPeer->syncFd, &fileAck, sizeof(SFileAck));
@ -195,7 +195,11 @@ static int32_t syncRestoreWal(SSyncPeer *pPeer, uint64_t *wver) {
} }
lastVer = pHead->version; lastVer = pHead->version;
(*pNode->writeToCache)(pNode->vgId, pHead, TAOS_QTYPE_WAL, NULL); ret = (*pNode->writeToCache)(pNode->vgId, pHead, TAOS_QTYPE_WAL, NULL);
if (ret != 0) {
sError("%s, failed to restore record since %s, hver:%" PRIu64, pPeer->id, tstrerror(ret), pHead->version);
break;
}
} }
if (code < 0) { if (code < 0) {

View File

@ -104,7 +104,7 @@ static int32_t syncRetrieveFile(SSyncPeer *pPeer) {
fileInfo.magic = (*pNode->getFileInfo)(pNode->vgId, fileInfo.name, &fileInfo.index, TAOS_SYNC_MAX_INDEX, fileInfo.magic = (*pNode->getFileInfo)(pNode->vgId, fileInfo.name, &fileInfo.index, TAOS_SYNC_MAX_INDEX,
&fileInfo.size, &fileInfo.fversion); &fileInfo.size, &fileInfo.fversion);
syncBuildFileInfo(&fileInfo, pNode->vgId); syncBuildFileInfo(&fileInfo, pNode->vgId);
sDebug("%s, file:%s info is sent, index:%d size:%" PRId64 " fver:%" PRIu64 " magic:%d", pPeer->id, fileInfo.name, sDebug("%s, file:%s info is sent, index:%d size:%" PRId64 " fver:%" PRIu64 " magic:%u", pPeer->id, fileInfo.name,
fileInfo.index, fileInfo.size, fileInfo.fversion, fileInfo.magic); fileInfo.index, fileInfo.size, fileInfo.fversion, fileInfo.magic);
// send the file info // send the file info
@ -143,10 +143,10 @@ static int32_t syncRetrieveFile(SSyncPeer *pPeer) {
// if sync is not required, continue // if sync is not required, continue
if (fileAck.sync == 0) { if (fileAck.sync == 0) {
fileInfo.index++; fileInfo.index++;
sDebug("%s, %s is the same", pPeer->id, fileInfo.name); sDebug("%s, %s is the same, fver:%" PRIu64, pPeer->id, fileInfo.name, fileInfo.fversion);
continue; continue;
} else { } else {
sDebug("%s, %s will be sent", pPeer->id, fileInfo.name); sDebug("%s, %s will be sent, fver:%" PRIu64, pPeer->id, fileInfo.name, fileInfo.fversion);
} }
// get the full path to file // get the full path to file
@ -328,7 +328,8 @@ static int32_t syncProcessLastWal(SSyncPeer *pPeer, char *wname, int64_t index)
// if bytes > 0, file is updated, or fversion is not reached but file still open, read again // if bytes > 0, file is updated, or fversion is not reached but file still open, read again
once = 1; once = 1;
offset += bytes; offset += bytes;
sDebug("%s, continue retrieve last wal, bytes:%d offset:%" PRId64, pPeer->id, bytes, offset); sDebug("%s, continue retrieve last wal, bytes:%d offset:%" PRId64 " sver:%" PRIu64 " fver:%" PRIu64, pPeer->id,
bytes, offset, pPeer->sversion, fversion);
} }
return -1; return -1;

View File

@ -477,8 +477,6 @@ void taosHashEmpty(SHashObj *pHashObj) {
return; return;
} }
uDebug("hash:%p cleanup hash table", pHashObj);
SHashNode *pNode, *pNext; SHashNode *pNode, *pNext;
__wr_lock(&pHashObj->lock, pHashObj->type); __wr_lock(&pHashObj->lock, pHashObj->type);

View File

@ -27,6 +27,7 @@ void vnodeCleanupRead(void);
int32_t vnodeWriteToRQueue(void *pVnode, void *pCont, int32_t contLen, int8_t qtype, void *rparam); int32_t vnodeWriteToRQueue(void *pVnode, void *pCont, int32_t contLen, int8_t qtype, void *rparam);
void vnodeFreeFromRQueue(void *pVnode, SVReadMsg *pRead); void vnodeFreeFromRQueue(void *pVnode, SVReadMsg *pRead);
int32_t vnodeProcessRead(void *pVnode, SVReadMsg *pRead); int32_t vnodeProcessRead(void *pVnode, SVReadMsg *pRead);
void vnodeWaitReadCompleted(void *pVnode);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -37,6 +37,7 @@ bool vnodeSetResetStatus(SVnodeObj* pVnode);
bool vnodeInInitStatus(SVnodeObj* pVnode); bool vnodeInInitStatus(SVnodeObj* pVnode);
bool vnodeInReadyStatus(SVnodeObj* pVnode); bool vnodeInReadyStatus(SVnodeObj* pVnode);
bool vnodeInReadyOrUpdatingStatus(SVnodeObj* pVnode);
bool vnodeInClosingStatus(SVnodeObj* pVnode); bool vnodeInClosingStatus(SVnodeObj* pVnode);
bool vnodeInResetStatus(SVnodeObj* pVnode); bool vnodeInResetStatus(SVnodeObj* pVnode);

View File

@ -27,6 +27,7 @@ void vnodeCleanupWrite(void);
int32_t vnodeWriteToWQueue(void *pVnode, void *pHead, int32_t qtype, void *pRpcMsg); int32_t vnodeWriteToWQueue(void *pVnode, void *pHead, int32_t qtype, void *pRpcMsg);
void vnodeFreeFromWQueue(void *pVnode, SVWriteMsg *pWrite); void vnodeFreeFromWQueue(void *pVnode, SVWriteMsg *pWrite);
int32_t vnodeProcessWrite(void *pVnode, void *pHead, int32_t qtype, void *pRspRet); int32_t vnodeProcessWrite(void *pVnode, void *pHead, int32_t qtype, void *pRspRet);
void vnodeWaitWriteCompleted(void *pVnode);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -153,6 +153,11 @@ static int32_t vnodeAlterImp(SVnodeObj *pVnode, SCreateVnodeMsg *pVnodeCfg) {
int32_t vnodeAlter(void *vparam, SCreateVnodeMsg *pVnodeCfg) { int32_t vnodeAlter(void *vparam, SCreateVnodeMsg *pVnodeCfg) {
SVnodeObj *pVnode = vparam; SVnodeObj *pVnode = vparam;
if (pVnode->dbCfgVersion == pVnodeCfg->cfg.dbCfgVersion && pVnode->vgCfgVersion == pVnodeCfg->cfg.vgCfgVersion) {
vDebug("vgId:%d, dbCfgVersion:%d and vgCfgVersion:%d not change", pVnode->vgId, pVnode->dbCfgVersion,
pVnode->vgCfgVersion);
return TSDB_CODE_SUCCESS;
}
// vnode in non-ready state and still needs to return success instead of TSDB_CODE_VND_INVALID_STATUS // vnode in non-ready state and still needs to return success instead of TSDB_CODE_VND_INVALID_STATUS
// dbCfgVersion can be corrected by status msg // dbCfgVersion can be corrected by status msg
@ -411,15 +416,12 @@ void vnodeDestroy(SVnodeObj *pVnode) {
} }
void vnodeCleanUp(SVnodeObj *pVnode) { void vnodeCleanUp(SVnodeObj *pVnode) {
if (!vnodeInInitStatus(pVnode)) { vDebug("vgId:%d, vnode will cleanup, refCount:%d pVnode:%p", pVnode->vgId, pVnode->refCount, pVnode);
// it may be in updateing or reset state, then it shall wait
int32_t i = 0; vnodeSetClosingStatus(pVnode);
while (!vnodeSetClosingStatus(pVnode)) {
if (++i % 1000 == 0) { // release local resources only after cutting off outside connections
sched_yield(); qQueryMgmtNotifyClosed(pVnode->qMgmt);
}
}
}
// stop replication module // stop replication module
if (pVnode->sync > 0) { if (pVnode->sync > 0) {
@ -428,10 +430,7 @@ void vnodeCleanUp(SVnodeObj *pVnode) {
syncStop(sync); syncStop(sync);
} }
vDebug("vgId:%d, vnode will cleanup, refCount:%d pVnode:%p", pVnode->vgId, pVnode->refCount, pVnode); vDebug("vgId:%d, vnode is cleaned, refCount:%d pVnode:%p", pVnode->vgId, pVnode->refCount, pVnode);
// release local resources only after cutting off outside connections
qQueryMgmtNotifyClosed(pVnode->qMgmt);
vnodeRelease(pVnode); vnodeRelease(pVnode);
} }

View File

@ -88,22 +88,15 @@ void vnodeFreeFromRQueue(void *vparam, SVReadMsg *pRead) {
vnodeRelease(pVnode); vnodeRelease(pVnode);
} }
int32_t vnodeWriteToRQueue(void *vparam, void *pCont, int32_t contLen, int8_t qtype, void *rparam) { static SVReadMsg *vnodeBuildVReadMsg(SVnodeObj *pVnode, void *pCont, int32_t contLen, int8_t qtype, SRpcMsg *pRpcMsg) {
SVnodeObj *pVnode = vparam;
if (qtype == TAOS_QTYPE_RPC || qtype == TAOS_QTYPE_QUERY) {
int32_t code = vnodeCheckRead(pVnode);
if (code != TSDB_CODE_SUCCESS) return code;
}
int32_t size = sizeof(SVReadMsg) + contLen; int32_t size = sizeof(SVReadMsg) + contLen;
SVReadMsg *pRead = taosAllocateQitem(size); SVReadMsg *pRead = taosAllocateQitem(size);
if (pRead == NULL) { if (pRead == NULL) {
return TSDB_CODE_VND_OUT_OF_MEMORY; terrno = TSDB_CODE_VND_OUT_OF_MEMORY;
return NULL;
} }
if (rparam != NULL) { if (pRpcMsg != NULL) {
SRpcMsg *pRpcMsg = rparam;
pRead->rpcHandle = pRpcMsg->handle; pRead->rpcHandle = pRpcMsg->handle;
pRead->rpcAhandle = pRpcMsg->ahandle; pRead->rpcAhandle = pRpcMsg->ahandle;
pRead->msgType = pRpcMsg->msgType; pRead->msgType = pRpcMsg->msgType;
@ -119,13 +112,35 @@ int32_t vnodeWriteToRQueue(void *vparam, void *pCont, int32_t contLen, int8_t qt
pRead->qtype = qtype; pRead->qtype = qtype;
atomic_add_fetch_32(&pVnode->refCount, 1); atomic_add_fetch_32(&pVnode->refCount, 1);
return pRead;
}
int32_t vnodeWriteToRQueue(void *vparam, void *pCont, int32_t contLen, int8_t qtype, void *rparam) {
SVReadMsg *pRead = vnodeBuildVReadMsg(vparam, pCont, contLen, qtype, rparam);
if (pRead == NULL) {
assert(terrno != 0);
return terrno;
}
SVnodeObj *pVnode = vparam;
int32_t code = vnodeCheckRead(pVnode);
if (code != TSDB_CODE_SUCCESS) {
taosFreeQitem(pRead);
vnodeRelease(pVnode);
return code;
}
atomic_add_fetch_32(&pVnode->queuedRMsg, 1); atomic_add_fetch_32(&pVnode->queuedRMsg, 1);
if (pRead->code == TSDB_CODE_RPC_NETWORK_UNAVAIL || pRead->msgType == TSDB_MSG_TYPE_FETCH) { if (pRead->code == TSDB_CODE_RPC_NETWORK_UNAVAIL || pRead->msgType == TSDB_MSG_TYPE_FETCH) {
vTrace("vgId:%d, write into vfetch queue, refCount:%d queued:%d", pVnode->vgId, pVnode->refCount, pVnode->queuedRMsg); vTrace("vgId:%d, write into vfetch queue, refCount:%d queued:%d", pVnode->vgId, pVnode->refCount,
pVnode->queuedRMsg);
return taosWriteQitem(pVnode->fqueue, qtype, pRead); return taosWriteQitem(pVnode->fqueue, qtype, pRead);
} else { } else {
vTrace("vgId:%d, write into vquery queue, refCount:%d queued:%d", pVnode->vgId, pVnode->refCount, pVnode->queuedRMsg); vTrace("vgId:%d, write into vquery queue, refCount:%d queued:%d", pVnode->vgId, pVnode->refCount,
pVnode->queuedRMsg);
return taosWriteQitem(pVnode->qqueue, qtype, pRead); return taosWriteQitem(pVnode->qqueue, qtype, pRead);
} }
} }
@ -420,3 +435,5 @@ int32_t vnodeNotifyCurrentQhandle(void *handle, void *qhandle, int32_t vgId) {
vTrace("QInfo:%p register qhandle to connect:%p", qhandle, handle); vTrace("QInfo:%p register qhandle to connect:%p", qhandle, handle);
return rpcReportProgress(handle, (char *)pMsg, sizeof(SRetrieveTableMsg)); return rpcReportProgress(handle, (char *)pMsg, sizeof(SRetrieveTableMsg));
} }
void vnodeWaitReadCompleted(void *pVnode) {}

View File

@ -15,6 +15,8 @@
#define _DEFAULT_SOURCE #define _DEFAULT_SOURCE
#include "os.h" #include "os.h"
#include "taosmsg.h"
#include "query.h"
#include "vnodeStatus.h" #include "vnodeStatus.h"
char* vnodeStatus[] = { char* vnodeStatus[] = {
@ -44,11 +46,13 @@ bool vnodeSetReadyStatus(SVnodeObj* pVnode) {
vDebug("vgId:%d, cannot set status:ready, old:%s", pVnode->vgId, vnodeStatus[pVnode->status]); vDebug("vgId:%d, cannot set status:ready, old:%s", pVnode->vgId, vnodeStatus[pVnode->status]);
} }
qQueryMgmtReOpen(pVnode->qMgmt);
pthread_mutex_unlock(&pVnode->statusMutex); pthread_mutex_unlock(&pVnode->statusMutex);
return set; return set;
} }
bool vnodeSetClosingStatus(SVnodeObj* pVnode) { static bool vnodeSetClosingStatusImp(SVnodeObj* pVnode) {
bool set = false; bool set = false;
pthread_mutex_lock(&pVnode->statusMutex); pthread_mutex_lock(&pVnode->statusMutex);
@ -63,6 +67,20 @@ bool vnodeSetClosingStatus(SVnodeObj* pVnode) {
return set; return set;
} }
bool vnodeSetClosingStatus(SVnodeObj* pVnode) {
if (!vnodeInInitStatus(pVnode)) {
// it may be in updating or reset state, then it shall wait
int32_t i = 0;
while (!vnodeSetClosingStatusImp(pVnode)) {
if (++i % 1000 == 0) {
sched_yield();
}
}
}
return true;
}
bool vnodeSetUpdatingStatus(SVnodeObj* pVnode) { bool vnodeSetUpdatingStatus(SVnodeObj* pVnode) {
bool set = false; bool set = false;
pthread_mutex_lock(&pVnode->statusMutex); pthread_mutex_lock(&pVnode->statusMutex);
@ -117,6 +135,18 @@ bool vnodeInReadyStatus(SVnodeObj* pVnode) {
return in; return in;
} }
bool vnodeInReadyOrUpdatingStatus(SVnodeObj* pVnode) {
bool in = false;
pthread_mutex_lock(&pVnode->statusMutex);
if (pVnode->status == TAOS_VN_STATUS_READY || pVnode->status == TAOS_VN_STATUS_UPDATING) {
in = true;
}
pthread_mutex_unlock(&pVnode->statusMutex);
return in;
}
bool vnodeInClosingStatus(SVnodeObj* pVnode) { bool vnodeInClosingStatus(SVnodeObj* pVnode) {
bool in = false; bool in = false;
pthread_mutex_lock(&pVnode->statusMutex); pthread_mutex_lock(&pVnode->statusMutex);

View File

@ -90,7 +90,10 @@ int32_t vnodeProcessWrite(void *vparam, void *wparam, int32_t qtype, void *rpara
// write into WAL // write into WAL
code = walWrite(pVnode->wal, pHead); code = walWrite(pVnode->wal, pHead);
if (code < 0) return code; if (code < 0) {
vError("vgId:%d, hver:%" PRIu64 " vver:%" PRIu64 " code:0x%x", pVnode->vgId, pHead->version, pVnode->version, code);
return code;
}
pVnode->version = pHead->version; pVnode->version = pHead->version;
@ -120,12 +123,6 @@ static int32_t vnodeCheckWrite(SVnodeObj *pVnode) {
return TSDB_CODE_APP_NOT_READY; return TSDB_CODE_APP_NOT_READY;
} }
if (vnodeInClosingStatus(pVnode)) {
vDebug("vgId:%d, vnode status is %s, refCount:%d pVnode:%p", pVnode->vgId, vnodeStatus[pVnode->status],
pVnode->refCount, pVnode);
return TSDB_CODE_APP_NOT_READY;
}
if (pVnode->isFull) { if (pVnode->isFull) {
vDebug("vgId:%d, vnode is full, refCount:%d", pVnode->vgId, pVnode->refCount); vDebug("vgId:%d, vnode is full, refCount:%d", pVnode->vgId, pVnode->refCount);
return TSDB_CODE_VND_IS_FULL; return TSDB_CODE_VND_IS_FULL;
@ -248,12 +245,21 @@ static int32_t vnodeWriteToWQueueImp(SVWriteMsg *pWrite) {
if (pWrite->qtype == TAOS_QTYPE_RPC) { if (pWrite->qtype == TAOS_QTYPE_RPC) {
int32_t code = vnodeCheckWrite(pVnode); int32_t code = vnodeCheckWrite(pVnode);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
vError("vgId:%d, failed to write into vwqueue since %s", pVnode->vgId, tstrerror(code));
taosFreeQitem(pWrite); taosFreeQitem(pWrite);
vnodeRelease(pVnode); vnodeRelease(pVnode);
return code; return code;
} }
} }
if (!vnodeInReadyOrUpdatingStatus(pVnode)) {
vError("vgId:%d, failed to write into vwqueue, vstatus is %s, refCount:%d pVnode:%p", pVnode->vgId,
vnodeStatus[pVnode->status], pVnode->refCount, pVnode);
taosFreeQitem(pWrite);
vnodeRelease(pVnode);
return TSDB_CODE_APP_NOT_READY;
}
int32_t queued = atomic_add_fetch_32(&pVnode->queuedWMsg, 1); int32_t queued = atomic_add_fetch_32(&pVnode->queuedWMsg, 1);
if (queued > MAX_QUEUED_MSG_NUM) { if (queued > MAX_QUEUED_MSG_NUM) {
int32_t ms = (queued / MAX_QUEUED_MSG_NUM) * 10 + 3; int32_t ms = (queued / MAX_QUEUED_MSG_NUM) * 10 + 3;
@ -337,4 +343,6 @@ static int32_t vnodePerformFlowCtrl(SVWriteMsg *pWrite) {
pWrite->processedCount); pWrite->processedCount);
return TSDB_CODE_VND_ACTION_IN_PROGRESS; return TSDB_CODE_VND_ACTION_IN_PROGRESS;
} }
} }
void vnodeWaitWriteCompleted(void *pVnode) {}

10
tests/Jenkinsfile vendored
View File

@ -98,7 +98,15 @@ pipeline {
sh ''' sh '''
cd ${WKC}/tests/examples/JDBC/JDBCDemo/ cd ${WKC}/tests/examples/JDBC/JDBCDemo/
mvn clean package assembly:single -DskipTests >/dev/null mvn clean package assembly:single -DskipTests >/dev/null
java -jar target/jdbcChecker-SNAPSHOT-jar-with-dependencies.jar -host 127.0.0.1 java -jar target/JDBCDemo-SNAPSHOT-jar-with-dependencies.jar -host 127.0.0.1
'''
}
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh '''
cd ${WKC}/src/connector/jdbc
mvn clean package -Dmaven.test.skip=true >/dev/null
cd ${WKC}/tests/examples/JDBC/JDBCDemo/
java --class-path=../../../../src/connector/jdbc/target:$JAVA_HOME/jre/lib/ext -jar target/JDBCDemo-SNAPSHOT-jar-with-dependencies.jar -host 127.0.0.1
''' '''
} }
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {

View File

@ -10,12 +10,14 @@ run C# version taosdemo
=== ===
Usage: mono taosdemo.exe [OPTION...] Usage: mono taosdemo.exe [OPTION...]
--help Show usage.
-h host, The host to connect to TDengine. Default is localhost. -h host, The host to connect to TDengine. Default is localhost.
-p port, The TCP/IP port number to use for the connection. Default is 0. -p port, The TCP/IP port number to use for the connection. Default is 0.
-u user, The user name to use when connecting to the server. Default is 'root'. -u user, The user name to use when connecting to the server. Default is 'root'.
-P password, The password to use when connecting to the server. Default is 'taosdata'. -P password, The password to use when connecting to the server. Default is 'taosdata'.
-d database, Destination database. Default is 'test'. -d database, Destination database. Default is 'test'.
-a replica, Set the replica parameters of the database, Default 1, min: 1, max: 3. -a replica, Set the replica parameters of the database, Default 1, min: 1, max: 5.
-m table_prefix, Table prefix name. Default is 't'. -m table_prefix, Table prefix name. Default is 't'.
-s sql file, The select sql file. -s sql file, The select sql file.
-M stable, Use super table. -M stable, Use super table.
@ -26,8 +28,8 @@ Usage: mono taosdemo.exe [OPTION...]
-l num_of_cols_per_record, The number of columns per record. Default is 3. -l num_of_cols_per_record, The number of columns per record. Default is 3.
-T num_of_threads, The number of threads. Default is 10. -T num_of_threads, The number of threads. Default is 10.
-r num_of_records_per_req, The number of records per request. Default is 1000. -r num_of_records_per_req, The number of records per request. Default is 1000.
-t num_of_tables, The number of tables. Default is 10000. -t num_of_tables, The number of tables. Default is 1.
-n num_of_records_per_table, The number of records per table. Default is 10000. -n num_of_records_per_table, The number of records per table. Default is 1.
-c config_directory, Configuration directory. Default is '/etc/taos/'. -c config_directory, Configuration directory. Default is '/etc/taos/'.
-x flag, Insert only flag. -x flag, Insert only flag.
-O order, Insert mode--0: In order, 1: Out of order. Default is in order. -O order, Insert mode--0: In order, 1: Out of order. Default is in order.

View File

@ -1 +0,0 @@
../../../../src/connector/C#/TDengineDriver.cs

View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace TDengineDriver
{
enum TDengineDataType
{
TSDB_DATA_TYPE_NULL = 0, // 1 bytes
TSDB_DATA_TYPE_BOOL = 1, // 1 bytes
TSDB_DATA_TYPE_TINYINT = 2, // 1 bytes
TSDB_DATA_TYPE_SMALLINT = 3, // 2 bytes
TSDB_DATA_TYPE_INT = 4, // 4 bytes
TSDB_DATA_TYPE_BIGINT = 5, // 8 bytes
TSDB_DATA_TYPE_FLOAT = 6, // 4 bytes
TSDB_DATA_TYPE_DOUBLE = 7, // 8 bytes
TSDB_DATA_TYPE_BINARY = 8, // string
TSDB_DATA_TYPE_TIMESTAMP = 9,// 8 bytes
TSDB_DATA_TYPE_NCHAR = 10 // unicode string
}
enum TDengineInitOption
{
TSDB_OPTION_LOCALE = 0,
TSDB_OPTION_CHARSET = 1,
TSDB_OPTION_TIMEZONE = 2,
TDDB_OPTION_CONFIGDIR = 3,
TDDB_OPTION_SHELL_ACTIVITY_TIMER = 4
}
class TDengineMeta
{
public string name;
public short size;
public byte type;
public string TypeName()
{
switch ((TDengineDataType)type)
{
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
return "BOOLEAN";
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
return "BYTE";
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
return "SHORT";
case TDengineDataType.TSDB_DATA_TYPE_INT:
return "INT";
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
return "LONG";
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
return "FLOAT";
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
return "DOUBLE";
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
return "STRING";
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
return "TIMESTAMP";
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
return "NCHAR";
default:
return "undefine";
}
}
}
class TDengine
{
public const int TSDB_CODE_SUCCESS = 0;
[DllImport("taos", EntryPoint = "taos_init", CallingConvention = CallingConvention.Cdecl)]
static extern public void Init();
[DllImport("taos", EntryPoint = "taos_cleanup", CallingConvention = CallingConvention.Cdecl)]
static extern public void Cleanup();
[DllImport("taos", EntryPoint = "taos_options", CallingConvention = CallingConvention.Cdecl)]
static extern public void Options(int option, string value);
[DllImport("taos", EntryPoint = "taos_connect", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr Connect(string ip, string user, string password, string db, short port);
[DllImport("taos", EntryPoint = "taos_errstr", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr taos_errstr(IntPtr res);
static public string Error(IntPtr res)
{
IntPtr errPtr = taos_errstr(res);
return Marshal.PtrToStringAnsi(errPtr);
}
[DllImport("taos", EntryPoint = "taos_errno", CallingConvention = CallingConvention.Cdecl)]
static extern public int ErrorNo(IntPtr res);
[DllImport("taos", EntryPoint = "taos_query", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr Query(IntPtr conn, string sqlstr);
[DllImport("taos", EntryPoint = "taos_affected_rows", CallingConvention = CallingConvention.Cdecl)]
static extern public int AffectRows(IntPtr res);
[DllImport("taos", EntryPoint = "taos_field_count", CallingConvention = CallingConvention.Cdecl)]
static extern public int FieldCount(IntPtr res);
[DllImport("taos", EntryPoint = "taos_fetch_fields", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr taos_fetch_fields(IntPtr res);
static public List<TDengineMeta> FetchFields(IntPtr res)
{
const int fieldSize = 68;
List<TDengineMeta> metas = new List<TDengineMeta>();
if (res == IntPtr.Zero)
{
return metas;
}
int fieldCount = FieldCount(res);
IntPtr fieldsPtr = taos_fetch_fields(res);
for (int i = 0; i < fieldCount; ++i)
{
int offset = i * fieldSize;
TDengineMeta meta = new TDengineMeta();
meta.name = Marshal.PtrToStringAnsi(fieldsPtr + offset);
meta.type = Marshal.ReadByte(fieldsPtr + offset + 65);
meta.size = Marshal.ReadInt16(fieldsPtr + offset + 66);
metas.Add(meta);
}
return metas;
}
[DllImport("taos", EntryPoint = "taos_fetch_row", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr FetchRows(IntPtr res);
[DllImport("taos", EntryPoint = "taos_free_result", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr FreeResult(IntPtr res);
[DllImport("taos", EntryPoint = "taos_close", CallingConvention = CallingConvention.Cdecl)]
static extern public int Close(IntPtr taos);
}
}

View File

@ -26,10 +26,10 @@ namespace TDengineDriver
class TDengineTest class TDengineTest
{ {
//connect parameters //connect parameters
private string host; private string host = "127.0.0.1";
private string configDir; private string configDir = "C:/TDengine/cfg";
private string user; private string user = "root";
private string password; private string password = "taosdata";
private short port = 0; private short port = 0;
//sql parameters //sql parameters
@ -40,11 +40,12 @@ namespace TDengineDriver
private bool isInsertOnly = false; private bool isInsertOnly = false;
private int queryMode = 1; private int queryMode = 1;
private long recordsPerTable = 10000; private long recordsPerTable = 1;
private int recordsPerRequest = 1; private int recordsPerRequest = 1;
private int colsPerRecord = 3; private int colsPerRecord = 3;
private long batchRows = 1000; private long batchRows = 1000;
private long numOfTables = 10000; private long numOfTables = 1;
private short replica = 1;
private IntPtr conn = IntPtr.Zero; private IntPtr conn = IntPtr.Zero;
// private long rowsInserted = 0; // private long rowsInserted = 0;
@ -66,6 +67,8 @@ namespace TDengineDriver
Console.WriteLine("Usage: mono taosdemo.exe [OPTION...]"); Console.WriteLine("Usage: mono taosdemo.exe [OPTION...]");
Console.WriteLine(""); Console.WriteLine("");
string indent = " "; string indent = " ";
Console.WriteLine("{0}{1}", indent, "--help Show usage.");
Console.WriteLine("");
Console.Write("{0}{1}", indent, "-h"); Console.Write("{0}{1}", indent, "-h");
Console.Write("{0}{1}{2}\n", indent, indent, "host, The host to connect to TDengine. Default is localhost."); Console.Write("{0}{1}{2}\n", indent, indent, "host, The host to connect to TDengine. Default is localhost.");
Console.Write("{0}{1}", indent, "-p"); Console.Write("{0}{1}", indent, "-p");
@ -77,7 +80,7 @@ namespace TDengineDriver
Console.Write("{0}{1}", indent, "-d"); Console.Write("{0}{1}", indent, "-d");
Console.Write("{0}{1}{2}\n", indent, indent, "database, Destination database. Default is 'test'."); Console.Write("{0}{1}{2}\n", indent, indent, "database, Destination database. Default is 'test'.");
Console.Write("{0}{1}", indent, "-a"); Console.Write("{0}{1}", indent, "-a");
Console.Write("{0}{1}{2}\n", indent, indent, "replica, Set the replica parameters of the database, Default 1, min: 1, max: 3."); Console.Write("{0}{1}{2}\n", indent, indent, "replica, Set the replica parameters of the database, Default 1, min: 1, max: 5.");
Console.Write("{0}{1}", indent, "-m"); Console.Write("{0}{1}", indent, "-m");
Console.Write("{0}{1}{2}\n", indent, indent, "table_prefix, Table prefix name. Default is 't'."); Console.Write("{0}{1}{2}\n", indent, indent, "table_prefix, Table prefix name. Default is 't'.");
Console.Write("{0}{1}", indent, "-s"); Console.Write("{0}{1}", indent, "-s");
@ -99,9 +102,9 @@ namespace TDengineDriver
Console.Write("{0}{1}", indent, "-r"); Console.Write("{0}{1}", indent, "-r");
Console.Write("{0}{1}{2}\n", indent, indent, "num_of_records_per_req, The number of records per request. Default is 1000."); Console.Write("{0}{1}{2}\n", indent, indent, "num_of_records_per_req, The number of records per request. Default is 1000.");
Console.Write("{0}{1}", indent, "-t"); Console.Write("{0}{1}", indent, "-t");
Console.Write("{0}{1}{2}\n", indent, indent, "num_of_tables, The number of tables. Default is 10000."); Console.Write("{0}{1}{2}\n", indent, indent, "num_of_tables, The number of tables. Default is 1.");
Console.Write("{0}{1}", indent, "-n"); Console.Write("{0}{1}", indent, "-n");
Console.Write("{0}{1}{2}\n", indent, indent, "num_of_records_per_table, The number of records per table. Default is 10000."); Console.Write("{0}{1}{2}\n", indent, indent, "num_of_records_per_table, The number of records per table. Default is 1.");
Console.Write("{0}{1}", indent, "-c"); Console.Write("{0}{1}", indent, "-c");
Console.Write("{0}{1}{2}\n", indent, indent, "config_directory, Configuration directory. Default is '/etc/taos/'."); Console.Write("{0}{1}{2}\n", indent, indent, "config_directory, Configuration directory. Default is '/etc/taos/'.");
Console.Write("{0}{1}", indent, "-x"); Console.Write("{0}{1}", indent, "-x");
@ -133,14 +136,15 @@ namespace TDengineDriver
tablePrefix = this.GetArgumentAsString(argv, "-m", "t"); tablePrefix = this.GetArgumentAsString(argv, "-m", "t");
isInsertOnly = this.GetArgumentAsFlag(argv, "-x"); isInsertOnly = this.GetArgumentAsFlag(argv, "-x");
queryMode = (int)this.GetArgumentAsLong(argv, "-q", 0, 1, 0); queryMode = (int)this.GetArgumentAsLong(argv, "-q", 0, 1, 0);
numOfTables = this.GetArgumentAsLong(argv, "-t", 1, 1000000000, 10000); numOfTables = this.GetArgumentAsLong(argv, "-t", 1, 1000000000, 1);
batchRows = this.GetArgumentAsLong(argv, "-r", 1, 10000, 1000); batchRows = this.GetArgumentAsLong(argv, "-r", 1, 10000, 1000);
recordsPerTable = this.GetArgumentAsLong(argv, "-n", 1, 100000000000, 10000); recordsPerTable = this.GetArgumentAsLong(argv, "-n", 1, 100000000000, 1);
recordsPerRequest = (int)this.GetArgumentAsLong(argv, "-r", 1, 10000, 1); recordsPerRequest = (int)this.GetArgumentAsLong(argv, "-r", 1, 10000, 1);
colsPerRecord = (int)this.GetArgumentAsLong(argv, "-l", 1, 1024, 3); colsPerRecord = (int)this.GetArgumentAsLong(argv, "-l", 1, 1024, 3);
configDir = this.GetArgumentAsString(argv, "-c", "C:/TDengine/cfg"); configDir = this.GetArgumentAsString(argv, "-c", "C:/TDengine/cfg");
useStable = this.GetArgumentAsFlag(argv, "-M"); useStable = this.GetArgumentAsFlag(argv, "-M");
replica = (short)this.GetArgumentAsLong(argv, "-a", 1, 5, 1);
methodOfDelete = (short)this.GetArgumentAsLong(argv, "-D", 0, 3, 0); methodOfDelete = (short)this.GetArgumentAsLong(argv, "-D", 0, 3, 0);
numOfThreads = (short)this.GetArgumentAsLong(argv, "-T", 1, 10000, 1); numOfThreads = (short)this.GetArgumentAsLong(argv, "-T", 1, 10000, 1);
order = this.GetArgumentAsFlag(argv, "-O"); order = this.GetArgumentAsFlag(argv, "-O");
@ -153,13 +157,14 @@ namespace TDengineDriver
Console.Write("# Server IP: {0}\n", host); Console.Write("# Server IP: {0}\n", host);
Console.Write("# User: {0}\n", user); Console.Write("# User: {0}\n", user);
Console.Write("# Password: {0}\n", password); Console.Write("# Password: {0}\n", password);
Console.Write("# Use super table: {0}\n", useStable);
Console.Write("# Number of Columns per record: {0}\n", colsPerRecord); Console.Write("# Number of Columns per record: {0}\n", colsPerRecord);
Console.Write("# Number of Threads: {0}\n", numOfThreads); Console.Write("# Number of Threads: {0}\n", numOfThreads);
Console.Write("# Number of Tables: {0}\n", numOfTables); Console.Write("# Number of Tables: {0}\n", numOfTables);
Console.Write("# Number of Data per Table: {0}\n", recordsPerTable); Console.Write("# Number of Data per Table: {0}\n", recordsPerTable);
Console.Write("# Records/Request: {0}\n", recordsPerRequest); Console.Write("# Records/Request: {0}\n", recordsPerRequest);
Console.Write("# Database name: {0}\n", dbName); Console.Write("# Database name: {0}\n", dbName);
Console.Write("# Replica: {0}\n", replica);
Console.Write("# Use STable: {0}\n", useStable);
Console.Write("# Table prefix: {0}\n", tablePrefix); Console.Write("# Table prefix: {0}\n", tablePrefix);
Console.Write("# Data order: {0}\n", order); Console.Write("# Data order: {0}\n", order);
Console.Write("# Data out of order rate: {0}\n", rateOfOutorder); Console.Write("# Data out of order rate: {0}\n", rateOfOutorder);
@ -280,7 +285,7 @@ namespace TDengineDriver
public void ConnectTDengine() public void ConnectTDengine()
{ {
string db = ""; string db = "";
DebugPrintFormat("host:{0} user:{1}, pass:{2}; db:{3}, port:{4}", DebugPrintFormat("host:{0} user:{1}, pass:{2}; db:{3}, port:{4}\n",
this.host, this.user, this.password, db, this.port); this.host, this.user, this.password, db, this.port);
this.conn = TDengine.Connect(this.host, this.user, this.password, db, this.port); this.conn = TDengine.Connect(this.host, this.user, this.password, db, this.port);
if (this.conn == IntPtr.Zero) if (this.conn == IntPtr.Zero)
@ -320,6 +325,7 @@ namespace TDengineDriver
createTableThread.verbose = verbose; createTableThread.verbose = verbose;
createTableThread.dbName = this.dbName; createTableThread.dbName = this.dbName;
createTableThread.tablePrefix = this.tablePrefix; createTableThread.tablePrefix = this.tablePrefix;
createTableThread.useStable = useStable;
if (useStable) if (useStable)
{ {
createTableThread.stableName = stableName; createTableThread.stableName = stableName;
@ -363,7 +369,7 @@ namespace TDengineDriver
public void CreateDb() public void CreateDb()
{ {
StringBuilder sql = new StringBuilder(); StringBuilder sql = new StringBuilder();
sql.Append("CREATE DATABASE IF NOT EXISTS ").Append(this.dbName); sql.Append("CREATE DATABASE IF NOT EXISTS ").Append(this.dbName).Append(" replica ").Append(this.replica);
IntPtr res = TDengine.Query(this.conn, sql.ToString()); IntPtr res = TDengine.Query(this.conn, sql.ToString());
if (res != IntPtr.Zero) if (res != IntPtr.Zero)
{ {
@ -429,7 +435,7 @@ namespace TDengineDriver
insertThread.tablePrefix = this.tablePrefix; insertThread.tablePrefix = this.tablePrefix;
if (useStable) if (useStable)
{ {
insertThread.stableName = stableName; // insertThread.stableName = stableName;
} }
insertThread.conn = conn; insertThread.conn = conn;
@ -584,15 +590,20 @@ namespace TDengineDriver
tester.InitTDengine(); tester.InitTDengine();
tester.ConnectTDengine(); tester.ConnectTDengine();
tester.dropDatabase();
tester.CreateDb();
if (tester.useStable == true) if (tester.isInsertOnly == false)
{ {
tester.CreateStable(); tester.dropDatabase();
} tester.CreateDb();
tester.CreateTablesByThreads();
if (tester.useStable == true)
{
tester.CreateStable();
}
tester.CreateTablesByThreads();
}
Stopwatch watch = Stopwatch.StartNew(); Stopwatch watch = Stopwatch.StartNew();
tester.InsertByThreads(); tester.InsertByThreads();
@ -619,7 +630,7 @@ namespace TDengineDriver
public string dbName { set; get; } public string dbName { set; get; }
public IntPtr conn { set; get; } public IntPtr conn { set; get; }
public string tablePrefix { set; get; } public string tablePrefix { set; get; }
public string stableName { set; get; } // public string stableName { set; get; }
public long recordsPerTable { set; get; } public long recordsPerTable { set; get; }
public long batchRows { set; get; } public long batchRows { set; get; }
public long numOfTables { set; get; } public long numOfTables { set; get; }
@ -643,9 +654,18 @@ namespace TDengineDriver
public void ThreadMain() public void ThreadMain()
{ {
DebugPrintFormat("InsertDataThread {0} from {1} to {2}", id, start, end); DebugPrintFormat("InsertDataThread {0} from {1} to {2}\n", id, start, end);
StringBuilder sql = new StringBuilder(); StringBuilder sql = new StringBuilder();
long beginTimestamp = 1551369600000L;
DateTime now = DateTime.Now;
int h = now.Hour;
int m = now.Minute;
int s = now.Second;
long baseTimestamp = 1609430400000; // 2021/01/01 0:0:0
DebugPrintFormat("beginTime is {0} + {1}h:{2}m:{3}s\n", baseTimestamp, h, m, s);
long beginTimestamp = baseTimestamp + ((h*60 + m) * 60 + s) * 1000;
long rowsInserted = 0; long rowsInserted = 0;
// System.DateTime startTime = new System.DateTime(); // System.DateTime startTime = new System.DateTime();
@ -660,7 +680,11 @@ namespace TDengineDriver
sql.Append("INSERT INTO "). sql.Append("INSERT INTO ").
Append(this.dbName).Append(".").Append(this.tablePrefix).Append(table). Append(this.dbName).Append(".").Append(this.tablePrefix).Append(table).
Append(" VALUES"); Append(" VALUES");
for (int batch = 0; batch < this.batchRows; ++batch) if (recordsPerTable < batchRows)
{
batchRows = recordsPerTable;
}
for (int batch = 0; batch < batchRows; ++batch)
{ {
sql.Append("(") sql.Append("(")
.Append(beginTimestamp + i + batch) .Append(beginTimestamp + i + batch)
@ -701,6 +725,7 @@ namespace TDengineDriver
public string tablePrefix { set; get; } public string tablePrefix { set; get; }
public string stableName { set; get; } public string stableName { set; get; }
public bool verbose { set; get; } public bool verbose { set; get; }
public bool useStable { set; get; }
private void DebugPrintFormat(string format, params object[] parameters) private void DebugPrintFormat(string format, params object[] parameters)
{ {
@ -720,7 +745,7 @@ namespace TDengineDriver
public void ThreadMain() public void ThreadMain()
{ {
DebugPrintFormat("CreateTable {0} from {1} to {2}", id, start, end); DebugPrintFormat("CreateTable {0} from {1} to {2}\n", id, start, end);
StringBuilder sql = new StringBuilder(); StringBuilder sql = new StringBuilder();
@ -728,9 +753,16 @@ namespace TDengineDriver
{ {
sql.Clear(); sql.Clear();
sql = sql.Append("CREATE TABLE IF NOT EXISTS "). sql = sql.Append("CREATE TABLE IF NOT EXISTS ").
Append(this.dbName).Append(".").Append(this.tablePrefix).Append(tableId). Append(this.dbName).Append(".").Append(this.tablePrefix).Append(tableId);
Append(" USING ").Append(this.dbName).Append(".").Append(this.stableName). if (useStable == true)
Append(" TAGS(").Append(tableId).Append(")"); {
sql = sql.Append(" USING ").Append(this.dbName).Append(".").Append(this.stableName).
Append(" TAGS(").Append(tableId).Append(")");
}
else
{
sql = sql.Append("(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 float, v7 double, v8 binary(10), v9 nchar(10))");
}
IntPtr res = TDengine.Query(this.conn, sql.ToString()); IntPtr res = TDengine.Query(this.conn, sql.ToString());
if (res != IntPtr.Zero) if (res != IntPtr.Zero)
{ {

View File

@ -5,17 +5,12 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.taosdata.jdbc</groupId> <groupId>com.taosdata.jdbc</groupId>
<artifactId>jdbcChecker</artifactId> <artifactId>JDBCDemo</artifactId>
<version>SNAPSHOT</version> <version>SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
@ -23,7 +18,7 @@
<configuration> <configuration>
<archive> <archive>
<manifest> <manifest>
<mainClass>com.taosdata.example.JdbcChecker</mainClass> <mainClass>com.taosdata.example.JDBCDemo</mainClass>
</manifest> </manifest>
</archive> </archive>
<descriptorRefs> <descriptorRefs>
@ -49,6 +44,7 @@
<target>8</target> <target>8</target>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
@ -56,18 +52,8 @@
<dependency> <dependency>
<groupId>com.taosdata.jdbc</groupId> <groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId> <artifactId>taos-jdbcdriver</artifactId>
<version>2.0.12</version> <version>2.0.15</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1,29 +1,37 @@
# How to Run the JDBC Demo Code On A Linux OS # How to Run the JDBC Demo Code On Linux OS
TDengine's JDBC demo project is organized in a Maven way so that users can easily compile, package and run the project. If you don't have Maven on your server, you may install it using TDengine's JDBC demo project is organized in a Maven way so that users can easily compile, package and run the project. If you don't have Maven on your server, you may install it using
<pre>sudo apt-get install maven</pre> ```
sudo apt-get install maven
```
## Install TDengine Client ## Install TDengine Client
Make sure you have already installed a tdengine client on your current develop environment. Make sure you have already installed a tdengine client on your current develop environment.
Download the tdengine package on our website: ``https://www.taosdata.com/cn/all-downloads/`` and install the client. Download the tdengine package on our website: ``https://www.taosdata.com/cn/all-downloads/`` and install the client.
## How to run jdbcChecker ## Run jdbcDemo using mvn plugin
<pre>mvn clean compile exec:java -Dexec.mainClass="com.taosdata.example.JdbcChecker" -Dexec.args="-host localhost"</pre>
## How to run jdbcTaosDemo
run command: run command:
<pre> mvn clean compile exec:java -Dexec.mainClass="com.taosdata.example.jdbcTaosdemo.JdbcTaosdemo"</pre> ```
mvn clean compile exec:java -Dexec.mainClass="com.taosdata.example.JdbcDemo"
```
and run with your customed args and run with your customed args
<pre>mvn clean compile exec:java -Dexec.mainClass="com.taosdata.example.jdbcTaosdemo.JdbcTaosdemo" -Dexec.args="-host localhost"</pre> ```
mvn clean compile exec:java -Dexec.mainClass="com.taosdata.example.JdbcDemo" -Dexec.args="-host [HOSTNAME]"
```
## Compile the Demo Code and Run It ## Compile the Demo Code and Run It
To compile taos-jdbcdriver, go to the source directory ``TDengine/src/connector/jdbc`` and execute
```
mvn clean package -Dmaven.test.skip=true
```
To compile the demo project, go to the source directory ``TDengine/tests/examples/JDBC/JDBCDemo`` and execute To compile the demo project, go to the source directory ``TDengine/tests/examples/JDBC/JDBCDemo`` and execute
```
<pre>
mvn clean package assembly:single mvn clean package assembly:single
</pre> ```
The ``pom.xml`` is configured to package all the dependencies into one executable jar file. To run JDBCDemo.jar, go to ``TDengine/tests/examples/JDBC/JDBCDemo`` and execute
```
java -Djava.ext.dirs=../../../../src/connector/jdbc/target:$JAVA_HOME/jre/lib/ext -jar target/JDBCDemo-SNAPSHOT-jar-with-dependencies.jar -host [HOSTNAME]
```
To run it, go to ``examples/JDBC/JDBCDemo/target`` and execute
<pre>java -jar jdbcChecker-SNAPSHOT-jar-with-dependencies.jar -host localhost</pre>

View File

@ -1,56 +1,77 @@
package com.taosdata.example; package com.taosdata.example;
import com.taosdata.jdbc.TSDBDriver;
import java.sql.*; import java.sql.*;
import java.util.Properties; import java.util.Properties;
public class JdbcChecker { public class JDBCDemo {
private static String host; private static String host;
private static String dbName = "test"; private static String driverType = "jni";
private static String tbName = "weather"; private static final String dbName = "test";
private static final String tbName = "weather";
private Connection connection; private Connection connection;
/** public static void main(String[] args) {
* get connection for (int i = 0; i < args.length; i++) {
**/ if ("-host".equalsIgnoreCase(args[i]) && i < args.length - 1)
host = args[++i];
if ("-driverType".equalsIgnoreCase(args[i]) && i < args.length - 1) {
driverType = args[++i];
if (!"jni".equalsIgnoreCase(driverType) && !"restful".equalsIgnoreCase(driverType))
printHelp();
}
}
if (host == null) {
printHelp();
}
JDBCDemo demo = new JDBCDemo();
demo.init();
demo.createDatabase();
demo.useDatabase();
demo.dropTable();
demo.createTable();
demo.insert();
demo.select();
demo.dropTable();
demo.close();
}
private void init() { private void init() {
// get connection
try { try {
Class.forName("com.taosdata.jdbc.TSDBDriver"); String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata";
if (driverType.equals("restful")) {
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata";
} else {
Class.forName("com.taosdata.jdbc.TSDBDriver");
}
Properties properties = new Properties(); Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host); properties.setProperty("host", host);
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); properties.setProperty("charset", "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); properties.setProperty("locale", "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); properties.setProperty("timezone", "UTC-8");
System.out.println("get connection starting..."); System.out.println("get connection starting...");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties); connection = DriverManager.getConnection(url, properties);
if (connection != null) if (connection != null)
System.out.println("[ OK ] Connection established."); System.out.println("[ OK ] Connection established.");
} catch (ClassNotFoundException | SQLException e) { } catch (ClassNotFoundException | SQLException e) {
throw new RuntimeException("connection failed: " + host); e.printStackTrace();
} }
} }
/**
* create database
*/
private void createDatabase() { private void createDatabase() {
String sql = "create database if not exists " + dbName; String sql = "create database if not exists " + dbName;
exuete(sql); exuete(sql);
} }
/**
* use database
*/
private void useDatabase() { private void useDatabase() {
String sql = "use " + dbName; String sql = "use " + dbName;
exuete(sql); exuete(sql);
} }
/** private void select() {
* select
*/
private void checkSelect() {
final String sql = "select * from test.weather"; final String sql = "select * from test.weather";
executeQuery(sql); executeQuery(sql);
} }
@ -79,40 +100,21 @@ public class JdbcChecker {
} }
} }
private String formatString(String str) { private void insert() {
StringBuilder sb = new StringBuilder();
int blankCnt = (26 - str.length()) / 2;
for (int j = 0; j < blankCnt; j++)
sb.append(" ");
sb.append(str);
for (int j = 0; j < blankCnt; j++)
sb.append(" ");
sb.append("|");
return sb.toString();
}
/**
* insert
*/
private void checkInsert() {
final String sql = "insert into test.weather (ts, temperature, humidity) values(now, 20.5, 34)"; final String sql = "insert into test.weather (ts, temperature, humidity) values(now, 20.5, 34)";
exuete(sql); exuete(sql);
} }
/**
* create table
*/
private void createTable() { private void createTable() {
final String sql = "create table if not exists " + dbName + "." + tbName + " (ts timestamp, temperature float, humidity int)"; final String sql = "create table if not exists " + dbName + "." + tbName + " (ts timestamp, temperature float, humidity int)";
exuete(sql); exuete(sql);
} }
private final void printSql(String sql, boolean succeed, long cost) { private void printSql(String sql, boolean succeed, long cost) {
System.out.println("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql); System.out.println("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql);
} }
private final void exuete(String sql) { private void exuete(String sql) {
try (Statement statement = connection.createStatement()) { try (Statement statement = connection.createStatement()) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
boolean execute = statement.execute(sql); boolean execute = statement.execute(sql);
@ -120,7 +122,7 @@ public class JdbcChecker {
printSql(sql, execute, (end - start)); printSql(sql, execute, (end - start));
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -135,39 +137,15 @@ public class JdbcChecker {
} }
} }
private void checkDropTable() { private void dropTable() {
final String sql = "drop table if exists " + dbName + "." + tbName + ""; final String sql = "drop table if exists " + dbName + "." + tbName + "";
exuete(sql); exuete(sql);
} }
public static void main(String[] args) { private static void printHelp() {
for (int i = 0; i < args.length; i++) { System.out.println("Usage: java -jar JdbcDemo.jar -host <hostname> -driverType <jni|restful>");
if ("-host".equalsIgnoreCase(args[i]) && i < args.length - 1) { System.exit(0);
host = args[++i];
}
if ("-db".equalsIgnoreCase(args[i]) && i < args.length - 1) {
dbName = args[++i];
}
if ("-t".equalsIgnoreCase(args[i]) && i < args.length - 1) {
tbName = args[++i];
}
}
if (host == null) {
System.out.println("Usage: java -jar JDBCConnectorChecker.jar -host <hostname>");
return;
}
JdbcChecker checker = new JdbcChecker();
checker.init();
checker.createDatabase();
checker.useDatabase();
checker.checkDropTable();
checker.createTable();
checker.checkInsert();
checker.checkSelect();
checker.checkDropTable();
checker.close();
} }
} }

View File

@ -1,357 +0,0 @@
package com.taosdata.example.jdbcTaosdemo;
import com.taosdata.example.jdbcTaosdemo.domain.JdbcTaosdemoConfig;
import com.taosdata.example.jdbcTaosdemo.task.CreateTableTask;
import com.taosdata.example.jdbcTaosdemo.task.InsertTableDatetimeTask;
import com.taosdata.example.jdbcTaosdemo.task.InsertTableTask;
import com.taosdata.example.jdbcTaosdemo.utils.ConnectionFactory;
import com.taosdata.example.jdbcTaosdemo.utils.SqlSpeller;
import com.taosdata.example.jdbcTaosdemo.utils.TimeStampUtil;
import org.apache.log4j.Logger;
import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class JdbcTaosdemo {
private static Logger logger = Logger.getLogger(JdbcTaosdemo.class);
private final JdbcTaosdemoConfig config;
private Connection connection;
public JdbcTaosdemo(JdbcTaosdemoConfig config) {
this.config = config;
}
public static void main(String[] args) {
// parse config from args
JdbcTaosdemoConfig config = new JdbcTaosdemoConfig(args);
boolean isHelp = Arrays.asList(args).contains("--help");
if (isHelp) {
JdbcTaosdemoConfig.printHelp();
return;
}
if (config.getHost() == null) {
JdbcTaosdemoConfig.printHelp();
return;
}
JdbcTaosdemo taosdemo = new JdbcTaosdemo(config);
// establish connection
taosdemo.init();
// drop database
taosdemo.dropDatabase();
// create database
taosdemo.createDatabase();
// use db
taosdemo.useDatabase();
// create super table
taosdemo.createSuperTable();
// create sub tables
taosdemo.createTableMultiThreads();
boolean infinite = Arrays.asList(args).contains("--infinite");
if (infinite) {
logger.info("!!! Infinite Insert Mode Started. !!!");
taosdemo.insertInfinite();
} else {
// insert into table
taosdemo.insertMultiThreads();
// select from sub table
taosdemo.selectFromTableLimit();
taosdemo.selectCountFromTable();
taosdemo.selectAvgMinMaxFromTable();
// select last from
taosdemo.selectLastFromTable();
// select from super table
taosdemo.selectFromSuperTableLimit();
taosdemo.selectCountFromSuperTable();
taosdemo.selectAvgMinMaxFromSuperTable();
//select avg ,max from stb where tag
taosdemo.selectAvgMinMaxFromSuperTableWhereTag();
//select last from stb where location = ''
taosdemo.selectLastFromSuperTableWhere();
// select group by
taosdemo.selectGroupBy();
// select like
taosdemo.selectLike();
// select where ts >= ts<=
taosdemo.selectLastOneHour();
taosdemo.selectLastOneDay();
taosdemo.selectLastOneWeek();
taosdemo.selectLastOneMonth();
taosdemo.selectLastOneYear();
// drop super table
if (config.isDeleteTable())
taosdemo.dropSuperTable();
taosdemo.close();
}
}
/**
* establish the connection
*/
private void init() {
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
connection = ConnectionFactory.build(config);
if (connection != null)
logger.info("[ OK ] Connection established.");
} catch (ClassNotFoundException | SQLException e) {
logger.error(e.getMessage());
throw new RuntimeException("connection failed: " + config.getHost());
}
}
/**
* create database
*/
private void createDatabase() {
String sql = SqlSpeller.createDatabaseSQL(config.getDbName(), config.getKeep(), config.getDays());
execute(sql);
}
/**
* drop database
*/
private void dropDatabase() {
String sql = SqlSpeller.dropDatabaseSQL(config.getDbName());
execute(sql);
}
/**
* use database
*/
private void useDatabase() {
String sql = SqlSpeller.useDatabaseSQL(config.getDbName());
execute(sql);
}
/**
* create super table
*/
private void createSuperTable() {
String sql = SqlSpeller.createSuperTableSQL(config.getStbName());
execute(sql);
}
/**
* create table use super table with multi threads
*/
private void createTableMultiThreads() {
try {
final int tableSize = config.getNumberOfTable() / config.getNumberOfThreads();
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < config.getNumberOfThreads(); i++) {
Thread thread = new Thread(new CreateTableTask(config, i * tableSize, tableSize), "Thread-" + i);
threads.add(thread);
thread.start();
}
for (Thread thread : threads) {
thread.join();
}
logger.info("<<< Multi Threads create table finished.");
} catch (InterruptedException e) {
logger.error(e.getMessage());
e.printStackTrace();
}
}
/**
* insert data infinitely
*/
private void insertInfinite() {
try {
final long startDatetime = TimeStampUtil.datetimeToLong("2005-01-01 00:00:00.000");
final long finishDatetime = TimeStampUtil.datetimeToLong("2030-01-01 00:00:00.000");
final int tableSize = config.getNumberOfTable() / config.getNumberOfThreads();
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < config.getNumberOfThreads(); i++) {
Thread thread = new Thread(new InsertTableDatetimeTask(config, i * tableSize, tableSize, startDatetime, finishDatetime), "Thread-" + i);
threads.add(thread);
thread.start();
}
for (Thread thread : threads) {
thread.join();
}
logger.info("<<< Multi Threads insert table finished.");
} catch (InterruptedException e) {
logger.error(e.getMessage());
e.printStackTrace();
}
}
private void insertMultiThreads() {
try {
final int tableSize = config.getNumberOfTable() / config.getNumberOfThreads();
final int numberOfRecordsPerTable = config.getNumberOfRecordsPerTable();
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < config.getNumberOfThreads(); i++) {
Thread thread = new Thread(new InsertTableTask(config, i * tableSize, tableSize, numberOfRecordsPerTable), "Thread-" + i);
threads.add(thread);
thread.start();
}
for (Thread thread : threads) {
thread.join();
}
logger.info("<<< Multi Threads insert table finished.");
} catch (InterruptedException e) {
logger.error(e.getMessage());
e.printStackTrace();
}
}
private void selectFromTableLimit() {
String sql = SqlSpeller.selectFromTableLimitSQL(config.getDbName(), config.getTbPrefix(), 1, 10, 0);
executeQuery(sql);
}
private void selectCountFromTable() {
String sql = SqlSpeller.selectCountFromTableSQL(config.getDbName(), config.getTbPrefix(), 1);
executeQuery(sql);
}
private void selectAvgMinMaxFromTable() {
String sql = SqlSpeller.selectAvgMinMaxFromTableSQL("current", config.getDbName(), config.getTbPrefix(), 1);
executeQuery(sql);
}
private void selectLastFromTable() {
String sql = SqlSpeller.selectLastFromTableSQL(config.getDbName(), config.getTbPrefix(), 1);
executeQuery(sql);
}
private void selectFromSuperTableLimit() {
String sql = SqlSpeller.selectFromSuperTableLimitSQL(config.getDbName(), config.getStbName(), 10, 0);
executeQuery(sql);
}
private void selectCountFromSuperTable() {
String sql = SqlSpeller.selectCountFromSuperTableSQL(config.getDbName(), config.getStbName());
executeQuery(sql);
}
private void selectAvgMinMaxFromSuperTable() {
String sql = SqlSpeller.selectAvgMinMaxFromSuperTableSQL("current", config.getDbName(), config.getStbName());
executeQuery(sql);
}
private void selectAvgMinMaxFromSuperTableWhereTag() {
String sql = SqlSpeller.selectAvgMinMaxFromSuperTableWhere("current", config.getDbName(), config.getStbName());
executeQuery(sql);
}
private void selectLastFromSuperTableWhere() {
String sql = SqlSpeller.selectLastFromSuperTableWhere("current", config.getDbName(), config.getStbName());
executeQuery(sql);
}
private void selectGroupBy() {
String sql = SqlSpeller.selectGroupBy("current", config.getDbName(), config.getStbName());
executeQuery(sql);
}
private void selectLike() {
String sql = SqlSpeller.selectLike(config.getDbName(), config.getStbName());
executeQuery(sql);
}
private void selectLastOneHour() {
String sql = SqlSpeller.selectLastOneHour(config.getDbName(), config.getStbName());
executeQuery(sql);
}
private void selectLastOneDay() {
String sql = SqlSpeller.selectLastOneDay(config.getDbName(), config.getStbName());
executeQuery(sql);
}
private void selectLastOneWeek() {
String sql = SqlSpeller.selectLastOneWeek(config.getDbName(), config.getStbName());
executeQuery(sql);
}
private void selectLastOneMonth() {
String sql = SqlSpeller.selectLastOneMonth(config.getDbName(), config.getStbName());
executeQuery(sql);
}
private void selectLastOneYear() {
String sql = SqlSpeller.selectLastOneYear(config.getDbName(), config.getStbName());
executeQuery(sql);
}
private void close() {
try {
if (connection != null) {
this.connection.close();
logger.info("connection closed.");
}
} catch (SQLException e) {
logger.error(e.getMessage());
e.printStackTrace();
}
}
/**
* drop super table
*/
private void dropSuperTable() {
String sql = SqlSpeller.dropSuperTableSQL(config.getDbName(), config.getStbName());
execute(sql);
}
/**
* execute sql, use this method when sql is create, alter, drop..
*/
private void execute(String sql) {
try (Statement statement = connection.createStatement()) {
long start = System.currentTimeMillis();
boolean execute = statement.execute(sql);
long end = System.currentTimeMillis();
printSql(sql, execute, (end - start));
} catch (SQLException e) {
logger.error("ERROR execute SQL ===> " + sql);
logger.error(e.getMessage());
e.printStackTrace();
}
}
private static void printSql(String sql, boolean succeed, long cost) {
System.out.println("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql);
}
private void executeQuery(String sql) {
try (Statement statement = connection.createStatement()) {
long start = System.currentTimeMillis();
ResultSet resultSet = statement.executeQuery(sql);
long end = System.currentTimeMillis();
printSql(sql, true, (end - start));
printResult(resultSet);
} catch (SQLException e) {
logger.error("ERROR execute SQL ===> " + sql);
logger.error(e.getMessage());
e.printStackTrace();
}
}
private static void printResult(ResultSet resultSet) throws SQLException {
ResultSetMetaData metaData = resultSet.getMetaData();
while (resultSet.next()) {
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= metaData.getColumnCount(); i++) {
String columnLabel = metaData.getColumnLabel(i);
String value = resultSet.getString(i);
sb.append(columnLabel + ": " + value + "\t");
}
System.out.println(sb.toString());
}
}
}

View File

@ -1,153 +0,0 @@
package com.taosdata.example.jdbcTaosdemo.domain;
public final class JdbcTaosdemoConfig {
//The host to connect to TDengine. Must insert one
private String host;
//The TCP/IP port number to use for the connection. Default is 6030.
private int port = 6030;
//The TDengine user name to use when connecting to the server. Default is 'root'
private String user = "root";
//The password to use when connecting to the server. Default is 'taosdata'
private String password = "taosdata";
//Destination database. Default is 'test'
private String dbName = "test";
//keep
private int keep = 36500;
//days
private int days = 120;
//Super table Name. Default is 'meters'
private String stbName = "meters";
//Table name prefix. Default is 'd'
private String tbPrefix = "d";
//The number of tables. Default is 10.
private int numberOfTable = 10;
//The number of records per table. Default is 2
private int numberOfRecordsPerTable = 2;
//The number of records per request. Default is 100
private int numberOfRecordsPerRequest = 100;
//The number of threads. Default is 1.
private int numberOfThreads = 1;
//Delete data. Default is false
private boolean deleteTable = false;
public static void printHelp() {
System.out.println("Usage: java -jar JdbcTaosDemo.jar [OPTION...]");
System.out.println("-h host The host to connect to TDengine. you must input one");
System.out.println("-p port The TCP/IP port number to use for the connection. Default is 6030");
System.out.println("-u user The TDengine user name to use when connecting to the server. Default is 'root'");
System.out.println("-P password The password to use when connecting to the server.Default is 'taosdata'");
System.out.println("-d database Destination database. Default is 'test'");
System.out.println("-m tablePrefix Table prefix name. Default is 'd'");
System.out.println("-t num_of_tables The number of tables. Default is 10");
System.out.println("-n num_of_records_per_table The number of records per table. Default is 2");
System.out.println("-r num_of_records_per_req The number of records per request. Default is 100");
System.out.println("-T num_of_threads The number of threads. Default is 1");
System.out.println("-D delete table Delete data methods. Default is false");
System.out.println("--help Give this help list");
// System.out.println("--infinite infinite insert mode");
}
/**
* parse args from command line
*
* @param args command line args
* @return JdbcTaosdemoConfig
*/
public JdbcTaosdemoConfig(String[] args) {
for (int i = 0; i < args.length; i++) {
if ("-h".equals(args[i]) && i < args.length - 1) {
host = args[++i];
}
if ("-p".equals(args[i]) && i < args.length - 1) {
port = Integer.parseInt(args[++i]);
}
if ("-u".equals(args[i]) && i < args.length - 1) {
user = args[++i];
}
if ("-P".equals(args[i]) && i < args.length - 1) {
password = args[++i];
}
if ("-d".equals(args[i]) && i < args.length - 1) {
dbName = args[++i];
}
if ("-m".equals(args[i]) && i < args.length - 1) {
tbPrefix = args[++i];
}
if ("-t".equals(args[i]) && i < args.length - 1) {
numberOfTable = Integer.parseInt(args[++i]);
}
if ("-n".equals(args[i]) && i < args.length - 1) {
numberOfRecordsPerTable = Integer.parseInt(args[++i]);
}
if ("-r".equals(args[i]) && i < args.length - 1) {
numberOfRecordsPerRequest = Integer.parseInt(args[++i]);
}
if ("-T".equals(args[i]) && i < args.length - 1) {
numberOfThreads = Integer.parseInt(args[++i]);
}
if ("-D".equals(args[i]) && i < args.length - 1) {
deleteTable = Boolean.parseBoolean(args[++i]);
}
}
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public String getUser() {
return user;
}
public String getPassword() {
return password;
}
public String getDbName() {
return dbName;
}
public int getKeep() {
return keep;
}
public int getDays() {
return days;
}
public String getStbName() {
return stbName;
}
public String getTbPrefix() {
return tbPrefix;
}
public int getNumberOfTable() {
return numberOfTable;
}
public int getNumberOfRecordsPerTable() {
return numberOfRecordsPerTable;
}
public int getNumberOfThreads() {
return numberOfThreads;
}
public boolean isDeleteTable() {
return deleteTable;
}
public int getNumberOfRecordsPerRequest() {
return numberOfRecordsPerRequest;
}
}

View File

@ -1,42 +0,0 @@
package com.taosdata.example.jdbcTaosdemo.task;
import com.taosdata.example.jdbcTaosdemo.domain.JdbcTaosdemoConfig;
import com.taosdata.example.jdbcTaosdemo.utils.ConnectionFactory;
import com.taosdata.example.jdbcTaosdemo.utils.SqlSpeller;
import org.apache.log4j.Logger;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
public class CreateTableTask implements Runnable {
private static Logger logger = Logger.getLogger(CreateTableTask.class);
private final JdbcTaosdemoConfig config;
private final int startIndex;
private final int tableNumber;
public CreateTableTask(JdbcTaosdemoConfig config, int startIndex, int tableNumber) {
this.config = config;
this.startIndex = startIndex;
this.tableNumber = tableNumber;
}
@Override
public void run() {
try {
Connection connection = ConnectionFactory.build(config);
for (int i = startIndex; i < startIndex + tableNumber; i++) {
Statement statement = connection.createStatement();
String sql = SqlSpeller.createTableSQL(i + 1, config.getDbName(), config.getStbName());
statement.execute(sql);
statement.close();
logger.info(">>> " + sql);
}
connection.close();
} catch (SQLException e) {
logger.error(e.getMessage());
e.printStackTrace();
}
}
}

View File

@ -1,49 +0,0 @@
package com.taosdata.example.jdbcTaosdemo.task;
import com.taosdata.example.jdbcTaosdemo.domain.JdbcTaosdemoConfig;
import com.taosdata.example.jdbcTaosdemo.utils.ConnectionFactory;
import com.taosdata.example.jdbcTaosdemo.utils.SqlSpeller;
import org.apache.log4j.Logger;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
public class InsertTableDatetimeTask implements Runnable {
private static Logger logger = Logger.getLogger(InsertTableDatetimeTask.class);
private final JdbcTaosdemoConfig config;
private final int startTableIndex;
private final int tableNumber;
private final long startDatetime;
private final long finishedDatetime;
public InsertTableDatetimeTask(JdbcTaosdemoConfig config, int startTableIndex, int tableNumber, long startDatetime, long finishedDatetime) {
this.config = config;
this.startTableIndex = startTableIndex;
this.tableNumber = tableNumber;
this.startDatetime = startDatetime;
this.finishedDatetime = finishedDatetime;
}
@Override
public void run() {
try {
Connection connection = ConnectionFactory.build(config);
int valuesCount = config.getNumberOfRecordsPerRequest();
for (long ts = startDatetime; ts < finishedDatetime; ts += valuesCount) {
for (int i = startTableIndex; i < startTableIndex + tableNumber; i++) {
String sql = SqlSpeller.insertBatchSizeRowsSQL(config.getDbName(), config.getTbPrefix(), i + 1, ts, valuesCount);
Statement statement = connection.createStatement();
statement.execute(sql);
statement.close();
logger.info(Thread.currentThread().getName() + ">>> " + sql);
}
}
connection.close();
} catch (SQLException e) {
logger.error(e.getMessage());
e.printStackTrace();
}
}
}

View File

@ -1,57 +0,0 @@
package com.taosdata.example.jdbcTaosdemo.task;
import com.taosdata.example.jdbcTaosdemo.domain.JdbcTaosdemoConfig;
import com.taosdata.example.jdbcTaosdemo.utils.ConnectionFactory;
import com.taosdata.example.jdbcTaosdemo.utils.SqlSpeller;
import org.apache.log4j.Logger;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
public class InsertTableTask implements Runnable {
private static final Logger logger = Logger.getLogger(InsertTableTask.class);
private final JdbcTaosdemoConfig config;
private final int startTbIndex;
private final int tableNumber;
private final int recordsNumberPerTable;
public InsertTableTask(JdbcTaosdemoConfig config, int startTbIndex, int tableNumber, int recordsNumberPerTable) {
this.config = config;
this.startTbIndex = startTbIndex;
this.tableNumber = tableNumber;
this.recordsNumberPerTable = recordsNumberPerTable;
}
@Override
public void run() {
try {
Connection connection = ConnectionFactory.build(config);
int keep = config.getKeep();
Instant end = Instant.now();
Instant start = end.minus(Duration.ofDays(keep - 1));
long timeGap = ChronoUnit.MILLIS.between(start, end) / (recordsNumberPerTable - 1);
// iterate insert
for (int j = 0; j < recordsNumberPerTable; j++) {
long ts = start.toEpochMilli() + (j * timeGap);
// insert data into echo table
for (int i = startTbIndex; i < startTbIndex + tableNumber; i++) {
String sql = SqlSpeller.insertBatchSizeRowsSQL(config.getDbName(), config.getTbPrefix(), i + 1, ts, config.getNumberOfRecordsPerRequest());
logger.info(Thread.currentThread().getName() + ">>> " + sql);
Statement statement = connection.createStatement();
statement.execute(sql);
statement.close();
}
}
connection.close();
} catch (SQLException e) {
logger.error(e.getMessage());
e.printStackTrace();
}
}
}

View File

@ -1,32 +0,0 @@
package com.taosdata.example.jdbcTaosdemo.utils;
import com.taosdata.example.jdbcTaosdemo.domain.JdbcTaosdemoConfig;
import com.taosdata.jdbc.TSDBDriver;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class ConnectionFactory {
public static Connection build(JdbcTaosdemoConfig config) throws SQLException {
return build(config.getHost(), config.getPort(), config.getDbName(), config.getUser(), config.getPassword());
}
public static Connection build(String host, int port, String dbName) throws SQLException {
return build(host, port, dbName, "root", "taosdata");
}
private static Connection build(String host, int port, String dbName, String user, String password) throws SQLException {
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, user);
properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, password);
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");
return DriverManager.getConnection("jdbc:TAOS://" + host + ":" + port + "/" + dbName + "", properties);
}
}

View File

@ -1,126 +0,0 @@
package com.taosdata.example.jdbcTaosdemo.utils;
import java.util.Random;
public class SqlSpeller {
private static final Random random = new Random(System.currentTimeMillis());
private static final String[] locations = {
"Beijing", "Shanghai", "Guangzhou", "Shenzhen",
"HangZhou", "Tianjin", "Wuhan", "Changsha", "Nanjing", "Xian"
};
public static String createDatabaseSQL(String dbName, int keep, int days) {
return "create database if not exists " + dbName + " keep " + keep + " days " + days;
}
public static String dropDatabaseSQL(String dbName) {
return "drop database if exists " + dbName;
}
public static String useDatabaseSQL(String dbName) {
return "use " + dbName;
}
public static String createSuperTableSQL(String superTableName) {
return "create table if not exists " + superTableName + "(ts timestamp, current float, voltage int, phase float) tags(location binary(64), groupId int)";
}
public static String dropSuperTableSQL(String dbName, String superTableName) {
return "drop table if exists " + dbName + "." + superTableName;
}
public static String createTableSQL(int tableIndex, String dbName, String superTableName) {
String location = locations[random.nextInt(locations.length)];
return "create table d" + tableIndex + " using " + dbName + "." + superTableName + " tags('" + location + "'," + tableIndex + ")";
}
public static String insertOneRowSQL(String dbName, String tbPrefix, int tableIndex, long ts) {
float current = 10 + random.nextFloat();
int voltage = 200 + random.nextInt(20);
float phase = random.nextFloat();
String sql = "insert into " + dbName + "." + tbPrefix + "" + tableIndex + " " + "values(" + ts + ", " + current + ", " + voltage + ", " + phase + ")";
return sql;
}
public static String insertBatchSizeRowsSQL(String dbName, String tbPrefix, int tbIndex, long ts, int valuesCount) {
float current = 10 + random.nextFloat();
int voltage = 200 + random.nextInt(20);
float phase = random.nextFloat();
StringBuilder sb = new StringBuilder();
sb.append("insert into " + dbName + "." + tbPrefix + "" + tbIndex + " " + "values");
for (int i = 0; i < valuesCount; i++) {
sb.append("(" + (ts + i) + ", " + current + ", " + voltage + ", " + phase + ") ");
}
return sb.toString();
}
public static String selectFromTableLimitSQL(String dbName, String tbPrefix, int tbIndex, int limit, int offset) {
return "select * from " + dbName + "." + tbPrefix + "" + tbIndex + " limit " + limit + " offset " + offset;
}
public static String selectCountFromTableSQL(String dbName, String tbPrefix, int tbIndex) {
return "select count(*) from " + dbName + "." + tbPrefix + "" + tbIndex;
}
public static String selectAvgMinMaxFromTableSQL(String field, String dbName, String tbPrefix, int tbIndex) {
return "select avg(" + field + "),min(" + field + "),max(" + field + ") from " + dbName + "." + tbPrefix + "" + tbIndex;
}
public static String selectFromSuperTableLimitSQL(String dbName, String stbName, int limit, int offset) {
return "select * from " + dbName + "." + stbName + " limit " + limit + " offset " + offset;
}
public static String selectCountFromSuperTableSQL(String dbName, String stableName) {
return "select count(*) from " + dbName + "." + stableName;
}
public static String selectAvgMinMaxFromSuperTableSQL(String field, String dbName, String stbName) {
return "select avg(" + field + "),min(" + field + "),max(" + field + ") from " + dbName + "." + stbName + "";
}
public static String selectLastFromTableSQL(String dbName, String tbPrefix, int tbIndex) {
return "select last(*) from " + dbName + "." + tbPrefix + "" + tbIndex;
}
//select avg ,max from stb where tag
public static String selectAvgMinMaxFromSuperTableWhere(String field, String dbName, String stbName) {
return "select avg(" + field + "),min(" + field + "),max(" + field + ") from " + dbName + "." + stbName + " where location = '" + locations[random.nextInt(locations.length)] + "'";
}
//select last from stb where
public static String selectLastFromSuperTableWhere(String field, String dbName, String stbName) {
return "select last(" + field + ") from " + dbName + "." + stbName + " where location = '" + locations[random.nextInt(locations.length)] + "'";
}
public static String selectGroupBy(String field, String dbName, String stbName) {
return "select avg(" + field + ") from " + dbName + "." + stbName + " group by location";
}
public static String selectLike(String dbName, String stbName) {
return "select * from " + dbName + "." + stbName + " where location like 'S%'";
}
public static String selectLastOneHour(String dbName, String stbName) {
return "select * from " + dbName + "." + stbName + " where ts >= now - 1h";
}
public static String selectLastOneDay(String dbName, String stbName) {
return "select * from " + dbName + "." + stbName + " where ts >= now - 1d";
}
public static String selectLastOneWeek(String dbName, String stbName) {
return "select * from " + dbName + "." + stbName + " where ts >= now - 1w";
}
public static String selectLastOneMonth(String dbName, String stbName) {
return "select * from " + dbName + "." + stbName + " where ts >= now - 1n";
}
public static String selectLastOneYear(String dbName, String stbName) {
return "select * from " + dbName + "." + stbName + " where ts >= now - 1y";
}
// select group by
// select like
// select ts >= ts<=
}

View File

@ -1,37 +0,0 @@
package com.taosdata.example.jdbcTaosdemo.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
public class TimeStampUtil {
private static final String datetimeFormat = "yyyy-MM-dd HH:mm:ss.SSS";
public static long datetimeToLong(String dateTime) {
SimpleDateFormat sdf = new SimpleDateFormat(datetimeFormat);
try {
return sdf.parse(dateTime).getTime();
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
public static String longToDatetime(long time) {
SimpleDateFormat sdf = new SimpleDateFormat(datetimeFormat);
return sdf.format(new Date(time));
}
public static void main(String[] args) throws ParseException {
// Instant now = Instant.now();
// System.out.println(now);
// Instant years20Ago = now.minus(Duration.ofDays(365));
// System.out.println(years20Ago);
}
}

View File

@ -1,21 +0,0 @@
### 设置###
log4j.rootLogger=debug,stdout,DebugLog,ErrorLog
### 输出信息到控制抬 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=logs/error.log ###
log4j.appender.DebugLog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DebugLog.File=logs/debug.log
log4j.appender.DebugLog.Append=true
log4j.appender.DebugLog.Threshold=DEBUG
log4j.appender.DebugLog.layout=org.apache.log4j.PatternLayout
log4j.appender.DebugLog.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=logs/error.log ###
log4j.appender.ErrorLog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ErrorLog.File=logs/error.log
log4j.appender.ErrorLog.Append=true
log4j.appender.ErrorLog.Threshold=ERROR
log4j.appender.ErrorLog.layout=org.apache.log4j.PatternLayout
log4j.appender.ErrorLog.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

View File

@ -1,52 +0,0 @@
package com.taosdata.example.jdbcTaosdemo.utils;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import static org.junit.Assert.*;
public class TimeStampUtilTest {
@Test
public void datetimeToLong() {
final String startTime = "2005-01-01 00:00:00.000";
long start = TimeStampUtil.datetimeToLong(startTime);
assertEquals(1104508800000l, start);
}
@Test
public void longToDatetime() {
String datetime = TimeStampUtil.longToDatetime(1510000000000L);
assertEquals("2017-11-07 04:26:40.000", datetime);
}
@Test
public void getStartDateTime() {
int keep = 365;
Instant end = Instant.now();
System.out.println(end.toString());
System.out.println(end.toEpochMilli());
Instant start = end.minus(Duration.ofDays(keep));
System.out.println(start.toString());
System.out.println(start.toEpochMilli());
int numberOfRecordsPerTable = 10;
long timeGap = ChronoUnit.MILLIS.between(start, end) / (numberOfRecordsPerTable - 1);
System.out.println(timeGap);
System.out.println("===========================");
for (int i = 0; i < numberOfRecordsPerTable; i++) {
long ts = start.toEpochMilli() + (i * timeGap);
System.out.println(i + " : " + ts);
}
}
}

View File

@ -82,12 +82,27 @@ public class ConnectionPoolDemo {
init(dataSource); init(dataSource);
ExecutorService executor = Executors.newFixedThreadPool(threadCount); try {
while (true) { Connection connection = dataSource.getConnection();
executor.execute(new InsertTask(dataSource, dbName, tableSize, batchSize)); Statement statement = connection.createStatement();
if (sleep > 0) String sql = "insert into " + dbName + ".t_1 values('2020-01-01 00:00:00.000',12.12,111)";
TimeUnit.MILLISECONDS.sleep(sleep); int affectRows = statement.executeUpdate(sql);
System.out.println("affectRows >>> " + affectRows);
affectRows = statement.executeUpdate(sql);
System.out.println("affectRows >>> " + affectRows);
statement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
} }
// ExecutorService executor = Executors.newFixedThreadPool(threadCount);
// while (true) {
// executor.execute(new InsertTask(dataSource, dbName, tableSize, batchSize));
// if (sleep > 0)
// TimeUnit.MILLISECONDS.sleep(sleep);
// }
} }
private static void init(DataSource dataSource) { private static void init(DataSource dataSource) {

View File

@ -6,7 +6,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan(basePackages = {"com.taosdata.jdbc.springbootdemo.dao"}) @MapperScan(basePackages = {"com.taosdata.jdbc.springbootdemo.dao"})
@SpringBootApplication @SpringBootApplication
public class SpringbootdemoApplication { public class cd {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(SpringbootdemoApplication.class, args); SpringApplication.run(SpringbootdemoApplication.class, args);

View File

@ -2,41 +2,87 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.taosdata</groupId> <groupId>com.taosdata</groupId>
<artifactId>taosdemo</artifactId> <artifactId>taosdemo</artifactId>
<version>2.0</version> <version>2.0</version>
<name>taosdemo</name> <name>taosdemo</name>
<packaging>jar</packaging>
<description>Demo project for TDengine</description> <description>Demo project for TDengine</description>
<properties> <properties>
<java.version>1.8</java.version> <spring.version>5.3.2</spring.version>
</properties> </properties>
<dependencies> <dependencies>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.5</version>
</dependency>
<!-- taos jdbc --> <!-- taos jdbc -->
<dependency> <dependency>
<groupId>com.taosdata.jdbc</groupId> <groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId> <artifactId>taos-jdbcdriver</artifactId>
<version>2.0.14</version> <version>2.0.15</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/taos-jdbcdriver-2.0.15-dist.jar</systemPath>
</dependency> </dependency>
<!-- mysql --> <!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<!-- mysql: just for test -->
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version> <version>5.1.47</version>
</dependency> <scope>test</scope>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.2</version>
</dependency> </dependency>
<!-- log4j --> <!-- log4j -->
<dependency> <dependency>
@ -44,46 +90,19 @@
<artifactId>log4j</artifactId> <artifactId>log4j</artifactId>
<version>1.2.17</version> <version>1.2.17</version>
</dependency> </dependency>
<!-- junit -->
<!-- springboot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.12</version> <version>4.12</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <!-- lombok -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<optional>true</optional> <version>1.18.16</version>
</dependency> <scope>provided</scope>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@ -94,6 +113,7 @@
<includes> <includes>
<include>**/*.properties</include> <include>**/*.properties</include>
<include>**/*.xml</include> <include>**/*.xml</include>
<include>**/*.jar</include>
</includes> </includes>
<filtering>true</filtering> <filtering>true</filtering>
</resource> </resource>
@ -108,10 +128,41 @@
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<!-- 指定JdbcChecker为mainClass -->
<mainClass>com.taosdata.taosdemo.TaosDemoApplication</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

View File

@ -0,0 +1,3 @@
需求:
1. 可以读lowa的配置文件
2. 支持对JNI方式和Restful方式的taos-driver

View File

@ -0,0 +1,112 @@
package com.taosdata.taosdemo;
import com.taosdata.taosdemo.components.DataSourceFactory;
import com.taosdata.taosdemo.components.JdbcTaosdemoConfig;
import com.taosdata.taosdemo.domain.SuperTableMeta;
import com.taosdata.taosdemo.service.DatabaseService;
import com.taosdata.taosdemo.service.SubTableService;
import com.taosdata.taosdemo.service.SuperTableService;
import com.taosdata.taosdemo.service.data.SuperTableMetaGenerator;
import org.apache.log4j.Logger;
import javax.sql.DataSource;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class TaosDemoApplication {
private static Logger logger = Logger.getLogger(TaosDemoApplication.class);
public static void main(String[] args) throws IOException {
// 读配置参数
JdbcTaosdemoConfig config = new JdbcTaosdemoConfig(args);
boolean isHelp = Arrays.asList(args).contains("--help");
if (isHelp || config.host == null || config.host.isEmpty()) {
// if (isHelp) {
JdbcTaosdemoConfig.printHelp();
System.exit(0);
}
// 初始化
final DataSource dataSource = DataSourceFactory.getInstance(config.host, config.port, config.user, config.password);
final DatabaseService databaseService = new DatabaseService(dataSource);
final SuperTableService superTableService = new SuperTableService(dataSource);
final SubTableService subTableService = new SubTableService(dataSource);
// 创建数据库
long start = System.currentTimeMillis();
Map<String, String> databaseParam = new HashMap<>();
databaseParam.put("database", config.database);
databaseParam.put("keep", Integer.toString(config.keep));
databaseParam.put("days", Integer.toString(config.days));
databaseParam.put("replica", Integer.toString(config.replica));
//TODO: other database parameters
databaseService.createDatabase(databaseParam);
databaseService.useDatabase(config.database);
long end = System.currentTimeMillis();
logger.info(">>> create database time cost : " + (end - start) + " ms.");
/**********************************************************************************/
// 构造超级表的meta
SuperTableMeta superTableMeta;
// create super table
if (config.superTableSQL != null) {
// use a sql to create super table
superTableMeta = SuperTableMetaGenerator.generate(config.superTableSQL);
if (config.database != null && !config.database.isEmpty())
superTableMeta.setDatabase(config.database);
} else if (config.numOfFields == 0) {
String sql = "create table " + config.database + "." + config.superTable + " (ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)";
superTableMeta = SuperTableMetaGenerator.generate(sql);
} else {
// create super table with specified field size and tag size
superTableMeta = SuperTableMetaGenerator.generate(config.database, config.superTable, config.numOfFields, config.prefixOfFields, config.numOfTags, config.prefixOfTags);
}
/**********************************************************************************/
// 建表
start = System.currentTimeMillis();
if (config.doCreateTable) {
superTableService.drop(superTableMeta.getDatabase(), superTableMeta.getName());
superTableService.create(superTableMeta);
if (!config.autoCreateTable) {
// 批量建子表
subTableService.createSubTable(superTableMeta, config.numOfTables, config.prefixOfTable, config.numOfThreadsForCreate);
}
}
end = System.currentTimeMillis();
logger.error(">>> create table time cost : " + (end - start) + " ms.");
/**********************************************************************************/
// 插入
long tableSize = config.numOfTables;
int threadSize = config.numOfThreadsForInsert;
long startTime = getProperStartTime(config.startTime, config.keep);
if (tableSize < threadSize)
threadSize = (int) tableSize;
long gap = (long) Math.ceil((0.0d + tableSize) / threadSize);
start = System.currentTimeMillis();
// multi threads to insert
int affectedRows = subTableService.insertMultiThreads(superTableMeta, threadSize, tableSize, startTime, gap, config);
end = System.currentTimeMillis();
logger.error("insert " + affectedRows + " rows, time cost: " + (end - start) + " ms");
/**********************************************************************************/
// 删除表
if (config.dropTable) {
superTableService.drop(config.database, config.superTable);
}
System.exit(0);
}
private static long getProperStartTime(long startTime, int keep) {
Instant now = Instant.now();
long earliest = now.minus(Duration.ofDays(keep - 1)).toEpochMilli();
if (startTime == 0 || startTime < earliest) {
startTime = earliest;
}
return startTime;
}
}

View File

@ -1,15 +0,0 @@
package com.taosdata.taosdemo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan(basePackages = {"com.taosdata.taosdemo.mapper"})
@SpringBootApplication
public class TaosdemoApplication {
public static void main(String[] args) {
SpringApplication.run(TaosdemoApplication.class, args);
}
}

View File

@ -0,0 +1,63 @@
package com.taosdata.taosdemo.components;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
@Component
public class DataSourceFactory {
private static DataSource instance;
public static DataSource getInstance(String host, int port, String user, String password) throws IOException {
if (instance == null) {
synchronized (DataSourceFactory.class) {
if (instance == null) {
InputStream is = DataSourceFactory.class.getClassLoader().getResourceAsStream("application.properties");
Properties properties = new Properties();
properties.load(is);
HikariConfig config = new HikariConfig();
if (properties.containsKey("jdbc.driver")) {
// String driverName = properties.getProperty("jdbc.driver");
// System.out.println(">>> load driver : " + driverName);
// try {
// Class.forName(driverName);
// } catch (ClassNotFoundException e) {
// e.printStackTrace();
// }
config.setDriverClassName(properties.getProperty("jdbc.driver"));
} else {
config.setDriverClassName("com.taosdata.jdbc.TSDBDriver");
}
if ("com.taosdata.jdbc.rs.RestfulDriver".equalsIgnoreCase(properties.getProperty("jdbc.driver")))
config.setJdbcUrl("jdbc:TAOS-RS://" + host + ":6041/?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC-8");
else
config.setJdbcUrl("jdbc:TAOS://" + host + ":" + port + "/?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC-8");
config.setUsername(user);
config.setPassword(password);
// maximum-pool-size
if (properties.containsKey("hikari.maximum-pool-size"))
config.setMaximumPoolSize(Integer.parseInt(properties.getProperty("hikari.maximum-pool-size")));
else
config.setMaximumPoolSize(500);
// minimum-idle
if (properties.containsKey("hikari.minimum-idle"))
config.setMinimumIdle(Integer.parseInt(properties.getProperty("hikari.minimum-idle")));
else
config.setMinimumIdle(100);
config.setMaxLifetime(0);
instance = new HikariDataSource(config);
}
}
}
return instance;
}
}

View File

@ -1,4 +1,6 @@
package com.taosdata.taosdemo.utils; package com.taosdata.taosdemo.components;
import com.taosdata.taosdemo.utils.TimeStampUtil;
public final class JdbcTaosdemoConfig { public final class JdbcTaosdemoConfig {
// instance // instance
@ -7,10 +9,14 @@ public final class JdbcTaosdemoConfig {
public String user = "root"; //user public String user = "root"; //user
public String password = "taosdata"; //password public String password = "taosdata"; //password
// database // database
public String database = "test"; //database public String database = "jdbcdb"; //database
public int keep = 3650; //keep public int keep = 3650; //keep
public int days = 30; //days public int days = 30; //days
public int replica = 1; //replica public int replica = 1; //replica
public int blocks = 16;
public int cache = 8;
public String precision = "ms";
//super table //super table
public boolean doCreateTable = true; public boolean doCreateTable = true;
public String superTable = "weather"; //super table name public String superTable = "weather"; //super table name
@ -20,19 +26,19 @@ public final class JdbcTaosdemoConfig {
public int numOfTags; public int numOfTags;
public String superTableSQL; public String superTableSQL;
//sub table //sub table
public String tablePrefix = "t"; public String prefixOfTable = "t";
public int numOfTables = 100;
public int numOfThreadsForCreate = 1;
// insert task // insert task
public boolean autoCreateTable; public boolean autoCreateTable;
public int numOfRowsPerTable = 100; public long numOfTables = 10;
public long numOfRowsPerTable = 10;
public int numOfTablesPerSQL = 1;
public int numOfValuesPerSQL = 1;
public int numOfThreadsForCreate = 1;
public int numOfThreadsForInsert = 1; public int numOfThreadsForInsert = 1;
public int numOfTablesPerSQL = 10;
public int numOfValuesPerSQL = 10;
public long startTime; public long startTime;
public long timeGap; public long timeGap = 1;
public int sleep = 0; public int frequency;
public int order = 0; public int order;
public int rate = 10; public int rate = 10;
public long range = 1000l; public long range = 1000l;
// select task // select task
@ -48,10 +54,14 @@ public final class JdbcTaosdemoConfig {
System.out.println("-user The TDengine user name to use when connecting to the server. Default is 'root'"); System.out.println("-user The TDengine user name to use when connecting to the server. Default is 'root'");
System.out.println("-password The password to use when connecting to the server.Default is 'taosdata'"); System.out.println("-password The password to use when connecting to the server.Default is 'taosdata'");
// database // database
System.out.println("-database Destination database. Default is 'test'"); System.out.println("-database Destination database. Default is 'jdbcdb'");
System.out.println("-keep database keep parameter. Default is 3650"); System.out.println("-keep database keep parameter. Default is 3650");
System.out.println("-days database days parameter. Default is 30"); System.out.println("-days database days parameter. Default is 30");
System.out.println("-replica database replica parameter. Default 1, min: 1, max: 3"); System.out.println("-replica database replica parameter. Default 1, min: 1, max: 3");
System.out.println("-blocks database blocks parameter. Default is 16");
System.out.println("-cache database cache parameter. Default is 8");
System.out.println("-precision database precision parameter. Default is ms");
// super table // super table
System.out.println("-doCreateTable do create super table and sub table, true or false, Default true"); System.out.println("-doCreateTable do create super table and sub table, true or false, Default true");
System.out.println("-superTable super table name. Default 'weather'"); System.out.println("-superTable super table name. Default 'weather'");
@ -63,7 +73,7 @@ public final class JdbcTaosdemoConfig {
" Default is 'create table weather(ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int). \n" + " Default is 'create table weather(ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int). \n" +
" if you use this parameter, the numOfFields and numOfTags will be invalid'"); " if you use this parameter, the numOfFields and numOfTags will be invalid'");
// sub table // sub table
System.out.println("-tablePrefix The prefix of sub tables. Default is 't'"); System.out.println("-prefixOfTable The prefix of sub tables. Default is 't'");
System.out.println("-numOfTables The number of tables. Default is 1"); System.out.println("-numOfTables The number of tables. Default is 1");
System.out.println("-numOfThreadsForCreate The number of thread during create sub table. Default is 1"); System.out.println("-numOfThreadsForCreate The number of thread during create sub table. Default is 1");
// insert task // insert task
@ -74,11 +84,10 @@ public final class JdbcTaosdemoConfig {
System.out.println("-numOfValuesPerSQL The number of value per SQL. Default is 1"); System.out.println("-numOfValuesPerSQL The number of value per SQL. Default is 1");
System.out.println("-startTime start time for insert task, The format is \"yyyy-MM-dd HH:mm:ss.SSS\"."); System.out.println("-startTime start time for insert task, The format is \"yyyy-MM-dd HH:mm:ss.SSS\".");
System.out.println("-timeGap the number of time gap. Default is 1000 ms"); System.out.println("-timeGap the number of time gap. Default is 1000 ms");
System.out.println("-sleep The number of milliseconds for sleep after each insert. default is 0"); System.out.println("-frequency the number of records per second inserted into one table. default is 0, do not control frequency");
System.out.println("-order Insert mode--0: In order, 1: Out of order. Default is in order"); System.out.println("-order Insert mode--0: In order, 1: Out of order. Default is in order");
System.out.println("-rate The proportion of data out of order. effective only if order is 1. min 0, max 100, default is 10"); System.out.println("-rate The proportion of data out of order. effective only if order is 1. min 0, max 100, default is 10");
System.out.println("-range The range of data out of order. effective only if order is 1. default is 1000 ms"); System.out.println("-range The range of data out of order. effective only if order is 1. default is 1000 ms");
// query task // query task
// System.out.println("-sqlFile The select sql file"); // System.out.println("-sqlFile The select sql file");
// drop task // drop task
@ -120,6 +129,15 @@ public final class JdbcTaosdemoConfig {
if ("-replica".equals(args[i]) && i < args.length - 1) { if ("-replica".equals(args[i]) && i < args.length - 1) {
replica = Integer.parseInt(args[++i]); replica = Integer.parseInt(args[++i]);
} }
if ("-blocks".equals(args[i]) && i < args.length - 1) {
blocks = Integer.parseInt(args[++i]);
}
if ("-cache".equals(args[i]) && i < args.length - 1) {
cache = Integer.parseInt(args[++i]);
}
if ("-precision".equals(args[i]) && i < args.length - 1) {
precision = args[++i];
}
// super table // super table
if ("-doCreateTable".equals(args[i]) && i < args.length - 1) { if ("-doCreateTable".equals(args[i]) && i < args.length - 1) {
doCreateTable = Boolean.parseBoolean(args[++i]); doCreateTable = Boolean.parseBoolean(args[++i]);
@ -143,11 +161,11 @@ public final class JdbcTaosdemoConfig {
superTableSQL = args[++i]; superTableSQL = args[++i];
} }
// sub table // sub table
if ("-tablePrefix".equals(args[i]) && i < args.length - 1) { if ("-prefixOfTable".equals(args[i]) && i < args.length - 1) {
tablePrefix = args[++i]; prefixOfTable = args[++i];
} }
if ("-numOfTables".equals(args[i]) && i < args.length - 1) { if ("-numOfTables".equals(args[i]) && i < args.length - 1) {
numOfTables = Integer.parseInt(args[++i]); numOfTables = Long.parseLong(args[++i]);
} }
if ("-autoCreateTable".equals(args[i]) && i < args.length - 1) { if ("-autoCreateTable".equals(args[i]) && i < args.length - 1) {
autoCreateTable = Boolean.parseBoolean(args[++i]); autoCreateTable = Boolean.parseBoolean(args[++i]);
@ -157,7 +175,7 @@ public final class JdbcTaosdemoConfig {
} }
// insert task // insert task
if ("-numOfRowsPerTable".equals(args[i]) && i < args.length - 1) { if ("-numOfRowsPerTable".equals(args[i]) && i < args.length - 1) {
numOfRowsPerTable = Integer.parseInt(args[++i]); numOfRowsPerTable = Long.parseLong(args[++i]);
} }
if ("-numOfThreadsForInsert".equals(args[i]) && i < args.length - 1) { if ("-numOfThreadsForInsert".equals(args[i]) && i < args.length - 1) {
numOfThreadsForInsert = Integer.parseInt(args[++i]); numOfThreadsForInsert = Integer.parseInt(args[++i]);
@ -174,8 +192,8 @@ public final class JdbcTaosdemoConfig {
if ("-timeGap".equals(args[i]) && i < args.length - 1) { if ("-timeGap".equals(args[i]) && i < args.length - 1) {
timeGap = Long.parseLong(args[++i]); timeGap = Long.parseLong(args[++i]);
} }
if ("-sleep".equals(args[i]) && i < args.length - 1) { if ("-frequency".equals(args[i]) && i < args.length - 1) {
sleep = Integer.parseInt(args[++i]); frequency = Integer.parseInt(args[++i]);
} }
if ("-order".equals(args[i]) && i < args.length - 1) { if ("-order".equals(args[i]) && i < args.length - 1) {
order = Integer.parseInt(args[++i]); order = Integer.parseInt(args[++i]);
@ -197,8 +215,4 @@ public final class JdbcTaosdemoConfig {
} }
} }
public static void main(String[] args) {
JdbcTaosdemoConfig config = new JdbcTaosdemoConfig(args);
}
} }

View File

@ -0,0 +1,39 @@
package com.taosdata.taosdemo.components;
import com.alibaba.fastjson.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class JsonConfig {
public static void main(String[] args) {
JsonConfig config = new JsonConfig();
String str = config.read("insert.json");
JSONObject jsonObject = JSONObject.parseObject(str);
System.out.println(jsonObject);
}
private String read(String fileName) {
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(JsonConfig.class.getClassLoader().getResourceAsStream(fileName))
);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
return fileName;
}
}

View File

@ -1,174 +0,0 @@
package com.taosdata.taosdemo.components;
import com.taosdata.taosdemo.domain.*;
import com.taosdata.taosdemo.service.DatabaseService;
import com.taosdata.taosdemo.service.SubTableService;
import com.taosdata.taosdemo.service.SuperTableService;
import com.taosdata.taosdemo.service.data.SubTableMetaGenerator;
import com.taosdata.taosdemo.service.data.SubTableValueGenerator;
import com.taosdata.taosdemo.service.data.SuperTableMetaGenerator;
import com.taosdata.taosdemo.utils.JdbcTaosdemoConfig;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Component
public class TaosDemoCommandLineRunner implements CommandLineRunner {
private static Logger logger = Logger.getLogger(TaosDemoCommandLineRunner.class);
@Autowired
private DatabaseService databaseService;
@Autowired
private SuperTableService superTableService;
@Autowired
private SubTableService subTableService;
private SuperTableMeta superTableMeta;
private List<SubTableMeta> subTableMetaList;
private List<SubTableValue> subTableValueList;
private List<List<SubTableValue>> dataList;
@Override
public void run(String... args) throws Exception {
// 读配置参数
JdbcTaosdemoConfig config = new JdbcTaosdemoConfig(args);
boolean isHelp = Arrays.asList(args).contains("--help");
if (isHelp) {
JdbcTaosdemoConfig.printHelp();
System.exit(0);
}
// 准备数据
prepareData(config);
// 创建数据库
createDatabaseTask(config);
// 建表
createTableTask(config);
// 插入
insertTask(config);
// 查询: 1. 生成查询语句, 2. 执行查询
// 删除表
if (config.dropTable) {
superTableService.drop(config.database, config.superTable);
}
System.exit(0);
}
private void createDatabaseTask(JdbcTaosdemoConfig config) {
long start = System.currentTimeMillis();
Map<String, String> databaseParam = new HashMap<>();
databaseParam.put("database", config.database);
databaseParam.put("keep", Integer.toString(config.keep));
databaseParam.put("days", Integer.toString(config.days));
databaseParam.put("replica", Integer.toString(config.replica));
//TODO: other database parameters
databaseService.dropDatabase(config.database);
databaseService.createDatabase(databaseParam);
databaseService.useDatabase(config.database);
long end = System.currentTimeMillis();
logger.info(">>> insert time cost : " + (end - start) + " ms.");
}
// 建超级表三种方式1. 指定SQL2. 指定field和tags的个数3. 默认
private void createTableTask(JdbcTaosdemoConfig config) {
long start = System.currentTimeMillis();
if (config.doCreateTable) {
superTableService.create(superTableMeta);
// 批量建子表
subTableService.createSubTable(subTableMetaList, config.numOfThreadsForCreate);
}
long end = System.currentTimeMillis();
logger.info(">>> create table time cost : " + (end - start) + " ms.");
}
private void insertTask(JdbcTaosdemoConfig config) {
long start = System.currentTimeMillis();
int numOfThreadsForInsert = config.numOfThreadsForInsert;
int sleep = config.sleep;
if (config.autoCreateTable) {
// 批量插入自动建表
dataList.stream().forEach(subTableValues -> {
subTableService.insertAutoCreateTable(subTableValues, numOfThreadsForInsert);
sleep(sleep);
});
} else {
dataList.stream().forEach(subTableValues -> {
subTableService.insert(subTableValues, numOfThreadsForInsert);
sleep(sleep);
});
}
long end = System.currentTimeMillis();
logger.info(">>> insert time cost : " + (end - start) + " ms.");
}
private void prepareData(JdbcTaosdemoConfig config) {
long start = System.currentTimeMillis();
// 超级表的meta
superTableMeta = createSupertable(config);
// 子表的meta
subTableMetaList = SubTableMetaGenerator.generate(superTableMeta, config.numOfTables, config.tablePrefix);
// 子表的data
subTableValueList = SubTableValueGenerator.generate(subTableMetaList, config.numOfRowsPerTable, config.startTime, config.timeGap);
// 如果有乱序给数据搞乱
if (config.order != 0) {
SubTableValueGenerator.disrupt(subTableValueList, config.rate, config.range);
}
// 分割数据
int numOfTables = config.numOfTables;
int numOfTablesPerSQL = config.numOfTablesPerSQL;
int numOfRowsPerTable = config.numOfRowsPerTable;
int numOfValuesPerSQL = config.numOfValuesPerSQL;
dataList = SubTableValueGenerator.split(subTableValueList, numOfTables, numOfTablesPerSQL, numOfRowsPerTable, numOfValuesPerSQL);
long end = System.currentTimeMillis();
logger.info(">>> prepare data time cost : " + (end - start) + " ms.");
}
private SuperTableMeta createSupertable(JdbcTaosdemoConfig config) {
SuperTableMeta tableMeta;
// create super table
logger.info(">>> create super table <<<");
if (config.superTableSQL != null) {
// use a sql to create super table
tableMeta = SuperTableMetaGenerator.generate(config.superTableSQL);
} else if (config.numOfFields == 0) {
// default sql = "create table test.weather (ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)";
SuperTableMeta superTableMeta = new SuperTableMeta();
superTableMeta.setDatabase(config.database);
superTableMeta.setName(config.superTable);
List<FieldMeta> fields = new ArrayList<>();
fields.add(new FieldMeta("ts", "timestamp"));
fields.add(new FieldMeta("temperature", "float"));
fields.add(new FieldMeta("humidity", "int"));
superTableMeta.setFields(fields);
List<TagMeta> tags = new ArrayList<>();
tags.add(new TagMeta("location", "nchar(64)"));
tags.add(new TagMeta("groupId", "int"));
superTableMeta.setTags(tags);
return superTableMeta;
} else {
// create super table with specified field size and tag size
tableMeta = SuperTableMetaGenerator.generate(config.database, config.superTable, config.numOfFields, config.prefixOfFields, config.numOfTags, config.prefixOfTags);
}
return tableMeta;
}
private static void sleep(int sleep) {
if (sleep <= 0)
return;
try {
TimeUnit.MILLISECONDS.sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

View File

@ -1,40 +0,0 @@
package com.taosdata.taosdemo.controller;
import com.taosdata.taosdemo.service.DatabaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping
public class DatabaseController {
@Autowired
private DatabaseService databaseService;
/**
* create database
***/
@PostMapping
public int create(@RequestBody Map<String, String> map) {
return databaseService.createDatabase(map);
}
/**
* drop database
**/
@DeleteMapping("/{dbname}")
public int delete(@PathVariable("dbname") String dbname) {
return databaseService.dropDatabase(dbname);
}
/**
* use database
**/
@GetMapping("/{dbname}")
public int use(@PathVariable("dbname") String dbname) {
return databaseService.useDatabase(dbname);
}
}

View File

@ -1,17 +0,0 @@
package com.taosdata.taosdemo.controller;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class InsertController {
//TODO多线程写一张表, thread = 10, table = 1
//TODO一个批次写多张表, insert into t1 using weather values() t2 using weather values()
//TODO插入的频率
//TODO指定一张表内的records数量
//TODO是否乱序
//TODO乱序的比例乱序的范围
//TODO先建表自动建表
//TODO一个批次写多张表
}

View File

@ -1,45 +0,0 @@
package com.taosdata.taosdemo.controller;
import com.taosdata.taosdemo.domain.TableValue;
import com.taosdata.taosdemo.service.SuperTableService;
import com.taosdata.taosdemo.service.TableService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SubTableController {
@Autowired
private TableService tableService;
@Autowired
private SuperTableService superTableService;
//TODO: 使用supertable创建一个子表
//TODO使用supertable创建多个子表
//TODO使用supertable多线程创建子表
//TODO使用supertable多线程创建子表指定子表的name_prefix子表的数量使用线程的个数
/**
* 创建表超级表或者普通表
**/
/**
* 创建超级表的子表
**/
@PostMapping("/{database}/{superTable}")
public int createTable(@PathVariable("database") String database,
@PathVariable("superTable") String superTable,
@RequestBody TableValue tableMetadta) {
tableMetadta.setDatabase(database);
return 0;
}
}

View File

@ -1,26 +0,0 @@
package com.taosdata.taosdemo.controller;
import com.taosdata.taosdemo.domain.SuperTableMeta;
import com.taosdata.taosdemo.service.SuperTableService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
public class SuperTableController {
@Autowired
private SuperTableService superTableService;
@PostMapping("/{database}")
public int createTable(@PathVariable("database") String database, @RequestBody SuperTableMeta tableMetadta) {
tableMetadta.setDatabase(database);
return superTableService.create(tableMetadta);
}
//TODO: 删除超级表
//TODO查询超级表
//TODO统计查询表
}

View File

@ -1,11 +0,0 @@
package com.taosdata.taosdemo.controller;
public class TableController {
//TODO创建普通表create table(ts timestamp, temperature float)
//TODO创建普通表指定表的列数包括第一列timestamp
//TODO创建普通表指定表每列的name和type
}

View File

@ -0,0 +1,23 @@
package com.taosdata.taosdemo.dao;
import java.util.Map;
public interface DatabaseMapper {
// create database if not exists XXX
void createDatabase(String dbname);
// drop database if exists XXX
void dropDatabase(String dbname);
// create database if not exists XXX keep XX days XX replica XX
void createDatabaseWithParameters(Map<String, String> map);
// use XXX
void useDatabase(String dbname);
//TODO: alter database
//TODO: show database
}

View File

@ -0,0 +1,47 @@
package com.taosdata.taosdemo.dao;
import com.taosdata.taosdemo.utils.SqlSpeller;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
import java.util.Map;
public class DatabaseMapperImpl implements DatabaseMapper {
private static final Logger logger = Logger.getLogger(DatabaseMapperImpl.class);
private final JdbcTemplate jdbcTemplate;
public DatabaseMapperImpl(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public void createDatabase(String dbname) {
String sql = "create database if not exists " + dbname;
jdbcTemplate.execute(sql);
logger.info("SQL >>> " + sql);
}
@Override
public void dropDatabase(String dbname) {
String sql = "drop database if exists " + dbname;
jdbcTemplate.update(sql);
logger.info("SQL >>> " + sql);
}
@Override
public void createDatabaseWithParameters(Map<String, String> map) {
String sql = SqlSpeller.createDatabase(map);
jdbcTemplate.execute(sql);
logger.info("SQL >>> " + sql);
}
@Override
public void useDatabase(String dbname) {
String sql = "use " + dbname;
jdbcTemplate.execute(sql);
logger.info("SQL >>> " + sql);
}
}

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