Merge remote-tracking branch 'origin/develop' into feature/os
This commit is contained in:
commit
4b720b383a
|
@ -41,13 +41,10 @@ def pre_test(){
|
||||||
|
|
||||||
cd ${WKC}
|
cd ${WKC}
|
||||||
git checkout develop
|
git checkout develop
|
||||||
git reset --hard HEAD~10
|
git reset --hard HEAD~10 >/dev/null
|
||||||
git pull
|
git pull
|
||||||
git fetch
|
git fetch origin +refs/pull/${CHANGE_ID}/merge
|
||||||
git checkout ${CHANGE_BRANCH}
|
git checkout -qf FETCH_HEAD
|
||||||
git reset --hard HEAD~10
|
|
||||||
git pull
|
|
||||||
git merge develop
|
|
||||||
cd ${WK}
|
cd ${WK}
|
||||||
git reset --hard HEAD~10
|
git reset --hard HEAD~10
|
||||||
git checkout develop
|
git checkout develop
|
||||||
|
@ -87,11 +84,14 @@ pipeline {
|
||||||
steps {
|
steps {
|
||||||
|
|
||||||
pre_test()
|
pre_test()
|
||||||
sh '''
|
timeout(time: 90, unit: 'MINUTES'){
|
||||||
cd ${WKC}/tests
|
sh '''
|
||||||
find pytest -name '*'sql|xargs rm -rf
|
cd ${WKC}/tests
|
||||||
./test-all.sh p1
|
find pytest -name '*'sql|xargs rm -rf
|
||||||
date'''
|
./test-all.sh p1
|
||||||
|
date'''
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('python_2') {
|
stage('python_2') {
|
||||||
|
@ -112,12 +112,14 @@ pipeline {
|
||||||
}
|
}
|
||||||
stage('test_b1') {
|
stage('test_b1') {
|
||||||
agent{label 'b1'}
|
agent{label 'b1'}
|
||||||
steps {
|
steps {
|
||||||
pre_test()
|
timeout(time: 90, unit: 'MINUTES'){
|
||||||
sh '''
|
pre_test()
|
||||||
cd ${WKC}/tests
|
sh '''
|
||||||
./test-all.sh b1fq
|
cd ${WKC}/tests
|
||||||
date'''
|
./test-all.sh b1fq
|
||||||
|
date'''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,12 +139,14 @@ pipeline {
|
||||||
./handle_crash_gen_val_log.sh
|
./handle_crash_gen_val_log.sh
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
sh '''
|
timeout(time: 90, unit: 'MINUTES'){
|
||||||
date
|
sh '''
|
||||||
cd ${WKC}/tests
|
date
|
||||||
./test-all.sh b2fq
|
cd ${WKC}/tests
|
||||||
date
|
./test-all.sh b2fq
|
||||||
'''
|
date
|
||||||
|
'''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,12 +161,14 @@ pipeline {
|
||||||
./valgrind-test.sh 2>&1 > mem-error-out.log
|
./valgrind-test.sh 2>&1 > mem-error-out.log
|
||||||
./handle_val_log.sh
|
./handle_val_log.sh
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
sh '''
|
timeout(time: 90, unit: 'MINUTES'){
|
||||||
date
|
sh '''
|
||||||
cd ${WKC}/tests
|
date
|
||||||
./test-all.sh b3fq
|
cd ${WKC}/tests
|
||||||
date'''
|
./test-all.sh b3fq
|
||||||
|
date'''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
|
@ -9,7 +9,7 @@
|
||||||
TDengine 采用 SQL 作为查询语言。应用程序可以通过 C/C++, Java, Go, Python 连接器发送 SQL 语句,用户可以通过 TDengine 提供的命令行(Command Line Interface, CLI)工具 TAOS Shell 手动执行 SQL 即席查询(Ad-Hoc Query)。TDengine 支持如下查询功能:
|
TDengine 采用 SQL 作为查询语言。应用程序可以通过 C/C++, Java, Go, Python 连接器发送 SQL 语句,用户可以通过 TDengine 提供的命令行(Command Line Interface, CLI)工具 TAOS Shell 手动执行 SQL 即席查询(Ad-Hoc Query)。TDengine 支持如下查询功能:
|
||||||
|
|
||||||
- 单列、多列数据查询
|
- 单列、多列数据查询
|
||||||
- 标签和数值的多种过滤条件:\>, \<, =, \<>, like 等
|
- 标签和数值的多种过滤条件:>, <, =, <>, like 等
|
||||||
- 聚合结果的分组(Group by)、排序(Order by)、约束输出(Limit/Offset)
|
- 聚合结果的分组(Group by)、排序(Order by)、约束输出(Limit/Offset)
|
||||||
- 数值列及聚合结果的四则运算
|
- 数值列及聚合结果的四则运算
|
||||||
- 时间戳对齐的连接查询(Join Query: 隐式连接)操作
|
- 时间戳对齐的连接查询(Join Query: 隐式连接)操作
|
||||||
|
|
|
@ -58,26 +58,26 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic
|
||||||
|
|
||||||
- **创建数据库**
|
- **创建数据库**
|
||||||
|
|
||||||
```mysql
|
```mysql
|
||||||
CREATE DATABASE [IF NOT EXISTS] db_name [KEEP keep] [UPDATE 1];
|
CREATE DATABASE [IF NOT EXISTS] db_name [KEEP keep] [UPDATE 1];
|
||||||
```
|
```
|
||||||
说明:
|
说明:
|
||||||
|
|
||||||
1) KEEP是该数据库的数据保留多长天数,缺省是3650天(10年),数据库会自动删除超过时限的数据;
|
1) KEEP是该数据库的数据保留多长天数,缺省是3650天(10年),数据库会自动删除超过时限的数据;
|
||||||
|
|
||||||
2) UPDATE 标志数据库支持更新相同时间戳数据;
|
2) UPDATE 标志数据库支持更新相同时间戳数据;
|
||||||
|
|
||||||
3) 数据库名最大长度为33;
|
3) 数据库名最大长度为33;
|
||||||
|
|
||||||
4) 一条SQL 语句的最大长度为65480个字符;
|
4) 一条SQL 语句的最大长度为65480个字符;
|
||||||
|
|
||||||
5) 数据库还有更多与存储相关的配置参数,请参见系统管理。
|
5) 数据库还有更多与存储相关的配置参数,请参见系统管理。
|
||||||
|
|
||||||
- **显示系统当前参数**
|
- **显示系统当前参数**
|
||||||
|
|
||||||
```mysql
|
```mysql
|
||||||
SHOW VARIABLES;
|
SHOW VARIABLES;
|
||||||
```
|
```
|
||||||
|
|
||||||
- **使用数据库**
|
- **使用数据库**
|
||||||
|
|
||||||
|
@ -1125,11 +1125,8 @@ SELECT function_list FROM stb_name
|
||||||
- WHERE语句可以指定查询的起止时间和其他过滤条件
|
- WHERE语句可以指定查询的起止时间和其他过滤条件
|
||||||
- FILL语句指定某一时间区间数据缺失的情况下的填充模式。填充模式包括以下几种:
|
- FILL语句指定某一时间区间数据缺失的情况下的填充模式。填充模式包括以下几种:
|
||||||
1. 不进行填充:NONE(默认填充模式)。
|
1. 不进行填充:NONE(默认填充模式)。
|
||||||
|
|
||||||
2. VALUE填充:固定值填充,此时需要指定填充的数值。例如:fill(value, 1.23)。
|
2. VALUE填充:固定值填充,此时需要指定填充的数值。例如:fill(value, 1.23)。
|
||||||
|
|
||||||
3. NULL填充:使用NULL填充数据。例如:fill(null)。
|
3. NULL填充:使用NULL填充数据。例如:fill(null)。
|
||||||
|
|
||||||
4. PREV填充:使用前一个非NULL值填充数据。例如:fill(prev)。
|
4. PREV填充:使用前一个非NULL值填充数据。例如:fill(prev)。
|
||||||
|
|
||||||
说明:
|
说明:
|
||||||
|
|
|
@ -124,10 +124,10 @@ taosd -C
|
||||||
对于一个应用场景,可能有多种数据特征的数据并存,最佳的设计是将具有相同数据特征的表放在一个库里,这样一个应用有多个库,而每个库可以配置不同的存储参数,从而保证系统有最优的性能。TDengine允许应用在创建库时指定上述存储参数,如果指定,该参数就将覆盖对应的系统配置参数。举例,有下述SQL:
|
对于一个应用场景,可能有多种数据特征的数据并存,最佳的设计是将具有相同数据特征的表放在一个库里,这样一个应用有多个库,而每个库可以配置不同的存储参数,从而保证系统有最优的性能。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时,涉及集群相关的一些参数必须与已有集群的配置相同,否则不能成功加入到集群中。会进行校验的参数如下:
|
TDengine集群中加入一个新的dnode时,涉及集群相关的一些参数必须与已有集群的配置相同,否则不能成功加入到集群中。会进行校验的参数如下:
|
||||||
|
|
||||||
|
|
|
@ -197,7 +197,7 @@ select * from meters where ts > now - 1d and current > 10;
|
||||||
且`restart`是 **false**(**0**),用户程序就不会读到之前已经读取的数据了。
|
且`restart`是 **false**(**0**),用户程序就不会读到之前已经读取的数据了。
|
||||||
|
|
||||||
`taos_subscribe`的最后一个参数是以毫秒为单位的轮询周期。
|
`taos_subscribe`的最后一个参数是以毫秒为单位的轮询周期。
|
||||||
在同步模式下,如过前后两次调用`taos_consume`的时间间隔小于此时间,
|
在同步模式下,如果前后两次调用`taos_consume`的时间间隔小于此时间,
|
||||||
`taos_consume`会阻塞,直到间隔超过此时间。
|
`taos_consume`会阻塞,直到间隔超过此时间。
|
||||||
异步模式下,这个时间是两次调用回调函数的最小时间间隔。
|
异步模式下,这个时间是两次调用回调函数的最小时间间隔。
|
||||||
|
|
||||||
|
@ -414,7 +414,7 @@ TDengine通过查询函数向用户提供毫秒级的数据获取能力。直接
|
||||||
|
|
||||||
TDengine分配固定大小的内存空间作为缓存空间,缓存空间可根据应用的需求和硬件资源配置。通过适当的设置缓存空间,TDengine可以提供极高性能的写入和查询的支持。TDengine中每个虚拟节点(virtual node)创建时分配独立的缓存池。每个虚拟节点管理自己的缓存池,不同虚拟节点间不共享缓存池。每个虚拟节点内部所属的全部表共享该虚拟节点的缓存池。
|
TDengine分配固定大小的内存空间作为缓存空间,缓存空间可根据应用的需求和硬件资源配置。通过适当的设置缓存空间,TDengine可以提供极高性能的写入和查询的支持。TDengine中每个虚拟节点(virtual node)创建时分配独立的缓存池。每个虚拟节点管理自己的缓存池,不同虚拟节点间不共享缓存池。每个虚拟节点内部所属的全部表共享该虚拟节点的缓存池。
|
||||||
|
|
||||||
TDengine将内存池按块划分进行管理,数据在内存块里按照列式存储。一个vnode的内存池是在vnode创建时按块分配好的,而且每个内存块按照先进先出的原则进行管理。一张表所需要的内存块是从vnode的内存池中进行分配的,块的大小由系统配置参数cache决定。每张表最大内存块的数目由配置参数tblocks决定,每张表平均的内存块的个数由配置参数ablocks决定。因此对于一个vnode, 总的内存大小为: `cache * ablocks * tables`。内存块参数cache不宜过小,一个cache block需要能存储至少几十条以上记录,才会有效率。参数ablocks最小为2,保证每张表平均至少能分配两个内存块。
|
TDengine将内存池按块划分进行管理,数据在内存块里是以行(row)的形式存储。一个vnode的内存池是在vnode创建时按块分配好,而且每个内存块按照先进先出的原则进行管理。在创建内存池时,块的大小由系统配置参数cache决定;每个vnode中内存块的数目则由配置参数blocks决定。因此对于一个vnode,总的内存大小为:`cache * blocks`。一个cache block需要保证每张表能存储至少几十条以上记录,才会有效率。
|
||||||
|
|
||||||
你可以通过函数last_row快速获取一张表或一张超级表的最后一条记录,这样很便于在大屏显示各设备的实时状态或采集值。例如:
|
你可以通过函数last_row快速获取一张表或一张超级表的最后一条记录,这样很便于在大屏显示各设备的实时状态或采集值。例如:
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,7 @@ SHOW MNODES;
|
||||||
|
|
||||||
## Arbitrator的使用
|
## Arbitrator的使用
|
||||||
|
|
||||||
如果副本数为偶数,当一个vnode group里一半vnode不工作时,是无法从中选出master的。同理,一半mnode不工作时,是无法选出mnode的master的,因为存在“split brain”问题。为解决这个问题,TDengine引入了arbitrator的概念。Arbitrator模拟一个vnode或mnode在工作,但只简单的负责网络连接,不处理任何数据插入或访问。只要包含arbitrator在内,超过半数的vnode或mnode工作,那么该vnode group或mnode组就可以正常的提供数据插入或查询服务。比如对于副本数为2的情形,如果一个节点A离线,但另外一个节点B正常,而且能连接到arbitrator, 那么节点B就能正常工作。
|
如果副本数为偶数,当一个vnode group里一半vnode不工作时,是无法从中选出master的。同理,一半mnode不工作时,是无法选出mnode的master的,因为存在“split brain”问题。为解决这个问题,TDengine引入了Arbitrator的概念。Arbitrator模拟一个vnode或mnode在工作,但只简单的负责网络连接,不处理任何数据插入或访问。只要包含Arbitrator在内,超过半数的vnode或mnode工作,那么该vnode group或mnode组就可以正常的提供数据插入或查询服务。比如对于副本数为2的情形,如果一个节点A离线,但另外一个节点B正常,而且能连接到Arbitrator,那么节点B就能正常工作。
|
||||||
|
|
||||||
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,系统也不会去建立连接。
|
||||||
|
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
#集群安装、管理
|
|
||||||
|
|
||||||
多个taosd的运行实例可以组成一个集群,以保证TDengine的高可靠运行,并提供水平扩展能力。要了解TDengine 2.0的集群管理,需要对集群的基本概念有所了解,请看TDengine 2.0整体架构一章。
|
|
||||||
|
|
||||||
集群的每个节点是由End Point来唯一标识的,End Point是由FQDN(Fully Qualified Domain Name)外加Port组成,比如 h1.taosdata.com:6030。一般FQDN就是服务器的hostname,可通过Linux命令“hostname"获取。端口是这个节点对外服务的端口号,缺省是6030,但可以通过taos.cfg里配置参数serverPort进行修改。
|
|
||||||
|
|
||||||
TDengine的集群管理极其简单,除添加和删除节点需要人工干预之外,其他全部是自动完成,最大程度的降低了运维的工作量。本章对集群管理的操作做详细的描述。
|
|
||||||
|
|
||||||
##安装、创建第一个节点
|
|
||||||
|
|
||||||
集群是由一个一个dnode组成的,是从一个dnode的创建开始的。创建第一个节点很简单,就按照["立即开始“](https://www.taosdata.com/cn/getting-started/)一章的方法进行安装、启动即可。
|
|
||||||
|
|
||||||
启动后,请执行taos, 启动taos shell,从shell里执行命令"show dnodes;",如下所示:
|
|
||||||
```
|
|
||||||
Welcome to the TDengine shell from Linux, Client Version:2.0.0.0
|
|
||||||
Copyright (c) 2017 by TAOS Data, Inc. All rights reserved.
|
|
||||||
|
|
||||||
taos> show dnodes;
|
|
||||||
id | end_point | vnodes | cores | status | role | create_time |
|
|
||||||
=====================================================================================
|
|
||||||
1 | h1.taos.com:6030 | 0 | 2 | ready | any | 2020-07-31 03:49:29.202 |
|
|
||||||
Query OK, 1 row(s) in set (0.006385s)
|
|
||||||
|
|
||||||
taos>
|
|
||||||
```
|
|
||||||
上述命令里,可以看到这个刚启动的这个节点的End Point是:h1.taos.com:6030
|
|
||||||
|
|
||||||
## 安装、创建后续节点
|
|
||||||
|
|
||||||
将新的节点添加到现有集群,具体有以下几步:
|
|
||||||
|
|
||||||
1. 按照["立即开始“](https://www.taosdata.com/cn/getting-started/)一章的方法进行安装,但不要启动taosd
|
|
||||||
|
|
||||||
2. 如果是使用涛思数据的官方安装包进行安装,在安装结束时,会询问集群的End Port, 输入第一个节点的End Point即可。如果是源码安装,请编辑配置文件taos.cfg(缺省是在/etc/taos/目录),增加一行:
|
|
||||||
|
|
||||||
```
|
|
||||||
firstEp h1.taos.com:6030
|
|
||||||
```
|
|
||||||
|
|
||||||
请注意将示例的“h1.taos.com:6030" 替换为你自己第一个节点的End Point
|
|
||||||
|
|
||||||
3. 按照["立即开始“](https://www.taosdata.com/cn/getting-started/)一章的方法启动taosd
|
|
||||||
|
|
||||||
4. 在Linux shell里执行命令"hostname"找出本机的FQDN, 假设为h2.taos.com。如果无法找到,可以查看taosd日志文件taosdlog.0里前面几行日志(一般在/var/log/taos目录),fqdn以及port都会打印出来。
|
|
||||||
|
|
||||||
5. 在第一个节点,使用CLI程序taos, 登录进TDengine系统, 使用命令:
|
|
||||||
|
|
||||||
```
|
|
||||||
CREATE DNODE "h2.taos.com:6030";
|
|
||||||
```
|
|
||||||
|
|
||||||
将新节点的End Point添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。请注意将示例的“h2.taos.com:6030" 替换为你自己第一个节点的End Point
|
|
||||||
|
|
||||||
6. 使用命令
|
|
||||||
|
|
||||||
```
|
|
||||||
SHOW DNODES;
|
|
||||||
```
|
|
||||||
|
|
||||||
查看新节点是否被成功加入。
|
|
||||||
|
|
||||||
按照上述步骤可以源源不断的将新的节点加入到集群。
|
|
||||||
|
|
||||||
**提示:**
|
|
||||||
|
|
||||||
- firstEp, secondEp这两个参数仅仅在该节点第一次加入集群时有作用,加入集群后,该节点会保存最新的mnode的End Point列表,不再依赖这两个参数。
|
|
||||||
- 两个没有配置first, second参数的dnode启动后,会独立运行起来。这个时候,无法将其中一个节点加入到另外一个节点,形成集群。**无法将两个独立的集群合并成为新的集群**。
|
|
||||||
|
|
||||||
##节点管理
|
|
||||||
|
|
||||||
###添加节点
|
|
||||||
执行CLI程序taos, 使用root账号登录进系统, 执行:
|
|
||||||
```
|
|
||||||
CREATE DNODE "fqdn:port";
|
|
||||||
```
|
|
||||||
将新节点的End Point添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。一个节点对外服务的fqdn和port可以通过配置文件taos.cfg进行配置,缺省是自动获取。
|
|
||||||
|
|
||||||
###删除节点
|
|
||||||
执行CLI程序taos, 使用root账号登录进TDengine系统,执行:
|
|
||||||
```
|
|
||||||
DROP DNODE "fqdn:port";
|
|
||||||
```
|
|
||||||
其中fqdn是被删除的节点的FQDN,port是其对外服务器的端口号
|
|
||||||
|
|
||||||
###查看节点
|
|
||||||
执行CLI程序taos,使用root账号登录进TDengine系统,执行:
|
|
||||||
```
|
|
||||||
SHOW DNODES;
|
|
||||||
```
|
|
||||||
它将列出集群中所有的dnode,每个dnode的fqdn:port, 状态(ready, offline等),vnode数目,还未使用的vnode数目等信息。在添加或删除一个节点后,可以使用该命令查看。
|
|
||||||
|
|
||||||
如果集群配置了Arbitrator,那么它也会在这个节点列表中显示出来,其role列的值会是“arb”。
|
|
||||||
|
|
||||||
###查看虚拟节点组
|
|
||||||
|
|
||||||
为充分利用多核技术,并提供scalability,数据需要分片处理。因此TDengine会将一个DB的数据切分成多份,存放在多个vnode里。这些vnode可能分布在多个dnode里,这样就实现了水平扩展。一个vnode仅仅属于一个DB,但一个DB可以有多个vnode。vnode的是mnode根据当前系统资源的情况,自动进行分配的,无需任何人工干预。
|
|
||||||
|
|
||||||
执行CLI程序taos,使用root账号登录进TDengine系统,执行:
|
|
||||||
```
|
|
||||||
SHOW VGROUPS;
|
|
||||||
```
|
|
||||||
##高可用性
|
|
||||||
TDengine通过多副本的机制来提供系统的高可用性。副本数是与DB关联的,一个集群里可以有多个DB,根据运营的需求,每个DB可以配置不同的副本数。创建数据库时,通过参数replica 指定副本数(缺省为1)。如果副本数为1,系统的可靠性无法保证,只要数据所在的节点宕机,就将无法提供服务。集群的节点数必须大于等于副本数,否则创建表时将返回错误“more dnodes are needed"。比如下面的命令将创建副本数为3的数据库demo:
|
|
||||||
```
|
|
||||||
CREATE DATABASE demo replica 3;
|
|
||||||
```
|
|
||||||
一个DB里的数据会被切片分到多个vnode group,vnode group里的vnode数目就是DB的副本数,同一个vnode group里各vnode的数据是完全一致的。为保证高可用性,vnode group里的vnode一定要分布在不同的dnode里(实际部署时,需要在不同的物理机上),只要一个vgroup里超过半数的vnode处于工作状态,这个vgroup就能正常的对外服务。
|
|
||||||
|
|
||||||
一个dnode里可能有多个DB的数据,因此一个dnode离线时,可能会影响到多个DB。如果一个vnode group里的一半或一半以上的vnode不工作,那么该vnode group就无法对外服务,无法插入或读取数据,这样会影响到它所属的DB的一部分表的d读写操作。
|
|
||||||
|
|
||||||
因为vnode的引入,无法简单的给出结论:“集群中过半dnode工作,集群就应该工作”。但是对于简单的情形,很好下结论。比如副本数为3,只有三个dnode,那如果仅有一个节点不工作,整个集群还是可以正常工作的,但如果有两个节点不工作,那整个集群就无法正常工作了。
|
|
||||||
|
|
||||||
##Mnode的高可用
|
|
||||||
TDengine集群是由mnode (taosd的一个模块,逻辑节点) 负责管理的,为保证mnode的高可用,可以配置多个mnode副本,副本数由系统配置参数numOfMnodes决定,有效范围为1-3。为保证元数据的强一致性,mnode副本之间是通过同步的方式进行数据复制的。
|
|
||||||
|
|
||||||
一个集群有多个dnode, 但一个dnode至多运行一个mnode实例。多个dnode情况下,哪个dnode可以作为mnode呢?这是完全由系统根据整个系统资源情况,自动指定的。用户可通过CLI程序taos,在TDengine的console里,执行如下命令:
|
|
||||||
```
|
|
||||||
SHOW MNODES;
|
|
||||||
```
|
|
||||||
来查看mnode列表,该列表将列出mnode所处的dnode的End Point和角色(master, slave, unsynced 或offline)。
|
|
||||||
当集群中第一个节点启动时,该节点一定会运行一个mnode实例,否则该dnode无法正常工作,因为一个系统是必须有至少一个mnode的。如果numOfMnodes配置为2,启动第二个dnode时,该dnode也将运行一个mnode实例。
|
|
||||||
|
|
||||||
为保证mnode服务的高可用性,numOfMnodes必须设置为2或更大。因为mnode保存的元数据必须是强一致的,如果numOfMnodes大于2,复制参数quorum自动设为2,也就是说,至少要保证有两个副本写入数据成功,才通知客户端应用写入成功。
|
|
||||||
|
|
||||||
##负载均衡
|
|
||||||
|
|
||||||
有三种情况,将触发负载均衡,而且都无需人工干预。
|
|
||||||
|
|
||||||
- 当一个新节点添加进集群时,系统将自动触发负载均衡,一些节点上的数据将被自动转移到新节点上,无需任何人工干预。
|
|
||||||
- 当一个节点从集群中移除时,系统将自动把该节点上的数据转移到其他节点,无需任何人工干预。
|
|
||||||
- 如果一个节点过热(数据量过大),系统将自动进行负载均衡,将该节点的一些vnode自动挪到其他节点。
|
|
||||||
|
|
||||||
当上述三种情况发生时,系统将启动一各个节点的负载计算,从而决定如何挪动。
|
|
||||||
|
|
||||||
##节点离线处理
|
|
||||||
如果一个节点离线,TDengine集群将自动检测到。有如下两种情况:
|
|
||||||
- 改节点离线超过一定时间(taos.cfg里配置参数offlineThreshold控制时长),系统将自动把该节点删除,产生系统报警信息,触发负载均衡流程。如果该被删除的节点重现上线时,它将无法加入集群,需要系统管理员重新将其添加进集群才会开始工作。
|
|
||||||
- 离线后,在offlineThreshold的时长内重新上线,系统将自动启动数据恢复流程,等数据完全恢复后,该节点将开始正常工作。
|
|
||||||
|
|
||||||
##Arbitrator的使用
|
|
||||||
|
|
||||||
如果副本数为偶数,当一个vnode group里一半vnode不工作时,是无法从中选出master的。同理,一半mnode不工作时,是无法选出mnode的master的,因为存在“split brain”问题。为解决这个问题,TDengine引入了arbitrator的概念。Arbitrator模拟一个vnode或mnode在工作,但只简单的负责网络连接,不处理任何数据插入或访问。只要包含arbitrator在内,超过半数的vnode或mnode工作,那么该vnode group或mnode组就可以正常的提供数据插入或查询服务。比如对于副本数为2的情形,如果一个节点A离线,但另外一个节点B正常,而且能连接到arbitrator, 那么节点B就能正常工作。
|
|
||||||
|
|
||||||
TDengine安装包里带有一个执行程序tarbitrator, 找任何一台Linux服务器运行它即可。该程序对系统资源几乎没有要求,只需要保证有网络连接即可。该应用的命令行参数`-p`可以指定其对外服务的端口号,缺省是6030。配置每个taosd实例时,可以在配置文件taos.cfg里将参数arbitrator设置为Arbitrator的End Point。如果该参数配置了,当副本数为偶数时,系统将自动连接配置的Arbitrator。
|
|
||||||
|
|
||||||
在配置了Arbitrator的情况下,它也会显示在“show dnodes;”指令给出的节点列表中。
|
|
|
@ -1,62 +1,62 @@
|
||||||
# Java Connector
|
# Java Connector
|
||||||
|
|
||||||
Java连接器支持的系统有:
|
TDengine 提供了遵循 JDBC 标准(3.0)API 规范的 `taos-jdbcdriver` 实现,可在 maven 的中央仓库 [Sonatype Repository][1] 搜索下载。
|
||||||
| **CPU类型** | x64(64bit) | | | ARM64 | ARM32 |
|
|
||||||
| ------------ | ------------ | -------- | -------- | -------- | -------- |
|
|
||||||
| **OS类型** | Linux | Win64 | Win32 | Linux | Linux |
|
|
||||||
| **支持与否** | **支持** | **支持** | **支持** | **支持** | **支持** |
|
|
||||||
|
|
||||||
Java连接器的使用请参见<a href=https://www.taosdata.com/blog/2020/11/11/1955.html>视频教程</a>。
|
`taos-jdbcdriver` 的实现包括 2 种形式: JDBC-JNI 和 JDBC-RESTful(taos-jdbcdriver-2.0.17 开始支持 JDBC-RESTful)。 JDBC-JNI 通过调用客户端 libtaos.so(或 taos.dll )的本地方法实现, JDBC-RESTful 则在内部封装了 RESTful 接口实现。
|
||||||
|
|
||||||
TDengine 为了方便 Java 应用使用,提供了遵循 JDBC 标准(3.0)API 规范的 `taos-jdbcdriver` 实现。目前可以通过 [Sonatype Repository][1] 搜索并下载。
|

|
||||||
|
|
||||||
由于 TDengine 是使用 c 语言开发的,使用 taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库。
|
上图显示了 3 种 Java 应用使用连接器访问 TDengine 的方式:
|
||||||
|
|
||||||
* libtaos.so
|
* JDBC-JNI:Java 应用在物理节点1(pnode1)上使用 JDBC-JNI 的 API ,直接调用客户端 API(libtaos.so 或 taos.dll)将写入和查询请求发送到位于物理节点2(pnode2)上的 taosd 实例。
|
||||||
在 linux 系统中成功安装 TDengine 后,依赖的本地函数库 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so,该目录包含在 Linux 自动扫描路径上,无需单独指定。
|
* RESTful:应用将 SQL 发送给位于物理节点2(pnode2)上的 RESTful 连接器,再调用客户端 API(libtaos.so)。
|
||||||
|
* JDBC-RESTful:Java 应用通过 JDBC-RESTful 的 API ,将 SQL 封装成一个 RESTful 请求,发送给物理节点2的 RESTful 连接器。
|
||||||
|
|
||||||
* taos.dll
|
TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致,但时序空间数据库与关系对象型数据库服务的对象和技术特征存在差异,导致 `taos-jdbcdriver` 与传统的 JDBC driver 也存在一定差异。在使用时需要注意以下几点:
|
||||||
在 windows 系统中安装完客户端之后,驱动包依赖的 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。
|
|
||||||
|
|
||||||
> 注意:在 windows 环境开发时需要安装 TDengine 对应的 [windows 客户端][14],Linux 服务器安装完 TDengine 之后默认已安装 client,也可以单独安装 [Linux 客户端][15] 连接远程 TDengine Server。
|
* TDengine 目前不支持针对单条数据记录的删除操作。
|
||||||
|
* 目前不支持事务操作。
|
||||||
TDengine 的 JDBC 驱动实现尽可能的与关系型数据库驱动保持一致,但时序空间数据库与关系对象型数据库服务的对象和技术特征的差异导致 taos-jdbcdriver 并未完全实现 JDBC 标准规范。在使用时需要注意以下几点:
|
|
||||||
|
|
||||||
* TDengine 不提供针对单条数据记录的删除和修改的操作,驱动中也没有支持相关方法。
|
|
||||||
* 由于不支持删除和修改,所以也不支持事务操作。
|
|
||||||
* 目前不支持表间的 union 操作。
|
* 目前不支持表间的 union 操作。
|
||||||
* 目前不支持嵌套查询(nested query),对每个 Connection 的实例,至多只能有一个打开的 ResultSet 实例;如果在 ResultSet还没关闭的情况下执行了新的查询,TSDBJDBCDriver 则会自动关闭上一个 ResultSet。
|
* 目前不支持嵌套查询(nested query)。
|
||||||
|
* 对每个 Connection 的实例,至多只能有一个打开的 ResultSet 实例;如果在 ResultSet 还没关闭的情况下执行了新的查询,taos-jdbcdriver 会自动关闭上一个 ResultSet。
|
||||||
|
|
||||||
## TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本
|
|
||||||
|
|
||||||
| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
|
## JDBC-JNI和JDBC-RESTful的对比
|
||||||
| --- | --- | --- |
|
|
||||||
| 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
|
<table >
|
||||||
|
<tr align="center"><th>对比项</th><th>JDBC-JNI</th><th>JDBC-RESTful</th></tr>
|
||||||
|
<tr align="center">
|
||||||
|
<td>支持的操作系统</td>
|
||||||
|
<td>linux、windows</td>
|
||||||
|
<td>全平台</td>
|
||||||
|
</tr>
|
||||||
|
<tr align="center">
|
||||||
|
<td>是否需要安装 client</td>
|
||||||
|
<td>需要</td>
|
||||||
|
<td>不需要</td>
|
||||||
|
</tr>
|
||||||
|
<tr align="center">
|
||||||
|
<td>server 升级后是否需要升级 client</td>
|
||||||
|
<td>需要</td>
|
||||||
|
<td>不需要</td>
|
||||||
|
</tr>
|
||||||
|
<tr align="center">
|
||||||
|
<td>写入性能</td>
|
||||||
|
<td colspan="2">JDBC-RESTful 是 JDBC-JNI 的 50%~90% </td>
|
||||||
|
</tr>
|
||||||
|
<tr align="center">
|
||||||
|
<td>查询性能</td>
|
||||||
|
<td colspan="2">JDBC-RESTful 与 JDBC-JNI 没有差别</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下:
|
|
||||||
|
|
||||||
| TDengine DataType | Java DataType |
|
## 如何获取 taos-jdbcdriver
|
||||||
| --- | --- |
|
|
||||||
| 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
|
|
||||||
|
|
||||||
### maven 仓库
|
### maven 仓库
|
||||||
|
|
||||||
目前 taos-jdbcdriver 已经发布到 [Sonatype Repository][1] 仓库,且各大仓库都已同步。
|
目前 taos-jdbcdriver 已经发布到 [Sonatype Repository][1] 仓库,且各大仓库都已同步。
|
||||||
|
|
||||||
* [sonatype][8]
|
* [sonatype][8]
|
||||||
* [mvnrepository][9]
|
* [mvnrepository][9]
|
||||||
* [maven.aliyun][10]
|
* [maven.aliyun][10]
|
||||||
|
@ -67,30 +67,63 @@ maven 项目中使用如下 pom.xml 配置即可:
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.taosdata.jdbc</groupId>
|
<groupId>com.taosdata.jdbc</groupId>
|
||||||
<artifactId>taos-jdbcdriver</artifactId>
|
<artifactId>taos-jdbcdriver</artifactId>
|
||||||
<version>2.0.4</version>
|
<version>2.0.17</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 源码编译打包
|
### 源码编译打包
|
||||||
|
|
||||||
下载 [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
|
```java
|
||||||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||||||
String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata";
|
String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata";
|
||||||
Connection conn = DriverManager.getConnection(jdbcUrl);
|
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 的使用请参见<a href=https://www.taosdata.com/blog/2020/11/11/1955.html>视频教程</a>。
|
||||||
|
|
||||||
TDengine 的 JDBC URL 规范格式为:
|
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中的配置参数如下:
|
url中的配置参数如下:
|
||||||
* user:登录 TDengine 用户名,默认值 root。
|
* user:登录 TDengine 用户名,默认值 root。
|
||||||
* password:用户登录密码,默认值 taosdata。
|
* password:用户登录密码,默认值 taosdata。
|
||||||
|
@ -99,13 +132,17 @@ url中的配置参数如下:
|
||||||
* locale:客户端语言环境,默认值系统当前 locale。
|
* locale:客户端语言环境,默认值系统当前 locale。
|
||||||
* timezone:客户端使用的时区,默认值为系统当前时区。
|
* timezone:客户端使用的时区,默认值为系统当前时区。
|
||||||
|
|
||||||
#### 使用JdbcUrl和Properties获取连接
|
|
||||||
|
|
||||||
除了通过指定的jdbcUrl获取连接,还可以使用Properties指定建立连接时的参数,如下所示:
|
|
||||||
|
#### 指定URL和Properties获取连接
|
||||||
|
|
||||||
|
除了通过指定的 URL 获取连接,还可以使用 Properties 指定建立连接时的参数,如下所示:
|
||||||
```java
|
```java
|
||||||
public Connection getConn() throws Exception{
|
public Connection getConn() throws Exception{
|
||||||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
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://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();
|
Properties connProps = new Properties();
|
||||||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||||||
|
@ -114,9 +151,10 @@ public Connection getConn() throws Exception{
|
||||||
return conn;
|
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_USER:登录 TDengine 用户名,默认值 root。
|
||||||
* TSDBDriver.PROPERTY_KEY_PASSWORD:用户登录密码,默认值 taosdata。
|
* TSDBDriver.PROPERTY_KEY_PASSWORD:用户登录密码,默认值 taosdata。
|
||||||
* TSDBDriver.PROPERTY_KEY_CONFIG_DIR:客户端配置文件目录路径,Linux OS 上默认值 /etc/taos ,Windows OS 上默认值 C:/TDengine/cfg。
|
* 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_LOCALE:客户端语言环境,默认值系统当前 locale。
|
||||||
* TSDBDriver.PROPERTY_KEY_TIME_ZONE:客户端使用的时区,默认值为系统当前时区。
|
* TSDBDriver.PROPERTY_KEY_TIME_ZONE:客户端使用的时区,默认值为系统当前时区。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### 使用客户端配置文件建立连接
|
#### 使用客户端配置文件建立连接
|
||||||
当使用JDBC连接TDengine集群时,可以使用客户端配置文件,在客户端配置文件中指定集群的firstEp、secondEp参数。
|
|
||||||
|
当使用 JDBC-JNI 连接 TDengine 集群时,可以使用客户端配置文件,在客户端配置文件中指定集群的 firstEp、secondEp参数。
|
||||||
如下所示:
|
如下所示:
|
||||||
1. 在java中不指定hostname和port
|
|
||||||
|
1. 在 Java 应用中不指定 hostname 和 port
|
||||||
```java
|
```java
|
||||||
public Connection getConn() throws Exception{
|
public Connection getConn() throws Exception{
|
||||||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||||||
|
@ -140,7 +182,7 @@ public Connection getConn() throws Exception{
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
2. 在配置文件中指定firstEp和secondEp
|
2. 在配置文件中指定 firstEp 和 secondEp
|
||||||
```
|
```
|
||||||
# first fully qualified domain name (FQDN) for TDengine system
|
# first fully qualified domain name (FQDN) for TDengine system
|
||||||
firstEp cluster_node1:6030
|
firstEp cluster_node1:6030
|
||||||
|
@ -155,17 +197,19 @@ secondEp cluster_node2:6030
|
||||||
# locale en_US.UTF-8
|
# locale en_US.UTF-8
|
||||||
```
|
```
|
||||||
|
|
||||||
以上示例,jdbc会使用客户端的配置文件,建立到hostname为cluster_node1,端口为6030,数据库名为test的连接。当集群中firstEp节点失效时,JDBC会尝试使用secondEp连接集群。
|
以上示例,jdbc 会使用客户端的配置文件,建立到 hostname 为 cluster_node1、端口为 6030、数据库名为 test 的连接。当集群中 firstEp 节点失效时,JDBC 会尝试使用 secondEp 连接集群。
|
||||||
TDengine中,只要保证firstEp和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 的参数中指定。
|
1. JDBC URL 参数,如上所述,可以在 JDBC URL 的参数中指定。
|
||||||
2. Properties connProps
|
2. Properties connProps
|
||||||
3. 客户端配置文件 taos.cfg
|
3. 客户端配置文件 taos.cfg
|
||||||
例如:在url中指定了password为taosdata,在Properties中指定了password为taosdemo,那么,JDBC会使用url中的password建立连接。
|
|
||||||
|
例如:在 url 中指定了 password 为 taosdata,在 Properties 中指定了 password 为 taosdemo,那么,JDBC 会使用 url 中的 password 建立连接。
|
||||||
|
|
||||||
> 更多详细配置请参考[客户端配置][13]
|
> 更多详细配置请参考[客户端配置][13]
|
||||||
|
|
||||||
|
@ -183,6 +227,7 @@ stmt.executeUpdate("use db");
|
||||||
// create table
|
// create table
|
||||||
stmt.executeUpdate("create table if not exists tb (ts timestamp, temperature int, humidity float)");
|
stmt.executeUpdate("create table if not exists tb (ts timestamp, temperature int, humidity float)");
|
||||||
```
|
```
|
||||||
|
|
||||||
> 注意:如果不使用 `use db` 指定数据库,则后续对表的操作都需要增加数据库名称作为前缀,如 db.tb。
|
> 注意:如果不使用 `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.");
|
System.out.println("insert " + affectedRows + " rows.");
|
||||||
```
|
```
|
||||||
|
|
||||||
> now 为系统内部函数,默认为服务器当前时间。
|
> now 为系统内部函数,默认为服务器当前时间。
|
||||||
> `now + 1s` 代表服务器当前时间往后加 1 秒,数字后面代表时间单位:a(毫秒), s(秒), m(分), h(小时), d(天),w(周), n(月), y(年)。
|
> `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);
|
System.out.printf("%s, %d, %s\n", ts, temperature, humidity);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> 查询和操作关系型数据库一致,使用下标获取返回字段内容时从 1 开始,建议使用字段名称获取。
|
> 查询和操作关系型数据库一致,使用下标获取返回字段内容时从 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();
|
stmt.close();
|
||||||
conn.close();
|
conn.close();
|
||||||
```
|
```
|
||||||
|
|
||||||
> `注意务必要将 connection 进行关闭`,否则会出现连接泄露。
|
> `注意务必要将 connection 进行关闭`,否则会出现连接泄露。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 与连接池使用
|
## 与连接池使用
|
||||||
|
|
||||||
**HikariCP**
|
**HikariCP**
|
||||||
|
@ -306,6 +356,7 @@ conn.close();
|
||||||
connection.close(); // put back to conneciton pool
|
connection.close(); // put back to conneciton pool
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> 通过 HikariDataSource.getConnection() 获取连接后,使用完成后需要调用 close() 方法,实际上它并不会关闭连接,只是放回连接池中。
|
> 通过 HikariDataSource.getConnection() 获取连接后,使用完成后需要调用 close() 方法,实际上它并不会关闭连接,只是放回连接池中。
|
||||||
> 更多 HikariCP 使用问题请查看[官方说明][5]
|
> 更多 HikariCP 使用问题请查看[官方说明][5]
|
||||||
|
|
||||||
|
@ -356,6 +407,7 @@ public static void main(String[] args) throws Exception {
|
||||||
connection.close(); // put back to conneciton pool
|
connection.close(); // put back to conneciton pool
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> 更多 druid 使用问题请查看[官方说明][6]
|
> 更多 druid 使用问题请查看[官方说明][6]
|
||||||
|
|
||||||
**注意事项**
|
**注意事项**
|
||||||
|
@ -370,10 +422,43 @@ server_status()|
|
||||||
Query OK, 1 row(s) in set (0.000141s)
|
Query OK, 1 row(s) in set (0.000141s)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 与框架使用
|
## 与框架使用
|
||||||
|
|
||||||
* Spring JdbcTemplate 中使用 taos-jdbcdriver,可参考 [SpringJdbcTemplate][11]
|
* 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。
|
**原因**:程序没有找到依赖的本地函数库 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
|
* 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
|
[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
|
[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
|
[15]: https://www.taosdata.com/cn/getting-started/#%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,9 @@ TDengine还没有一组专用的validation queries。然而建议你使用系统
|
||||||
|
|
||||||
## 9. 我可以删除或更新一条记录吗?
|
## 9. 我可以删除或更新一条记录吗?
|
||||||
|
|
||||||
不能。因为TDengine是为联网设备采集的数据设计的,不容许修改。但TDengine提供数据保留策略,只要数据记录超过保留时长,就会被自动删除。
|
TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。
|
||||||
|
|
||||||
|
从 2.0.8.0 开始,TDengine 支持更新已经写入数据的功能。使用更新功能需要在创建数据库时使用 UPDATE 1 参数,之后可以使用 INSERT INTO 命令更新已经写入的相同时间戳数据。UPDATE 参数不支持 ALTER DATABASE 命令修改。没有使用 UPDATE 1 参数创建的数据库,写入相同时间戳的数据不会修改之前的数据,也不会报错。
|
||||||
|
|
||||||
## 10. 我怎么创建超过1024列的表?
|
## 10. 我怎么创建超过1024列的表?
|
||||||
|
|
||||||
|
@ -132,8 +134,3 @@ TDengine是根据hostname唯一标志一台机器的,在数据文件从机器A
|
||||||
- 2.0.7.0 及以后的版本,到/var/lib/taos/dnode下,修复dnodeEps.json的dnodeId对应的FQDN,重启。确保机器内所有机器的此文件是完全相同的。
|
- 2.0.7.0 及以后的版本,到/var/lib/taos/dnode下,修复dnodeEps.json的dnodeId对应的FQDN,重启。确保机器内所有机器的此文件是完全相同的。
|
||||||
- 1.x 和 2.x 版本的存储结构不兼容,需要使用迁移工具或者自己开发应用导出导入数据。
|
- 1.x 和 2.x 版本的存储结构不兼容,需要使用迁移工具或者自己开发应用导出导入数据。
|
||||||
|
|
||||||
## 17. TDengine 是否支持删除或更新已经写入的数据?
|
|
||||||
|
|
||||||
TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。
|
|
||||||
|
|
||||||
从 2.0.8.0 开始,TDengine 支持更新已经写入数据的功能。使用更新功能需要在创建数据库时使用 UPDATE 1 参数,之后可以使用 INSERT INTO 命令更新已经写入的相同时间戳数据。UPDATE 参数不支持 ALTER DATABASE 命令修改。没有使用 UPDATE 1 参数创建的数据库,写入相同时间戳的数据不会修改之前的数据,也不会报错。
|
|
|
@ -222,7 +222,7 @@ MQTT是一流行的物联网数据传输协议,TDengine 可以很方便的接
|
||||||
|
|
||||||
## EMQ Broker 直接写入
|
## EMQ Broker 直接写入
|
||||||
|
|
||||||
<a href="https://github.com/emqx/emqx">EMQ</a>是一开源的MQTT Broker软件,无需任何代码,只需要在EMQ Dashboard里使用“规则”做简单配置,即可将MQTT的数据直接写入TDengine。EMQ X 支持通过 发送到 Web 服务 的方式保存数据到 TDengine,也在企业版上提供原生的 TDEngine 驱动实现直接保存。详细使用方法请参考<a href="https://docs.emqx.io/broker/latest/cn/rule/rule-example.html#%E4%BF%9D%E5%AD%98%E6%95%B0%E6%8D%AE%E5%88%B0-tdengine">EMQ 官方文档</a>。
|
<a href="https://github.com/emqx/emqx">EMQ</a>是一开源的MQTT Broker软件,无需任何代码,只需要在EMQ Dashboard里使用“规则”做简单配置,即可将MQTT的数据直接写入TDengine。EMQ X 支持通过 发送到 Web 服务 的方式保存数据到 TDengine,也在企业版上提供原生的 TDengine 驱动实现直接保存。详细使用方法请参考<a href="https://docs.emqx.io/broker/latest/cn/rule/rule-example.html#%E4%BF%9D%E5%AD%98%E6%95%B0%E6%8D%AE%E5%88%B0-tdengine">EMQ 官方文档</a>。
|
||||||
|
|
||||||
## HiveMQ Broker 直接写入
|
## HiveMQ Broker 直接写入
|
||||||
|
|
||||||
|
|
|
@ -265,9 +265,6 @@
|
||||||
# maximum display width of binary and nchar fields in the shell. The parts exceeding this limit will be hidden
|
# maximum display width of binary and nchar fields in the shell. The parts exceeding this limit will be hidden
|
||||||
# maxBinaryDisplayWidth 30
|
# maxBinaryDisplayWidth 30
|
||||||
|
|
||||||
# enable/disable telemetry reporting
|
|
||||||
# telemetryReporting 1
|
|
||||||
|
|
||||||
# enable/disable stream (continuous query)
|
# enable/disable stream (continuous query)
|
||||||
# stream 1
|
# stream 1
|
||||||
|
|
||||||
|
|
|
@ -535,6 +535,12 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
|
||||||
return null;
|
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 {
|
public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException {
|
||||||
if (conn == null || conn.isClosed()) {
|
if (conn == null || conn.isClosed()) {
|
||||||
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
|
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())
|
if (catalog == null || catalog.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
stmt.executeUpdate("use " + catalog);
|
ResultSet databases = stmt.executeQuery("show databases");
|
||||||
ResultSet resultSet0 = stmt.executeQuery("show tables");
|
String dbname = null;
|
||||||
GetTablesResultSet getTablesResultSet = new GetTablesResultSet(resultSet0, catalog, schemaPattern, tableNamePattern, types);
|
while (databases.next()) {
|
||||||
return getTablesResultSet;
|
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<ColumnMetaData> 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<TSDBResultSetRowData> 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));
|
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
|
||||||
|
|
||||||
try (Statement stmt = conn.createStatement()) {
|
try (Statement stmt = conn.createStatement()) {
|
||||||
|
DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
|
||||||
|
// set up ColumnMetaDataList
|
||||||
|
List<ColumnMetaData> 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<TSDBResultSetRowData> rowDataList = new ArrayList<>();
|
||||||
ResultSet rs = stmt.executeQuery("show databases");
|
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 {
|
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
|
// set up ColumnMetaDataList
|
||||||
List<ColumnMetaData> columnMetaDataList = new ArrayList<>(1);
|
List<ColumnMetaData> columnMetaDataList = new ArrayList<>();
|
||||||
ColumnMetaData colMetaData = new ColumnMetaData();
|
ColumnMetaData colMetaData = new ColumnMetaData();
|
||||||
colMetaData.setColIndex(0);
|
colMetaData.setColIndex(0);
|
||||||
colMetaData.setColName("TABLE_TYPE");
|
colMetaData.setColName("TABLE_TYPE");
|
||||||
colMetaData.setColSize(10);
|
colMetaData.setColSize(10);
|
||||||
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
|
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
|
||||||
columnMetaDataList.add(colMetaData);
|
columnMetaDataList.add(colMetaData);
|
||||||
|
resultSet.setColumnMetaDataList(columnMetaDataList);
|
||||||
|
|
||||||
// set up rowDataList
|
// set up rowDataList
|
||||||
List<TSDBResultSetRowData> rowDataList = new ArrayList<>(2);
|
List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
|
||||||
TSDBResultSetRowData rowData = new TSDBResultSetRowData();
|
TSDBResultSetRowData rowData = new TSDBResultSetRowData(1);
|
||||||
rowData.setString(0, "TABLE");
|
rowData.setString(0, "TABLE");
|
||||||
rowDataList.add(rowData);
|
rowDataList.add(rowData);
|
||||||
rowData = new TSDBResultSetRowData();
|
rowData = new TSDBResultSetRowData(1);
|
||||||
rowData.setString(0, "STABLE");
|
rowData.setString(0, "STABLE");
|
||||||
rowDataList.add(rowData);
|
rowDataList.add(rowData);
|
||||||
|
|
||||||
resultSet.setColumnMetaDataList(columnMetaDataList);
|
|
||||||
resultSet.setRowDataList(rowDataList);
|
resultSet.setRowDataList(rowDataList);
|
||||||
|
|
||||||
return resultSet;
|
return resultSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
|
public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException {
|
||||||
throws SQLException {
|
if (conn == null || conn.isClosed())
|
||||||
|
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
|
||||||
|
|
||||||
/** add by zyyang **********/
|
try (Statement stmt = conn.createStatement()) {
|
||||||
Statement stmt = null;
|
|
||||||
if (null != conn && !conn.isClosed()) {
|
|
||||||
stmt = conn.createStatement();
|
|
||||||
if (catalog == null || catalog.isEmpty())
|
if (catalog == null || catalog.isEmpty())
|
||||||
return null;
|
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();
|
DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
|
||||||
// set up ColumnMetaDataList
|
// set up ColumnMetaDataList
|
||||||
List<ColumnMetaData> columnMetaDataList = new ArrayList<>(24);
|
List<ColumnMetaData> 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);
|
||||||
columnMetaDataList.add(null);
|
// DECIMAL_DIGITS
|
||||||
// add TABLE_NAME
|
ColumnMetaData col9 = new ColumnMetaData();
|
||||||
ColumnMetaData colMetaData = new ColumnMetaData();
|
col9.setColIndex(9);
|
||||||
colMetaData.setColIndex(3);
|
col9.setColName("DECIMAL_DIGITS");
|
||||||
colMetaData.setColName("TABLE_NAME");
|
col9.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
|
||||||
colMetaData.setColSize(193);
|
columnMetaDataList.add(col9);
|
||||||
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);
|
|
||||||
// add NUM_PREC_RADIX
|
// add NUM_PREC_RADIX
|
||||||
colMetaData = new ColumnMetaData();
|
ColumnMetaData col10 = new ColumnMetaData();
|
||||||
colMetaData.setColIndex(10);
|
col10.setColIndex(10);
|
||||||
colMetaData.setColName("NUM_PREC_RADIX");
|
col10.setColName("NUM_PREC_RADIX");
|
||||||
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
|
col10.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
|
||||||
columnMetaDataList.add(colMetaData);
|
columnMetaDataList.add(col10);
|
||||||
// add NULLABLE
|
// NULLABLE
|
||||||
colMetaData = new ColumnMetaData();
|
ColumnMetaData col11 = new ColumnMetaData();
|
||||||
colMetaData.setColIndex(11);
|
col11.setColIndex(11);
|
||||||
colMetaData.setColName("NULLABLE");
|
col11.setColName("NULLABLE");
|
||||||
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
|
col11.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
|
||||||
columnMetaDataList.add(colMetaData);
|
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);
|
resultSet.setColumnMetaDataList(columnMetaDataList);
|
||||||
|
|
||||||
|
|
||||||
// set up rowDataList
|
// set up rowDataList
|
||||||
ResultSet resultSet0 = stmt.executeQuery("describe " + tableNamePattern);
|
ResultSet rs = stmt.executeQuery("describe " + dbname + "." + tableNamePattern);
|
||||||
List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
|
List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while (resultSet0.next()) {
|
while (rs.next()) {
|
||||||
TSDBResultSetRowData rowData = new TSDBResultSetRowData(24);
|
TSDBResultSetRowData rowData = new TSDBResultSetRowData(24);
|
||||||
|
// set TABLE_CAT
|
||||||
|
rowData.setString(0, dbname);
|
||||||
// set TABLE_NAME
|
// set TABLE_NAME
|
||||||
rowData.setString(2, tableNamePattern);
|
rowData.setString(2, tableNamePattern);
|
||||||
// set COLUMN_NAME
|
// set COLUMN_NAME
|
||||||
rowData.setString(3, resultSet0.getString(1));
|
rowData.setString(3, rs.getString("Field"));
|
||||||
// set DATA_TYPE
|
// set DATA_TYPE
|
||||||
String typeName = resultSet0.getString(2);
|
String typeName = rs.getString("Type");
|
||||||
rowData.setInt(4, getDataType(typeName));
|
rowData.setInt(4, getDataType(typeName));
|
||||||
// set TYPE_NAME
|
// set TYPE_NAME
|
||||||
rowData.setString(5, typeName);
|
rowData.setString(5, typeName);
|
||||||
// set COLUMN_SIZE
|
// set COLUMN_SIZE
|
||||||
int length = resultSet0.getInt(3);
|
int length = rs.getInt("Length");
|
||||||
rowData.setInt(6, getColumnSize(typeName, length));
|
rowData.setInt(6, getColumnSize(typeName, length));
|
||||||
// set DECIMAL_DIGITS
|
// set DECIMAL_DIGITS
|
||||||
rowData.setInt(8, getDecimalDigits(typeName));
|
rowData.setInt(8, getDecimalDigits(typeName));
|
||||||
|
@ -686,22 +821,18 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
|
||||||
rowData.setInt(9, 10);
|
rowData.setInt(9, 10);
|
||||||
// set NULLABLE
|
// set NULLABLE
|
||||||
rowData.setInt(10, getNullable(index, typeName));
|
rowData.setInt(10, getNullable(index, typeName));
|
||||||
|
// set REMARKS
|
||||||
|
rowData.setString(11, rs.getString("Note"));
|
||||||
rowDataList.add(rowData);
|
rowDataList.add(rowData);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
resultSet.setRowDataList(rowDataList);
|
resultSet.setRowDataList(rowDataList);
|
||||||
|
|
||||||
// GetColumnsResultSet getColumnsResultSet = new GetColumnsResultSet(resultSet0, catalog, schemaPattern, tableNamePattern, columnNamePattern);
|
|
||||||
// return getColumnsResultSet;
|
|
||||||
// DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
|
|
||||||
return resultSet;
|
return resultSet;
|
||||||
} else {
|
|
||||||
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
/*************************/
|
|
||||||
|
|
||||||
// return getEmptyResultSet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getNullable(int index, String typeName) {
|
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 {
|
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<ColumnMetaData> 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<TSDBResultSetRowData> 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 {
|
public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {
|
||||||
|
@ -876,12 +1082,72 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
|
||||||
return false;
|
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();
|
return getEmptyResultSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
|
public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws
|
||||||
return getEmptyResultSet();
|
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<ColumnMetaData> 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<TSDBResultSetRowData> 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,
|
public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern,
|
||||||
|
|
|
@ -26,9 +26,9 @@ public class TSDBResultSetRowData {
|
||||||
public TSDBResultSetRowData(int colSize) {
|
public TSDBResultSetRowData(int colSize) {
|
||||||
this.setColSize(colSize);
|
this.setColSize(colSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TSDBResultSetRowData() {
|
public TSDBResultSetRowData() {
|
||||||
this.data = new ArrayList<Object>();
|
this.data = new ArrayList<>();
|
||||||
this.setColSize(0);
|
this.setColSize(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ public class TSDBResultSetRowData {
|
||||||
if (this.colSize == 0) {
|
if (this.colSize == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.data = new ArrayList<Object>(colSize);
|
this.data = new ArrayList<>(colSize);
|
||||||
this.data.addAll(Collections.nCopies(this.colSize, null));
|
this.data.addAll(Collections.nCopies(this.colSize, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ public class TSDBResultSetRowData {
|
||||||
|
|
||||||
public boolean getBoolean(int col, int srcType) throws SQLException {
|
public boolean getBoolean(int col, int srcType) throws SQLException {
|
||||||
Object obj = data.get(col);
|
Object obj = data.get(col);
|
||||||
|
|
||||||
switch(srcType) {
|
switch(srcType) {
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return (Boolean) obj;
|
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return (Boolean) obj;
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return ((Float) obj) == 1.0? Boolean.TRUE:Boolean.FALSE;
|
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return ((Float) obj) == 1.0? Boolean.TRUE:Boolean.FALSE;
|
||||||
|
@ -64,10 +64,10 @@ public class TSDBResultSetRowData {
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return ((Long) obj) == 1L? Boolean.TRUE:Boolean.FALSE;
|
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return ((Long) obj) == 1L? Boolean.TRUE:Boolean.FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Boolean.TRUE;
|
return Boolean.TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setByte(int col, byte value) {
|
public void setByte(int col, byte value) {
|
||||||
data.set(col, value);
|
data.set(col, value);
|
||||||
}
|
}
|
||||||
|
@ -82,20 +82,20 @@ public class TSDBResultSetRowData {
|
||||||
|
|
||||||
public int getInt(int col, int srcType) throws SQLException {
|
public int getInt(int col, int srcType) throws SQLException {
|
||||||
Object obj = data.get(col);
|
Object obj = data.get(col);
|
||||||
|
|
||||||
switch(srcType) {
|
switch(srcType) {
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0;
|
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0;
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return ((Float) obj).intValue();
|
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return ((Float) obj).intValue();
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: return ((Double)obj).intValue();
|
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: return ((Double)obj).intValue();
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_TINYINT: return (Byte) obj;
|
case TSDBConstants.TSDB_DATA_TYPE_TINYINT: return (Byte) obj;
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:return (Short) obj;
|
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:return (Short) obj;
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_INT: return (Integer) obj;
|
case TSDBConstants.TSDB_DATA_TYPE_INT: return (Integer) obj;
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return ((Long) obj).intValue();
|
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return ((Long) obj).intValue();
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
|
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_BINARY: return Integer.parseInt((String) obj);
|
case TSDBConstants.TSDB_DATA_TYPE_BINARY: return Integer.parseInt((String) obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ public class TSDBResultSetRowData {
|
||||||
|
|
||||||
public long getLong(int col, int srcType) throws SQLException {
|
public long getLong(int col, int srcType) throws SQLException {
|
||||||
Object obj = data.get(col);
|
Object obj = data.get(col);
|
||||||
|
|
||||||
switch(srcType) {
|
switch(srcType) {
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0;
|
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0;
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return ((Float) obj).longValue();
|
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return ((Float) obj).longValue();
|
||||||
|
@ -116,9 +116,9 @@ public class TSDBResultSetRowData {
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return (Long) obj;
|
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return (Long) obj;
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
|
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_BINARY: return Long.parseLong((String) obj);
|
case TSDBConstants.TSDB_DATA_TYPE_BINARY: return Long.parseLong((String) obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ public class TSDBResultSetRowData {
|
||||||
|
|
||||||
public float getFloat(int col, int srcType) throws SQLException {
|
public float getFloat(int col, int srcType) throws SQLException {
|
||||||
Object obj = data.get(col);
|
Object obj = data.get(col);
|
||||||
|
|
||||||
switch(srcType) {
|
switch(srcType) {
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0;
|
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0;
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return (Float) obj;
|
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return (Float) obj;
|
||||||
|
@ -139,7 +139,7 @@ public class TSDBResultSetRowData {
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return (Long) obj;
|
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return (Long) obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ public class TSDBResultSetRowData {
|
||||||
|
|
||||||
public double getDouble(int col, int srcType) throws SQLException {
|
public double getDouble(int col, int srcType) throws SQLException {
|
||||||
Object obj = data.get(col);
|
Object obj = data.get(col);
|
||||||
|
|
||||||
switch(srcType) {
|
switch(srcType) {
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0;
|
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0;
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return (Float) obj;
|
case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return (Float) obj;
|
||||||
|
@ -160,7 +160,7 @@ public class TSDBResultSetRowData {
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
||||||
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return (Long) obj;
|
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return (Long) obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ public class TSDBResultSetRowData {
|
||||||
* The original type may not be a string type, but will be converted to by calling this method
|
* The original type may not be a string type, but will be converted to by calling this method
|
||||||
* @param col column index
|
* @param col column index
|
||||||
* @return
|
* @return
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
public String getString(int col, int srcType) throws SQLException {
|
public String getString(int col, int srcType) throws SQLException {
|
||||||
if (srcType == TSDBConstants.TSDB_DATA_TYPE_BINARY || srcType == TSDBConstants.TSDB_DATA_TYPE_NCHAR) {
|
if (srcType == TSDBConstants.TSDB_DATA_TYPE_BINARY || srcType == TSDBConstants.TSDB_DATA_TYPE_NCHAR) {
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
import com.taosdata.jdbc.TSDBDriver;
|
|
||||||
|
|
||||||
import java.sql.*;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
public class TestTSDBDatabaseMetaData {
|
|
||||||
|
|
||||||
public static void main(String[] args) throws SQLException {
|
|
||||||
Connection connection = null;
|
|
||||||
DatabaseMetaData dbMetaData = null;
|
|
||||||
ResultSet resSet = null;
|
|
||||||
try {
|
|
||||||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
|
||||||
Properties properties = new Properties();
|
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, "localhost");
|
|
||||||
connection = DriverManager.getConnection("jdbc:TAOS://localhost:0/", properties);
|
|
||||||
dbMetaData = connection.getMetaData();
|
|
||||||
resSet = dbMetaData.getCatalogs();
|
|
||||||
while(resSet.next()) {
|
|
||||||
for (int i = 1; i <= resSet.getMetaData().getColumnCount(); i++) {
|
|
||||||
System.out.printf("dbMetaData.getCatalogs(%d) = %s\n", i, resSet.getString(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resSet.close();
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
if (null != connection) {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,7 +10,7 @@ import java.util.Properties;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class StatementTest extends BaseTest {
|
public class StatementTest {
|
||||||
static Connection connection = null;
|
static Connection connection = null;
|
||||||
static Statement statement = null;
|
static Statement statement = null;
|
||||||
static String dbName = "test";
|
static String dbName = "test";
|
||||||
|
@ -26,14 +26,29 @@ public class StatementTest extends BaseTest {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
|
|
||||||
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/?user=root&password=taosdata", properties);
|
||||||
|
|
||||||
statement = connection.createStatement();
|
statement = connection.createStatement();
|
||||||
statement.executeUpdate("drop database if exists " + dbName);
|
statement.executeUpdate("drop database if exists " + dbName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCase() {
|
||||||
|
try {
|
||||||
|
ResultSet rs = statement.executeQuery("show databases");
|
||||||
|
ResultSetMetaData metaData = rs.getMetaData();
|
||||||
|
while (rs.next()) {
|
||||||
|
for (int i = 1; i <= metaData.getColumnCount(); i++) {
|
||||||
|
System.out.print(metaData.getColumnLabel(i) + ":" + rs.getString(i) + "\t");
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,9 +69,6 @@ public class StatementTest extends BaseTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnsupport() {
|
public void testUnsupport() {
|
||||||
// if(null == resSet) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
TSDBStatement tsdbStatement = (TSDBStatement) statement;
|
TSDBStatement tsdbStatement = (TSDBStatement) statement;
|
||||||
try {
|
try {
|
||||||
tsdbStatement.unwrap(null);
|
tsdbStatement.unwrap(null);
|
||||||
|
@ -163,11 +175,10 @@ public class StatementTest extends BaseTest {
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void close() throws Exception {
|
public static void close() throws Exception {
|
||||||
if (!statement.isClosed()) {
|
if (!statement.isClosed()) {
|
||||||
statement.executeUpdate("drop database " + dbName);
|
statement.executeUpdate("drop database if exists " + dbName);
|
||||||
statement.close();
|
statement.close();
|
||||||
connection.close();
|
connection.close();
|
||||||
Thread.sleep(10);
|
Thread.sleep(10);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,7 @@ import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.*;
|
||||||
import java.sql.DriverManager;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
public class TSDBDatabaseMetaDataTest {
|
public class TSDBDatabaseMetaDataTest {
|
||||||
|
@ -642,7 +639,15 @@ public class TSDBDatabaseMetaDataTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getTables() throws SQLException {
|
public void getTables() throws SQLException {
|
||||||
Assert.assertNull(metaData.getTables("", "", "*", null));
|
ResultSet tables = metaData.getTables("log", "", null, null);
|
||||||
|
ResultSetMetaData metaData = tables.getMetaData();
|
||||||
|
while (tables.next()) {
|
||||||
|
System.out.print(metaData.getColumnLabel(3) + ":" + tables.getString(3) + "\t");
|
||||||
|
System.out.print(metaData.getColumnLabel(4) + ":" + tables.getString(4) + "\t");
|
||||||
|
System.out.print(metaData.getColumnLabel(5) + ":" + tables.getString(5) + "\n");
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
Assert.assertNotNull(tables);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -652,17 +657,41 @@ public class TSDBDatabaseMetaDataTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getCatalogs() throws SQLException {
|
public void getCatalogs() throws SQLException {
|
||||||
Assert.assertNotNull(metaData.getCatalogs());
|
ResultSet catalogs = metaData.getCatalogs();
|
||||||
|
ResultSetMetaData meta = catalogs.getMetaData();
|
||||||
|
while (catalogs.next()) {
|
||||||
|
for (int i = 1; i <= meta.getColumnCount(); i++) {
|
||||||
|
System.out.print(meta.getColumnLabel(i) + ": " + catalogs.getString(i));
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getTableTypes() throws SQLException {
|
public void getTableTypes() throws SQLException {
|
||||||
|
ResultSet tableTypes = metaData.getTableTypes();
|
||||||
|
while (tableTypes.next()) {
|
||||||
|
System.out.println(tableTypes.getString("TABLE_TYPE"));
|
||||||
|
}
|
||||||
Assert.assertNotNull(metaData.getTableTypes());
|
Assert.assertNotNull(metaData.getTableTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getColumns() throws SQLException {
|
public void getColumns() throws SQLException {
|
||||||
Assert.assertNotNull(metaData.getColumns("", "", "", ""));
|
ResultSet columns = metaData.getColumns("log", "", "dn", "");
|
||||||
|
ResultSetMetaData meta = columns.getMetaData();
|
||||||
|
while (columns.next()) {
|
||||||
|
System.out.print(meta.getColumnLabel(1) + ": " + columns.getString(1) + "\t");
|
||||||
|
System.out.print(meta.getColumnLabel(3) + ": " + columns.getString(3) + "\t");
|
||||||
|
System.out.print(meta.getColumnLabel(4) + ": " + columns.getString(4) + "\t");
|
||||||
|
System.out.print(meta.getColumnLabel(5) + ": " + columns.getString(5) + "\t");
|
||||||
|
System.out.print(meta.getColumnLabel(6) + ": " + columns.getString(6) + "\t");
|
||||||
|
System.out.print(meta.getColumnLabel(7) + ": " + columns.getString(7) + "\t");
|
||||||
|
System.out.print(meta.getColumnLabel(9) + ": " + columns.getString(9) + "\t");
|
||||||
|
System.out.print(meta.getColumnLabel(10) + ": " + columns.getString(10) + "\t");
|
||||||
|
System.out.print(meta.getColumnLabel(11) + ": " + columns.getString(11) + "\n");
|
||||||
|
System.out.print(meta.getColumnLabel(12) + ": " + columns.getString(12) + "\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -687,7 +716,15 @@ public class TSDBDatabaseMetaDataTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getPrimaryKeys() throws SQLException {
|
public void getPrimaryKeys() throws SQLException {
|
||||||
Assert.assertNotNull(metaData.getPrimaryKeys("", "", ""));
|
ResultSet rs = metaData.getPrimaryKeys("log", "", "dn1");
|
||||||
|
while (rs.next()) {
|
||||||
|
System.out.println("TABLE_NAME: " + rs.getString("TABLE_NAME"));
|
||||||
|
System.out.println("COLUMN_NAME: " + rs.getString("COLUMN_NAME"));
|
||||||
|
System.out.println("KEY_SEQ: " + rs.getString("KEY_SEQ"));
|
||||||
|
System.out.println("PK_NAME: " + rs.getString("PK_NAME"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.assertNotNull(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -812,7 +849,12 @@ public class TSDBDatabaseMetaDataTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSuperTables() throws SQLException {
|
public void getSuperTables() throws SQLException {
|
||||||
Assert.assertNotNull(metaData.getSuperTables("", "", ""));
|
ResultSet rs = metaData.getSuperTables("log", "", "dn1");
|
||||||
|
while (rs.next()) {
|
||||||
|
System.out.println("TABLE_NAME: " + rs.getString("TABLE_NAME"));
|
||||||
|
System.out.println("SUPERTABLE_NAME: " + rs.getString("SUPERTABLE_NAME"));
|
||||||
|
}
|
||||||
|
Assert.assertNotNull(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -3,15 +3,15 @@
|
||||||
* @module CTaosInterface
|
* @module CTaosInterface
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const ref = require('ref');
|
const ref = require('ref-napi');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const ffi = require('ffi');
|
const ffi = require('ffi-napi');
|
||||||
const ArrayType = require('ref-array');
|
const ArrayType = require('ref-array-napi');
|
||||||
const Struct = require('ref-struct');
|
const Struct = require('ref-struct-napi');
|
||||||
const FieldTypes = require('./constants');
|
const FieldTypes = require('./constants');
|
||||||
const errors = require ('./error');
|
const errors = require ('./error');
|
||||||
const TaosObjects = require('./taosobjects');
|
const TaosObjects = require('./taosobjects');
|
||||||
const { NULL_POINTER } = require('ref');
|
const { NULL_POINTER } = require('ref-napi');
|
||||||
|
|
||||||
module.exports = CTaosInterface;
|
module.exports = CTaosInterface;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const ref = require('ref');
|
const ref = require('ref-napi');
|
||||||
require('./globalfunc.js')
|
require('./globalfunc.js')
|
||||||
const CTaosInterface = require('./cinterface')
|
const CTaosInterface = require('./cinterface')
|
||||||
const errors = require ('./error')
|
const errors = require ('./error')
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,31 +1,34 @@
|
||||||
{
|
{
|
||||||
"name": "td2.0-connector",
|
"name": "td2.0-connector",
|
||||||
"version": "2.0.5",
|
"version": "2.0.6",
|
||||||
"description": "A Node.js connector for TDengine.",
|
"description": "A Node.js connector for TDengine.",
|
||||||
"main": "tdengine.js",
|
"main": "tdengine.js",
|
||||||
|
"directories": {
|
||||||
|
"test": "test"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node test/test.js"
|
"test": "node test/test.js"
|
||||||
},
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/taosdata/tdengine.git"
|
||||||
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"TDengine",
|
"TDengine",
|
||||||
"TAOS Data",
|
"TAOS Data",
|
||||||
"Time Series Database",
|
"Time Series Database",
|
||||||
"Connector"
|
"Connector"
|
||||||
],
|
],
|
||||||
"author": "StoneT2000",
|
"author": "TaosData Inc.",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0-or-later",
|
||||||
"dependencies": {
|
|
||||||
"ffi": "^2.3.0",
|
|
||||||
"node-gyp": "^5.0.2",
|
|
||||||
"ref": "^1.3.5",
|
|
||||||
"ref-array": "^1.2.0"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/taosdata/tdengine",
|
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/taosdata/tdengine/issues"
|
"url": "https://github.com/taosdata/tdengine/issues"
|
||||||
},
|
},
|
||||||
"repository": {
|
"homepage": "https://github.com/taosdata/tdengine#readme",
|
||||||
"type": "git",
|
"dependencies": {
|
||||||
"url": "https://github.com/taosdata/tdengine.git"
|
"ffi-napi": "^3.1.0",
|
||||||
|
"ref-array-napi": "^1.2.1",
|
||||||
|
"ref-napi": "^1.5.2",
|
||||||
|
"ref-struct-napi": "^1.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -504,13 +504,13 @@ int64_t taosTimeTruncate(int64_t t, const SInterval* pInterval, int32_t precisio
|
||||||
int64_t end = 0;
|
int64_t end = 0;
|
||||||
|
|
||||||
// not enough time range
|
// not enough time range
|
||||||
if (INT64_MAX - start > pInterval->interval - 1) {
|
if (start < 0 || INT64_MAX - start > pInterval->interval - 1) {
|
||||||
end = start + pInterval->interval - 1;
|
end = start + pInterval->interval - 1;
|
||||||
|
|
||||||
while(end < t && ((start + pInterval->sliding) <= INT64_MAX)) { // move forward to the correct time window
|
while(end < t && ((start + pInterval->sliding) <= INT64_MAX)) { // move forward to the correct time window
|
||||||
start += pInterval->sliding;
|
start += pInterval->sliding;
|
||||||
|
|
||||||
if (INT64_MAX - start > pInterval->interval - 1) {
|
if (start < 0 || INT64_MAX - start > pInterval->interval - 1) {
|
||||||
end = start + pInterval->interval - 1;
|
end = start + pInterval->interval - 1;
|
||||||
} else {
|
} else {
|
||||||
end = INT64_MAX;
|
end = INT64_MAX;
|
||||||
|
|
|
@ -48,7 +48,6 @@ public class JDBCDemo {
|
||||||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||||||
}
|
}
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
properties.setProperty("host", host);
|
|
||||||
properties.setProperty("charset", "UTF-8");
|
properties.setProperty("charset", "UTF-8");
|
||||||
properties.setProperty("locale", "en_US.UTF-8");
|
properties.setProperty("locale", "en_US.UTF-8");
|
||||||
properties.setProperty("timezone", "UTC-8");
|
properties.setProperty("timezone", "UTC-8");
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.taosdata.example;
|
||||||
|
|
||||||
|
import java.sql.*;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
public class JdbcRestfulDemo {
|
||||||
|
private static final String host = "master";
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
// load JDBC-restful driver
|
||||||
|
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
|
||||||
|
// use port 6041 in url when use JDBC-restful
|
||||||
|
String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata";
|
||||||
|
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.setProperty("charset", "UTF-8");
|
||||||
|
properties.setProperty("locale", "en_US.UTF-8");
|
||||||
|
properties.setProperty("timezone", "UTC-8");
|
||||||
|
|
||||||
|
Connection conn = DriverManager.getConnection(url, properties);
|
||||||
|
Statement stmt = conn.createStatement();
|
||||||
|
|
||||||
|
stmt.execute("create database if not exists restful_test");
|
||||||
|
stmt.execute("use restful_test");
|
||||||
|
stmt.execute("create table restful_test.weather(ts timestamp, temperature float) tags(location nchar(64))");
|
||||||
|
stmt.executeUpdate("insert into t1 using restful_test.weather tags('北京') values(now, 18.2)");
|
||||||
|
ResultSet rs = stmt.executeQuery("select * from restful_test.weather");
|
||||||
|
ResultSetMetaData meta = rs.getMetaData();
|
||||||
|
while (rs.next()) {
|
||||||
|
for (int i = 1; i <= meta.getColumnCount(); i++) {
|
||||||
|
System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t");
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt.close();
|
||||||
|
conn.close();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -67,9 +67,9 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.taosdata.jdbc</groupId>
|
<groupId>com.taosdata.jdbc</groupId>
|
||||||
<artifactId>taos-jdbcdriver</artifactId>
|
<artifactId>taos-jdbcdriver</artifactId>
|
||||||
<version>2.0.15</version>
|
<version>2.0.16</version>
|
||||||
<scope>system</scope>
|
<!-- <scope>system</scope>-->
|
||||||
<systemPath>${project.basedir}/src/main/resources/lib/taos-jdbcdriver-2.0.15-dist.jar</systemPath>
|
<!-- <systemPath>${project.basedir}/src/main/resources/lib/taos-jdbcdriver-2.0.15-dist.jar</systemPath>-->
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- fastjson -->
|
<!-- fastjson -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
Binary file not shown.
|
@ -1,4 +1,5 @@
|
||||||
const taos = require('td2.0-connector');
|
const taos = require('td2.0-connector');
|
||||||
|
//const taos = require('../../../src/connector/nodejs/');
|
||||||
|
|
||||||
|
|
||||||
var host = null;
|
var host = null;
|
||||||
|
|
|
@ -24,6 +24,17 @@ class TDTestCase:
|
||||||
tdSql.init(conn.cursor(), logSql)
|
tdSql.init(conn.cursor(), logSql)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
tdSql.query("show users")
|
||||||
|
rows = tdSql.queryRows
|
||||||
|
|
||||||
|
tdSql.execute("create user test PASS 'test' ")
|
||||||
|
tdSql.query("show users")
|
||||||
|
tdSql.checkRows(rows + 1)
|
||||||
|
|
||||||
|
tdSql.error("create user tdenginetdenginetdengine PASS 'test' ")
|
||||||
|
|
||||||
|
tdSql.error("create user tdenginet PASS '1234512345123456' ")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tdSql.execute("create account a&cc PASS 'pass123'")
|
tdSql.execute("create account a&cc PASS 'pass123'")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -31,6 +42,7 @@ class TDTestCase:
|
||||||
return
|
return
|
||||||
|
|
||||||
tdLog.exit("drop built-in user is error.")
|
tdLog.exit("drop built-in user is error.")
|
||||||
|
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
tdSql.close()
|
tdSql.close()
|
||||||
|
|
|
@ -126,6 +126,8 @@ class TDTestCase:
|
||||||
for i in range(2, size):
|
for i in range(2, size):
|
||||||
tdSql.checkData(0, i, self.rowNum * (size - i))
|
tdSql.checkData(0, i, self.rowNum * (size - i))
|
||||||
|
|
||||||
|
tdSql.error("alter local debugflag 143")
|
||||||
|
|
||||||
tdSql.execute("create table st(ts timestamp, c1 int) tags(t1 float)")
|
tdSql.execute("create table st(ts timestamp, c1 int) tags(t1 float)")
|
||||||
tdSql.execute("create table t0 using st tags(null)")
|
tdSql.execute("create table t0 using st tags(null)")
|
||||||
tdSql.execute("alter table t0 set tag t1=2.1")
|
tdSql.execute("alter table t0 set tag t1=2.1")
|
||||||
|
|
|
@ -175,6 +175,7 @@ python3 ./test.py -f query/bug2119.py
|
||||||
python3 ./test.py -f query/isNullTest.py
|
python3 ./test.py -f query/isNullTest.py
|
||||||
python3 ./test.py -f query/queryWithTaosdKilled.py
|
python3 ./test.py -f query/queryWithTaosdKilled.py
|
||||||
python3 ./test.py -f query/floatCompare.py
|
python3 ./test.py -f query/floatCompare.py
|
||||||
|
python3 ./test.py -f query/queryGroupbySort.py
|
||||||
|
|
||||||
#stream
|
#stream
|
||||||
python3 ./test.py -f stream/metric_1.py
|
python3 ./test.py -f stream/metric_1.py
|
||||||
|
@ -258,4 +259,7 @@ python3 ./test.py -f update/merge_commit_last.py
|
||||||
python3 ./test.py -f update/bug_td2279.py
|
python3 ./test.py -f update/bug_td2279.py
|
||||||
|
|
||||||
# wal
|
# wal
|
||||||
python3 ./test.py -f wal/addOldWalTest.py
|
python3 ./test.py -f wal/addOldWalTest.py
|
||||||
|
|
||||||
|
# account
|
||||||
|
python3 ./test.py -f account/account_create.py
|
|
@ -28,19 +28,24 @@ class TDTestCase:
|
||||||
def run(self):
|
def run(self):
|
||||||
tdSql.prepare()
|
tdSql.prepare()
|
||||||
|
|
||||||
tdSql.execute(
|
tdSql.execute("CREATE TABLE meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int)")
|
||||||
"create table stb(ts timestamp,i int) tags (p_id nchar(20));")
|
tdSql.execute("CREATE TABLE D1001 USING meters TAGS ('Beijing.Chaoyang', 2)")
|
||||||
tdSql.execute(
|
tdSql.execute("CREATE TABLE D1002 USING meters TAGS ('Beijing.Chaoyang', 3)")
|
||||||
"insert into tb using stb tags('11231') values (%d, %d) (%d, %d) (%d, %d) (%d, %d)"
|
tdSql.execute("INSERT INTO D1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6, 218, 0.33) (1538548696800, 12.3, 221, 0.31)")
|
||||||
% (self.ts, 12, self.ts + 1, 15, self.ts + 2, 15, self.ts + 3, 12))
|
tdSql.execute("INSERT INTO D1002 VALUES (1538548685001, 10.5, 220, 0.28) (1538548696800, 12.3, 221, 0.31)")
|
||||||
|
|
||||||
tdSql.query(''' select last(ts) p_time,i from stb where p_id='11231' and ts>=%d and ts <=%d
|
|
||||||
group by i order by time desc limit 100 ''' % (self.ts, self.ts + 4))
|
|
||||||
tdSql.checkRows(2)
|
|
||||||
tdSql.checkData(0, 0, "2018-09-17 09:00:00.003000")
|
|
||||||
tdSql.checkData(1, 0, "2018-09-17 09:00:00.002000")
|
|
||||||
|
|
||||||
|
tdSql.query("SELECT SUM(current), AVG(voltage) FROM meters WHERE groupId > 1 INTERVAL(1s) GROUP BY location order by ts DESC")
|
||||||
|
tdSql.checkRows(3)
|
||||||
|
tdSql.checkData(0, 0, "2018-10-03 14:38:16")
|
||||||
|
tdSql.checkData(1, 0, "2018-10-03 14:38:15")
|
||||||
|
tdSql.checkData(2, 0, "2018-10-03 14:38:05")
|
||||||
|
|
||||||
|
tdSql.query("SELECT SUM(current), AVG(voltage) FROM meters WHERE groupId > 1 INTERVAL(1s) GROUP BY location order by ts ASC")
|
||||||
|
tdSql.checkRows(3)
|
||||||
|
tdSql.checkData(0, 0, "2018-10-03 14:38:05")
|
||||||
|
tdSql.checkData(1, 0, "2018-10-03 14:38:15")
|
||||||
|
tdSql.checkData(2, 0, "2018-10-03 14:38:16")
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
tdSql.close()
|
tdSql.close()
|
||||||
tdLog.success("%s successfully executed" % __file__)
|
tdLog.success("%s successfully executed" % __file__)
|
||||||
|
|
Loading…
Reference in New Issue