diff --git a/Jenkinsfile b/Jenkinsfile
index ebac32cb241af1a35556262690544f84ca94d9fc..73bb832d8ea4c16d65f6fff88cb8844415c19f9c 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -41,13 +41,10 @@ def pre_test(){
cd ${WKC}
git checkout develop
- git reset --hard HEAD~10
- git pull
- git fetch
- git checkout ${CHANGE_BRANCH}
- git reset --hard HEAD~10
+ git reset --hard HEAD~10 >/dev/null
git pull
- git merge develop
+ git fetch origin +refs/pull/${CHANGE_ID}/merge
+ git checkout -qf FETCH_HEAD
cd ${WK}
git reset --hard HEAD~10
git checkout develop
@@ -87,11 +84,14 @@ pipeline {
steps {
pre_test()
- sh '''
- cd ${WKC}/tests
- find pytest -name '*'sql|xargs rm -rf
- ./test-all.sh p1
- date'''
+ timeout(time: 90, unit: 'MINUTES'){
+ sh '''
+ cd ${WKC}/tests
+ find pytest -name '*'sql|xargs rm -rf
+ ./test-all.sh p1
+ date'''
+ }
+
}
}
stage('python_2') {
@@ -112,12 +112,14 @@ pipeline {
}
stage('test_b1') {
agent{label 'b1'}
- steps {
- pre_test()
- sh '''
- cd ${WKC}/tests
- ./test-all.sh b1fq
- date'''
+ steps {
+ timeout(time: 90, unit: 'MINUTES'){
+ pre_test()
+ sh '''
+ cd ${WKC}/tests
+ ./test-all.sh b1fq
+ date'''
+ }
}
}
@@ -137,12 +139,14 @@ pipeline {
./handle_crash_gen_val_log.sh
'''
}
- sh '''
- date
- cd ${WKC}/tests
- ./test-all.sh b2fq
- date
- '''
+ timeout(time: 90, unit: 'MINUTES'){
+ sh '''
+ date
+ cd ${WKC}/tests
+ ./test-all.sh b2fq
+ date
+ '''
+ }
}
}
@@ -157,12 +161,14 @@ pipeline {
./valgrind-test.sh 2>&1 > mem-error-out.log
./handle_val_log.sh
'''
- }
- sh '''
- date
- cd ${WKC}/tests
- ./test-all.sh b3fq
- date'''
+ }
+ timeout(time: 90, unit: 'MINUTES'){
+ sh '''
+ date
+ cd ${WKC}/tests
+ ./test-all.sh b3fq
+ date'''
+ }
}
}
diff --git a/documentation20/webdocs/assets/tdengine-jdbc-connector.png b/documentation20/webdocs/assets/tdengine-jdbc-connector.png
new file mode 100644
index 0000000000000000000000000000000000000000..fdf1dd3fcc5ee222c4a8753efa2c95c5257314bf
Binary files /dev/null and b/documentation20/webdocs/assets/tdengine-jdbc-connector.png differ
diff --git a/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md b/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md
index 1aef888cff39c527fc19368bee28ed270b48f9f1..4563b5b5fcce75697e6c731622e32666df3f8bdf 100644
--- a/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md
+++ b/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md
@@ -743,7 +743,7 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
应用字段:不能应用在timestamp、binary、nchar、bool类型字段。
- 适用于:表。
+ 适用于:表。(从 2.0.15 版本开始,本函数也支持超级表)
示例:
```mysql
diff --git a/documentation20/webdocs/markdowndocs/administrator-ch.md b/documentation20/webdocs/markdowndocs/administrator-ch.md
index 9eee5b2b69cad573f62a1fa4890ff73c43026bd1..a343f7e97079566208b707b36e46b219f26772e2 100644
--- a/documentation20/webdocs/markdowndocs/administrator-ch.md
+++ b/documentation20/webdocs/markdowndocs/administrator-ch.md
@@ -124,10 +124,10 @@ taosd -C
对于一个应用场景,可能有多种数据特征的数据并存,最佳的设计是将具有相同数据特征的表放在一个库里,这样一个应用有多个库,而每个库可以配置不同的存储参数,从而保证系统有最优的性能。TDengine允许应用在创建库时指定上述存储参数,如果指定,该参数就将覆盖对应的系统配置参数。举例,有下述SQL:
```
- create database demo days 10 cache 32 blocks 8 replica 3;
+ create database demo days 10 cache 32 blocks 8 replica 3 update 1;
```
-该SQL创建了一个库demo, 每个数据文件存储10天数据,内存块为32兆字节,每个VNODE占用8个内存块,副本数为3,而其他参数与系统配置完全一致。
+该SQL创建了一个库demo, 每个数据文件存储10天数据,内存块为32兆字节,每个VNODE占用8个内存块,副本数为3,允许更新,而其他参数与系统配置完全一致。
TDengine集群中加入一个新的dnode时,涉及集群相关的一些参数必须与已有集群的配置相同,否则不能成功加入到集群中。会进行校验的参数如下:
diff --git a/documentation20/webdocs/markdowndocs/connector-ch.md b/documentation20/webdocs/markdowndocs/connector-ch.md
index da9c2e5a119e56243e517e9de0e248184d3c3c93..bcaabe3c0a48837cc50d1d2f5f212a57c8e5c912 100644
--- a/documentation20/webdocs/markdowndocs/connector-ch.md
+++ b/documentation20/webdocs/markdowndocs/connector-ch.md
@@ -288,13 +288,6 @@ C/C++的API类似于MySQL的C API。应用程序使用时,需要包含TDengine
* res:`taos_query_a`回调时返回的结果集
* fp:回调函数。其参数`param`是用户可定义的传递给回调函数的参数结构体;`numOfRows`是获取到的数据的行数(不是整个查询结果集的函数)。 在回调函数中,应用可以通过调用`taos_fetch_row`前向迭代获取批量记录中每一行记录。读完一块内的所有记录后,应用需要在回调函数中继续调用`taos_fetch_rows_a`获取下一批记录进行处理,直到返回的记录数(numOfRows)为零(结果返回完成)或记录数为负值(查询出错)。
-- `void taos_fetch_row_a(TAOS_RES *res, void (*fp)(void *param, TAOS_RES *, TAOS_ROW row), void *param);`
-
- 异步获取一条记录。其中:
-
- * res:`taos_query_a`回调时返回的结果集
- * fp:回调函数。其参数`param`是应用提供的一个用于回调的参数。回调时,第三个参数`row`指向一行记录。不同于`taos_fetch_rows_a`,应用无需调用`taos_fetch_row`来获取一行数据,更加简单,但数据提取性能不及批量获取的API。
-
TDengine的异步API均采用非阻塞调用模式。应用程序可以用多线程同时打开多张表,并可以同时对每张打开的表进行查询或者插入操作。需要指出的是,**客户端应用必须确保对同一张表的操作完全串行化**,即对同一个表的插入或查询操作未完成时(未返回时),不能够执行第二个插入或查询操作。
### 参数绑定API
diff --git a/documentation20/webdocs/markdowndocs/connector-java-ch.md b/documentation20/webdocs/markdowndocs/connector-java-ch.md
index 7ba573d2e44bb3848d13a2f6b7cb81038843a291..759dd43e1cf4dd42e94036814dc42ff4ca141355 100644
--- a/documentation20/webdocs/markdowndocs/connector-java-ch.md
+++ b/documentation20/webdocs/markdowndocs/connector-java-ch.md
@@ -1,62 +1,62 @@
# Java Connector
-Java连接器支持的系统有:
-| **CPU类型** | x64(64bit) | | | ARM64 | ARM32 |
-| ------------ | ------------ | -------- | -------- | -------- | -------- |
-| **OS类型** | Linux | Win64 | Win32 | Linux | Linux |
-| **支持与否** | **支持** | **支持** | **支持** | **支持** | **支持** |
+TDengine 提供了遵循 JDBC 标准(3.0)API 规范的 `taos-jdbcdriver` 实现,可在 maven 的中央仓库 [Sonatype Repository][1] 搜索下载。
-Java连接器的使用请参见视频教程。
+`taos-jdbcdriver的` 实现包括 2 种形式: JDBC-JNI 和 JDBC-RESTful(taos-jdbcdriver-2.0.16 开始支持 JDBC-RESTful)。 JDBC-JNI 通过调用客户端 libtaos.so(或 taos.dll )的本地方法实现, JDBC-RESTful 则在内部封装了 RESTful 接口实现。
-TDengine 为了方便 Java 应用使用,提供了遵循 JDBC 标准(3.0)API 规范的 `taos-jdbcdriver` 实现。目前可以通过 [Sonatype Repository][1] 搜索并下载。
+![tdengine-connector](../assets/tdengine-jdbc-connector.png)
-由于 TDengine 是使用 c 语言开发的,使用 taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库。
+上图显示了 3 种 Java 应用使用连接器访问 TDengine 的方式:
-* libtaos.so
- 在 linux 系统中成功安装 TDengine 后,依赖的本地函数库 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so,该目录包含在 Linux 自动扫描路径上,无需单独指定。
-
-* taos.dll
- 在 windows 系统中安装完客户端之后,驱动包依赖的 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。
+* JDBC-JNI:Java 应用在物理节点1(pnode1)上使用 JDBC-JNI 的 API ,直接调用客户端 API(libtaos.so 或 taos.dll)将写入和查询请求发送到位于物理节点2(pnode2)上的 taosd 实例。
+* RESTful:应用将 SQL 发送给位于物理节点2(pnode2)上的 RESTful 连接器,再调用客户端 API(libtaos.so)。
+* JDBC-RESTful:Java 应用通过 JDBC-RESTful 的 API ,将 SQL 封装成一个 RESTful 请求,发送给物理节点2的 RESTful 连接器。
-> 注意:在 windows 环境开发时需要安装 TDengine 对应的 [windows 客户端][14],Linux 服务器安装完 TDengine 之后默认已安装 client,也可以单独安装 [Linux 客户端][15] 连接远程 TDengine Server。
+TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致,但时序空间数据库与关系对象型数据库服务的对象和技术特征存在差异,导致 `taos-jdbcdriver` 与传统的 JDBC driver 也存在一定差异。在使用时需要注意以下几点:
-TDengine 的 JDBC 驱动实现尽可能的与关系型数据库驱动保持一致,但时序空间数据库与关系对象型数据库服务的对象和技术特征的差异导致 taos-jdbcdriver 并未完全实现 JDBC 标准规范。在使用时需要注意以下几点:
-
-* TDengine 不提供针对单条数据记录的删除和修改的操作,驱动中也没有支持相关方法。
-* 由于不支持删除和修改,所以也不支持事务操作。
+* TDengine 目前不支持针对单条数据记录的删除操作。
+* 目前不支持事务操作。
* 目前不支持表间的 union 操作。
-* 目前不支持嵌套查询(nested query),对每个 Connection 的实例,至多只能有一个打开的 ResultSet 实例;如果在 ResultSet还没关闭的情况下执行了新的查询,TSDBJDBCDriver 则会自动关闭上一个 ResultSet。
-
-## TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本
-
-| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
-| --- | --- | --- |
-| 2.0.12 及以上 | 2.0.8.0 及以上 | 1.8.x |
-| 2.0.4 - 2.0.11 | 2.0.0.0 - 2.0.7.x | 1.8.x |
-| 1.0.3 | 1.6.1.x 及以上 | 1.8.x |
-| 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
-| 1.0.1 | 1.6.1.x 及以上 | 1.8.x |
-
-## TDengine DataType 和 Java DataType
-
-TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下:
-
-| TDengine DataType | Java DataType |
-| --- | --- |
-| TIMESTAMP | java.sql.Timestamp |
-| INT | java.lang.Integer |
-| BIGINT | java.lang.Long |
-| FLOAT | java.lang.Float |
-| DOUBLE | java.lang.Double |
-| SMALLINT, TINYINT |java.lang.Short |
-| BOOL | java.lang.Boolean |
-| BINARY, NCHAR | java.lang.String |
-
-## 如何获取 TAOS-JDBCDriver
+* 目前不支持嵌套查询(nested query)。
+* 对每个 Connection 的实例,至多只能有一个打开的 ResultSet 实例;如果在 ResultSet 还没关闭的情况下执行了新的查询,taos-jdbcdriver 会自动关闭上一个 ResultSet。
+
+
+## JDBC-JNI和JDBC-RESTful的对比
+
+
+对比项 | JDBC-JNI | JDBC-RESTful |
+
+ 支持的操作系统 |
+ linux、windows |
+ 全平台 |
+
+
+ 是否需要安装 client |
+ 需要 |
+ 不需要 |
+
+
+ server 升级后是否需要升级 client |
+ 需要 |
+ 不需要 |
+
+
+ 写入性能 |
+ JDBC-RESTful 是 JDBC-JNI 的 50%~90% |
+
+
+ 查询性能 |
+ JDBC-RESTful 与 JDBC-JNI 没有差别 |
+
+
+
+
+## 如何获取 taos-jdbcdriver
### maven 仓库
目前 taos-jdbcdriver 已经发布到 [Sonatype Repository][1] 仓库,且各大仓库都已同步。
+
* [sonatype][8]
* [mvnrepository][9]
* [maven.aliyun][10]
@@ -67,30 +67,63 @@ maven 项目中使用如下 pom.xml 配置即可:
com.taosdata.jdbc
taos-jdbcdriver
- 2.0.4
+ 2.0.16
```
### 源码编译打包
-下载 [TDengine][3] 源码之后,进入 taos-jdbcdriver 源码目录 `src/connector/jdbc` 执行 `mvn clean package` 即可生成相应 jar 包。
+下载 [TDengine][3] 源码之后,进入 taos-jdbcdriver 源码目录 `src/connector/jdbc` 执行 `mvn clean package -Dmaven.test.skip=true` 即可生成相应 jar 包。
+
-## 使用说明
+
+## JDBC的使用说明
### 获取连接
-#### 通过JdbcUrl获取连接
+#### 指定URL获取连接
+
+通过指定URL获取连接,如下所示:
+
+```java
+Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
+String jdbcUrl = "jdbc:TAOS-RS://taosdemo.com:6041/test?user=root&password=taosdata";
+Connection conn = DriverManager.getConnection(jdbcUrl);
+```
+
+以上示例,使用 **JDBC-RESTful** 的 driver,建立了到 hostname 为 taosdemo.com,端口为 6041,数据库名为 test 的连接。这个 URL 中指定用户名(user)为 root,密码(password)为 taosdata。
+
+使用 JDBC-RESTful 接口,不需要依赖本地函数库。与 JDBC-JNI 相比,仅需要:
+
+1. driverClass 指定为“com.taosdata.jdbc.rs.RestfulDriver”;
+2. jdbcUrl 以“jdbc:TAOS-RS://”开头;
+3. 使用 6041 作为连接端口。
+
+如果希望获得更好的写入和查询性能,Java 应用可以使用 **JDBC-JNI** 的driver,如下所示:
-通过指定的jdbcUrl获取连接,如下所示:
```java
Class.forName("com.taosdata.jdbc.TSDBDriver");
String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata";
Connection conn = DriverManager.getConnection(jdbcUrl);
```
-以上示例,建立了到hostname为taosdemo.com,端口为6030(TDengine的默认端口),数据库名为test的连接。这个url中指定用户名(user)为root,密码(password)为taosdata。
+
+以上示例,使用了 JDBC-JNI 的 driver,建立了到 hostname 为 taosdemo.com,端口为 6030(TDengine 的默认端口),数据库名为 test 的连接。这个 URL 中指定用户名(user)为 root,密码(password)为 taosdata。
+
+**注意**:使用 JDBC-JNI 的 driver,taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库。
+
+* libtaos.so
+ 在 linux 系统中成功安装 TDengine 后,依赖的本地函数库 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so,该目录包含在 Linux 自动扫描路径上,无需单独指定。
+
+* taos.dll
+ 在 windows 系统中安装完客户端之后,驱动包依赖的 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。
+
+> 在 windows 环境开发时需要安装 TDengine 对应的 [windows 客户端][14],Linux 服务器安装完 TDengine 之后默认已安装 client,也可以单独安装 [Linux 客户端][15] 连接远程 TDengine Server。
+
+JDBC-JNI 的使用请参见视频教程。
TDengine 的 JDBC URL 规范格式为:
-`jdbc:TAOS://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
+`jdbc:[TAOS|TAOS-RS]://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
+
url中的配置参数如下:
* user:登录 TDengine 用户名,默认值 root。
* password:用户登录密码,默认值 taosdata。
@@ -99,13 +132,17 @@ url中的配置参数如下:
* locale:客户端语言环境,默认值系统当前 locale。
* timezone:客户端使用的时区,默认值为系统当前时区。
-#### 使用JdbcUrl和Properties获取连接
-除了通过指定的jdbcUrl获取连接,还可以使用Properties指定建立连接时的参数,如下所示:
+
+#### 指定URL和Properties获取连接
+
+除了通过指定的 URL 获取连接,还可以使用 Properties 指定建立连接时的参数,如下所示:
```java
public Connection getConn() throws Exception{
Class.forName("com.taosdata.jdbc.TSDBDriver");
+ // Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata";
+ // String jdbcUrl = "jdbc:TAOS-RS://taosdemo.com:6041/test?user=root&password=taosdata";
Properties connProps = new Properties();
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
@@ -114,9 +151,10 @@ public Connection getConn() throws Exception{
return conn;
}
```
-以上示例,建立一个到hostname为taosdemo.com,端口为6030,数据库名为test的连接。这个连接在url中指定了用户名(user)为root,密码(password)为taosdata,并在connProps中指定了使用的字符集、语言环境、时区等信息。
-properties中的配置参数如下:
+以上示例,建立一个到 hostname 为 taosdemo.com,端口为 6030,数据库名为 test 的连接。注释为使用 JDBC-RESTful 时的方法。这个连接在 url 中指定了用户名(user)为 root,密码(password)为 taosdata,并在 connProps 中指定了使用的字符集、语言环境、时区等信息。
+
+properties 中的配置参数如下:
* TSDBDriver.PROPERTY_KEY_USER:登录 TDengine 用户名,默认值 root。
* TSDBDriver.PROPERTY_KEY_PASSWORD:用户登录密码,默认值 taosdata。
* TSDBDriver.PROPERTY_KEY_CONFIG_DIR:客户端配置文件目录路径,Linux OS 上默认值 /etc/taos ,Windows OS 上默认值 C:/TDengine/cfg。
@@ -124,10 +162,14 @@ properties中的配置参数如下:
* TSDBDriver.PROPERTY_KEY_LOCALE:客户端语言环境,默认值系统当前 locale。
* TSDBDriver.PROPERTY_KEY_TIME_ZONE:客户端使用的时区,默认值为系统当前时区。
+
+
#### 使用客户端配置文件建立连接
-当使用JDBC连接TDengine集群时,可以使用客户端配置文件,在客户端配置文件中指定集群的firstEp、secondEp参数。
+
+当使用 JDBC-JNI 连接 TDengine 集群时,可以使用客户端配置文件,在客户端配置文件中指定集群的 firstEp、secondEp参数。
如下所示:
-1. 在java中不指定hostname和port
+
+1. 在 Java 应用中不指定 hostname 和 port
```java
public Connection getConn() throws Exception{
Class.forName("com.taosdata.jdbc.TSDBDriver");
@@ -140,7 +182,7 @@ public Connection getConn() throws Exception{
return conn;
}
```
-2. 在配置文件中指定firstEp和secondEp
+2. 在配置文件中指定 firstEp 和 secondEp
```
# first fully qualified domain name (FQDN) for TDengine system
firstEp cluster_node1:6030
@@ -155,17 +197,19 @@ secondEp cluster_node2:6030
# locale en_US.UTF-8
```
-以上示例,jdbc会使用客户端的配置文件,建立到hostname为cluster_node1,端口为6030,数据库名为test的连接。当集群中firstEp节点失效时,JDBC会尝试使用secondEp连接集群。
-TDengine中,只要保证firstEp和secondEp中一个节点有效,就可以正常建立到集群的连接。
+以上示例,jdbc 会使用客户端的配置文件,建立到 hostname 为 cluster_node1、端口为 6030、数据库名为 test 的连接。当集群中 firstEp 节点失效时,JDBC 会尝试使用 secondEp 连接集群。
+TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可以正常建立到集群的连接。
-> 注意:这里的配置文件指的是调用JDBC Connector的应用程序所在机器上的配置文件,Linux OS 上默认值 /etc/taos/taos.cfg ,Windows OS 上默认值 C://TDengine/cfg/taos.cfg。
+> 注意:这里的配置文件指的是调用 JDBC Connector 的应用程序所在机器上的配置文件,Linux OS 上默认值 /etc/taos/taos.cfg ,Windows OS 上默认值 C://TDengine/cfg/taos.cfg。
#### 配置参数的优先级
-通过以上3种方式获取连接,如果配置参数在url、Properties、客户端配置文件中有重复,则参数的`优先级由高到低`分别如下:
+
+通过以上 3 种方式获取连接,如果配置参数在 url、Properties、客户端配置文件中有重复,则参数的`优先级由高到低`分别如下:
1. JDBC URL 参数,如上所述,可以在 JDBC URL 的参数中指定。
2. Properties connProps
3. 客户端配置文件 taos.cfg
-例如:在url中指定了password为taosdata,在Properties中指定了password为taosdemo,那么,JDBC会使用url中的password建立连接。
+
+例如:在 url 中指定了 password 为 taosdata,在 Properties 中指定了 password 为 taosdemo,那么,JDBC 会使用 url 中的 password 建立连接。
> 更多详细配置请参考[客户端配置][13]
@@ -183,6 +227,7 @@ stmt.executeUpdate("use db");
// create table
stmt.executeUpdate("create table if not exists tb (ts timestamp, temperature int, humidity float)");
```
+
> 注意:如果不使用 `use db` 指定数据库,则后续对表的操作都需要增加数据库名称作为前缀,如 db.tb。
### 插入数据
@@ -193,6 +238,7 @@ int affectedRows = stmt.executeUpdate("insert into tb values(now, 23, 10.3) (now
System.out.println("insert " + affectedRows + " rows.");
```
+
> now 为系统内部函数,默认为服务器当前时间。
> `now + 1s` 代表服务器当前时间往后加 1 秒,数字后面代表时间单位:a(毫秒), s(秒), m(分), h(小时), d(天),w(周), n(月), y(年)。
@@ -214,6 +260,7 @@ while(resultSet.next()){
System.out.printf("%s, %d, %s\n", ts, temperature, humidity);
}
```
+
> 查询和操作关系型数据库一致,使用下标获取返回字段内容时从 1 开始,建议使用字段名称获取。
### 订阅
@@ -248,7 +295,7 @@ while(true) {
}
```
-`consume` 方法返回一个结果集,其中包含从上次 `consume` 到目前为止的所有新数据。请务必按需选择合理的调用 `consume` 的频率(如例子中的`Thread.sleep(1000)`),否则会给服务端造成不必要的压力。
+`consume` 方法返回一个结果集,其中包含从上次 `consume` 到目前为止的所有新数据。请务必按需选择合理的调用 `consume` 的频率(如例子中的 `Thread.sleep(1000)`),否则会给服务端造成不必要的压力。
#### 关闭订阅
@@ -265,8 +312,11 @@ resultSet.close();
stmt.close();
conn.close();
```
+
> `注意务必要将 connection 进行关闭`,否则会出现连接泄露。
+
+
## 与连接池使用
**HikariCP**
@@ -306,6 +356,7 @@ conn.close();
connection.close(); // put back to conneciton pool
}
```
+
> 通过 HikariDataSource.getConnection() 获取连接后,使用完成后需要调用 close() 方法,实际上它并不会关闭连接,只是放回连接池中。
> 更多 HikariCP 使用问题请查看[官方说明][5]
@@ -356,6 +407,7 @@ public static void main(String[] args) throws Exception {
connection.close(); // put back to conneciton pool
}
```
+
> 更多 druid 使用问题请查看[官方说明][6]
**注意事项**
@@ -370,10 +422,43 @@ server_status()|
Query OK, 1 row(s) in set (0.000141s)
```
+
+
## 与框架使用
* Spring JdbcTemplate 中使用 taos-jdbcdriver,可参考 [SpringJdbcTemplate][11]
-* Springboot + Mybatis 中使用,可参考 [springbootdemo][12]
+* Springboot + Mybatis 中使用,可参考 [springbootdemo
+
+
+
+## TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本
+
+| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
+| -------------------- | ----------------- | -------- |
+| 2.0.12 及以上 | 2.0.8.0 及以上 | 1.8.x |
+| 2.0.4 - 2.0.11 | 2.0.0.0 - 2.0.7.x | 1.8.x |
+| 1.0.3 | 1.6.1.x 及以上 | 1.8.x |
+| 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
+| 1.0.1 | 1.6.1.x 及以上 | 1.8.x |
+
+
+
+## TDengine DataType 和 Java DataType
+
+TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下:
+
+| TDengine DataType | Java DataType |
+| ----------------- | ------------------ |
+| TIMESTAMP | java.sql.Timestamp |
+| INT | java.lang.Integer |
+| BIGINT | java.lang.Long |
+| FLOAT | java.lang.Float |
+| DOUBLE | java.lang.Double |
+| SMALLINT, TINYINT | java.lang.Short |
+| BOOL | java.lang.Boolean |
+| BINARY, NCHAR | java.lang.String |
+
+
## 常见问题
@@ -381,7 +466,7 @@ Query OK, 1 row(s) in set (0.000141s)
**原因**:程序没有找到依赖的本地函数库 taos。
- **解决方法**:windows 下可以将 C:\TDengine\driver\taos.dll 拷贝到 C:\Windows\System32\ 目录下,linux 下将建立如下软链 ` ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` 即可。
+ **解决方法**:windows 下可以将 C:\TDengine\driver\taos.dll 拷贝到 C:\Windows\System32\ 目录下,linux 下将建立如下软链 `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` 即可。
* java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform
@@ -406,3 +491,4 @@ Query OK, 1 row(s) in set (0.000141s)
[13]: https://www.taosdata.com/cn/documentation20/administrator/#%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%85%8D%E7%BD%AE
[14]: https://www.taosdata.com/cn/all-downloads/#TDengine-Windows-Client
[15]: https://www.taosdata.com/cn/getting-started/#%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B
+
diff --git a/documentation20/webdocs/markdowndocs/faq-ch.md b/documentation20/webdocs/markdowndocs/faq-ch.md
index 79139078c13bda797299b470b417061c61169a10..cd6f0ae08caf19340b6cef9a9428abcb66c97dc6 100644
--- a/documentation20/webdocs/markdowndocs/faq-ch.md
+++ b/documentation20/webdocs/markdowndocs/faq-ch.md
@@ -85,7 +85,9 @@ TDengine还没有一组专用的validation queries。然而建议你使用系统
## 9. 我可以删除或更新一条记录吗?
-不能。因为TDengine是为联网设备采集的数据设计的,不容许修改。但TDengine提供数据保留策略,只要数据记录超过保留时长,就会被自动删除。
+TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。
+
+从 2.0.8.0 开始,TDengine 支持更新已经写入数据的功能。使用更新功能需要在创建数据库时使用 UPDATE 1 参数,之后可以使用 INSERT INTO 命令更新已经写入的相同时间戳数据。UPDATE 参数不支持 ALTER DATABASE 命令修改。没有使用 UPDATE 1 参数创建的数据库,写入相同时间戳的数据不会修改之前的数据,也不会报错。
## 10. 我怎么创建超过1024列的表?
@@ -132,8 +134,3 @@ TDengine是根据hostname唯一标志一台机器的,在数据文件从机器A
- 2.0.7.0 及以后的版本,到/var/lib/taos/dnode下,修复dnodeEps.json的dnodeId对应的FQDN,重启。确保机器内所有机器的此文件是完全相同的。
- 1.x 和 2.x 版本的存储结构不兼容,需要使用迁移工具或者自己开发应用导出导入数据。
-## 17. TDengine 是否支持删除或更新已经写入的数据?
-
-TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。
-
-从 2.0.8.0 开始,TDengine 支持更新已经写入数据的功能。使用更新功能需要在创建数据库时使用 UPDATE 1 参数,之后可以使用 INSERT INTO 命令更新已经写入的相同时间戳数据。UPDATE 参数不支持 ALTER DATABASE 命令修改。没有使用 UPDATE 1 参数创建的数据库,写入相同时间戳的数据不会修改之前的数据,也不会报错。
\ No newline at end of file
diff --git a/packaging/cfg/taos.cfg b/packaging/cfg/taos.cfg
index 2908a8a21e503acd96c4d9d3976c9ee67bb86561..73004fe7b722d2fd2c15930f69a38d78aca4220d 100644
--- a/packaging/cfg/taos.cfg
+++ b/packaging/cfg/taos.cfg
@@ -265,9 +265,6 @@
# maximum display width of binary and nchar fields in the shell. The parts exceeding this limit will be hidden
# maxBinaryDisplayWidth 30
-# enable/disable telemetry reporting
-# telemetryReporting 1
-
# enable/disable stream (continuous query)
# stream 1
diff --git a/src/client/inc/tscSubquery.h b/src/client/inc/tscSubquery.h
index 7529891635f47fb4f2b68ede5b48ed5640c8f00a..e1370513ef28b4eb86d4caf8c7b34481f334c512 100644
--- a/src/client/inc/tscSubquery.h
+++ b/src/client/inc/tscSubquery.h
@@ -47,7 +47,6 @@ void tscLockByThread(int64_t *lockedBy);
void tscUnlockByThread(int64_t *lockedBy);
-
#ifdef __cplusplus
}
#endif
diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h
index 652e5bdd47b5bfa3adfdb8b8f58e94399c4de810..085791e45c0920174d6091328c4c5ae4f570eac0 100644
--- a/src/client/inc/tsclient.h
+++ b/src/client/inc/tsclient.h
@@ -317,7 +317,8 @@ typedef struct STscObj {
} STscObj;
typedef struct SSubqueryState {
- int32_t numOfRemain; // the number of remain unfinished subquery
+ pthread_mutex_t mutex;
+ int8_t *states;
int32_t numOfSub; // the number of total sub-queries
uint64_t numOfRetrievedRows; // total number of points in this query
} SSubqueryState;
diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c
index 6280cc520a9adf7b2d8686455b1524a8b356af83..c9c877c04319d43af7acad0ebe921a62800a20f0 100644
--- a/src/client/src/tscLocalMerge.c
+++ b/src/client/src/tscLocalMerge.c
@@ -1427,6 +1427,10 @@ int32_t tscDoLocalMerge(SSqlObj *pSql) {
tscResetForNextRetrieve(pRes);
if (pSql->signature != pSql || pRes == NULL || pRes->pLocalReducer == NULL) { // all data has been processed
+ if (pRes->code == TSDB_CODE_SUCCESS) {
+ return pRes->code;
+ }
+
tscError("%p local merge abort due to error occurs, code:%s", pSql, tstrerror(pRes->code));
return pRes->code;
}
diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c
index 64268124da93b30de4109ac5134eb87c759725d2..98c5374212d36746421658a5bdaf2f20768d1cb3 100644
--- a/src/client/src/tscSQLParser.c
+++ b/src/client/src/tscSQLParser.c
@@ -264,6 +264,7 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
case TSDB_SQL_DROP_DB: {
const char* msg2 = "invalid name";
const char* msg3 = "param name too long";
+ const char* msg4 = "table is not super table";
SStrToken* pzName = &pInfo->pDCLInfo->a[0];
if ((pInfo->type != TSDB_SQL_DROP_DNODE) && (tscValidateName(pzName) != TSDB_CODE_SUCCESS)) {
@@ -285,6 +286,18 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
if(code != TSDB_CODE_SUCCESS) {
return code;
}
+
+ if (pInfo->pDCLInfo->tableType == TSDB_SUPER_TABLE) {
+ code = tscGetTableMeta(pSql, pTableMetaInfo);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
+ }
+
+ if (!UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
+ }
+ }
+
} else if (pInfo->type == TSDB_SQL_DROP_DNODE) {
pzName->n = strdequote(pzName->z);
strncpy(pTableMetaInfo->name, pzName->z, pzName->n);
@@ -4794,6 +4807,7 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
const char* msg17 = "invalid column name";
const char* msg18 = "primary timestamp column cannot be dropped";
const char* msg19 = "invalid new tag name";
+ const char* msg20 = "table is not super table";
int32_t code = TSDB_CODE_SUCCESS;
@@ -4819,6 +4833,10 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
+ if (pAlterSQL->tableType == TSDB_SUPER_TABLE && !(UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo))) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg20);
+ }
+
if (pAlterSQL->type == TSDB_ALTER_TABLE_ADD_TAG_COLUMN || pAlterSQL->type == TSDB_ALTER_TABLE_DROP_TAG_COLUMN ||
pAlterSQL->type == TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN) {
if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) {
diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c
index 537e81413fdd74f54d74c1bb887f28498b0b7379..953680c43e68a45f507501253a24afb2e260d940 100644
--- a/src/client/src/tscServer.c
+++ b/src/client/src/tscServer.c
@@ -2193,7 +2193,7 @@ int tscProcessDropTableRsp(SSqlObj *pSql) {
tscDebug("%p remove table meta after drop table:%s, numOfRemain:%d", pSql, pTableMetaInfo->name,
(int32_t) taosHashGetSize(tscTableMetaInfo));
- assert(pTableMetaInfo->pTableMeta == NULL);
+ pTableMetaInfo->pTableMeta = NULL;
return 0;
}
diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c
index 2622246111894caf39f3c1c37923d1a7207935b6..ee9526e297f0b748df52e5e7b5cd552a2f39df34 100644
--- a/src/client/src/tscSubquery.c
+++ b/src/client/src/tscSubquery.c
@@ -55,6 +55,58 @@ static void skipRemainValue(STSBuf* pTSBuf, tVariant* tag1) {
}
}
+static void subquerySetState(SSqlObj *pSql, SSubqueryState *subState, int idx, int8_t state) {
+ assert(idx < subState->numOfSub);
+ assert(subState->states);
+
+ pthread_mutex_lock(&subState->mutex);
+
+ tscDebug("subquery:%p,%d state set to %d", pSql, idx, state);
+
+ subState->states[idx] = state;
+
+ pthread_mutex_unlock(&subState->mutex);
+}
+
+static bool allSubqueryDone(SSqlObj *pParentSql) {
+ bool done = true;
+ SSubqueryState *subState = &pParentSql->subState;
+
+ //lock in caller
+
+ for (int i = 0; i < subState->numOfSub; i++) {
+ if (0 == subState->states[i]) {
+ tscDebug("%p subquery:%p,%d is NOT finished, total:%d", pParentSql, pParentSql->pSubs[i], i, subState->numOfSub);
+ done = false;
+ break;
+ } else {
+ tscDebug("%p subquery:%p,%d is finished, total:%d", pParentSql, pParentSql->pSubs[i], i, subState->numOfSub);
+ }
+ }
+
+ return done;
+}
+
+static bool subAndCheckDone(SSqlObj *pSql, SSqlObj *pParentSql, int idx) {
+ SSubqueryState *subState = &pParentSql->subState;
+
+ assert(idx < subState->numOfSub);
+
+ pthread_mutex_lock(&subState->mutex);
+
+ tscDebug("%p subquery:%p,%d state set to 1", pParentSql, pSql, idx);
+
+ subState->states[idx] = 1;
+
+ bool done = allSubqueryDone(pParentSql);
+
+ pthread_mutex_unlock(&subState->mutex);
+
+ return done;
+}
+
+
+
static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJoinSupporter* pSupporter2, STimeWindow * win) {
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex);
@@ -367,10 +419,6 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) {
// scan all subquery, if one sub query has only ts, ignore it
tscDebug("%p start to launch secondary subqueries, %d out of %d needs to query", pSql, numOfSub, pSql->subState.numOfSub);
- //the subqueries that do not actually launch the secondary query to virtual node is set as completed.
- SSubqueryState* pState = &pSql->subState;
- pState->numOfRemain = numOfSub;
-
bool success = true;
for (int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
@@ -403,6 +451,7 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) {
success = false;
break;
}
+
tscClearSubqueryInfo(&pNew->cmd);
pSql->pSubs[i] = pNew;
@@ -480,6 +529,8 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) {
}
}
+ subquerySetState(pPrevSub, &pSql->subState, i, 0);
+
size_t numOfCols = taosArrayGetSize(pQueryInfo->colList);
tscDebug("%p subquery:%p tableIndex:%d, vgroupIndex:%d, type:%d, exprInfo:%" PRIzu ", colList:%" PRIzu ", fieldsInfo:%d, name:%s",
pSql, pNew, 0, pTableMetaInfo->vgroupIndex, pQueryInfo->type, taosArrayGetSize(pQueryInfo->exprList),
@@ -517,20 +568,25 @@ void freeJoinSubqueryObj(SSqlObj* pSql) {
SJoinSupporter* p = pSub->param;
tscDestroyJoinSupporter(p);
- if (pSub->res.code == TSDB_CODE_SUCCESS) {
- taos_free_result(pSub);
- }
+ taos_free_result(pSub);
+ pSql->pSubs[i] = NULL;
}
+ if (pSql->subState.states) {
+ pthread_mutex_destroy(&pSql->subState.mutex);
+ }
+
+ tfree(pSql->subState.states);
+
+
pSql->subState.numOfSub = 0;
}
-static void quitAllSubquery(SSqlObj* pSqlObj, SJoinSupporter* pSupporter) {
- assert(pSqlObj->subState.numOfRemain > 0);
-
- if (atomic_sub_fetch_32(&pSqlObj->subState.numOfRemain, 1) <= 0) {
- tscError("%p all subquery return and query failed, global code:%s", pSqlObj, tstrerror(pSqlObj->res.code));
+static void quitAllSubquery(SSqlObj* pSqlSub, SSqlObj* pSqlObj, SJoinSupporter* pSupporter) {
+ if (subAndCheckDone(pSqlSub, pSqlObj, pSupporter->subqueryIndex)) {
+ tscError("%p all subquery return and query failed, global code:%s", pSqlObj, tstrerror(pSqlObj->res.code));
freeJoinSubqueryObj(pSqlObj);
+ return;
}
//tscDestroyJoinSupporter(pSupporter);
@@ -777,6 +833,15 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
assert(TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY));
+ if (pParentSql->res.code != TSDB_CODE_SUCCESS) {
+ tscError("%p abort query due to other subquery failure. code:%d, global code:%d", pSql, numOfRows, pParentSql->res.code);
+ quitAllSubquery(pSql, pParentSql, pSupporter);
+
+ tscAsyncResultOnError(pParentSql);
+
+ return;
+ }
+
// check for the error code firstly
if (taos_errno(pSql) != TSDB_CODE_SUCCESS) {
// todo retry if other subqueries are not failed
@@ -785,7 +850,7 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
tscError("%p sub query failed, code:%s, index:%d", pSql, tstrerror(numOfRows), pSupporter->subqueryIndex);
pParentSql->res.code = numOfRows;
- quitAllSubquery(pParentSql, pSupporter);
+ quitAllSubquery(pSql, pParentSql, pSupporter);
tscAsyncResultOnError(pParentSql);
return;
@@ -802,7 +867,7 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
tscError("%p failed to malloc memory", pSql);
pParentSql->res.code = TAOS_SYSTEM_ERROR(errno);
- quitAllSubquery(pParentSql, pSupporter);
+ quitAllSubquery(pSql, pParentSql, pSupporter);
tscAsyncResultOnError(pParentSql);
return;
@@ -844,9 +909,10 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
// no data exists in next vnode, mark the query completed
// only when there is no subquery exits any more, proceeds to get the intersect of the tuple sets.
- if (atomic_sub_fetch_32(&pParentSql->subState.numOfRemain, 1) > 0) {
+ if (!subAndCheckDone(pSql, pParentSql, pSupporter->subqueryIndex)) {
+ tscDebug("%p tagRetrieve:%p,%d completed, total:%d", pParentSql, tres, pSupporter->subqueryIndex, pParentSql->subState.numOfSub);
return;
- }
+ }
SArray *s1 = NULL, *s2 = NULL;
int32_t code = getIntersectionOfTableTuple(pQueryInfo, pParentSql, &s1, &s2);
@@ -891,8 +957,10 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
((SJoinSupporter*)psub2->param)->pVgroupTables = tscVgroupTableInfoClone(pTableMetaInfo2->pVgroupTables);
pParentSql->subState.numOfSub = 2;
- pParentSql->subState.numOfRemain = pParentSql->subState.numOfSub;
-
+
+ memset(pParentSql->subState.states, 0, sizeof(pParentSql->subState.states[0]) * pParentSql->subState.numOfSub);
+ tscDebug("%p reset all sub states to 0", pParentSql);
+
for (int32_t m = 0; m < pParentSql->subState.numOfSub; ++m) {
SSqlObj* sub = pParentSql->pSubs[m];
issueTSCompQuery(sub, sub->param, pParentSql);
@@ -915,6 +983,15 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
assert(!TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_SEC_STAGE));
+ if (pParentSql->res.code != TSDB_CODE_SUCCESS) {
+ tscError("%p abort query due to other subquery failure. code:%d, global code:%d", pSql, numOfRows, pParentSql->res.code);
+ quitAllSubquery(pSql, pParentSql, pSupporter);
+
+ tscAsyncResultOnError(pParentSql);
+
+ return;
+ }
+
// check for the error code firstly
if (taos_errno(pSql) != TSDB_CODE_SUCCESS) {
// todo retry if other subqueries are not failed yet
@@ -922,7 +999,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
tscError("%p sub query failed, code:%s, index:%d", pSql, tstrerror(numOfRows), pSupporter->subqueryIndex);
pParentSql->res.code = numOfRows;
- quitAllSubquery(pParentSql, pSupporter);
+ quitAllSubquery(pSql, pParentSql, pSupporter);
tscAsyncResultOnError(pParentSql);
return;
@@ -937,7 +1014,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
pParentSql->res.code = TAOS_SYSTEM_ERROR(errno);
- quitAllSubquery(pParentSql, pSupporter);
+ quitAllSubquery(pSql, pParentSql, pSupporter);
tscAsyncResultOnError(pParentSql);
@@ -955,7 +1032,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
pParentSql->res.code = TAOS_SYSTEM_ERROR(errno);
- quitAllSubquery(pParentSql, pSupporter);
+ quitAllSubquery(pSql, pParentSql, pSupporter);
tscAsyncResultOnError(pParentSql);
@@ -1009,9 +1086,9 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
return;
}
- if (atomic_sub_fetch_32(&pParentSql->subState.numOfRemain, 1) > 0) {
+ if (!subAndCheckDone(pSql, pParentSql, pSupporter->subqueryIndex)) {
return;
- }
+ }
tscDebug("%p all subquery retrieve ts complete, do ts block intersect", pParentSql);
@@ -1049,6 +1126,17 @@ static void joinRetrieveFinalResCallback(void* param, TAOS_RES* tres, int numOfR
SSqlRes* pRes = &pSql->res;
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+
+ if (pParentSql->res.code != TSDB_CODE_SUCCESS) {
+ tscError("%p abort query due to other subquery failure. code:%d, global code:%d", pSql, numOfRows, pParentSql->res.code);
+ quitAllSubquery(pSql, pParentSql, pSupporter);
+
+ tscAsyncResultOnError(pParentSql);
+
+ return;
+ }
+
+
if (taos_errno(pSql) != TSDB_CODE_SUCCESS) {
assert(numOfRows == taos_errno(pSql));
@@ -1088,9 +1176,8 @@ static void joinRetrieveFinalResCallback(void* param, TAOS_RES* tres, int numOfR
}
}
- assert(pState->numOfRemain > 0);
- if (atomic_sub_fetch_32(&pState->numOfRemain, 1) > 0) {
- tscDebug("%p sub:%p completed, remain:%d, total:%d", pParentSql, tres, pState->numOfRemain, pState->numOfSub);
+ if (!subAndCheckDone(pSql, pParentSql, pSupporter->subqueryIndex)) {
+ tscDebug("%p sub:%p,%d completed, total:%d", pParentSql, tres, pSupporter->subqueryIndex, pState->numOfSub);
return;
}
@@ -1205,15 +1292,16 @@ void tscFetchDatablockForSubquery(SSqlObj* pSql) {
}
}
- // get the number of subquery that need to retrieve the next vnode.
+
if (orderedPrjQuery) {
for (int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
SSqlObj* pSub = pSql->pSubs[i];
if (pSub != NULL && pSub->res.row >= pSub->res.numOfRows && pSub->res.completed) {
- pSql->subState.numOfRemain++;
+ subquerySetState(pSub, &pSql->subState, i, 0);
}
}
}
+
for (int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
SSqlObj* pSub = pSql->pSubs[i];
@@ -1270,7 +1358,19 @@ void tscFetchDatablockForSubquery(SSqlObj* pSql) {
// retrieve data from current vnode.
tscDebug("%p retrieve data from %d subqueries", pSql, numOfFetch);
SJoinSupporter* pSupporter = NULL;
- pSql->subState.numOfRemain = numOfFetch;
+
+ for (int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
+ SSqlObj* pSql1 = pSql->pSubs[i];
+ if (pSql1 == NULL) {
+ continue;
+ }
+
+ SSqlRes* pRes1 = &pSql1->res;
+
+ if (pRes1->row >= pRes1->numOfRows) {
+ subquerySetState(pSql1, &pSql->subState, i, 0);
+ }
+ }
for (int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
SSqlObj* pSql1 = pSql->pSubs[i];
@@ -1372,7 +1472,8 @@ void tscJoinQueryCallback(void* param, TAOS_RES* tres, int code) {
// retrieve actual query results from vnode during the second stage join subquery
if (pParentSql->res.code != TSDB_CODE_SUCCESS) {
tscError("%p abort query due to other subquery failure. code:%d, global code:%d", pSql, code, pParentSql->res.code);
- quitAllSubquery(pParentSql, pSupporter);
+ quitAllSubquery(pSql, pParentSql, pSupporter);
+
tscAsyncResultOnError(pParentSql);
return;
@@ -1384,7 +1485,8 @@ void tscJoinQueryCallback(void* param, TAOS_RES* tres, int code) {
tscError("%p abort query, code:%s, global code:%s", pSql, tstrerror(code), tstrerror(pParentSql->res.code));
pParentSql->res.code = code;
- quitAllSubquery(pParentSql, pSupporter);
+
+ quitAllSubquery(pSql, pParentSql, pSupporter);
tscAsyncResultOnError(pParentSql);
return;
@@ -1408,9 +1510,9 @@ void tscJoinQueryCallback(void* param, TAOS_RES* tres, int code) {
// In case of consequence query from other vnode, do not wait for other query response here.
if (!(pTableMetaInfo->vgroupIndex > 0 && tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0))) {
- if (atomic_sub_fetch_32(&pParentSql->subState.numOfRemain, 1) > 0) {
+ if (!subAndCheckDone(pSql, pParentSql, pSupporter->subqueryIndex)) {
return;
- }
+ }
}
tscSetupOutputColumnIndex(pParentSql);
@@ -1422,6 +1524,7 @@ void tscJoinQueryCallback(void* param, TAOS_RES* tres, int code) {
if (pTableMetaInfo->vgroupIndex > 0 && tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
pSql->fp = joinRetrieveFinalResCallback; // continue retrieve data
pSql->cmd.command = TSDB_SQL_FETCH;
+
tscProcessSql(pSql);
} else { // first retrieve from vnode during the secondary stage sub-query
// set the command flag must be after the semaphore been correctly set.
@@ -1457,8 +1560,7 @@ int32_t tscCreateJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- pSql->pSubs[pSql->subState.numOfRemain++] = pNew;
- assert(pSql->subState.numOfRemain <= pSql->subState.numOfSub);
+ pSql->pSubs[tableIndex] = pNew;
if (QUERY_IS_JOIN_QUERY(pQueryInfo->type)) {
addGroupInfoForSubquery(pSql, pNew, 0, tableIndex);
@@ -1590,6 +1692,19 @@ void tscHandleMasterJoinQuery(SSqlObj* pSql) {
int32_t code = TSDB_CODE_SUCCESS;
pSql->subState.numOfSub = pQueryInfo->numOfTables;
+ if (pSql->subState.states == NULL) {
+ pSql->subState.states = calloc(pSql->subState.numOfSub, sizeof(*pSql->subState.states));
+ if (pSql->subState.states == NULL) {
+ code = TSDB_CODE_TSC_OUT_OF_MEMORY;
+ goto _error;
+ }
+
+ pthread_mutex_init(&pSql->subState.mutex, NULL);
+ }
+
+ memset(pSql->subState.states, 0, sizeof(*pSql->subState.states) * pSql->subState.numOfSub);
+ tscDebug("%p reset all sub states to 0", pSql);
+
bool hasEmptySub = false;
tscDebug("%p start subquery, total:%d", pSql, pQueryInfo->numOfTables);
@@ -1622,14 +1737,25 @@ void tscHandleMasterJoinQuery(SSqlObj* pSql) {
pSql->cmd.command = TSDB_SQL_RETRIEVE_EMPTY_RESULT;
(*pSql->fp)(pSql->param, pSql, 0);
} else {
+ int fail = 0;
for (int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
SSqlObj* pSub = pSql->pSubs[i];
+ if (fail) {
+ (*pSub->fp)(pSub->param, pSub, 0);
+ continue;
+ }
+
if ((code = tscProcessSql(pSub)) != TSDB_CODE_SUCCESS) {
- pSql->subState.numOfRemain = i - 1; // the already sent request will continue and do not go to the error process routine
- break;
+ pRes->code = code;
+ (*pSub->fp)(pSub->param, pSub, 0);
+ fail = 1;
}
}
+ if(fail) {
+ return;
+ }
+
pSql->cmd.command = TSDB_SQL_TABLE_JOIN_RETRIEVE;
}
@@ -1728,7 +1854,21 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
return ret;
}
- pState->numOfRemain = pState->numOfSub;
+ if (pState->states == NULL) {
+ pState->states = calloc(pState->numOfSub, sizeof(*pState->states));
+ if (pState->states == NULL) {
+ pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
+ tscAsyncResultOnError(pSql);
+ tfree(pMemoryBuf);
+ return ret;
+ }
+
+ pthread_mutex_init(&pState->mutex, NULL);
+ }
+
+ memset(pState->states, 0, sizeof(*pState->states) * pState->numOfSub);
+ tscDebug("%p reset all sub states to 0", pSql);
+
pRes->code = TSDB_CODE_SUCCESS;
int32_t i = 0;
@@ -1877,7 +2017,6 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO
assert(pSql != NULL);
SSubqueryState* pState = &pParentSql->subState;
- assert(pState->numOfRemain <= pState->numOfSub && pState->numOfRemain >= 0);
// retrieved in subquery failed. OR query cancelled in retrieve phase.
if (taos_errno(pSql) == TSDB_CODE_SUCCESS && pParentSql->res.code != TSDB_CODE_SUCCESS) {
@@ -1908,14 +2047,12 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO
}
}
- int32_t remain = -1;
- if ((remain = atomic_sub_fetch_32(&pState->numOfRemain, 1)) > 0) {
- tscDebug("%p sub:%p orderOfSub:%d freed, finished subqueries:%d", pParentSql, pSql, trsupport->subqueryIndex,
- pState->numOfSub - remain);
+ if (!subAndCheckDone(pSql, pParentSql, subqueryIndex)) {
+ tscDebug("%p sub:%p,%d freed, not finished, total:%d", pParentSql, pSql, trsupport->subqueryIndex, pState->numOfSub);
tscFreeRetrieveSup(pSql);
return;
- }
+ }
// all subqueries are failed
tscError("%p retrieve from %d vnode(s) completed,code:%s.FAILED.", pParentSql, pState->numOfSub,
@@ -1980,14 +2117,12 @@ static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* p
return;
}
- int32_t remain = -1;
- if ((remain = atomic_sub_fetch_32(&pParentSql->subState.numOfRemain, 1)) > 0) {
- tscDebug("%p sub:%p orderOfSub:%d freed, finished subqueries:%d", pParentSql, pSql, trsupport->subqueryIndex,
- pState->numOfSub - remain);
+ if (!subAndCheckDone(pSql, pParentSql, idx)) {
+ tscDebug("%p sub:%p orderOfSub:%d freed, not finished", pParentSql, pSql, trsupport->subqueryIndex);
tscFreeRetrieveSup(pSql);
return;
- }
+ }
// all sub-queries are returned, start to local merge process
pDesc->pColumnModel->capacity = trsupport->pExtMemBuffer[idx]->numOfElemsPerPage;
@@ -2033,7 +2168,6 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR
SSqlObj * pParentSql = trsupport->pParentSql;
SSubqueryState* pState = &pParentSql->subState;
- assert(pState->numOfRemain <= pState->numOfSub && pState->numOfRemain >= 0);
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, 0, 0);
SVgroupInfo *pVgroup = &pTableMetaInfo->vgroupList->vgroups[0];
@@ -2254,7 +2388,8 @@ static void multiVnodeInsertFinalize(void* param, TAOS_RES* tres, int numOfRows)
}
}
- if (atomic_sub_fetch_32(&pParentObj->subState.numOfRemain, 1) > 0) {
+ if (!subAndCheckDone(tres, pParentObj, pSupporter->index)) {
+ tscDebug("%p insert:%p,%d completed, total:%d", pParentObj, tres, pSupporter->index, pParentObj->subState.numOfSub);
return;
}
@@ -2288,6 +2423,8 @@ static void multiVnodeInsertFinalize(void* param, TAOS_RES* tres, int numOfRows)
STableMetaInfo* pMasterTableMetaInfo = tscGetTableMetaInfoFromCmd(&pParentObj->cmd, pSql->cmd.clauseIndex, 0);
tscAddTableMetaInfo(pQueryInfo, pMasterTableMetaInfo->name, NULL, NULL, NULL, NULL);
+ subquerySetState(pSql, &pParentObj->subState, i, 0);
+
tscDebug("%p, failed sub:%d, %p", pParentObj, i, pSql);
}
}
@@ -2302,7 +2439,6 @@ static void multiVnodeInsertFinalize(void* param, TAOS_RES* tres, int numOfRows)
}
pParentObj->cmd.parseFinished = false;
- pParentObj->subState.numOfRemain = numOfFailed;
tscResetSqlCmdObj(&pParentObj->cmd);
@@ -2378,7 +2514,19 @@ int32_t tscHandleMultivnodeInsert(SSqlObj *pSql) {
// the number of already initialized subqueries
int32_t numOfSub = 0;
- pSql->subState.numOfRemain = pSql->subState.numOfSub;
+ if (pSql->subState.states == NULL) {
+ pSql->subState.states = calloc(pSql->subState.numOfSub, sizeof(*pSql->subState.states));
+ if (pSql->subState.states == NULL) {
+ pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
+ goto _error;
+ }
+
+ pthread_mutex_init(&pSql->subState.mutex, NULL);
+ }
+
+ memset(pSql->subState.states, 0, sizeof(*pSql->subState.states) * pSql->subState.numOfSub);
+ tscDebug("%p reset all sub states to 0", pSql);
+
pSql->pSubs = calloc(pSql->subState.numOfSub, POINTER_BYTES);
if (pSql->pSubs == NULL) {
goto _error;
diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c
index 02cd9b9692ffa3e72270b57a4f1dd2dc146f0257..438836468bcb44b8c7d90a055d7b0a47cd2622e5 100644
--- a/src/client/src/tscUtil.c
+++ b/src/client/src/tscUtil.c
@@ -441,6 +441,12 @@ static void tscFreeSubobj(SSqlObj* pSql) {
pSql->pSubs[i] = NULL;
}
+ if (pSql->subState.states) {
+ pthread_mutex_destroy(&pSql->subState.mutex);
+ }
+
+ tfree(pSql->subState.states);
+
pSql->subState.numOfSub = 0;
}
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDatabaseMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDatabaseMetaData.java
index 4ea0fc79507dc1c0f5a963fba0e055491561a6b4..02556f6a73c9bc623c6c7a2c05ffea680596ac9a 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDatabaseMetaData.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDatabaseMetaData.java
@@ -535,6 +535,12 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
return null;
}
+ /**
+ * @Param catalog : database名称,"" 表示不属于任何database的table,null表示不使用database来缩小范围
+ * @Param schemaPattern : schema名称,""表示
+ * @Param tableNamePattern : 表名满足tableNamePattern的表, null表示返回所有表
+ * @Param types : 表类型,null表示返回所有类型
+ */
public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException {
if (conn == null || conn.isClosed()) {
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
@@ -544,10 +550,92 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
if (catalog == null || catalog.isEmpty())
return null;
- stmt.executeUpdate("use " + catalog);
- ResultSet resultSet0 = stmt.executeQuery("show tables");
- GetTablesResultSet getTablesResultSet = new GetTablesResultSet(resultSet0, catalog, schemaPattern, tableNamePattern, types);
- return getTablesResultSet;
+ ResultSet databases = stmt.executeQuery("show databases");
+ String dbname = null;
+ while (databases.next()) {
+ dbname = databases.getString("name");
+ if (dbname.equalsIgnoreCase(catalog))
+ break;
+ }
+ databases.close();
+ if (dbname == null)
+ return null;
+
+ stmt.execute("use " + dbname);
+ DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
+ List columnMetaDataList = new ArrayList<>();
+ ColumnMetaData col1 = new ColumnMetaData();
+ col1.setColIndex(1);
+ col1.setColName("TABLE_CAT");
+ col1.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col1);
+ ColumnMetaData col2 = new ColumnMetaData();
+ col2.setColIndex(2);
+ col2.setColName("TABLE_SCHEM");
+ col2.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col2);
+ ColumnMetaData col3 = new ColumnMetaData();
+ col3.setColIndex(3);
+ col3.setColName("TABLE_NAME");
+ col3.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col3);
+ ColumnMetaData col4 = new ColumnMetaData();
+ col4.setColIndex(4);
+ col4.setColName("TABLE_TYPE");
+ col4.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col4);
+ ColumnMetaData col5 = new ColumnMetaData();
+ col5.setColIndex(5);
+ col5.setColName("REMARKS");
+ col5.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col5);
+ ColumnMetaData col6 = new ColumnMetaData();
+ col6.setColIndex(6);
+ col6.setColName("TYPE_CAT");
+ col6.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col6);
+ ColumnMetaData col7 = new ColumnMetaData();
+ col7.setColIndex(7);
+ col7.setColName("TYPE_SCHEM");
+ col7.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col7);
+ ColumnMetaData col8 = new ColumnMetaData();
+ col8.setColIndex(8);
+ col8.setColName("TYPE_NAME");
+ col8.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col8);
+ ColumnMetaData col9 = new ColumnMetaData();
+ col9.setColIndex(9);
+ col9.setColName("SELF_REFERENCING_COL_NAME");
+ col9.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col9);
+ ColumnMetaData col10 = new ColumnMetaData();
+ col10.setColIndex(10);
+ col10.setColName("REF_GENERATION");
+ col10.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col10);
+ resultSet.setColumnMetaDataList(columnMetaDataList);
+
+ List rowDataList = new ArrayList<>();
+ ResultSet tables = stmt.executeQuery("show tables");
+ while (tables.next()) {
+ TSDBResultSetRowData rowData = new TSDBResultSetRowData(10);
+ rowData.setString(2, tables.getString("table_name"));
+ rowData.setString(3, "TABLE");
+ rowData.setString(4, "");
+ rowDataList.add(rowData);
+ }
+
+ ResultSet stables = stmt.executeQuery("show stables");
+ while (stables.next()) {
+ TSDBResultSetRowData rowData = new TSDBResultSetRowData(10);
+ rowData.setString(2, stables.getString("name"));
+ rowData.setString(3, "TABLE");
+ rowData.setString(4, "STABLE");
+ rowDataList.add(rowData);
+ }
+ resultSet.setRowDataList(rowDataList);
+ return resultSet;
}
}
@@ -560,125 +648,172 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
try (Statement stmt = conn.createStatement()) {
+ DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
+ // set up ColumnMetaDataList
+ List columnMetaDataList = new ArrayList<>(24);
+ // TABLE_CAT
+ ColumnMetaData col1 = new ColumnMetaData();
+ col1.setColIndex(1);
+ col1.setColName("TABLE_CAT");
+ col1.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col1);
+ resultSet.setColumnMetaDataList(columnMetaDataList);
+
+ List rowDataList = new ArrayList<>();
ResultSet rs = stmt.executeQuery("show databases");
- return new CatalogResultSet(rs);
+ while (rs.next()) {
+ TSDBResultSetRowData rowData = new TSDBResultSetRowData(1);
+ rowData.setString(0, rs.getString("name"));
+ rowDataList.add(rowData);
+ }
+ resultSet.setRowDataList(rowDataList);
+ return resultSet;
}
}
public ResultSet getTableTypes() throws SQLException {
- DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
+ if (conn == null || conn.isClosed())
+ throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
+ DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
// set up ColumnMetaDataList
- List columnMetaDataList = new ArrayList<>(1);
+ List columnMetaDataList = new ArrayList<>();
ColumnMetaData colMetaData = new ColumnMetaData();
colMetaData.setColIndex(0);
colMetaData.setColName("TABLE_TYPE");
colMetaData.setColSize(10);
- colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
+ colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
columnMetaDataList.add(colMetaData);
+ resultSet.setColumnMetaDataList(columnMetaDataList);
// set up rowDataList
- List rowDataList = new ArrayList<>(2);
- TSDBResultSetRowData rowData = new TSDBResultSetRowData();
+ List rowDataList = new ArrayList<>();
+ TSDBResultSetRowData rowData = new TSDBResultSetRowData(1);
rowData.setString(0, "TABLE");
rowDataList.add(rowData);
- rowData = new TSDBResultSetRowData();
+ rowData = new TSDBResultSetRowData(1);
rowData.setString(0, "STABLE");
rowDataList.add(rowData);
-
- resultSet.setColumnMetaDataList(columnMetaDataList);
resultSet.setRowDataList(rowDataList);
+
return resultSet;
}
- public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
- throws SQLException {
+ public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException {
+ if (conn == null || conn.isClosed())
+ throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
- /** add by zyyang **********/
- Statement stmt = null;
- if (null != conn && !conn.isClosed()) {
- stmt = conn.createStatement();
+ try (Statement stmt = conn.createStatement()) {
if (catalog == null || catalog.isEmpty())
return null;
- stmt.executeUpdate("use " + catalog);
+ ResultSet databases = stmt.executeQuery("show databases");
+ String dbname = null;
+ while (databases.next()) {
+ dbname = databases.getString("name");
+ if (dbname.equalsIgnoreCase(catalog))
+ break;
+ }
+ databases.close();
+ if (dbname == null)
+ return null;
+
+ stmt.execute("use " + dbname);
DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
// set up ColumnMetaDataList
List columnMetaDataList = new ArrayList<>(24);
+ // TABLE_CAT
+ ColumnMetaData col1 = new ColumnMetaData();
+ col1.setColIndex(1);
+ col1.setColName("TABLE_CAT");
+ col1.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col1);
+ // TABLE_SCHEM
+ ColumnMetaData col2 = new ColumnMetaData();
+ col2.setColIndex(2);
+ col2.setColName("TABLE_SCHEM");
+ col2.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col2);
+ // TABLE_NAME
+ ColumnMetaData col3 = new ColumnMetaData();
+ col3.setColIndex(3);
+ col3.setColName("TABLE_NAME");
+ col3.setColSize(193);
+ col3.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col3);
+ // COLUMN_NAME
+ ColumnMetaData col4 = new ColumnMetaData();
+ col4.setColIndex(4);
+ col4.setColName("COLUMN_NAME");
+ col4.setColSize(65);
+ col4.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col4);
+ // DATA_TYPE
+ ColumnMetaData col5 = new ColumnMetaData();
+ col5.setColIndex(5);
+ col5.setColName("DATA_TYPE");
+ col5.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
+ columnMetaDataList.add(col5);
+ // TYPE_NAME
+ ColumnMetaData col6 = new ColumnMetaData();
+ col6.setColIndex(6);
+ col6.setColName("TYPE_NAME");
+ col6.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col6);
+ // COLUMN_SIZE
+ ColumnMetaData col7 = new ColumnMetaData();
+ col7.setColIndex(7);
+ col7.setColName("COLUMN_SIZE");
+ col7.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
+ columnMetaDataList.add(col7);
+ // BUFFER_LENGTH ,not used
columnMetaDataList.add(null);
- columnMetaDataList.add(null);
- // add TABLE_NAME
- ColumnMetaData colMetaData = new ColumnMetaData();
- colMetaData.setColIndex(3);
- colMetaData.setColName("TABLE_NAME");
- colMetaData.setColSize(193);
- colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
- columnMetaDataList.add(colMetaData);
- // add COLUMN_NAME
- colMetaData = new ColumnMetaData();
- colMetaData.setColIndex(4);
- colMetaData.setColName("COLUMN_NAME");
- colMetaData.setColSize(65);
- colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
- columnMetaDataList.add(colMetaData);
- // add DATA_TYPE
- colMetaData = new ColumnMetaData();
- colMetaData.setColIndex(5);
- colMetaData.setColName("DATA_TYPE");
- colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
- columnMetaDataList.add(colMetaData);
- // add TYPE_NAME
- colMetaData = new ColumnMetaData();
- colMetaData.setColIndex(6);
- colMetaData.setColName("TYPE_NAME");
- colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
- columnMetaDataList.add(colMetaData);
- // add COLUMN_SIZE
- colMetaData = new ColumnMetaData();
- colMetaData.setColIndex(7);
- colMetaData.setColName("COLUMN_SIZE");
- colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
- columnMetaDataList.add(colMetaData);
- // add BUFFER_LENGTH ,not used
- columnMetaDataList.add(null);
- // add DECIMAL_DIGITS
- colMetaData = new ColumnMetaData();
- colMetaData.setColIndex(9);
- colMetaData.setColName("DECIMAL_DIGITS");
- colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
- columnMetaDataList.add(colMetaData);
+ // DECIMAL_DIGITS
+ ColumnMetaData col9 = new ColumnMetaData();
+ col9.setColIndex(9);
+ col9.setColName("DECIMAL_DIGITS");
+ col9.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
+ columnMetaDataList.add(col9);
// add NUM_PREC_RADIX
- colMetaData = new ColumnMetaData();
- colMetaData.setColIndex(10);
- colMetaData.setColName("NUM_PREC_RADIX");
- colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
- columnMetaDataList.add(colMetaData);
- // add NULLABLE
- colMetaData = new ColumnMetaData();
- colMetaData.setColIndex(11);
- colMetaData.setColName("NULLABLE");
- colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
- columnMetaDataList.add(colMetaData);
-
+ ColumnMetaData col10 = new ColumnMetaData();
+ col10.setColIndex(10);
+ col10.setColName("NUM_PREC_RADIX");
+ col10.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
+ columnMetaDataList.add(col10);
+ // NULLABLE
+ ColumnMetaData col11 = new ColumnMetaData();
+ col11.setColIndex(11);
+ col11.setColName("NULLABLE");
+ col11.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
+ columnMetaDataList.add(col11);
+ // REMARKS
+ ColumnMetaData col12 = new ColumnMetaData();
+ col12.setColIndex(12);
+ col12.setColName("REMARKS");
+ col12.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col12);
resultSet.setColumnMetaDataList(columnMetaDataList);
+
// set up rowDataList
- ResultSet resultSet0 = stmt.executeQuery("describe " + tableNamePattern);
+ ResultSet rs = stmt.executeQuery("describe " + dbname + "." + tableNamePattern);
List rowDataList = new ArrayList<>();
int index = 0;
- while (resultSet0.next()) {
+ while (rs.next()) {
TSDBResultSetRowData rowData = new TSDBResultSetRowData(24);
+ // set TABLE_CAT
+ rowData.setString(0, dbname);
// set TABLE_NAME
rowData.setString(2, tableNamePattern);
// set COLUMN_NAME
- rowData.setString(3, resultSet0.getString(1));
+ rowData.setString(3, rs.getString("Field"));
// set DATA_TYPE
- String typeName = resultSet0.getString(2);
+ String typeName = rs.getString("Type");
rowData.setInt(4, getDataType(typeName));
// set TYPE_NAME
rowData.setString(5, typeName);
// set COLUMN_SIZE
- int length = resultSet0.getInt(3);
+ int length = rs.getInt("Length");
rowData.setInt(6, getColumnSize(typeName, length));
// set DECIMAL_DIGITS
rowData.setInt(8, getDecimalDigits(typeName));
@@ -686,22 +821,18 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
rowData.setInt(9, 10);
// set NULLABLE
rowData.setInt(10, getNullable(index, typeName));
+ // set REMARKS
+ rowData.setString(11, rs.getString("Note"));
rowDataList.add(rowData);
index++;
}
resultSet.setRowDataList(rowDataList);
-
-// GetColumnsResultSet getColumnsResultSet = new GetColumnsResultSet(resultSet0, catalog, schemaPattern, tableNamePattern, columnNamePattern);
-// return getColumnsResultSet;
-// DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
return resultSet;
- } else {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
- }
-
- /*************************/
-// return getEmptyResultSet();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return null;
}
private int getNullable(int index, String typeName) {
@@ -778,7 +909,82 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
}
public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {
- return getEmptyResultSet();
+ if (conn == null || conn.isClosed())
+ throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
+
+ try (Statement stmt = conn.createStatement()) {
+ if (catalog == null || catalog.isEmpty())
+ return null;
+
+ ResultSet databases = stmt.executeQuery("show databases");
+ String dbname = null;
+ while (databases.next()) {
+ dbname = databases.getString("name");
+ if (dbname.equalsIgnoreCase(catalog))
+ break;
+ }
+ databases.close();
+ if (dbname == null)
+ return null;
+
+ stmt.execute("use " + dbname);
+ DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
+ // set up ColumnMetaDataList
+ List columnMetaDataList = new ArrayList<>();
+ // TABLE_CAT
+ ColumnMetaData col1 = new ColumnMetaData();
+ col1.setColIndex(0);
+ col1.setColName("TABLE_CAT");
+ col1.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col1);
+ // TABLE_SCHEM
+ ColumnMetaData col2 = new ColumnMetaData();
+ col2.setColIndex(1);
+ col2.setColName("TABLE_SCHEM");
+ col2.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col2);
+ // TABLE_NAME
+ ColumnMetaData col3 = new ColumnMetaData();
+ col3.setColIndex(2);
+ col3.setColName("TABLE_NAME");
+ col3.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col3);
+ // COLUMN_NAME
+ ColumnMetaData col4 = new ColumnMetaData();
+ col4.setColIndex(3);
+ col4.setColName("COLUMN_NAME");
+ col4.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col4);
+ // KEY_SEQ
+ ColumnMetaData col5 = new ColumnMetaData();
+ col5.setColIndex(4);
+ col5.setColName("KEY_SEQ");
+ col5.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
+ columnMetaDataList.add(col5);
+ // PK_NAME
+ ColumnMetaData col6 = new ColumnMetaData();
+ col6.setColIndex(5);
+ col6.setColName("PK_NAME");
+ col6.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col6);
+ resultSet.setColumnMetaDataList(columnMetaDataList);
+
+ // set rowData
+ List rowDataList = new ArrayList<>();
+ ResultSet rs = stmt.executeQuery("describe " + dbname + "." + table);
+ rs.next();
+ TSDBResultSetRowData rowData = new TSDBResultSetRowData(6);
+ rowData.setString(0, null);
+ rowData.setString(1, null);
+ rowData.setString(2, table);
+ String pkName = rs.getString(1);
+ rowData.setString(3, pkName);
+ rowData.setInt(4, 1);
+ rowData.setString(5, pkName);
+ rowDataList.add(rowData);
+ resultSet.setRowDataList(rowDataList);
+ return resultSet;
+ }
}
public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {
@@ -876,12 +1082,72 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
return false;
}
- public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {
+ 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 getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws
+ SQLException {
+ if (conn == null || conn.isClosed())
+ throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
+
+ try (Statement stmt = conn.createStatement()) {
+ if (catalog == null || catalog.isEmpty())
+ return null;
+
+ ResultSet databases = stmt.executeQuery("show databases");
+ String dbname = null;
+ while (databases.next()) {
+ dbname = databases.getString("name");
+ if (dbname.equalsIgnoreCase(catalog))
+ break;
+ }
+ databases.close();
+ if (dbname == null)
+ return null;
+
+ stmt.execute("use " + dbname);
+ DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
+ // set up ColumnMetaDataList
+ List columnMetaDataList = new ArrayList<>();
+ // TABLE_CAT
+ ColumnMetaData col1 = new ColumnMetaData();
+ col1.setColIndex(0);
+ col1.setColName("TABLE_CAT");
+ col1.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col1);
+ // TABLE_SCHEM
+ ColumnMetaData col2 = new ColumnMetaData();
+ col2.setColIndex(1);
+ col2.setColName("TABLE_SCHEM");
+ col2.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col2);
+ // TABLE_NAME
+ ColumnMetaData col3 = new ColumnMetaData();
+ col3.setColIndex(2);
+ col3.setColName("TABLE_NAME");
+ col3.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col3);
+ // SUPERTABLE_NAME
+ ColumnMetaData col4 = new ColumnMetaData();
+ col4.setColIndex(3);
+ col4.setColName("SUPERTABLE_NAME");
+ col4.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
+ columnMetaDataList.add(col4);
+ resultSet.setColumnMetaDataList(columnMetaDataList);
+
+ ResultSet rs = stmt.executeQuery("show tables like '" + tableNamePattern + "'");
+ List rowDataList = new ArrayList<>();
+ while (rs.next()) {
+ TSDBResultSetRowData rowData = new TSDBResultSetRowData(4);
+ rowData.setString(2, rs.getString(1));
+ rowData.setString(3, rs.getString(4));
+ rowDataList.add(rowData);
+ }
+ resultSet.setRowDataList(rowDataList);
+ return resultSet;
+ }
}
public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern,
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java
index c57f19550dd14719baecb835d76263df1e6a669b..6518bf10e444a05073206e1ef72b8f21a87e26b1 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java
@@ -26,9 +26,9 @@ public class TSDBResultSetRowData {
public TSDBResultSetRowData(int colSize) {
this.setColSize(colSize);
}
-
+
public TSDBResultSetRowData() {
- this.data = new ArrayList