Merge branch 'develop' into feature/query

This commit is contained in:
Haojun Liao 2021-01-23 15:13:55 +08:00
commit 2572641615
101 changed files with 2349 additions and 2975 deletions

64
Jenkinsfile vendored
View File

@ -41,13 +41,10 @@ def pre_test(){
cd ${WKC}
git checkout develop
git reset --hard HEAD~10
git reset --hard HEAD~10 >/dev/null
git pull
git fetch
git checkout ${CHANGE_BRANCH}
git reset --hard HEAD~10
git pull
git merge develop
git fetch origin +refs/pull/${CHANGE_ID}/merge
git checkout -qf FETCH_HEAD
cd ${WK}
git reset --hard HEAD~10
git checkout develop
@ -87,11 +84,14 @@ pipeline {
steps {
pre_test()
sh '''
cd ${WKC}/tests
find pytest -name '*'sql|xargs rm -rf
./test-all.sh p1
date'''
timeout(time: 90, unit: 'MINUTES'){
sh '''
cd ${WKC}/tests
find pytest -name '*'sql|xargs rm -rf
./test-all.sh p1
date'''
}
}
}
stage('python_2') {
@ -112,12 +112,14 @@ pipeline {
}
stage('test_b1') {
agent{label 'b1'}
steps {
pre_test()
sh '''
cd ${WKC}/tests
./test-all.sh b1fq
date'''
steps {
timeout(time: 90, unit: 'MINUTES'){
pre_test()
sh '''
cd ${WKC}/tests
./test-all.sh b1fq
date'''
}
}
}
@ -137,12 +139,14 @@ pipeline {
./handle_crash_gen_val_log.sh
'''
}
sh '''
date
cd ${WKC}/tests
./test-all.sh b2fq
date
'''
timeout(time: 90, unit: 'MINUTES'){
sh '''
date
cd ${WKC}/tests
./test-all.sh b2fq
date
'''
}
}
}
@ -157,12 +161,14 @@ pipeline {
./valgrind-test.sh 2>&1 > mem-error-out.log
./handle_val_log.sh
'''
}
sh '''
date
cd ${WKC}/tests
./test-all.sh b3fq
date'''
}
timeout(time: 90, unit: 'MINUTES'){
sh '''
date
cd ${WKC}/tests
./test-all.sh b3fq
date'''
}
}
}

View File

@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS)
#INSTALL(TARGETS taos RUNTIME DESTINATION driver)
#INSTALL(TARGETS shell RUNTIME DESTINATION .)
IF (TD_MVN_INSTALLED)
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.16-dist.jar DESTINATION connector/jdbc)
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.17-dist.jar DESTINATION connector/jdbc)
ENDIF ()
ELSEIF (TD_DARWIN)
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")

16
cmake/version.inc Normal file → Executable file
View File

@ -16,13 +16,25 @@ ENDIF ()
IF (DEFINED GITINFO)
SET(TD_VER_GIT ${GITINFO})
ELSE ()
SET(TD_VER_GIT "community")
execute_process(
COMMAND git log -1 --format=%H
WORKING_DIRECTORY ${TD_COMMUNITY_DIR}
OUTPUT_VARIABLE GIT_COMMITID
)
string (REGEX REPLACE "[\n\t\r]" "" GIT_COMMITID ${GIT_COMMITID})
SET(TD_VER_GIT ${GIT_COMMITID})
ENDIF ()
IF (DEFINED GITINFOI)
SET(TD_VER_GIT_INTERNAL ${GITINFOI})
ELSE ()
SET(TD_VER_GIT_INTERNAL "internal")
execute_process(
COMMAND git log -1 --format=%H
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMITID
)
string (REGEX REPLACE "[\n\t\r]" "" GIT_COMMITID ${GIT_COMMITID})
SET(TD_VER_GIT_INTERNAL ${GIT_COMMITID})
ENDIF ()
IF (DEFINED VERDATE)

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -179,7 +179,7 @@ taos> select avg(f1), max(f2), min(f3) from test.t10 interval(10s);
## **支持平台列表**
## 支持平台列表
### TDengine服务器支持的平台列表

View File

@ -9,7 +9,7 @@
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
- 数值列及聚合结果的四则运算
- 时间戳对齐的连接查询Join Query: 隐式连接)操作

View File

@ -58,26 +58,26 @@ TDengine缺省的时间戳是毫秒精度但通过修改配置参数enableMic
- **创建数据库**
```mysql
CREATE DATABASE [IF NOT EXISTS] db_name [KEEP keep] [UPDATE 1];
```
说明:
1) KEEP是该数据库的数据保留多长天数缺省是3650天(10年),数据库会自动删除超过时限的数据;
2) UPDATE 标志数据库支持更新相同时间戳数据;
3) 数据库名最大长度为33
4) 一条SQL 语句的最大长度为65480个字符
5) 数据库还有更多与存储相关的配置参数,请参见系统管理。
```mysql
CREATE DATABASE [IF NOT EXISTS] db_name [KEEP keep] [UPDATE 1];
```
说明:
1) KEEP是该数据库的数据保留多长天数缺省是3650天(10年),数据库会自动删除超过时限的数据;
2) UPDATE 标志数据库支持更新相同时间戳数据;
3) 数据库名最大长度为33
4) 一条SQL 语句的最大长度为65480个字符
5) 数据库还有更多与存储相关的配置参数,请参见系统管理。
- **显示系统当前参数**
```mysql
SHOW VARIABLES;
```
```mysql
SHOW VARIABLES;
```
- **使用数据库**
@ -698,13 +698,13 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
```mysql
SELECT TWA(field_name) FROM tb_name WHERE clause;
```
功能说明:时间加权平均函数。统计表/超级表中某列在一段时间内的时间加权平均。
功能说明:时间加权平均函数。统计表中某列在一段时间内的时间加权平均。
返回结果数据类型双精度浮点数Double。
应用字段不能应用在timestamp、binary、nchar、bool类型字段。
适用于:表、超级表
适用于:表。
- **SUM**
```mysql
@ -1125,11 +1125,8 @@ SELECT function_list FROM stb_name
- WHERE语句可以指定查询的起止时间和其他过滤条件
- FILL语句指定某一时间区间数据缺失的情况下的填充模式。填充模式包括以下几种
1. 不进行填充NONE(默认填充模式)。
2. VALUE填充固定值填充此时需要指定填充的数值。例如fill(value, 1.23)。
3. NULL填充使用NULL填充数据。例如fill(null)。
4. PREV填充使用前一个非NULL值填充数据。例如fill(prev)。
说明:

View File

@ -124,10 +124,10 @@ taosd -C
对于一个应用场景可能有多种数据特征的数据并存最佳的设计是将具有相同数据特征的表放在一个库里这样一个应用有多个库而每个库可以配置不同的存储参数从而保证系统有最优的性能。TDengine允许应用在创建库时指定上述存储参数如果指定该参数就将覆盖对应的系统配置参数。举例有下述SQL
```
create database demo days 10 cache 32 blocks 8 replica 3;
create database demo days 10 cache 32 blocks 8 replica 3 update 1;
```
该SQL创建了一个库demo, 每个数据文件存储10天数据内存块为32兆字节每个VNODE占用8个内存块副本数为3而其他参数与系统配置完全一致。
该SQL创建了一个库demo, 每个数据文件存储10天数据内存块为32兆字节每个VNODE占用8个内存块副本数为3允许更新,而其他参数与系统配置完全一致。
TDengine集群中加入一个新的dnode时涉及集群相关的一些参数必须与已有集群的配置相同否则不能成功加入到集群中。会进行校验的参数如下

View File

@ -197,7 +197,7 @@ select * from meters where ts > now - 1d and current > 10;
且`restart`是 **false****0**),用户程序就不会读到之前已经读取的数据了。
`taos_subscribe`的最后一个参数是以毫秒为单位的轮询周期。
在同步模式下,如前后两次调用`taos_consume`的时间间隔小于此时间,
在同步模式下,如前后两次调用`taos_consume`的时间间隔小于此时间,
`taos_consume`会阻塞,直到间隔超过此时间。
异步模式下,这个时间是两次调用回调函数的最小时间间隔。
@ -414,7 +414,7 @@ TDengine通过查询函数向用户提供毫秒级的数据获取能力。直接
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快速获取一张表或一张超级表的最后一条记录这样很便于在大屏显示各设备的实时状态或采集值。例如

View File

@ -225,7 +225,7 @@ SHOW MNODES;
## 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系统也不会去建立连接。

View File

@ -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是被删除的节点的FQDNport是其对外服务器的端口号
###查看节点
执行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 groupvnode 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;”指令给出的节点列表中。

View File

@ -1,62 +1,62 @@
# Java Connector
Java连接器支持的系统有
| **CPU类型** | x6464bit | | | ARM64 | ARM32 |
| ------------ | ------------ | -------- | -------- | -------- | -------- |
| **OS类型** | Linux | Win64 | Win32 | Linux | Linux |
| **支持与否** | **支持** | **支持** | **支持** | **支持** | **支持** |
TDengine 提供了遵循 JDBC 标准3.0API 规范的 `taos-jdbcdriver` 实现,可在 maven 的中央仓库 [Sonatype Repository][1] 搜索下载。
Java连接器的使用请参见<a href=https://www.taosdata.com/blog/2020/11/11/1955.html>视频教程</a>
`taos-jdbcdriver` 的实现包括 2 种形式: JDBC-JNI 和 JDBC-RESTfultaos-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-connector](../assets/tdengine-jdbc-connector.png)
由于 TDengine 是使用 c 语言开发的,使用 taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库。
上图显示了 3 种 Java 应用使用连接器访问 TDengine 的方式:
* libtaos.so
在 linux 系统中成功安装 TDengine 后,依赖的本地函数库 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so该目录包含在 Linux 自动扫描路径上,无需单独指定。
* JDBC-JNIJava 应用在物理节点1pnode1上使用 JDBC-JNI 的 API ,直接调用客户端 APIlibtaos.so 或 taos.dll将写入和查询请求发送到位于物理节点2pnode2上的 taosd 实例。
* RESTful应用将 SQL 发送给位于物理节点2pnode2上的 RESTful 连接器,再调用客户端 APIlibtaos.so
* JDBC-RESTfulJava 应用通过 JDBC-RESTful 的 API ,将 SQL 封装成一个 RESTful 请求发送给物理节点2的 RESTful 连接器。
* taos.dll
在 windows 系统中安装完客户端之后,驱动包依赖的 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。
TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致,但时序空间数据库与关系对象型数据库服务的对象和技术特征存在差异,导致 `taos-jdbcdriver` 与传统的 JDBC driver 也存在一定差异。在使用时需要注意以下几点:
> 注意:在 windows 环境开发时需要安装 TDengine 对应的 [windows 客户端][14]Linux 服务器安装完 TDengine 之后默认已安装 client也可以单独安装 [Linux 客户端][15] 连接远程 TDengine Server。
TDengine 的 JDBC 驱动实现尽可能的与关系型数据库驱动保持一致,但时序空间数据库与关系对象型数据库服务的对象和技术特征的差异导致 taos-jdbcdriver 并未完全实现 JDBC 标准规范。在使用时需要注意以下几点:
* TDengine 不提供针对单条数据记录的删除和修改的操作,驱动中也没有支持相关方法。
* 由于不支持删除和修改,所以也不支持事务操作。
* TDengine 目前不支持针对单条数据记录的删除操作。
* 目前不支持事务操作。
* 目前不支持表间的 union 操作。
* 目前不支持嵌套查询(nested query),对每个 Connection 的实例,至多只能有一个打开的 ResultSet 实例;如果在 ResultSet还没关闭的情况下执行了新的查询TSDBJDBCDriver 则会自动关闭上一个 ResultSet。
* 目前不支持嵌套查询nested query
* 对每个 Connection 的实例,至多只能有一个打开的 ResultSet 实例;如果在 ResultSet 还没关闭的情况下执行了新的查询taos-jdbcdriver 会自动关闭上一个 ResultSet。
## TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本
| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
| --- | --- | --- |
| 2.0.12 及以上 | 2.0.8.0 及以上 | 1.8.x |
| 2.0.4 - 2.0.11 | 2.0.0.0 - 2.0.7.x | 1.8.x |
| 1.0.3 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.1 | 1.6.1.x 及以上 | 1.8.x |
## JDBC-JNI和JDBC-RESTful的对比
## 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 |
| --- | --- |
| 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
## 如何获取 taos-jdbcdriver
### maven 仓库
目前 taos-jdbcdriver 已经发布到 [Sonatype Repository][1] 仓库,且各大仓库都已同步。
* [sonatype][8]
* [mvnrepository][9]
* [maven.aliyun][10]
@ -67,30 +67,63 @@ maven 项目中使用如下 pom.xml 配置即可:
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.4</version>
<version>2.0.17</version>
</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
Class.forName("com.taosdata.jdbc.TSDBDriver");
String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata";
Connection conn = DriverManager.getConnection(jdbcUrl);
```
以上示例建立了到hostname为taosdemo.com端口为6030TDengine的默认端口数据库名为test的连接。这个url中指定用户名user为root密码password为taosdata。
以上示例,使用了 JDBC-JNI 的 driver建立了到 hostname 为 taosdemo.com端口为 6030TDengine 的默认端口),数据库名为 test 的连接。这个 URL 中指定用户名user为 root密码password为 taosdata。
**注意**:使用 JDBC-JNI 的 drivertaos-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 规范格式为:
`jdbc:TAOS://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
`jdbc:[TAOS|TAOS-RS]://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
url中的配置参数如下
* user登录 TDengine 用户名,默认值 root。
* password用户登录密码默认值 taosdata。
@ -99,13 +132,17 @@ url中的配置参数如下
* locale客户端语言环境默认值系统当前 locale。
* timezone客户端使用的时区默认值为系统当前时区。
#### 使用JdbcUrl和Properties获取连接
除了通过指定的jdbcUrl获取连接还可以使用Properties指定建立连接时的参数如下所示
#### 指定URL和Properties获取连接
除了通过指定的 URL 获取连接,还可以使用 Properties 指定建立连接时的参数,如下所示:
```java
public Connection getConn() throws Exception{
Class.forName("com.taosdata.jdbc.TSDBDriver");
// Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata";
// String jdbcUrl = "jdbc:TAOS-RS://taosdemo.com:6041/test?user=root&password=taosdata";
Properties connProps = new Properties();
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
@ -114,9 +151,10 @@ public Connection getConn() throws Exception{
return conn;
}
```
以上示例建立一个到hostname为taosdemo.com端口为6030数据库名为test的连接。这个连接在url中指定了用户名(user)为root密码password为taosdata并在connProps中指定了使用的字符集、语言环境、时区等信息。
properties中的配置参数如下
以上示例,建立一个到 hostname 为 taosdemo.com端口为 6030数据库名为 test 的连接。注释为使用 JDBC-RESTful 时的方法。这个连接在 url 中指定了用户名(user)为 root密码password为 taosdata并在 connProps 中指定了使用的字符集、语言环境、时区等信息。
properties 中的配置参数如下:
* TSDBDriver.PROPERTY_KEY_USER登录 TDengine 用户名,默认值 root。
* TSDBDriver.PROPERTY_KEY_PASSWORD用户登录密码默认值 taosdata。
* TSDBDriver.PROPERTY_KEY_CONFIG_DIR客户端配置文件目录路径Linux OS 上默认值 /etc/taos Windows OS 上默认值 C:/TDengine/cfg。
@ -124,10 +162,14 @@ properties中的配置参数如下
* TSDBDriver.PROPERTY_KEY_LOCALE客户端语言环境默认值系统当前 locale。
* TSDBDriver.PROPERTY_KEY_TIME_ZONE客户端使用的时区默认值为系统当前时区。
#### 使用客户端配置文件建立连接
当使用JDBC连接TDengine集群时可以使用客户端配置文件在客户端配置文件中指定集群的firstEp、secondEp参数。
当使用 JDBC-JNI 连接 TDengine 集群时,可以使用客户端配置文件,在客户端配置文件中指定集群的 firstEp、secondEp参数。
如下所示:
1. 在java中不指定hostname和port
1. 在 Java 应用中不指定 hostname 和 port
```java
public Connection getConn() throws Exception{
Class.forName("com.taosdata.jdbc.TSDBDriver");
@ -140,7 +182,7 @@ public Connection getConn() throws Exception{
return conn;
}
```
2. 在配置文件中指定firstEp和secondEp
2. 在配置文件中指定 firstEp secondEp
```
# first fully qualified domain name (FQDN) for TDengine system
firstEp cluster_node1:6030
@ -155,17 +197,19 @@ secondEp cluster_node2:6030
# locale en_US.UTF-8
```
以上示例jdbc会使用客户端的配置文件建立到hostname为cluster_node1端口为6030数据库名为test的连接。当集群中firstEp节点失效时JDBC会尝试使用secondEp连接集群。
TDengine中只要保证firstEp和secondEp中一个节点有效就可以正常建立到集群的连接。
以上示例jdbc 会使用客户端的配置文件,建立到 hostname 为 cluster_node1、端口为 6030、数据库名为 test 的连接。当集群中 firstEp 节点失效时JDBC 会尝试使用 secondEp 连接集群。
TDengine 中,只要保证 firstEp secondEp 中一个节点有效,就可以正常建立到集群的连接。
> 注意这里的配置文件指的是调用JDBC Connector的应用程序所在机器上的配置文件Linux OS 上默认值 /etc/taos/taos.cfg Windows OS 上默认值 C://TDengine/cfg/taos.cfg。
> 注意:这里的配置文件指的是调用 JDBC Connector 的应用程序所在机器上的配置文件Linux OS 上默认值 /etc/taos/taos.cfg Windows OS 上默认值 C://TDengine/cfg/taos.cfg。
#### 配置参数的优先级
通过以上3种方式获取连接如果配置参数在url、Properties、客户端配置文件中有重复则参数的`优先级由高到低`分别如下:
通过以上 3 种方式获取连接,如果配置参数在 url、Properties、客户端配置文件中有重复则参数的`优先级由高到低`分别如下:
1. JDBC URL 参数,如上所述,可以在 JDBC URL 的参数中指定。
2. Properties connProps
3. 客户端配置文件 taos.cfg
例如在url中指定了password为taosdata在Properties中指定了password为taosdemo那么JDBC会使用url中的password建立连接。
例如:在 url 中指定了 password 为 taosdata在 Properties 中指定了 password 为 taosdemo那么JDBC 会使用 url 中的 password 建立连接。
> 更多详细配置请参考[客户端配置][13]
@ -183,6 +227,7 @@ stmt.executeUpdate("use db");
// create table
stmt.executeUpdate("create table if not exists tb (ts timestamp, temperature int, humidity float)");
```
> 注意:如果不使用 `use db` 指定数据库,则后续对表的操作都需要增加数据库名称作为前缀,如 db.tb。
### 插入数据
@ -193,6 +238,7 @@ int affectedRows = stmt.executeUpdate("insert into tb values(now, 23, 10.3) (now
System.out.println("insert " + affectedRows + " rows.");
```
> now 为系统内部函数,默认为服务器当前时间。
> `now + 1s` 代表服务器当前时间往后加 1 秒数字后面代表时间单位a(毫秒), s(秒), m(分), h(小时), d(天)w(周), n(月), y(年)。
@ -214,6 +260,7 @@ while(resultSet.next()){
System.out.printf("%s, %d, %s\n", ts, temperature, humidity);
}
```
> 查询和操作关系型数据库一致,使用下标获取返回字段内容时从 1 开始,建议使用字段名称获取。
### 订阅
@ -248,7 +295,7 @@ while(true) {
}
```
`consume` 方法返回一个结果集,其中包含从上次 `consume` 到目前为止的所有新数据。请务必按需选择合理的调用 `consume` 的频率(如例子中的`Thread.sleep(1000)`),否则会给服务端造成不必要的压力。
`consume` 方法返回一个结果集,其中包含从上次 `consume` 到目前为止的所有新数据。请务必按需选择合理的调用 `consume` 的频率(如例子中的 `Thread.sleep(1000)`),否则会给服务端造成不必要的压力。
#### 关闭订阅
@ -265,8 +312,11 @@ resultSet.close();
stmt.close();
conn.close();
```
> `注意务必要将 connection 进行关闭`,否则会出现连接泄露。
## 与连接池使用
**HikariCP**
@ -306,6 +356,7 @@ conn.close();
connection.close(); // put back to conneciton pool
}
```
> 通过 HikariDataSource.getConnection() 获取连接后,使用完成后需要调用 close() 方法,实际上它并不会关闭连接,只是放回连接池中。
> 更多 HikariCP 使用问题请查看[官方说明][5]
@ -356,6 +407,7 @@ public static void main(String[] args) throws Exception {
connection.close(); // put back to conneciton pool
}
```
> 更多 druid 使用问题请查看[官方说明][6]
**注意事项**
@ -370,10 +422,43 @@ server_status()|
Query OK, 1 row(s) in set (0.000141s)
```
## 与框架使用
* Spring JdbcTemplate 中使用 taos-jdbcdriver可参考 [SpringJdbcTemplate][11]
* Springboot + Mybatis 中使用,可参考 [springbootdemo][12]
* Springboot + Mybatis 中使用,可参考 [springbootdemo
## TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本
| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
| -------------------- | ----------------- | -------- |
| 2.0.12 及以上 | 2.0.8.0 及以上 | 1.8.x |
| 2.0.4 - 2.0.11 | 2.0.0.0 - 2.0.7.x | 1.8.x |
| 1.0.3 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.1 | 1.6.1.x 及以上 | 1.8.x |
## TDengine DataType 和 Java DataType
TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下:
| TDengine DataType | Java DataType |
| ----------------- | ------------------ |
| TIMESTAMP | java.sql.Timestamp |
| INT | java.lang.Integer |
| BIGINT | java.lang.Long |
| FLOAT | java.lang.Float |
| DOUBLE | java.lang.Double |
| SMALLINT, TINYINT | java.lang.Short |
| BOOL | java.lang.Boolean |
| BINARY, NCHAR | java.lang.String |
## 常见问题
@ -381,7 +466,7 @@ Query OK, 1 row(s) in set (0.000141s)
**原因**:程序没有找到依赖的本地函数库 taos。
**解决方法**windows 下可以将 C:\TDengine\driver\taos.dll 拷贝到 C:\Windows\System32\ 目录下linux 下将建立如下软链 ` ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` 即可。
**解决方法**windows 下可以将 C:\TDengine\driver\taos.dll 拷贝到 C:\Windows\System32\ 目录下linux 下将建立如下软链 `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` 即可。
* java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform
@ -406,3 +491,4 @@ Query OK, 1 row(s) in set (0.000141s)
[13]: https://www.taosdata.com/cn/documentation20/administrator/#%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%85%8D%E7%BD%AE
[14]: https://www.taosdata.com/cn/all-downloads/#TDengine-Windows-Client
[15]: https://www.taosdata.com/cn/getting-started/#%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B

View File

@ -85,7 +85,9 @@ TDengine还没有一组专用的validation queries。然而建议你使用系统
## 9. 我可以删除或更新一条记录吗?
不能。因为TDengine是为联网设备采集的数据设计的不容许修改。但TDengine提供数据保留策略只要数据记录超过保留时长就会被自动删除。
TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。
从 2.0.8.0 开始TDengine 支持更新已经写入数据的功能。使用更新功能需要在创建数据库时使用 UPDATE 1 参数,之后可以使用 INSERT INTO 命令更新已经写入的相同时间戳数据。UPDATE 参数不支持 ALTER DATABASE 命令修改。没有使用 UPDATE 1 参数创建的数据库,写入相同时间戳的数据不会修改之前的数据,也不会报错。
## 10. 我怎么创建超过1024列的表
@ -132,8 +134,3 @@ TDengine是根据hostname唯一标志一台机器的在数据文件从机器A
- 2.0.7.0 及以后的版本,到/var/lib/taos/dnode下修复dnodeEps.json的dnodeId对应的FQDN重启。确保机器内所有机器的此文件是完全相同的。
- 1.x 和 2.x 版本的存储结构不兼容,需要使用迁移工具或者自己开发应用导出导入数据。
## 17. TDengine 是否支持删除或更新已经写入的数据?
TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。
从 2.0.8.0 开始TDengine 支持更新已经写入数据的功能。使用更新功能需要在创建数据库时使用 UPDATE 1 参数,之后可以使用 INSERT INTO 命令更新已经写入的相同时间戳数据。UPDATE 参数不支持 ALTER DATABASE 命令修改。没有使用 UPDATE 1 参数创建的数据库,写入相同时间戳的数据不会修改之前的数据,也不会报错。

View File

@ -222,7 +222,7 @@ MQTT是一流行的物联网数据传输协议TDengine 可以很方便的接
## 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 直接写入

View File

@ -265,9 +265,6 @@
# maximum display width of binary and nchar fields in the shell. The parts exceeding this limit will be hidden
# maxBinaryDisplayWidth 30
# enable/disable telemetry reporting
# telemetryReporting 1
# enable/disable stream (continuous query)
# stream 1

View File

@ -1,14 +1,16 @@
FROM ubuntu:20.04
FROM ubuntu:18.04
WORKDIR /root
ARG version
RUN echo $version
COPY tdengine.tar.gz /root/
RUN tar -zxf tdengine.tar.gz
WORKDIR /root/TDengine-server-$version/
RUN /bin/bash install.sh -e no
ARG pkgFile
ARG dirName
RUN echo ${pkgFile}
RUN echo ${dirName}
COPY ${pkgFile} /root/
RUN tar -zxf ${pkgFile}
WORKDIR /root/${dirName}/
RUN /bin/bash install.sh -e no
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib"
ENV LANG=en_US.UTF-8

View File

@ -0,0 +1,44 @@
#!/bin/bash
set -e
#set -x
# dockerbuild.sh
# -n [version number]
# -p [xxxx]
# set parameters by default value
verNumber=""
passWord=""
while getopts "hn:p:" arg
do
case $arg in
n)
#echo "verNumber=$OPTARG"
verNumber=$(echo $OPTARG)
;;
p)
#echo "passWord=$OPTARG"
passWord=$(echo $OPTARG)
;;
h)
echo "Usage: `basename $0` -n [version number] "
echo " -p [password for docker hub] "
exit 0
;;
?) #unknow option
echo "unkonw argument"
exit 1
;;
esac
done
echo "verNumber=${verNumber}"
docker manifest create -a tdengine/tdengine:${verNumber} tdengine/tdengine-amd64:${verNumber} tdengine/tdengine-aarch64:${verNumber} tdengine/tdengine-aarch32:${verNumber}
docker login -u tdengine -p ${passWord} #replace the docker registry username and password
docker manifest push tdengine/tdengine:${verNumber}
# how set latest version ???

View File

@ -1,5 +0,0 @@
#!/bin/bash
set -x
docker build --rm -f "Dockerfile" -t tdengine/tdengine-aarch64:$1 "." --build-arg version=$1
docker login -u tdengine -p $2 #replace the docker registry username and password
docker push tdengine/tdengine-aarch64:$1

View File

@ -1,5 +1,63 @@
#!/bin/bash
set -x
docker build --rm -f "Dockerfile" -t tdengine/tdengine:$1 "." --build-arg version=$1
docker login -u tdengine -p $2 #replace the docker registry username and password
docker push tdengine/tdengine:$1
set -e
#set -x
# dockerbuild.sh
# -c [aarch32 | aarch64 | amd64 | x86 | mips64 ...]
# -f [pkg file]
# -n [version number]
# -p [password for docker hub]
# set parameters by default value
cpuType=amd64
verNumber=""
passWord=""
pkgFile=""
while getopts "hc:n:p:f:" arg
do
case $arg in
c)
#echo "cpuType=$OPTARG"
cpuType=$(echo $OPTARG)
;;
n)
#echo "verNumber=$OPTARG"
verNumber=$(echo $OPTARG)
;;
p)
#echo "passWord=$OPTARG"
passWord=$(echo $OPTARG)
;;
f)
#echo "pkgFile=$OPTARG"
pkgFile=$(echo $OPTARG)
;;
h)
echo "Usage: `basename $0` -c [aarch32 | aarch64 | amd64 | x86 | mips64 ...] "
echo " -f [pkg file] "
echo " -n [version number] "
echo " -p [password for docker hub] "
exit 0
;;
?) #unknow option
echo "unkonw argument"
exit 1
;;
esac
done
echo "cpuType=${cpuType} verNumber=${verNumber} pkgFile=${pkgFile} "
echo "$(pwd)"
echo "====NOTES: ${pkgFile} must be in the same directory as dockerbuild.sh===="
dirName=${pkgFile%-Linux*}
#echo "dirName=${dirName}"
docker build --rm -f "Dockerfile" -t tdengine/tdengine-${cpuType}:${verNumber} "." --build-arg pkgFile=${pkgFile} --build-arg dirName=${dirName}
docker login -u tdengine -p ${passWord} #replace the docker registry username and password
docker push tdengine/tdengine-${cpuType}:${verNumber}
# set this version to latest version
docker tag tdengine/tdengine-${cpuType}:${verNumber} tdengine/tdengine-${cpuType}:latest
docker push tdengine/tdengine-${cpuType}:latest

View File

@ -0,0 +1,56 @@
#!/bin/bash
#
set -e
#set -x
# dockerbuild.sh
# -c [aarch32 | aarch64 | amd64 | x86 | mips64 ...]
# -n [version number]
# -p [password for docker hub]
# set parameters by default value
cpuType=aarch64
verNumber=""
passWord=""
while getopts "hc:n:p:f:" arg
do
case $arg in
c)
#echo "cpuType=$OPTARG"
cpuType=$(echo $OPTARG)
;;
n)
#echo "verNumber=$OPTARG"
verNumber=$(echo $OPTARG)
;;
p)
#echo "passWord=$OPTARG"
passWord=$(echo $OPTARG)
;;
h)
echo "Usage: `basename $0` -c [aarch32 | aarch64 | amd64 | x86 | mips64 ...] "
echo " -n [version number] "
echo " -p [password for docker hub] "
exit 0
;;
?) #unknow option
echo "unkonw argument"
exit 1
;;
esac
done
pkgFile=TDengine-server-${verNumber}-Linux-${cpuType}.tar.gz
echo "cpuType=${cpuType} verNumber=${verNumber} pkgFile=${pkgFile} "
scriptDir=`pwd`
pkgDir=$scriptDir/../../release/
cp -f ${pkgDir}/${pkgFile} .
./dockerbuild.sh -c ${cpuType} -f ${pkgFile} -n ${verNumber} -p ${passWord}
rm -f ${pkgFile}

View File

@ -0,0 +1,144 @@
# Usage:
# sudo gdb -x ./taosd-dump-cfg.gdb
define attach_pidof
if $argc != 1
help attach_pidof
else
shell echo -e "\
set \$PID = "$(echo $(pidof $arg0) 0 | cut -d " " -f 1)"\n\
if \$PID > 0\n\
attach "$(pidof -s $arg0)"\n\
else\n\
print \"Process '"$arg0"' not found\"\n\
end" > /tmp/gdb.pidof
source /tmp/gdb.pidof
end
end
document attach_pidof
Attach to process by name
Usage: attach_pidof PROG_NAME
end
set $TAOS_CFG_VTYPE_INT8 = 0
set $TAOS_CFG_VTYPE_INT16 = 1
set $TAOS_CFG_VTYPE_INT32 = 2
set $TAOS_CFG_VTYPE_FLOAT = 3
set $TAOS_CFG_VTYPE_STRING = 4
set $TAOS_CFG_VTYPE_IPSTR = 5
set $TAOS_CFG_VTYPE_DIRECTORY = 6
set $TSDB_CFG_CTYPE_B_CONFIG = 1U
set $TSDB_CFG_CTYPE_B_SHOW = 2U
set $TSDB_CFG_CTYPE_B_LOG = 4U
set $TSDB_CFG_CTYPE_B_CLIENT = 8U
set $TSDB_CFG_CTYPE_B_OPTION = 16U
set $TSDB_CFG_CTYPE_B_NOT_PRINT = 32U
set $TSDB_CFG_PRINT_LEN = 53
define print_blank
if $argc == 1
set $blank_len = $arg0
while $blank_len > 0
printf "%s", " "
set $blank_len = $blank_len - 1
end
end
end
define dump_cfg
if $argc != 1
help dump_cfg
else
set $blen = $TSDB_CFG_PRINT_LEN - (int)strlen($arg0.option)
if $blen < 0
$blen = 0
end
#printf "%s: %d\n", "******blen: ", $blen
printf "%s: ", $arg0.option
print_blank $blen
if $arg0.valType == $TAOS_CFG_VTYPE_INT8
printf "%d\n", *((int8_t *) $arg0.ptr)
else
if $arg0.valType == $TAOS_CFG_VTYPE_INT16
printf "%d\n", *((int16_t *) $arg0.ptr)
else
if $arg0.valType == $TAOS_CFG_VTYPE_INT32
printf "%d\n", *((int32_t *) $arg0.ptr)
else
if $arg0.valType == $TAOS_CFG_VTYPE_FLOAT
printf "%f\n", *((float *) $arg0.ptr)
else
printf "%s\n", $arg0.ptr
end
end
end
end
end
end
document dump_cfg
Dump a cfg entry
Usage: dump_cfg cfg
end
set pagination off
attach_pidof taosd
set $idx=0
#print tsGlobalConfigNum
#set $end=$1
set $end=tsGlobalConfigNum
p "*=*=*=*=*=*=*=*=*= taos global config:"
#while ($idx .lt. $end)
while ($idx < $end)
# print tsGlobalConfig[$idx].option
set $cfg = tsGlobalConfig[$idx]
set $tsce = tscEmbedded
# p "1"
if ($tsce == 0)
if !($cfg.cfgType & $TSDB_CFG_CTYPE_B_CLIENT)
end
else
if $cfg.cfgType & $TSDB_CFG_CTYPE_B_NOT_PRINT
else
if !($cfg.cfgType & $TSDB_CFG_CTYPE_B_SHOW)
else
dump_cfg $cfg
end
end
end
set $idx=$idx+1
end
set $idx=0
p "*=*=*=*=*=*=*=*=*= taos local config:"
while ($idx < $end)
set $cfg = tsGlobalConfig[$idx]
set $tsce = tscEmbedded
if ($tsce == 0)
if !($cfg.cfgType & $TSDB_CFG_CTYPE_B_CLIENT)
end
else
if $cfg.cfgType & $TSDB_CFG_CTYPE_B_NOT_PRINT
else
if ($cfg.cfgType & $TSDB_CFG_CTYPE_B_SHOW)
else
dump_cfg $cfg
end
end
end
set $idx=$idx+1
end
detach
quit

View File

@ -56,7 +56,7 @@ int32_t bnInitThread() {
pthread_attr_destroy(&thattr);
if (ret != 0) {
mError("failed to create balance thread since %s", strerror(errno));
mError("failed to create balance thread since %s", strerror(ret));
return -1;
}

View File

@ -902,13 +902,17 @@ int32_t parseSlidingClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQu
int32_t tscSetTableFullName(STableMetaInfo* pTableMetaInfo, SStrToken* pTableName, SSqlObj* pSql) {
const char* msg1 = "name too long";
const char* msg2 = "acctId too long";
SSqlCmd* pCmd = &pSql->cmd;
int32_t code = TSDB_CODE_SUCCESS;
if (hasSpecifyDB(pTableName)) { // db has been specified in sql string so we ignore current db path
tNameSetAcctId(&pTableMetaInfo->name, getAccountId(pSql));
code = tNameSetAcctId(&pTableMetaInfo->name, getAccountId(pSql));
if (code != 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
char name[TSDB_TABLE_FNAME_LEN] = {0};
strncpy(name, pTableName->z, pTableName->n);

View File

@ -2228,6 +2228,8 @@ int tscProcessRetrieveRspFromNode(SSqlObj *pSql) {
SSqlRes *pRes = &pSql->res;
SSqlCmd *pCmd = &pSql->cmd;
assert(pRes->rspLen >= sizeof(SRetrieveTableRsp));
SRetrieveTableRsp *pRetrieve = (SRetrieveTableRsp *)pRes->pRsp;
if (pRetrieve == NULL) {
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;

View File

@ -110,6 +110,7 @@ static SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pa
rpcClose(pDnodeConn);
free(pObj->tscCorMgmtEpSet);
free(pObj);
return NULL;
}
memcpy(pObj->tscCorMgmtEpSet, &corMgmtEpSet, sizeof(SRpcCorEpSet));

View File

@ -367,6 +367,9 @@ int32_t tNameSetAcctId(SName* dst, const char* acct) {
}
tstrncpy(dst->acctId, acct, tListLen(dst->acctId));
assert(strlen(dst->acctId) > 0);
return 0;
}
@ -383,12 +386,14 @@ int32_t tNameFromString(SName* dst, const char* str, uint32_t type) {
int32_t len = (int32_t)(p - str);
// too long account id or too long db name
if (len >= tListLen(dst->acctId) || len == 0) {
if ((len >= tListLen(dst->acctId)) || (len <= 0)) {
return -1;
}
memcpy (dst->acctId, str, len);
dst->acctId[len] = 0;
assert(strlen(dst->acctId) > 0);
}
if ((type & T_NAME_DB) == T_NAME_DB) {
@ -404,7 +409,7 @@ int32_t tNameFromString(SName* dst, const char* str, uint32_t type) {
}
// too long account id or too long db name
if (len >= tListLen(dst->dbname) || len == 0) {
if ((len >= tListLen(dst->dbname)) || (len <= 0)) {
return -1;
}
@ -419,7 +424,7 @@ int32_t tNameFromString(SName* dst, const char* str, uint32_t type) {
int32_t len = (int32_t) strlen(start);
// too long account id or too long db name
if (len >= tListLen(dst->tname) || len == 0) {
if ((len >= tListLen(dst->tname)) || (len <= 0)) {
return -1;
}

View File

@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED)
ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME}
POST_BUILD
COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.16-dist.jar ${LIBRARY_OUTPUT_PATH}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.17-dist.jar ${LIBRARY_OUTPUT_PATH}
COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
COMMENT "build jdbc driver")
ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME})

View File

@ -5,7 +5,7 @@
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.16</version>
<version>2.0.17</version>
<packaging>jar</packaging>
<name>JDBCDriver</name>

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.16</version>
<version>2.0.17</version>
<packaging>jar</packaging>
<name>JDBCDriver</name>
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
@ -74,6 +74,14 @@
<version>1.2.58</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.7.0</version>
</dependency>
</dependencies>
<build>

View File

@ -1,28 +1,13 @@
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
public abstract class AbstractDatabaseMetaData implements DatabaseMetaData, Wrapper {
private final static String PRODUCT_NAME = "TDengine";
private final static String PRODUCT_VESION = "2.0.x.x";
private final static String DRIVER_NAME = "taos-jdbcdriver";
private final static String DRIVER_VERSION = "2.0.x";
private final static int DRIVER_MAJAR_VERSION = 2;
private final static int DRIVER_MINOR_VERSION = 0;
@ -67,9 +52,7 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
return PRODUCT_VESION;
}
public String getDriverName() throws SQLException {
return DRIVER_NAME;
}
public abstract String getDriverName() throws SQLException;
public String getDriverVersion() throws SQLException {
return DRIVER_VERSION;
@ -92,6 +75,7 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
}
public boolean supportsMixedCaseIdentifiers() throws SQLException {
//像databasetable这些对象的标识符在存储时是否采用大小写混合的模式
return false;
}
@ -100,7 +84,7 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
}
public boolean storesLowerCaseIdentifiers() throws SQLException {
return false;
return true;
}
public boolean storesMixedCaseIdentifiers() throws SQLException {
@ -168,10 +152,12 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
}
public boolean nullPlusNonNullIsNull() throws SQLException {
// null + non-null != null
return false;
}
public boolean supportsConvert() throws SQLException {
// 是否支持转换函数convert
return false;
}
@ -196,7 +182,7 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
}
public boolean supportsGroupBy() throws SQLException {
return false;
return true;
}
public boolean supportsGroupByUnrelated() throws SQLException {
@ -468,7 +454,7 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
}
public int getDefaultTransactionIsolation() throws SQLException {
return 0;
return Connection.TRANSACTION_NONE;
}
public boolean supportsTransactions() throws SQLException {
@ -476,6 +462,8 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
}
public boolean supportsTransactionIsolationLevel(int level) throws SQLException {
if (level == Connection.TRANSACTION_NONE)
return true;
return false;
}
@ -495,18 +483,113 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
return false;
}
public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern)
throws SQLException {
public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException {
return null;
}
public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern,
String columnNamePattern) throws SQLException {
public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException {
return null;
}
public abstract ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types)
throws SQLException;
public abstract ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException;
protected ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types, Connection connection) throws SQLException {
try (Statement stmt = connection.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();
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(0, dbname); //table_cat
rowData.setString(1, null); //TABLE_SCHEM
rowData.setString(2, tables.getString("table_name")); //TABLE_NAME
rowData.setString(3, "TABLE"); //TABLE_TYPE
rowData.setString(4, ""); //REMARKS
rowDataList.add(rowData);
}
ResultSet stables = stmt.executeQuery("show stables");
while (stables.next()) {
TSDBResultSetRowData rowData = new TSDBResultSetRowData(10);
rowData.setString(0, dbname); //TABLE_CAT
rowData.setString(1, null); //TABLE_SCHEM
rowData.setString(2, stables.getString("name")); //TABLE_NAME
rowData.setString(3, "TABLE"); //TABLE_TYPE
rowData.setString(4, "STABLE"); //REMARKS
rowDataList.add(rowData);
}
resultSet.setRowDataList(rowDataList);
return resultSet;
}
}
public ResultSet getSchemas() throws SQLException {
return getEmptyResultSet();
@ -516,32 +599,239 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
public ResultSet getTableTypes() throws SQLException {
DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
// set up ColumnMetaDataList
List<ColumnMetaData> columnMetaDataList = new ArrayList<ColumnMetaData>(1);
List<ColumnMetaData> columnMetaDataList = new ArrayList<>();
ColumnMetaData colMetaData = new ColumnMetaData();
colMetaData.setColIndex(0);
colMetaData.setColName("TABLE_TYPE");
colMetaData.setColSize(10);
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
columnMetaDataList.add(colMetaData);
resultSet.setColumnMetaDataList(columnMetaDataList);
// set up rowDataList
List<TSDBResultSetRowData> rowDataList = new ArrayList<TSDBResultSetRowData>(2);
TSDBResultSetRowData rowData = new TSDBResultSetRowData();
List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
TSDBResultSetRowData rowData = new TSDBResultSetRowData(1);
rowData.setString(0, "TABLE");
rowDataList.add(rowData);
rowData = new TSDBResultSetRowData();
rowData = new TSDBResultSetRowData(1);
rowData.setString(0, "STABLE");
rowDataList.add(rowData);
resultSet.setColumnMetaDataList(columnMetaDataList);
resultSet.setRowDataList(rowDataList);
return resultSet;
}
public abstract ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException;
protected ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern, Connection conn) {
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(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
ColumnMetaData col8 = new ColumnMetaData();
col8.setColIndex(8);
col8.setColName("BUFFER_LENGTH");
columnMetaDataList.add(col8);
// DECIMAL_DIGITS
ColumnMetaData col9 = new ColumnMetaData();
col9.setColIndex(9);
col9.setColName("DECIMAL_DIGITS");
col9.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(col9);
// add NUM_PREC_RADIX
ColumnMetaData col10 = new ColumnMetaData();
col10.setColIndex(10);
col10.setColName("NUM_PREC_RADIX");
col10.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(col10);
// NULLABLE
ColumnMetaData col11 = new ColumnMetaData();
col11.setColIndex(11);
col11.setColName("NULLABLE");
col11.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(col11);
// REMARKS
ColumnMetaData col12 = new ColumnMetaData();
col12.setColIndex(12);
col12.setColName("REMARKS");
col12.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
columnMetaDataList.add(col12);
// COLUMN_DEF
ColumnMetaData col13 = new ColumnMetaData();
col13.setColIndex(13);
col13.setColName("COLUMN_DEF");
col13.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
columnMetaDataList.add(col13);
//SQL_DATA_TYPE
ColumnMetaData col14 = new ColumnMetaData();
col14.setColIndex(14);
col14.setColName("SQL_DATA_TYPE");
col14.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(col14);
//SQL_DATETIME_SUB
ColumnMetaData col15 = new ColumnMetaData();
col15.setColIndex(15);
col15.setColName("SQL_DATETIME_SUB");
col15.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(col15);
//CHAR_OCTET_LENGTH
ColumnMetaData col16 = new ColumnMetaData();
col16.setColIndex(16);
col16.setColName("CHAR_OCTET_LENGTH");
col16.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(col16);
//ORDINAL_POSITION
ColumnMetaData col17 = new ColumnMetaData();
col17.setColIndex(17);
col17.setColName("ORDINAL_POSITION");
col17.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(col17);
// IS_NULLABLE
ColumnMetaData col18 = new ColumnMetaData();
col18.setColIndex(18);
col18.setColName("IS_NULLABLE");
col18.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
columnMetaDataList.add(col18);
//SCOPE_CATALOG
ColumnMetaData col19 = new ColumnMetaData();
col19.setColIndex(19);
col19.setColName("SCOPE_CATALOG");
col19.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
columnMetaDataList.add(col19);
//SCOPE_SCHEMA
ColumnMetaData col20 = new ColumnMetaData();
col20.setColIndex(20);
col20.setColName("SCOPE_SCHEMA");
col20.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
columnMetaDataList.add(col20);
//SCOPE_TABLE
ColumnMetaData col21 = new ColumnMetaData();
col21.setColIndex(21);
col21.setColName("SCOPE_TABLE");
col21.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
columnMetaDataList.add(col21);
//SOURCE_DATA_TYPE
ColumnMetaData col22 = new ColumnMetaData();
col22.setColIndex(22);
col22.setColName("SOURCE_DATA_TYPE");
col22.setColType(TSDBConstants.TSDB_DATA_TYPE_SMALLINT);
columnMetaDataList.add(col22);
//IS_AUTOINCREMENT
ColumnMetaData col23 = new ColumnMetaData();
col23.setColIndex(23);
col23.setColName("IS_AUTOINCREMENT");
col23.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
columnMetaDataList.add(col23);
//IS_GENERATEDCOLUMN
ColumnMetaData col24 = new ColumnMetaData();
col24.setColIndex(24);
col24.setColName("IS_GENERATEDCOLUMN");
col24.setColType(TSDBConstants.TSDB_DATA_TYPE_NCHAR);
columnMetaDataList.add(col24);
resultSet.setColumnMetaDataList(columnMetaDataList);
// set up rowDataList
ResultSet rs = stmt.executeQuery("describe " + dbname + "." + tableNamePattern);
List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
int index = 0;
while (rs.next()) {
TSDBResultSetRowData rowData = new TSDBResultSetRowData(24);
// set TABLE_CAT
rowData.setString(0, dbname);
// set TABLE_NAME
rowData.setString(2, tableNamePattern);
// set COLUMN_NAME
rowData.setString(3, rs.getString("Field"));
// set DATA_TYPE
String typeName = rs.getString("Type");
rowData.setInt(4, getDataType(typeName));
// set TYPE_NAME
rowData.setString(5, typeName);
// set COLUMN_SIZE
int length = rs.getInt("Length");
rowData.setInt(6, getColumnSize(typeName, length));
// set DECIMAL_DIGITS
rowData.setInt(8, getDecimalDigits(typeName));
// set NUM_PREC_RADIX
rowData.setInt(9, 10);
// set NULLABLE
rowData.setInt(10, getNullable(index, typeName));
// set REMARKS
rowData.setString(11, rs.getString("Note"));
rowDataList.add(rowData);
index++;
}
resultSet.setRowDataList(rowDataList);
return resultSet;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
protected int getNullable(int index, String typeName) {
if (index == 0 && "TIMESTAMP".equals(typeName))
return DatabaseMetaData.columnNoNulls;
@ -552,7 +842,6 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
switch (typeName) {
case "TIMESTAMP":
return 23;
default:
return 0;
}
@ -615,9 +904,7 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
return getEmptyResultSet();
}
public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {
return getEmptyResultSet();
}
public abstract ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException;
public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {
return getEmptyResultSet();
@ -718,9 +1005,7 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
return getEmptyResultSet();
}
public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
return getEmptyResultSet();
}
public abstract ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException;
public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern,
String attributeNamePattern) throws SQLException {
@ -728,15 +1013,17 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
}
public boolean supportsResultSetHoldability(int holdability) throws SQLException {
if (holdability == ResultSet.HOLD_CURSORS_OVER_COMMIT)
return true;
return false;
}
public int getResultSetHoldability() throws SQLException {
return 0;
return ResultSet.HOLD_CURSORS_OVER_COMMIT;
}
public int getDatabaseMajorVersion() throws SQLException {
return 0;
return 2;
}
public int getDatabaseMinorVersion() throws SQLException {
@ -744,7 +1031,7 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
}
public int getJDBCMajorVersion() throws SQLException {
return 0;
return 2;
}
public int getJDBCMinorVersion() throws SQLException {
@ -768,7 +1055,7 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
}
public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
return null;
return getEmptyResultSet();
}
public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
@ -805,4 +1092,180 @@ public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
private ResultSet getEmptyResultSet() {
return new EmptyResultSet();
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
try {
return iface.cast(this);
} catch (ClassCastException cce) {
throw new SQLException("Unable to unwrap to " + iface.toString());
}
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return iface.isInstance(this);
}
protected ResultSet getCatalogs(Connection conn) throws SQLException {
try (Statement stmt = conn.createStatement()) {
DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
// set up ColumnMetaDataList
List<ColumnMetaData> columnMetaDataList = new ArrayList<>();
// 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");
while (rs.next()) {
TSDBResultSetRowData rowData = new TSDBResultSetRowData(1);
rowData.setString(0, rs.getString("name"));
rowDataList.add(rowData);
}
resultSet.setRowDataList(rowDataList);
return resultSet;
}
}
protected ResultSet getPrimaryKeys(String catalog, String schema, String table, Connection conn) throws SQLException {
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;
}
}
protected ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern, Connection conn) throws SQLException {
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;
}
}
}

View File

@ -1,68 +0,0 @@
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
/*
* TDengine only supports a subset of the standard SQL, thus this implemetation of the
* standard JDBC API contains more or less some adjustments customized for certain
* compatibility needs.
*/
public class CatalogResultSet extends TSDBResultSetWrapper {
public CatalogResultSet(ResultSet resultSet) {
super.setOriginalResultSet(resultSet);
}
@Override
public String getString(int columnIndex) throws SQLException {
if (columnIndex <= 1) {
return super.getString(columnIndex);
} else {
return null;
}
}
@Override
public boolean getBoolean(int columnIndex) throws SQLException {
if (columnIndex <= 1) {
return super.getBoolean(columnIndex);
} else {
return false;
}
}
@Override
public byte[] getBytes(int columnIndex) throws SQLException {
if (columnIndex <= 1) {
return super.getBytes(columnIndex);
} else {
return null;
}
}
@Override
public Object getObject(int columnIndex) throws SQLException {
if (columnIndex <= 1) {
return super.getObject(columnIndex);
} else {
return null;
}
}
}

View File

@ -16,40 +16,40 @@ package com.taosdata.jdbc;
public class ColumnMetaData {
private int colType = 0;
private String colName = null;
private int colSize = -1;
private int colIndex = 0;
private int colType = 0;
private String colName = null;
private int colSize = -1;
private int colIndex = 0;
public int getColSize() {
return colSize;
}
public int getColSize() {
return colSize;
}
public void setColSize(int colSize) {
this.colSize = colSize;
}
public void setColSize(int colSize) {
this.colSize = colSize;
}
public int getColType() {
return colType;
}
public int getColType() {
return colType;
}
public void setColType(int colType) {
this.colType = colType;
}
public void setColType(int colType) {
this.colType = colType;
}
public String getColName() {
return colName;
}
public String getColName() {
return colName;
}
public void setColName(String colName) {
this.colName = colName;
}
public void setColName(String colName) {
this.colName = colName;
}
public int getColIndex() {
return colIndex;
}
public int getColIndex() {
return colIndex;
}
public void setColIndex(int colIndex) {
this.colIndex = colIndex;
}
public void setColIndex(int colIndex) {
this.colIndex = colIndex;
}
}

View File

@ -1,51 +0,0 @@
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.ResultSet;
/*
* TDengine only supports a subset of the standard SQL, thus this implemetation of the
* standard JDBC API contains more or less some adjustments customized for certain
* compatibility needs.
*/
public class GetColumnsResultSet extends TSDBResultSetWrapper {
private String catalog;
private String schemaPattern;
private String tableNamePattern;
private String columnNamePattern;
public GetColumnsResultSet(ResultSet resultSet, String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) {
super.setOriginalResultSet(resultSet);
this.catalog = catalog;
this.schemaPattern = schemaPattern;
this.tableNamePattern = tableNamePattern;
this.columnNamePattern = columnNamePattern;
}
@Override
public String getString(int columnIndex) {
switch (columnIndex) {
case 1:
return catalog;
case 2:
return null;
case 3:
return tableNamePattern;
default:
return null;
}
}
}

View File

@ -1,53 +0,0 @@
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
/*
* TDengine only supports a subset of the standard SQL, thus this implemetation of the
* standard JDBC API contains more or less some adjustments customized for certain
* compatibility needs.
*/
public class GetTablesResultSet extends TSDBResultSetWrapper {
private String catalog;
private String schemaPattern;
private String tableNamePattern;
private String[] types;
public GetTablesResultSet(ResultSet resultSet, String catalog, String schemaPattern, String tableNamePattern, String[] types) {
super.setOriginalResultSet(resultSet);
this.catalog = catalog;
this.schemaPattern = schemaPattern;
this.tableNamePattern = tableNamePattern;
this.types = types;
}
@Override
public String getString(int columnIndex) throws SQLException {
String ret = null;
switch (columnIndex) {
case 3:
return super.getString(1);
case 4:
return "table";
default:
return null;
}
}
}

View File

@ -14,11 +14,11 @@
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
public class TSDBDatabaseMetaData extends AbstractDatabaseMetaData {
private String url;
private String userName;
@ -29,31 +29,14 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
this.userName = userName;
}
public Connection getConnection() throws SQLException {
return this.conn;
}
public void setConnection(Connection conn) {
this.conn = conn;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
try {
return iface.cast(this);
} catch (ClassCastException cce) {
throw new SQLException("Unable to unwrap to " + iface.toString());
}
}
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return iface.isInstance(this);
}
public boolean allProceduresAreCallable() throws SQLException {
return false;
}
public boolean allTablesAreSelectable() throws SQLException {
return false;
}
public String getURL() throws SQLException {
return this.url;
}
@ -62,911 +45,52 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
return this.userName;
}
public boolean isReadOnly() throws SQLException {
return false;
}
public boolean nullsAreSortedHigh() throws SQLException {
return false;
}
public boolean nullsAreSortedLow() throws SQLException {
return !nullsAreSortedHigh();
}
public boolean nullsAreSortedAtStart() throws SQLException {
return true;
}
public boolean nullsAreSortedAtEnd() throws SQLException {
return !nullsAreSortedAtStart();
}
public String getDatabaseProductName() throws SQLException {
return "TDengine";
}
public String getDatabaseProductVersion() throws SQLException {
return "2.0.x.x";
}
public String getDriverName() throws SQLException {
return TSDBDriver.class.getName();
}
public String getDriverVersion() throws SQLException {
return "2.0.x";
}
public int getDriverMajorVersion() {
return 2;
}
public int getDriverMinorVersion() {
return 0;
}
public boolean usesLocalFiles() throws SQLException {
return false;
}
public boolean usesLocalFilePerTable() throws SQLException {
return false;
}
public boolean supportsMixedCaseIdentifiers() throws SQLException {
//像databasetable这些对象的标识符在存储时是否采用大小写混合的模式
return false;
}
public boolean storesUpperCaseIdentifiers() throws SQLException {
return false;
}
public boolean storesLowerCaseIdentifiers() throws SQLException {
return true;
}
public boolean storesMixedCaseIdentifiers() throws SQLException {
return false;
}
public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
//像databasetable这些对象的标识符在存储时是否采用大小写混合并带引号的模式
return false;
}
public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
return false;
}
public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
return false;
}
public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
return false;
}
public String getIdentifierQuoteString() throws SQLException {
return " ";
}
public String getSQLKeywords() throws SQLException {
return null;
}
public String getNumericFunctions() throws SQLException {
return null;
}
public String getStringFunctions() throws SQLException {
return null;
}
public String getSystemFunctions() throws SQLException {
return null;
}
public String getTimeDateFunctions() throws SQLException {
return null;
}
public String getSearchStringEscape() throws SQLException {
return null;
}
public String getExtraNameCharacters() throws SQLException {
return null;
}
public boolean supportsAlterTableWithAddColumn() throws SQLException {
return true;
}
public boolean supportsAlterTableWithDropColumn() throws SQLException {
return true;
}
public boolean supportsColumnAliasing() throws SQLException {
return true;
}
public boolean nullPlusNonNullIsNull() throws SQLException {
// null + non-null != null
return false;
}
public boolean supportsConvert() throws SQLException {
// 是否支持转换函数convert
return false;
}
public boolean supportsConvert(int fromType, int toType) throws SQLException {
return false;
}
public boolean supportsTableCorrelationNames() throws SQLException {
return false;
}
public boolean supportsDifferentTableCorrelationNames() throws SQLException {
return false;
}
public boolean supportsExpressionsInOrderBy() throws SQLException {
return false;
}
public boolean supportsOrderByUnrelated() throws SQLException {
return false;
}
public boolean supportsGroupBy() throws SQLException {
return true;
}
public boolean supportsGroupByUnrelated() throws SQLException {
return false;
}
public boolean supportsGroupByBeyondSelect() throws SQLException {
return false;
}
public boolean supportsLikeEscapeClause() throws SQLException {
return false;
}
public boolean supportsMultipleResultSets() throws SQLException {
return false;
}
public boolean supportsMultipleTransactions() throws SQLException {
return false;
}
public boolean supportsNonNullableColumns() throws SQLException {
return false;
}
public boolean supportsMinimumSQLGrammar() throws SQLException {
return false;
}
public boolean supportsCoreSQLGrammar() throws SQLException {
return false;
}
public boolean supportsExtendedSQLGrammar() throws SQLException {
return false;
}
public boolean supportsANSI92EntryLevelSQL() throws SQLException {
return false;
}
public boolean supportsANSI92IntermediateSQL() throws SQLException {
return false;
}
public boolean supportsANSI92FullSQL() throws SQLException {
return false;
}
public boolean supportsIntegrityEnhancementFacility() throws SQLException {
return false;
}
public boolean supportsOuterJoins() throws SQLException {
return false;
}
public boolean supportsFullOuterJoins() throws SQLException {
return false;
}
public boolean supportsLimitedOuterJoins() throws SQLException {
return false;
}
public String getSchemaTerm() throws SQLException {
return null;
}
public String getProcedureTerm() throws SQLException {
return null;
}
public String getCatalogTerm() throws SQLException {
return "database";
}
public boolean isCatalogAtStart() throws SQLException {
return true;
}
public String getCatalogSeparator() throws SQLException {
return ".";
}
public boolean supportsSchemasInDataManipulation() throws SQLException {
return false;
}
public boolean supportsSchemasInProcedureCalls() throws SQLException {
return false;
}
public boolean supportsSchemasInTableDefinitions() throws SQLException {
return false;
}
public boolean supportsSchemasInIndexDefinitions() throws SQLException {
return false;
}
public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {
return false;
}
public boolean supportsCatalogsInDataManipulation() throws SQLException {
return true;
}
public boolean supportsCatalogsInProcedureCalls() throws SQLException {
return false;
}
public boolean supportsCatalogsInTableDefinitions() throws SQLException {
return false;
}
public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
return false;
}
public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {
return false;
}
public boolean supportsPositionedDelete() throws SQLException {
return false;
}
public boolean supportsPositionedUpdate() throws SQLException {
return false;
}
public boolean supportsSelectForUpdate() throws SQLException {
return false;
}
public boolean supportsStoredProcedures() throws SQLException {
return false;
}
public boolean supportsSubqueriesInComparisons() throws SQLException {
return false;
}
public boolean supportsSubqueriesInExists() throws SQLException {
return false;
}
public boolean supportsSubqueriesInIns() throws SQLException {
return false;
}
public boolean supportsSubqueriesInQuantifieds() throws SQLException {
return false;
}
public boolean supportsCorrelatedSubqueries() throws SQLException {
return false;
}
public boolean supportsUnion() throws SQLException {
return false;
}
public boolean supportsUnionAll() throws SQLException {
return false;
}
public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
return false;
}
public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
return false;
}
public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
return false;
}
public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
return false;
}
public int getMaxBinaryLiteralLength() throws SQLException {
return 0;
}
public int getMaxCharLiteralLength() throws SQLException {
return 0;
}
public int getMaxColumnNameLength() throws SQLException {
return 0;
}
public int getMaxColumnsInGroupBy() throws SQLException {
return 0;
}
public int getMaxColumnsInIndex() throws SQLException {
return 0;
}
public int getMaxColumnsInOrderBy() throws SQLException {
return 0;
}
public int getMaxColumnsInSelect() throws SQLException {
return 0;
}
public int getMaxColumnsInTable() throws SQLException {
return 0;
}
public int getMaxConnections() throws SQLException {
return 0;
}
public int getMaxCursorNameLength() throws SQLException {
return 0;
}
public int getMaxIndexLength() throws SQLException {
return 0;
}
public int getMaxSchemaNameLength() throws SQLException {
return 0;
}
public int getMaxProcedureNameLength() throws SQLException {
return 0;
}
public int getMaxCatalogNameLength() throws SQLException {
return 0;
}
public int getMaxRowSize() throws SQLException {
return 0;
}
public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
return false;
}
public int getMaxStatementLength() throws SQLException {
return 0;
}
public int getMaxStatements() throws SQLException {
return 0;
}
public int getMaxTableNameLength() throws SQLException {
return 0;
}
public int getMaxTablesInSelect() throws SQLException {
return 0;
}
public int getMaxUserNameLength() throws SQLException {
return 0;
}
public int getDefaultTransactionIsolation() throws SQLException {
return Connection.TRANSACTION_NONE;
}
public boolean supportsTransactions() throws SQLException {
return false;
}
public boolean supportsTransactionIsolationLevel(int level) throws SQLException {
if (level == Connection.TRANSACTION_NONE)
return true;
return false;
}
public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {
return false;
}
public boolean supportsDataManipulationTransactionsOnly() throws SQLException {
return false;
}
public boolean dataDefinitionCausesTransactionCommit() throws SQLException {
return false;
}
public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
return false;
}
public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern)
throws SQLException {
return null;
}
public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern,
String columnNamePattern) throws SQLException {
return null;
}
/**
* @Param catalog : database名称"" 表示不属于任何database的tablenull表示不使用database来缩小范围
* @Param schemaPattern : schema名称""表示
* @Param tableNamePattern : 表名满足tableNamePattern的表, null表示返回所有表
* @Param types : 表类型null表示返回所有类型
*/
public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException {
if (conn == null || conn.isClosed()) {
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
}
try (Statement stmt = conn.createStatement()) {
if (catalog == null || catalog.isEmpty())
return null;
stmt.executeUpdate("use " + catalog);
ResultSet resultSet0 = stmt.executeQuery("show tables");
GetTablesResultSet getTablesResultSet = new GetTablesResultSet(resultSet0, catalog, schemaPattern, tableNamePattern, types);
return getTablesResultSet;
}
return super.getTables(catalog, schemaPattern, tableNamePattern, types, conn);
}
public ResultSet getSchemas() throws SQLException {
return getEmptyResultSet();
}
public ResultSet getCatalogs() throws SQLException {
if (conn == null || conn.isClosed())
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
try (Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery("show databases");
return new CatalogResultSet(rs);
}
return super.getCatalogs(conn);
}
public ResultSet getTableTypes() throws SQLException {
DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
// set up ColumnMetaDataList
List<ColumnMetaData> columnMetaDataList = new ArrayList<>(1);
ColumnMetaData colMetaData = new ColumnMetaData();
colMetaData.setColIndex(0);
colMetaData.setColName("TABLE_TYPE");
colMetaData.setColSize(10);
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
columnMetaDataList.add(colMetaData);
// set up rowDataList
List<TSDBResultSetRowData> rowDataList = new ArrayList<>(2);
TSDBResultSetRowData rowData = new TSDBResultSetRowData();
rowData.setString(0, "TABLE");
rowDataList.add(rowData);
rowData = new TSDBResultSetRowData();
rowData.setString(0, "STABLE");
rowDataList.add(rowData);
resultSet.setColumnMetaDataList(columnMetaDataList);
resultSet.setRowDataList(rowDataList);
return resultSet;
}
public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
throws SQLException {
/** add by zyyang **********/
Statement stmt = null;
if (null != conn && !conn.isClosed()) {
stmt = conn.createStatement();
if (catalog == null || catalog.isEmpty())
return null;
stmt.executeUpdate("use " + catalog);
DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
// set up ColumnMetaDataList
List<ColumnMetaData> columnMetaDataList = new ArrayList<>(24);
columnMetaDataList.add(null);
columnMetaDataList.add(null);
// add TABLE_NAME
ColumnMetaData colMetaData = new ColumnMetaData();
colMetaData.setColIndex(3);
colMetaData.setColName("TABLE_NAME");
colMetaData.setColSize(193);
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
columnMetaDataList.add(colMetaData);
// add COLUMN_NAME
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(4);
colMetaData.setColName("COLUMN_NAME");
colMetaData.setColSize(65);
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
columnMetaDataList.add(colMetaData);
// add DATA_TYPE
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(5);
colMetaData.setColName("DATA_TYPE");
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(colMetaData);
// add TYPE_NAME
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(6);
colMetaData.setColName("TYPE_NAME");
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
columnMetaDataList.add(colMetaData);
// add COLUMN_SIZE
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(7);
colMetaData.setColName("COLUMN_SIZE");
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(colMetaData);
// add BUFFER_LENGTH ,not used
columnMetaDataList.add(null);
// add DECIMAL_DIGITS
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(9);
colMetaData.setColName("DECIMAL_DIGITS");
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(colMetaData);
// add NUM_PREC_RADIX
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(10);
colMetaData.setColName("NUM_PREC_RADIX");
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(colMetaData);
// add NULLABLE
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(11);
colMetaData.setColName("NULLABLE");
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(colMetaData);
resultSet.setColumnMetaDataList(columnMetaDataList);
// set up rowDataList
ResultSet resultSet0 = stmt.executeQuery("describe " + tableNamePattern);
List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
int index = 0;
while (resultSet0.next()) {
TSDBResultSetRowData rowData = new TSDBResultSetRowData(24);
// set TABLE_NAME
rowData.setString(2, tableNamePattern);
// set COLUMN_NAME
rowData.setString(3, resultSet0.getString(1));
// set DATA_TYPE
String typeName = resultSet0.getString(2);
rowData.setInt(4, getDataType(typeName));
// set TYPE_NAME
rowData.setString(5, typeName);
// set COLUMN_SIZE
int length = resultSet0.getInt(3);
rowData.setInt(6, getColumnSize(typeName, length));
// set DECIMAL_DIGITS
rowData.setInt(8, getDecimalDigits(typeName));
// set NUM_PREC_RADIX
rowData.setInt(9, 10);
// set NULLABLE
rowData.setInt(10, getNullable(index, typeName));
rowDataList.add(rowData);
index++;
}
resultSet.setRowDataList(rowDataList);
// GetColumnsResultSet getColumnsResultSet = new GetColumnsResultSet(resultSet0, catalog, schemaPattern, tableNamePattern, columnNamePattern);
// return getColumnsResultSet;
// DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
return resultSet;
} else {
if (conn == null || conn.isClosed())
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
}
/*************************/
// return getEmptyResultSet();
return super.getTableTypes();
}
private int getNullable(int index, String typeName) {
if (index == 0 && "TIMESTAMP".equals(typeName))
return DatabaseMetaData.columnNoNulls;
return DatabaseMetaData.columnNullable;
}
private int getColumnSize(String typeName, int length) {
switch (typeName) {
case "TIMESTAMP":
return 23;
default:
return 0;
}
}
private int getDecimalDigits(String typeName) {
switch (typeName) {
case "FLOAT":
return 5;
case "DOUBLE":
return 9;
default:
return 0;
}
}
private int getDataType(String typeName) {
switch (typeName) {
case "TIMESTAMP":
return Types.TIMESTAMP;
case "INT":
return Types.INTEGER;
case "BIGINT":
return Types.BIGINT;
case "FLOAT":
return Types.FLOAT;
case "DOUBLE":
return Types.DOUBLE;
case "BINARY":
return Types.BINARY;
case "SMALLINT":
return Types.SMALLINT;
case "TINYINT":
return Types.TINYINT;
case "BOOL":
return Types.BOOLEAN;
case "NCHAR":
return Types.NCHAR;
default:
return Types.NULL;
}
}
public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern)
throws SQLException {
return getEmptyResultSet();
}
public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern)
throws SQLException {
return getEmptyResultSet();
}
public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable)
throws SQLException {
return getEmptyResultSet();
}
public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException {
return getEmptyResultSet();
public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException {
if (conn == null || conn.isClosed())
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
return super.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern, conn);
}
public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable,
String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getTypeInfo() throws SQLException {
return getEmptyResultSet();
}
public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate)
throws SQLException {
return getEmptyResultSet();
}
public boolean supportsResultSetType(int type) throws SQLException {
return false;
}
public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {
return false;
}
public boolean ownUpdatesAreVisible(int type) throws SQLException {
return false;
}
public boolean ownDeletesAreVisible(int type) throws SQLException {
return false;
}
public boolean ownInsertsAreVisible(int type) throws SQLException {
return false;
}
public boolean othersUpdatesAreVisible(int type) throws SQLException {
return false;
}
public boolean othersDeletesAreVisible(int type) throws SQLException {
return false;
}
public boolean othersInsertsAreVisible(int type) throws SQLException {
return false;
}
public boolean updatesAreDetected(int type) throws SQLException {
return false;
}
public boolean deletesAreDetected(int type) throws SQLException {
return false;
}
public boolean insertsAreDetected(int type) throws SQLException {
return false;
}
public boolean supportsBatchUpdates() throws SQLException {
return false;
}
public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types)
throws SQLException {
return getEmptyResultSet();
}
public Connection getConnection() throws SQLException {
return this.conn;
}
public boolean supportsSavepoints() throws SQLException {
return false;
}
public boolean supportsNamedParameters() throws SQLException {
return false;
}
public boolean supportsMultipleOpenResults() throws SQLException {
return false;
}
public boolean supportsGetGeneratedKeys() throws SQLException {
return false;
}
public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {
return getEmptyResultSet();
if (conn == null || conn.isClosed())
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
return super.getPrimaryKeys(catalog, schema, table, conn);
}
public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
return getEmptyResultSet();
if (conn == null || conn.isClosed())
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
return super.getSuperTables(catalog, schemaPattern, tableNamePattern, conn);
}
public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern,
String attributeNamePattern) throws SQLException {
return getEmptyResultSet();
}
public boolean supportsResultSetHoldability(int holdability) throws SQLException {
if (holdability == ResultSet.HOLD_CURSORS_OVER_COMMIT)
return true;
return false;
}
public int getResultSetHoldability() throws SQLException {
return ResultSet.HOLD_CURSORS_OVER_COMMIT;
}
public int getDatabaseMajorVersion() throws SQLException {
return 2;
}
public int getDatabaseMinorVersion() throws SQLException {
return 0;
}
public int getJDBCMajorVersion() throws SQLException {
return 2;
}
public int getJDBCMinorVersion() throws SQLException {
return 0;
}
public int getSQLStateType() throws SQLException {
return 0;
}
public boolean locatorsUpdateCopy() throws SQLException {
return false;
}
public boolean supportsStatementPooling() throws SQLException {
return false;
}
public RowIdLifetime getRowIdLifetime() throws SQLException {
return null;
}
public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
return null;
}
public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
return false;
}
public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
return false;
}
public ResultSet getClientInfoProperties() throws SQLException {
return getEmptyResultSet();
}
public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern)
throws SQLException {
return getEmptyResultSet();
}
public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern,
String columnNamePattern) throws SQLException {
return getEmptyResultSet();
}
public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern,
String columnNamePattern) throws SQLException {
return getEmptyResultSet();
}
public boolean generatedKeyAlwaysReturned() throws SQLException {
return false;
}
private ResultSet getEmptyResultSet() {
return new EmptyResultSet();
}
}

View File

@ -1,75 +0,0 @@
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.ParameterMetaData;
import java.sql.SQLException;
public class TSDBParameterMetaData implements ParameterMetaData {
@Override
public int getParameterCount() throws SQLException {
return 0;
}
@Override
public int isNullable(int param) throws SQLException {
return 0;
}
@Override
public boolean isSigned(int param) throws SQLException {
return false;
}
@Override
public int getPrecision(int param) throws SQLException {
return 0;
}
@Override
public int getScale(int param) throws SQLException {
return 0;
}
@Override
public int getParameterType(int param) throws SQLException {
return 0;
}
@Override
public String getParameterTypeName(int param) throws SQLException {
return null;
}
@Override
public String getParameterClassName(int param) throws SQLException {
return null;
}
@Override
public int getParameterMode(int param) throws SQLException {
return 0;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
}

View File

@ -26,9 +26,9 @@ public class TSDBResultSetRowData {
public TSDBResultSetRowData(int colSize) {
this.setColSize(colSize);
}
public TSDBResultSetRowData() {
this.data = new ArrayList<Object>();
this.data = new ArrayList<>();
this.setColSize(0);
}
@ -39,7 +39,7 @@ public class TSDBResultSetRowData {
if (this.colSize == 0) {
return;
}
this.data = new ArrayList<Object>(colSize);
this.data = new ArrayList<>(colSize);
this.data.addAll(Collections.nCopies(this.colSize, null));
}
@ -53,7 +53,7 @@ public class TSDBResultSetRowData {
public boolean getBoolean(int col, int srcType) throws SQLException {
Object obj = data.get(col);
switch(srcType) {
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return (Boolean) obj;
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_BIGINT: return ((Long) obj) == 1L? Boolean.TRUE:Boolean.FALSE;
}
return Boolean.TRUE;
}
public void setByte(int col, byte value) {
data.set(col, value);
}
@ -82,20 +82,20 @@ public class TSDBResultSetRowData {
public int getInt(int col, int srcType) throws SQLException {
Object obj = data.get(col);
switch(srcType) {
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_DOUBLE: return ((Double)obj).intValue();
case TSDBConstants.TSDB_DATA_TYPE_TINYINT: return (Byte) obj;
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:return (Short) obj;
case TSDBConstants.TSDB_DATA_TYPE_INT: return (Integer) obj;
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return ((Long) obj).intValue();
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
case TSDBConstants.TSDB_DATA_TYPE_BINARY: return Integer.parseInt((String) obj);
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_DOUBLE: return ((Double)obj).intValue();
case TSDBConstants.TSDB_DATA_TYPE_TINYINT: return (Byte) obj;
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:return (Short) obj;
case TSDBConstants.TSDB_DATA_TYPE_INT: return (Integer) obj;
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return ((Long) obj).intValue();
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
case TSDBConstants.TSDB_DATA_TYPE_BINARY: return Integer.parseInt((String) obj);
}
return 0;
}
@ -105,7 +105,7 @@ public class TSDBResultSetRowData {
public long getLong(int col, int srcType) throws SQLException {
Object obj = data.get(col);
switch(srcType) {
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0;
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_BIGINT: return (Long) obj;
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;
}
@ -128,7 +128,7 @@ public class TSDBResultSetRowData {
public float getFloat(int col, int srcType) throws SQLException {
Object obj = data.get(col);
switch(srcType) {
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0;
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_BIGINT: return (Long) obj;
}
return 0;
}
@ -149,7 +149,7 @@ public class TSDBResultSetRowData {
public double getDouble(int col, int srcType) throws SQLException {
Object obj = data.get(col);
switch(srcType) {
case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0;
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_BIGINT: return (Long) obj;
}
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
* @param col column index
* @return
* @throws SQLException
* @throws SQLException
*/
public String getString(int col, int srcType) throws SQLException {
if (srcType == TSDBConstants.TSDB_DATA_TYPE_BINARY || srcType == TSDBConstants.TSDB_DATA_TYPE_NCHAR) {

View File

@ -1,19 +0,0 @@
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
public interface TSDBSubscribeCallBack {
void invoke(TSDBResultSet resultSet);
}

View File

@ -29,177 +29,53 @@ public class RestfulDatabaseMetaData extends AbstractDatabaseMetaData {
}
@Override
public String getSchemaTerm() throws SQLException {
return null;
public String getDriverName() throws SQLException {
return RestfulDriver.class.getName();
}
@Override
public String getProcedureTerm() throws SQLException {
return null;
}
@Override
public String getCatalogTerm() throws SQLException {
return null;
}
@Override
public boolean isCatalogAtStart() throws SQLException {
return false;
}
@Override
public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException {
Statement stmt = null;
if (null != connection && !connection.isClosed()) {
stmt = connection.createStatement();
if (catalog == null || catalog.length() < 1) {
catalog = connection.getCatalog();
}
stmt.executeUpdate("use " + catalog);
ResultSet resultSet0 = stmt.executeQuery("show tables");
GetTablesResultSet getTablesResultSet = new GetTablesResultSet(resultSet0, catalog, schemaPattern, tableNamePattern, types);
return getTablesResultSet;
} else {
if (connection == null || connection.isClosed()) {
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
}
return super.getTables(catalog, schemaPattern, tableNamePattern, types, connection);
}
@Override
public ResultSet getCatalogs() throws SQLException {
if (connection != null && !connection.isClosed()) {
Statement stmt = connection.createStatement();
ResultSet resultSet0 = stmt.executeQuery("show databases");
CatalogResultSet resultSet = new CatalogResultSet(resultSet0);
return resultSet;
} else {
return new EmptyResultSet();
if (connection == null || connection.isClosed())
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
return super.getCatalogs(connection);
}
@Override
public ResultSet getTableTypes() throws SQLException {
if (connection == null || connection.isClosed()) {
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
}
return super.getTableTypes();
}
@Override
public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException {
Statement stmt = null;
if (null != connection && !connection.isClosed()) {
stmt = connection.createStatement();
if (catalog == null || catalog.length() < 1) {
catalog = connection.getCatalog();
}
stmt.execute("use " + catalog);
DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
// set up ColumnMetaDataList
List<ColumnMetaData> columnMetaDataList = new ArrayList<>(24);
columnMetaDataList.add(null);
columnMetaDataList.add(null);
// add TABLE_NAME
ColumnMetaData colMetaData = new ColumnMetaData();
colMetaData.setColIndex(3);
colMetaData.setColName("TABLE_NAME");
colMetaData.setColSize(193);
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
columnMetaDataList.add(colMetaData);
// add COLUMN_NAME
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(4);
colMetaData.setColName("COLUMN_NAME");
colMetaData.setColSize(65);
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
columnMetaDataList.add(colMetaData);
// add DATA_TYPE
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(5);
colMetaData.setColName("DATA_TYPE");
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(colMetaData);
// add TYPE_NAME
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(6);
colMetaData.setColName("TYPE_NAME");
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
columnMetaDataList.add(colMetaData);
// add COLUMN_SIZE
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(7);
colMetaData.setColName("COLUMN_SIZE");
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(colMetaData);
// add BUFFER_LENGTH ,not used
columnMetaDataList.add(null);
// add DECIMAL_DIGITS
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(9);
colMetaData.setColName("DECIMAL_DIGITS");
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(colMetaData);
// add NUM_PREC_RADIX
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(10);
colMetaData.setColName("NUM_PREC_RADIX");
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(colMetaData);
// add NULLABLE
colMetaData = new ColumnMetaData();
colMetaData.setColIndex(11);
colMetaData.setColName("NULLABLE");
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
columnMetaDataList.add(colMetaData);
resultSet.setColumnMetaDataList(columnMetaDataList);
// set up rowDataList
ResultSet resultSet0 = stmt.executeQuery("describe " + tableNamePattern);
List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
int index = 0;
while (resultSet0.next()) {
TSDBResultSetRowData rowData = new TSDBResultSetRowData(24);
// set TABLE_NAME
rowData.setString(2, tableNamePattern);
// set COLUMN_NAME
rowData.setString(3, resultSet0.getString(1));
// set DATA_TYPE
String typeName = resultSet0.getString(2);
rowData.setInt(4, getDataType(typeName));
// set TYPE_NAME
rowData.setString(5, typeName);
// set COLUMN_SIZE
int length = resultSet0.getInt(3);
rowData.setInt(6, getColumnSize(typeName, length));
// set DECIMAL_DIGITS
rowData.setInt(8, getDecimalDigits(typeName));
// set NUM_PREC_RADIX
rowData.setInt(9, 10);
// set NULLABLE
rowData.setInt(10, getNullable(index, typeName));
rowDataList.add(rowData);
index++;
}
resultSet.setRowDataList(rowDataList);
return resultSet;
} else {
if (connection == null || connection.isClosed())
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
}
return super.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern, connection);
}
@Override
public long getMaxLogicalLobSize() throws SQLException {
return 0;
public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {
if (connection == null || connection.isClosed())
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
return super.getPrimaryKeys(catalog, schema, table, connection);
}
@Override
public boolean supportsRefCursors() throws SQLException {
return false;
public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
if (connection == null || connection.isClosed())
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
return super.getSuperTables(catalog, schemaPattern, tableNamePattern, connection);
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
}

View File

@ -44,6 +44,8 @@ public class RestfulDriver extends AbstractTaosDriver {
String result = HttpClientPoolUtil.execute(loginUrl);
JSONObject jsonResult = JSON.parseObject(result);
String status = jsonResult.getString("status");
String token = jsonResult.getString("desc");
HttpClientPoolUtil.token = token;
if (!status.equals("succ")) {
throw new SQLException(jsonResult.getString("desc"));
}

View File

@ -23,6 +23,7 @@ import java.nio.charset.Charset;
public class HttpClientPoolUtil {
public static PoolingHttpClientConnectionManager cm = null;
public static CloseableHttpClient httpClient = null;
public static String token = "cm9vdDp0YW9zZGF0YQ==";
/**
* 默认content 类型
*/
@ -61,9 +62,7 @@ public class HttpClientPoolUtil {
try {
return Long.parseLong(value) * 1000;
} catch (Exception e) {
new Exception(
"format KeepAlive timeout exception, exception:" + e.toString())
.printStackTrace();
new Exception("format KeepAlive timeout exception, exception:" + e.toString()).printStackTrace();
}
}
}
@ -96,7 +95,7 @@ public class HttpClientPoolUtil {
initPools();
}
method = (HttpEntityEnclosingRequestBase) getRequest(uri, HttpPost.METHOD_NAME, DEFAULT_CONTENT_TYPE, 0);
method.setHeader("Authorization", "Basic cm9vdDp0YW9zZGF0YQ==");
method.setHeader("Authorization", "Taosd " + token);
method.setHeader("Content-Type", "text/plain");
method.setEntity(new StringEntity(data, Charset.forName("UTF-8")));
HttpContext context = HttpClientContext.create();

View File

@ -1,36 +0,0 @@
import com.taosdata.jdbc.TSDBDriver;
import com.taosdata.jdbc.TSDBPreparedStatement;
import java.sql.*;
import java.util.Properties;
public class TestPreparedStatement {
public static void main(String[] args) throws SQLException {
Connection connection = 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);
String rawSql = "select * from test.log0601";
// String[] params = new String[]{"ts", "c1"};
PreparedStatement pstmt = (TSDBPreparedStatement) connection.prepareStatement(rawSql);
ResultSet resSet = pstmt.executeQuery();
while(resSet.next()) {
for (int i = 1; i <= resSet.getMetaData().getColumnCount(); i++) {
System.out.printf("%d: %s \n", i, resSet.getString(i));
}
}
resSet.close();
pstmt.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
if (null != connection) {
connection.close();
}
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -13,17 +13,17 @@ import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
public class BatchInsertTest extends BaseTest {
public class BatchInsertTest {
static Connection connection = null;
static Statement statement = null;
static String dbName = "test";
static String stbName = "meters";
static String host = "localhost";
static int numOfTables = 30;
final static int numOfRecordsPerTable = 1000;
static long ts = 1496732686000l;
final static String tablePrefix = "t";
private Connection connection;
private static String dbName = "test";
private static String stbName = "meters";
private static String host = "127.0.0.1";
private static int numOfTables = 30;
private static int numOfRecordsPerTable = 1000;
private static long ts = 1496732686000l;
private static String tablePrefix = "t";
@Before
public void createDatabase() throws SQLException {
@ -32,65 +32,58 @@ public class BatchInsertTest extends BaseTest {
} catch (ClassNotFoundException e) {
return;
}
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
statement = connection.createStatement();
statement.executeUpdate("drop database if exists " + dbName);
statement.executeUpdate("create database if not exists " + dbName);
statement.executeUpdate("use " + dbName);
String createTableSql = "create table " + stbName + "(ts timestamp, f1 int, f2 int, f3 int) tags(areaid int, loc binary(20))";
statement.executeUpdate(createTableSql);
Statement stmt = connection.createStatement();
stmt.execute("drop database if exists " + dbName);
stmt.execute("create database if not exists " + dbName);
stmt.execute("use " + dbName);
for(int i = 0; i < numOfTables; i++) {
String createTableSql = "create table " + stbName + "(ts timestamp, f1 int, f2 int, f3 int) tags(areaid int, loc binary(20))";
stmt.execute(createTableSql);
for (int i = 0; i < numOfTables; i++) {
String loc = i % 2 == 0 ? "beijing" : "shanghai";
String createSubTalbesSql = "create table " + tablePrefix + i + " using " + stbName + " tags(" + i + ", '" + loc + "')";
statement.executeUpdate(createSubTalbesSql);
String createSubTalbesSql = "create table " + tablePrefix + i + " using " + stbName + " tags(" + i + ", '" + loc + "')";
stmt.execute(createSubTalbesSql);
}
stmt.close();
}
@Test
public void testBatchInsert() throws SQLException{
ExecutorService executorService = Executors.newFixedThreadPool(numOfTables);
for (int i = 0; i < numOfTables; i++) {
final int index = i;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
long startTime = System.currentTimeMillis();
Statement statement = connection.createStatement(); // get statement
StringBuilder sb = new StringBuilder();
sb.append("INSERT INTO " + tablePrefix + index + " VALUES");
Random rand = new Random();
for (int j = 1; j <= numOfRecordsPerTable; j++) {
sb.append("(" + (ts + j) + ", ");
sb.append(rand.nextInt(100) + ", ");
sb.append(rand.nextInt(100) + ", ");
sb.append(rand.nextInt(100) + ")");
}
statement.addBatch(sb.toString());
statement.executeBatch();
long endTime = System.currentTimeMillis();
System.out.println("Thread " + index + " takes " + (endTime - startTime) + " microseconds");
connection.commit();
statement.close();
} catch (Exception e) {
e.printStackTrace();
public void testBatchInsert() throws SQLException {
ExecutorService executorService = Executors.newFixedThreadPool(numOfTables);
for (int i = 0; i < numOfTables; i++) {
final int index = i;
executorService.execute(() -> {
try {
long startTime = System.currentTimeMillis();
Statement statement = connection.createStatement(); // get statement
StringBuilder sb = new StringBuilder();
sb.append("INSERT INTO " + tablePrefix + index + " VALUES");
Random rand = new Random();
for (int j = 1; j <= numOfRecordsPerTable; j++) {
sb.append("(" + (ts + j) + ", ");
sb.append(rand.nextInt(100) + ", ");
sb.append(rand.nextInt(100) + ", ");
sb.append(rand.nextInt(100) + ")");
}
statement.addBatch(sb.toString());
statement.executeBatch();
long endTime = System.currentTimeMillis();
System.out.println("Thread " + index + " takes " + (endTime - startTime) + " microseconds");
connection.commit();
statement.close();
} catch (Exception e) {
e.printStackTrace();
}
});
}
executorService.shutdown();
try {
@ -100,21 +93,23 @@ public class BatchInsertTest extends BaseTest {
}
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery("select * from meters");
ResultSet rs = statement.executeQuery("select * from meters");
int num = 0;
while (rs.next()) {
num++;
}
assertEquals(num, numOfTables * numOfRecordsPerTable);
}
assertEquals(num, numOfTables * numOfRecordsPerTable);
rs.close();
}
@After
public void close() throws Exception {
statement.close();
connection.close();
Thread.sleep(10);
public void close() {
try {
if (connection != null)
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -1,5 +1,6 @@
package com.taosdata.jdbc;
import org.junit.Assert;
import org.junit.Test;
import java.sql.Connection;
@ -8,53 +9,31 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import static org.junit.Assert.assertTrue;
public class ConnectionTest extends BaseTest {
static Connection connection = null;
static Statement statement = null;
static String dbName = "test";
static String stbName = "st";
static String host = "localhost";
public class ConnectionTest {
private Connection connection;
private Statement statement;
private static String host = "127.0.0.1";
@Test
public void testConnection() throws SQLException {
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
} catch (ClassNotFoundException e) {
return;
}
public void testConnection() {
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
assertTrue(null != connection);
statement = connection.createStatement();
assertTrue(null != statement);
// try reconnect
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
try {
statement.execute("create database if not exists " + dbName);
Class.forName("com.taosdata.jdbc.TSDBDriver");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
Assert.assertTrue(null != connection);
statement = connection.createStatement();
Assert.assertTrue(null != statement);
statement.close();
connection.close();
} catch (ClassNotFoundException e) {
return;
} catch (SQLException e) {
assert false : "create database error: " + e.getMessage();
}
try {
if (!connection.isClosed()) {
if (!statement.isClosed()) {
statement.executeUpdate("drop database " + dbName);
statement.close();
}
connection.close();
Thread.sleep(10);
}
} catch (Exception e) {
assert false : "close connection error: " + e.getMessage();
e.printStackTrace();
}
}
}

View File

@ -1,92 +1,112 @@
package com.taosdata.jdbc;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.*;
import org.junit.runners.MethodSorters;
import java.sql.*;
import java.util.Properties;
import static org.junit.Assert.assertEquals;
public class ImportTest extends BaseTest {
Connection connection = null;
Statement statement = null;
String dbName = "test";
String tName = "t0";
String host = "localhost";
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ImportTest {
private static Connection connection;
static String dbName = "test";
static String tName = "t0";
static String host = "127.0.0.1";
private static long ts;
@Before
public void createDatabase() throws SQLException {
@BeforeClass
public static void before() {
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
Statement stmt = connection.createStatement();
stmt.execute("create database if not exists " + dbName);
stmt.execute("create table if not exists " + dbName + "." + tName + " (ts timestamp, k int, v int)");
stmt.close();
ts = System.currentTimeMillis();
} catch (ClassNotFoundException e) {
return;
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
statement = connection.createStatement();
statement.executeUpdate("drop database if exists " + dbName);
statement.executeUpdate("create database if not exists " + dbName);
statement.executeUpdate("create table if not exists " + dbName + "." + tName + " (ts timestamp, k int, v int)");
}
@Test
public void insertData() throws Exception {
long ts = 1496732686000l;
for (int i = 0; i < 50; i++) {
ts++;
int row = statement.executeUpdate("insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")");
System.out.println("insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")\t" + row);
assertEquals(1, row);
}
}
@Test
public void selectData() throws Exception {
insertData();
String sql = "select * from test.t0";
ResultSet resSet = statement.executeQuery(sql);
while (resSet.next()) {
for (int i = 1; i <= resSet.getMetaData().getColumnCount(); i++) {
System.out.printf(i + ": " + resSet.getString(i) + "\t");
public void case001_insertData() throws Exception {
try (Statement stmt = connection.createStatement()) {
for (int i = 0; i < 50; i++) {
ts++;
int row = stmt.executeUpdate("import into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")");
System.out.println("import into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")\t" + row);
assertEquals(1, row);
}
}
resSet.close();
}
@Test
public void importData() throws Exception {
// 避免时间重复
long ts = 1496732686000l;
StringBuilder sqlBuilder = new StringBuilder("insert into ").append(dbName).append(".").append(tName).append(" values ");
for (int i = 0; i < 50; i++) {
int a = i / 5;
long t = ts + a;
sqlBuilder.append("(").append(t).append(",").append((100 + i)).append(",").append(i).append(") ");
}
System.out.println(sqlBuilder.toString());
int rows = statement.executeUpdate(sqlBuilder.toString());
System.out.println(rows);
assertEquals(10, rows);
public void case002_checkSum() {
Assert.assertEquals(50, select());
}
@After
public void close() throws Exception {
statement.executeUpdate("drop database " + dbName);
statement.close();
connection.close();
Thread.sleep(10);
private int select() {
int count = 0;
try (Statement stmt = connection.createStatement()) {
String sql = "select * from " + dbName + "." + tName;
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
count++;
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
return count;
}
@Test
public void case003_importData() {
// 避免时间重复
try (Statement stmt = connection.createStatement()) {
StringBuilder sqlBuilder = new StringBuilder("import into ").append(dbName).append(".").append(tName).append(" values ");
for (int i = 0; i < 50; i++) {
int a = i / 5;
long t = (++ts) + a;
sqlBuilder.append("(").append(t).append(",").append((100 + i)).append(",").append(i).append(") ");
}
System.out.println(sqlBuilder.toString());
int rows = stmt.executeUpdate(sqlBuilder.toString());
assertEquals(50, rows);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void case004_checkSum() {
Assert.assertEquals(100, select());
}
@AfterClass
public static void close() {
try {
if (connection != null) {
Statement statement = connection.createStatement();
statement.executeUpdate("drop database " + dbName);
statement.close();
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -4,7 +4,6 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import java.sql.*;
import java.util.Properties;
@ -12,7 +11,7 @@ import java.util.Properties;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@FixMethodOrder(MethodSorters.DEFAULT)
@FixMethodOrder()
public class PreparedStatementTest extends BaseTest {
static Connection connection = null;
static PreparedStatement statement = null;

View File

@ -9,61 +9,73 @@ import java.util.Properties;
import static org.junit.Assert.assertEquals;
public class SelectTest extends BaseTest {
Connection connection = null;
Statement statement = null;
public class SelectTest {
Connection connection;
String dbName = "test";
String tName = "t0";
String host = "localhost";
String host = "127.0.0.1";
@Before
public void createDatabaseAndTable() throws SQLException {
public void createDatabaseAndTable() {
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
Statement stmt = connection.createStatement();
stmt.execute("drop database if exists " + dbName);
stmt.execute("create database if not exists " + dbName);
stmt.execute("create table if not exists " + dbName + "." + tName + " (ts timestamp, k int, v int)");
stmt.close();
} catch (ClassNotFoundException e) {
return;
} catch (SQLException e) {
e.printStackTrace();
}
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
statement = connection.createStatement();
statement.executeUpdate("drop database if exists " + dbName);
statement.executeUpdate("create database if not exists " + dbName);
statement.executeUpdate("create table if not exists " + dbName + "." + tName + " (ts timestamp, k int, v int)");
}
@Test
public void selectData() throws SQLException {
public void selectData() {
long ts = 1496732686000l;
for (int i = 0; i < 50; i++) {
ts++;
int row = statement.executeUpdate("insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")");
System.out.println("insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")\t" + row);
assertEquals(1, row);
try (Statement stmt = connection.createStatement()) {
for (int i = 0; i < 50; i++) {
ts++;
int row = stmt.executeUpdate("insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")");
System.out.println("insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")\t" + row);
assertEquals(1, row);
}
String sql = "select * from " + dbName + "." + tName;
ResultSet resSet = stmt.executeQuery(sql);
int num = 0;
while (resSet.next()) {
num++;
}
resSet.close();
assertEquals(num, 50);
} catch (SQLException e) {
e.printStackTrace();
}
String sql = "select * from " + dbName + "." + tName;
ResultSet resSet = statement.executeQuery(sql);
int num = 0;
while (resSet.next()) {
num++;
}
resSet.close();
assertEquals(num, 50);
}
@After
public void close() throws Exception {
statement.executeUpdate("drop database " + dbName);
statement.close();
connection.close();
Thread.sleep(10);
public void close() {
try {
if (connection != null) {
Statement stmt = connection.createStatement();
stmt.executeUpdate("drop database " + dbName);
stmt.close();
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -12,69 +12,66 @@ import java.util.Properties;
import static org.junit.Assert.assertEquals;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class StableTest extends BaseTest {
static Connection connection = null;
static Statement statement = null;
static String dbName = "test";
static String stbName = "st";
static String host = "localhost";
public class StableTest {
private static Connection connection;
private static String dbName = "test";
private static String stbName = "st";
private static String host = "127.0.0.1";
@BeforeClass
public static void createDatabase() throws SQLException {
public static void createDatabase() {
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
Statement statement = connection.createStatement();
statement.execute("create database if not exists " + dbName);
statement.execute("use " + dbName);
statement.close();
} catch (ClassNotFoundException e) {
return;
} catch (SQLException e) {
e.printStackTrace();
}
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
statement = connection.createStatement();
statement.executeUpdate("create database if not exists " + dbName);
statement.executeQuery("use " + dbName);
}
// @Test
public void createStable() {
String sql = "create table " + stbName + " (ts timestamp, v1 int, v2 int) tags (tg nchar(20)) ";
try {
statement.executeUpdate(sql);
@Test
public void case001_createSuperTable() {
try (Statement stmt = connection.createStatement()) {
final String sql = "create table " + stbName + " (ts timestamp, v1 int, v2 int) tags (tg nchar(20)) ";
stmt.execute(sql);
} catch (SQLException e) {
assert false : "error create stable" + e.getMessage();
}
}
// @Test
public void createTable() {
String sql = "create table t1 using " + stbName + " tags (\"beijing\")";
try {
statement.executeUpdate(sql);
@Test
public void case002_createTable() {
try (Statement stmt = connection.createStatement()) {
final String sql = "create table t1 using " + stbName + " tags (\"beijing\")";
stmt.execute(sql);
} catch (SQLException e) {
assert false : "error create table" + e.getMessage();
}
}
@Test
public void describeSTable() {
createStable();
String sql = "describe " + stbName;
public void case003_describeSTable() {
int num = 0;
System.out.println("describe stable");
try {
ResultSet res = statement.executeQuery(sql);
while (res.next()) {
for (int i = 1; i <= res.getMetaData().getColumnCount(); i++) {
System.out.printf("%d: %s\n", i, res.getString(i));
try (Statement stmt = connection.createStatement()) {
String sql = "describe " + stbName;
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
System.out.println(i + ":" + rs.getString(i));
}
num++;
}
res.close();
rs.close();
assertEquals(4, num);
} catch (SQLException e) {
assert false : "error describe stable" + e.getMessage();
@ -82,41 +79,31 @@ public class StableTest extends BaseTest {
}
@Test
public void describeTable() {
createTable();
String sql = "describe t1";
public void case004_describeTable() {
int num = 0;
System.out.println("describe table");
try {
ResultSet res = statement.executeQuery(sql);
while (res.next()) {
for (int i = 1; i <= res.getMetaData().getColumnCount(); i++) {
System.out.printf("%d: %s\n", i, res.getString(i));
try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("describe t1");
while (rs.next()) {
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
System.out.printf("%d: %s\n", i, rs.getString(i));
}
num++;
}
res.close();
rs.close();
assertEquals(4, num);
} catch (SQLException e) {
assert false : "error describe stable" + e.getMessage();
}
}
// @Test
public void validCreateSql() {
String sql = "create table t2 using " + stbName + " tags (\"beijing\")";
boolean valid = ((TSDBConnection) connection).getConnection().validateCreateTableSql(sql);
assertEquals(true, valid);
}
@AfterClass
public static void close() throws Exception {
if (!statement.isClosed()) {
statement.executeUpdate("drop database " + dbName);
statement.close();
connection.close();
Thread.sleep(10);
public static void close() {
try {
if (connection != null)
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -10,7 +10,7 @@ import java.util.Properties;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class StatementTest extends BaseTest {
public class StatementTest {
static Connection connection = null;
static Statement statement = null;
static String dbName = "test";
@ -26,14 +26,29 @@ public class StatementTest extends BaseTest {
return;
}
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", properties);
statement = connection.createStatement();
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
public void testUnsupport() {
// if(null == resSet) {
// return;
// }
TSDBStatement tsdbStatement = (TSDBStatement) statement;
try {
tsdbStatement.unwrap(null);
@ -163,11 +175,10 @@ public class StatementTest extends BaseTest {
@AfterClass
public static void close() throws Exception {
if (!statement.isClosed()) {
statement.executeUpdate("drop database " + dbName);
statement.executeUpdate("drop database if exists " + dbName);
statement.close();
connection.close();
Thread.sleep(10);
}
}
}

View File

@ -1,28 +1,41 @@
package com.taosdata.jdbc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.*;
import java.util.Properties;
public class TSDBDatabaseMetaDataTest {
private TSDBDatabaseMetaData metaData;
private static final String host = "localhost";
private static final String host = "127.0.0.1";
private Connection connection;
@Before
public void before() throws ClassNotFoundException, SQLException {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
metaData = (TSDBDatabaseMetaData) DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata", properties).getMetaData();
@BeforeClass
public void before() {
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata", properties);
metaData = connection.getMetaData().unwrap(TSDBDatabaseMetaData.class);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
@AfterClass
public void after() {
try {
if (connection != null)
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
@ -642,7 +655,17 @@ public class TSDBDatabaseMetaDataTest {
@Test
public void getTables() throws SQLException {
Assert.assertNull(metaData.getTables("", "", "*", null));
System.out.println("****************************************************");
ResultSet tables = metaData.getTables("log", "", null, null);
ResultSetMetaData metaData = tables.getMetaData();
while (tables.next()) {
System.out.print(metaData.getColumnLabel(1) + ":" + tables.getString(1) + "\t");
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
@ -652,17 +675,47 @@ public class TSDBDatabaseMetaDataTest {
@Test
public void getCatalogs() throws SQLException {
Assert.assertNotNull(metaData.getCatalogs());
System.out.println("****************************************************");
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
public void getTableTypes() throws SQLException {
System.out.println("****************************************************");
ResultSet tableTypes = metaData.getTableTypes();
while (tableTypes.next()) {
System.out.println(tableTypes.getString("TABLE_TYPE"));
}
Assert.assertNotNull(metaData.getTableTypes());
}
@Test
public void getColumns() throws SQLException {
Assert.assertNotNull(metaData.getColumns("", "", "", ""));
System.out.println("****************************************************");
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
@ -687,7 +740,17 @@ public class TSDBDatabaseMetaDataTest {
@Test
public void getPrimaryKeys() throws SQLException {
Assert.assertNotNull(metaData.getPrimaryKeys("", "", ""));
System.out.println("****************************************************");
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
@ -812,7 +875,14 @@ public class TSDBDatabaseMetaDataTest {
@Test
public void getSuperTables() throws SQLException {
Assert.assertNotNull(metaData.getSuperTables("", "", ""));
System.out.println("****************************************************");
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
@ -871,11 +941,6 @@ public class TSDBDatabaseMetaDataTest {
Assert.assertNull(metaData.getRowIdLifetime());
}
@Test
public void testGetSchemas() throws SQLException {
Assert.assertNull(metaData.getSchemas());
}
@Test
public void supportsStoredFunctionsUsingCallSyntax() throws SQLException {
Assert.assertFalse(metaData.supportsStoredFunctionsUsingCallSyntax());

View File

@ -0,0 +1,65 @@
package com.taosdata.jdbc.rs;
import org.junit.Before;
import org.junit.Test;
import java.sql.*;
public class AuthenticationTest {
private static final String host = "127.0.0.1";
private static final String user = "root";
private static final String password = "123456";
private Connection conn;
@Test
public void test() {
// change password
try {
conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=" + user + "&password=taosdata");
Statement stmt = conn.createStatement();
stmt.execute("alter user " + user + " pass '" + password + "'");
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
// use new to login and execute query
try {
conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=" + user + "&password=" + password);
Statement stmt = conn.createStatement();
stmt.execute("show databases");
ResultSet rs = stmt.getResultSet();
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();
}
} catch (SQLException e) {
e.printStackTrace();
}
// change password back
try {
conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=" + user + "&password=" + password);
Statement stmt = conn.createStatement();
stmt.execute("alter user " + user + " pass 'taosdata'");
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Before
public void before() {
try {
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

View File

@ -6,6 +6,7 @@ import org.junit.Test;
import java.sql.*;
public class RestfulDriverTest {
private static final String host = "127.0.0.1";
@Test
public void connect() {
@ -15,9 +16,9 @@ public class RestfulDriverTest {
@Test
public void acceptsURL() throws SQLException {
Driver driver = new RestfulDriver();
boolean isAccept = driver.acceptsURL("jdbc:TAOS-RS://master:6041");
boolean isAccept = driver.acceptsURL("jdbc:TAOS-RS://" + host + ":6041");
Assert.assertTrue(isAccept);
isAccept = driver.acceptsURL("jdbc:TAOS://master:6041");
isAccept = driver.acceptsURL("jdbc:TAOS://" + host + ":6041");
Assert.assertFalse(isAccept);
}
@ -26,6 +27,9 @@ public class RestfulDriverTest {
Driver driver = new RestfulDriver();
final String url = "";
DriverPropertyInfo[] propertyInfo = driver.getPropertyInfo(url, null);
for (DriverPropertyInfo prop : propertyInfo) {
System.out.println(prop);
}
}
@Test

View File

@ -1,6 +1,5 @@
package com.taosdata.jdbc.rs;
import org.junit.*;
import org.junit.runners.MethodSorters;
@ -10,12 +9,13 @@ import java.util.Random;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class RestfulJDBCTest {
private static final String host = "127.0.0.1";
private Connection connection;
@Before
public void before() throws ClassNotFoundException, SQLException {
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
connection = DriverManager.getConnection("jdbc:TAOS-RS://master:6041/restful_test?user=root&password=taosdata");
connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/restful_test?user=root&password=taosdata");
}
@After

View File

@ -10,7 +10,7 @@ import java.sql.*;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SQLTest {
private static final String host = "master";
private static final String host = "127.0.0.1";
private static Connection connection;

View File

@ -21,4 +21,5 @@ public class SqlSyntaxValidatorTest {
Assert.assertTrue(SqlSyntaxValidator.isUseSql("drop database test"));
Assert.assertTrue(SqlSyntaxValidator.isUseSql("drop database if exist test"));
}
}

View File

@ -0,0 +1,67 @@
package com.taosdata.jdbc.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TimeStampUtil {
private static final String datetimeFormat = "yyyy-MM-dd HH:mm:ss.SSS";
public static long datetimeToLong(String dateTime) {
SimpleDateFormat sdf = new SimpleDateFormat(datetimeFormat);
try {
return sdf.parse(dateTime).getTime();
} catch (ParseException e) {
throw new IllegalArgumentException("invalid datetime string >>> " + dateTime);
}
}
public static String longToDatetime(long time) {
SimpleDateFormat sdf = new SimpleDateFormat(datetimeFormat);
return sdf.format(new Date(time));
}
public static class TimeTuple {
public Long start;
public Long end;
public Long timeGap;
TimeTuple(long start, long end, long timeGap) {
this.start = start;
this.end = end;
this.timeGap = timeGap;
}
}
public static TimeTuple range(long start, long timeGap, long size) {
long now = System.currentTimeMillis();
if (timeGap < 1)
timeGap = 1;
if (start == 0)
start = now - size * timeGap;
// 如果size小于1异常
if (size < 1)
throw new IllegalArgumentException("size less than 1.");
// 如果timeGap为1已经超长需要前移start
if (start + size > now) {
start = now - size;
return new TimeTuple(start, now, 1);
}
long end = start + (long) (timeGap * size);
if (end > now) {
//压缩timeGap
end = now;
double gap = (end - start) / (size * 1.0f);
if (gap < 1.0f) {
timeGap = 1;
start = end - size;
} else {
timeGap = (long) gap;
end = start + (long) (timeGap * size);
}
}
return new TimeTuple(start, end, timeGap);
}
}

View File

@ -3,15 +3,15 @@
* @module CTaosInterface
*/
const ref = require('ref');
const ref = require('ref-napi');
const os = require('os');
const ffi = require('ffi');
const ArrayType = require('ref-array');
const Struct = require('ref-struct');
const ffi = require('ffi-napi');
const ArrayType = require('ref-array-napi');
const Struct = require('ref-struct-napi');
const FieldTypes = require('./constants');
const errors = require ('./error');
const TaosObjects = require('./taosobjects');
const { NULL_POINTER } = require('ref');
const { NULL_POINTER } = require('ref-napi');
module.exports = CTaosInterface;

View File

@ -1,4 +1,4 @@
const ref = require('ref');
const ref = require('ref-napi');
require('./globalfunc.js')
const CTaosInterface = require('./cinterface')
const errors = require ('./error')

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +1,34 @@
{
"name": "td2.0-connector",
"version": "2.0.5",
"version": "2.0.6",
"description": "A Node.js connector for TDengine.",
"main": "tdengine.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "node test/test.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/taosdata/tdengine.git"
},
"keywords": [
"TDengine",
"TAOS Data",
"Time Series Database",
"Connector"
],
"author": "StoneT2000",
"license": "AGPL-3.0",
"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",
"author": "TaosData Inc.",
"license": "AGPL-3.0-or-later",
"bugs": {
"url": "https://github.com/taosdata/tdengine/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/taosdata/tdengine.git"
"homepage": "https://github.com/taosdata/tdengine#readme",
"dependencies": {
"ffi-napi": "^3.1.0",
"ref-array-napi": "^1.2.1",
"ref-napi": "^1.5.2",
"ref-struct-napi": "^1.1.1"
}
}

View File

@ -291,7 +291,7 @@ int32_t dnodeInitTelemetry() {
int32_t code = pthread_create(&tsTelemetryThread, &attr, telemetryThread, NULL);
pthread_attr_destroy(&attr);
if (code != 0) {
dTrace("failed to create telemetry thread, reason:%s", strerror(errno));
dTrace("failed to create telemetry thread, reason:%s", strerror(code));
}
dInfo("dnode telemetry is initialized");

View File

@ -4507,6 +4507,7 @@ void setParaFromArg(){
strncpy(g_Dbs.db[0].superTbls[0].sTblName, "meters", MAX_TB_NAME_SIZE);
g_Dbs.db[0].superTbls[0].childTblCount = g_args.num_of_tables;
g_Dbs.threadCount = g_args.num_of_threads;
g_Dbs.threadCountByCreateTbl = 1;
g_Dbs.queryMode = g_args.mode;
g_Dbs.db[0].superTbls[0].autoCreateTable = PRE_CREATE_SUBTBL;

View File

@ -50,6 +50,9 @@ int32_t mnodeProcessRead(SMnodeMsg *pMsg) {
if (!sdbIsMaster()) {
SMnodeRsp *rpcRsp = &pMsg->rpcRsp;
SRpcEpSet *epSet = rpcMallocCont(sizeof(SRpcEpSet));
if (!epSet) {
return TSDB_CODE_MND_OUT_OF_MEMORY;
}
mnodeGetMnodeEpSetForShell(epSet, true);
rpcRsp->rsp = epSet;
rpcRsp->len = sizeof(SRpcEpSet);

View File

@ -504,13 +504,13 @@ int64_t taosTimeTruncate(int64_t t, const SInterval* pInterval, int32_t precisio
int64_t end = 0;
// 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;
while(end < t && ((start + pInterval->sliding) <= INT64_MAX)) { // move forward to the correct time window
start += pInterval->sliding;
if (INT64_MAX - start > pInterval->interval - 1) {
if (start < 0 || INT64_MAX - start > pInterval->interval - 1) {
end = start + pInterval->interval - 1;
} else {
end = INT64_MAX;

View File

@ -39,7 +39,8 @@
#define HTTP_GC_TARGET_SIZE 512
#define HTTP_WRITE_RETRY_TIMES 500
#define HTTP_WRITE_WAIT_TIME_MS 5
#define HTTP_SESSION_ID_LEN (TSDB_USER_LEN + TSDB_KEY_LEN)
#define HTTP_PASSWORD_LEN TSDB_UNI_LEN
#define HTTP_SESSION_ID_LEN (TSDB_USER_LEN + HTTP_PASSWORD_LEN)
typedef enum HttpReqType {
HTTP_REQTYPE_OTHERS = 0,
@ -147,7 +148,7 @@ typedef struct HttpContext {
uint8_t parsed;
char ipstr[22];
char user[TSDB_USER_LEN]; // parsed from auth token or login message
char pass[TSDB_KEY_LEN];
char pass[HTTP_PASSWORD_LEN];
TAOS * taos;
void * ppContext;
HttpSession *session;

View File

@ -51,7 +51,7 @@ int32_t httpParseBasicAuthToken(HttpContext *pContext, char *token, int32_t len)
char *password = user + 1;
int32_t pass_len = (int32_t)((base64 + outlen) - password);
if (pass_len < 1 || pass_len >= TSDB_KEY_LEN) {
if (pass_len < 1 || pass_len >= HTTP_PASSWORD_LEN) {
httpError("context:%p, fd:%d, basic token:%s parse password error", pContext, pContext->fd, token);
free(base64);
return -1;
@ -73,7 +73,7 @@ int32_t httpParseTaosdAuthToken(HttpContext *pContext, char *token, int32_t len)
if (base64) free(base64);
return 01;
}
if (outlen != (TSDB_USER_LEN + TSDB_KEY_LEN)) {
if (outlen != (TSDB_USER_LEN + HTTP_PASSWORD_LEN)) {
httpError("context:%p, fd:%d, taosd token:%s length error", pContext, pContext->fd, token);
free(base64);
return -1;
@ -103,8 +103,8 @@ int32_t httpGenTaosdAuthToken(HttpContext *pContext, char *token, int32_t maxLen
size = sizeof(pContext->pass);
tstrncpy(buffer + sizeof(pContext->user), pContext->pass, size);
char *encrypt = taosDesEncode(KEY_DES_4, buffer, TSDB_USER_LEN + TSDB_KEY_LEN);
char *base64 = base64_encode((const unsigned char *)encrypt, TSDB_USER_LEN + TSDB_KEY_LEN);
char *encrypt = taosDesEncode(KEY_DES_4, buffer, TSDB_USER_LEN + HTTP_PASSWORD_LEN);
char *base64 = base64_encode((const unsigned char *)encrypt, TSDB_USER_LEN + HTTP_PASSWORD_LEN);
size_t len = strlen(base64);
tstrncpy(token, base64, len + 1);

View File

@ -59,11 +59,11 @@ bool gcGetUserFromUrl(HttpContext* pContext) {
bool gcGetPassFromUrl(HttpContext* pContext) {
HttpParser* pParser = pContext->parser;
if (pParser->path[GC_PASS_URL_POS].pos >= TSDB_KEY_LEN || pParser->path[GC_PASS_URL_POS].pos <= 0) {
if (pParser->path[GC_PASS_URL_POS].pos >= HTTP_PASSWORD_LEN || pParser->path[GC_PASS_URL_POS].pos <= 0) {
return false;
}
tstrncpy(pContext->pass, pParser->path[GC_PASS_URL_POS].str, TSDB_KEY_LEN);
tstrncpy(pContext->pass, pParser->path[GC_PASS_URL_POS].str, HTTP_PASSWORD_LEN);
return true;
}

View File

@ -72,11 +72,11 @@ bool restGetUserFromUrl(HttpContext* pContext) {
bool restGetPassFromUrl(HttpContext* pContext) {
HttpParser* pParser = pContext->parser;
if (pParser->path[REST_PASS_URL_POS].pos >= TSDB_KEY_LEN || pParser->path[REST_PASS_URL_POS].pos <= 0) {
if (pParser->path[REST_PASS_URL_POS].pos >= HTTP_PASSWORD_LEN || pParser->path[REST_PASS_URL_POS].pos <= 0) {
return false;
}
tstrncpy(pContext->pass, pParser->path[REST_PASS_URL_POS].str, TSDB_KEY_LEN);
tstrncpy(pContext->pass, pParser->path[REST_PASS_URL_POS].str, HTTP_PASSWORD_LEN);
return true;
}

View File

@ -60,7 +60,10 @@ void httpCleanUpConnect() {
HttpServer *pServer = &tsHttpServer;
if (pServer->pThreads == NULL) return;
pthread_join(pServer->thread, NULL);
if (taosCheckPthreadValid(pServer->thread)) {
pthread_join(pServer->thread, NULL);
}
for (int32_t i = 0; i < pServer->numOfThreads; ++i) {
HttpThread* pThread = pServer->pThreads + i;
if (pThread != NULL) {

View File

@ -324,7 +324,7 @@ bool tgGetUserFromUrl(HttpContext *pContext) {
bool tgGetPassFromUrl(HttpContext *pContext) {
HttpParser *pParser = pContext->parser;
if (pParser->path[TG_PASS_URL_POS].pos >= TSDB_KEY_LEN || pParser->path[TG_PASS_URL_POS].pos <= 0) {
if (pParser->path[TG_PASS_URL_POS].pos >= HTTP_PASSWORD_LEN || pParser->path[TG_PASS_URL_POS].pos <= 0) {
return false;
}

View File

@ -246,7 +246,10 @@ void monStopSystem() {
void monCleanupSystem() {
tsMonitor.quiting = 1;
monStopSystem();
pthread_join(tsMonitor.thread, NULL);
if (taosCheckPthreadValid(tsMonitor.thread)) {
pthread_join(tsMonitor.thread, NULL);
}
if (tsMonitor.conn != NULL) {
taos_close(tsMonitor.conn);
tsMonitor.conn = NULL;

View File

@ -154,7 +154,7 @@ void *taosInitTcpServer(uint32_t ip, uint16_t port, char *label, int numOfThread
if (code == 0) {
code = pthread_create(&pServerObj->thread, &thattr, taosAcceptTcpConnection, (void *)pServerObj);
if (code != 0) {
tError("%s failed to create TCP accept thread(%s)", label, strerror(errno));
tError("%s failed to create TCP accept thread(%s)", label, strerror(code));
}
}

View File

@ -140,6 +140,7 @@ void taosStopUdpConnection(void *handle) {
pConn = pSet->udpConn + i;
if (pConn->fd >=0) shutdown(pConn->fd, SHUT_RDWR);
if (pConn->fd >=0) taosCloseSocket(pConn->fd);
pConn->fd = -1;
}
for (int i = 0; i < pSet->threads; ++i) {
@ -198,8 +199,13 @@ static void *taosRecvUdpData(void *param) {
while (1) {
dataLen = recvfrom(pConn->fd, pConn->buffer, RPC_MAX_UDP_SIZE, 0, (struct sockaddr *)&sourceAdd, &addLen);
if(dataLen <= 0) {
tDebug("%s UDP socket was closed, exiting(%s)", pConn->label, strerror(errno));
break;
tDebug("%s UDP socket(fd:%d) receive dataLen(%d) error(%s)", pConn->label, pConn->fd, (int32_t)dataLen, strerror(errno));
// for windows usage, remote shutdown also returns - 1 in windows client
if (-1 == pConn->fd) {
break;
} else {
continue;
}
}
port = ntohs(sourceAdd.sin_port);

View File

@ -510,7 +510,9 @@ void taosCacheCleanup(SCacheObj *pCacheObj) {
}
pCacheObj->deleting = 1;
pthread_join(pCacheObj->refreshWorker, NULL);
if (taosCheckPthreadValid(pCacheObj->refreshWorker)) {
pthread_join(pCacheObj->refreshWorker, NULL);
}
uInfo("cache:%s will be cleaned up", pCacheObj->name);
doCleanupDataCache(pCacheObj);

View File

@ -274,7 +274,7 @@ void *taosIterateRef(int rsetId, int64_t rid) {
return NULL;
}
if (rid <= 0) {
if (rid < 0) {
uTrace("rsetId:%d rid:%" PRId64 " failed to iterate, rid not valid", rsetId, rid);
terrno = TSDB_CODE_REF_NOT_EXIST;
return NULL;

View File

@ -201,6 +201,8 @@ int32_t vnodeOpen(int32_t vgId) {
pthread_mutex_init(&pVnode->statusMutex, NULL);
vnodeSetInitStatus(pVnode);
tsdbIncCommitRef(pVnode->vgId);
int32_t code = vnodeReadCfg(pVnode);
if (code != TSDB_CODE_SUCCESS) {
vnodeCleanUp(pVnode);
@ -297,7 +299,6 @@ int32_t vnodeOpen(int32_t vgId) {
pVnode->events = NULL;
vDebug("vgId:%d, vnode is opened in %s, pVnode:%p", pVnode->vgId, rootDir, pVnode);
tsdbIncCommitRef(pVnode->vgId);
vnodeAddIntoHash(pVnode);

View File

@ -48,7 +48,6 @@ public class JDBCDemo {
Class.forName("com.taosdata.jdbc.TSDBDriver");
}
Properties properties = new Properties();
properties.setProperty("host", host);
properties.setProperty("charset", "UTF-8");
properties.setProperty("locale", "en_US.UTF-8");
properties.setProperty("timezone", "UTC-8");

View File

@ -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();
}
}
}

View File

@ -1,3 +1,5 @@
package com.taosdata.example;
import com.taosdata.jdbc.TSDBConnection;
import com.taosdata.jdbc.TSDBDriver;
import com.taosdata.jdbc.TSDBResultSet;
@ -6,9 +8,9 @@ import com.taosdata.jdbc.TSDBSubscribe;
import java.sql.DriverManager;
import java.util.Properties;
public class TestTSDBSubscribe {
public class SubscribeDemo {
public static TSDBConnection connectTDengine(String host, String database) throws Exception {
public static TSDBConnection getConnection(String host, String database) throws Exception {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
@ -17,7 +19,7 @@ public class TestTSDBSubscribe {
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
String cs = String.format("jdbc:TAOS://%s:0/%s", host, database);
return (TSDBConnection)DriverManager.getConnection(cs, properties);
return (TSDBConnection) DriverManager.getConnection(cs, properties);
}
public static void main(String[] args) throws Exception {
@ -43,21 +45,21 @@ public class TestTSDBSubscribe {
}
}
if (database.isEmpty() || topic.isEmpty() || sql.isEmpty()) {
System.err.println(usage);
return;
System.err.println(usage);
return;
}
TSDBConnection connection = null;
TSDBSubscribe sub = null;
try {
connection = connectTDengine(host, database);
connection = getConnection(host, database);
sub = ((TSDBConnection) connection).subscribe(topic, sql, false);
int total = 0;
while(true) {
while (true) {
TSDBResultSet rs = sub.consume();
int count = 0;
while(rs.next()) {
while (rs.next()) {
count++;
}
total += count;

View File

@ -67,9 +67,9 @@
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.15</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/taos-jdbcdriver-2.0.15-dist.jar</systemPath>
<version>2.0.17</version>
<!-- <scope>system</scope>-->
<!-- <systemPath>${project.basedir}/src/main/resources/lib/taos-jdbcdriver-2.0.15-dist.jar</systemPath>-->
</dependency>
<!-- fastjson -->
<dependency>

View File

@ -1,4 +1,5 @@
const taos = require('td2.0-connector');
//const taos = require('../../../src/connector/nodejs/');
var host = null;

View File

@ -24,6 +24,17 @@ class TDTestCase:
tdSql.init(conn.cursor(), logSql)
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:
tdSql.execute("create account a&cc PASS 'pass123'")
except Exception as e:
@ -31,6 +42,7 @@ class TDTestCase:
return
tdLog.exit("drop built-in user is error.")
def stop(self):
tdSql.close()

View File

@ -126,6 +126,8 @@ class TDTestCase:
for i in range(2, size):
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 t0 using st tags(null)")
tdSql.execute("alter table t0 set tag t1=2.1")

View File

@ -18,6 +18,8 @@ import time
import random
import requests
import argparse
import datetime
import string
from requests.auth import HTTPBasicAuth
func_list=['avg','count','twa','sum','stddev','leastsquares','min',
'max','first','last','top','bottom','percentile','apercentile',
@ -31,7 +33,7 @@ condition_list=[
'fill(null)'
]
where_list = ['_c0>now-10d',' <50'," like \'%a%\'"]
where_list = ['_c0>now-10d',' <50','like',' is null']
class ConcurrentInquiry:
# def __init__(self,ts=1500000001000,host='127.0.0.1',user='root',password='taosdata',dbname='test',
# stb_prefix='st',subtb_prefix='t',n_Therads=10,r_Therads=10,probabilities=0.05,loop=5,
@ -54,13 +56,15 @@ class ConcurrentInquiry:
self.subtb_stru_list=[]
self.stb_tag_list=[]
self.subtb_tag_list=[]
self.probabilities = [probabilities,1-probabilities]
self.ifjoin = [0,1]
self.probabilities = [1-probabilities,probabilities]
self.ifjoin = [1,0]
self.loop = loop
self.stableNum = stableNum
self.subtableNum = subtableNum
self.insertRows = insertRows
self.mix_table = mix_table
self.max_ts = datetime.datetime.now()
self.min_ts = datetime.datetime.now() - datetime.timedelta(days=5)
def SetThreadsNum(self,num):
self.numOfTherads=num
@ -103,6 +107,14 @@ class ConcurrentInquiry:
self.subtb_stru_list.append(tb)
self.subtb_tag_list.append(tag)
def get_timespan(self,cl): #获取时间跨度(仅第一个超级表)
sql = 'select first(_c0),last(_c0) from ' + self.dbname + '.' + self.stb_list[0] + ';'
print(sql)
cl.execute(sql)
for data in cl:
self.max_ts = data[1]
self.min_ts = data[0]
def get_full(self): #获取所有的表、表结构
host = self.host
user = self.user
@ -118,6 +130,7 @@ class ConcurrentInquiry:
self.r_subtb_list(cl,i)
self.r_stb_stru(cl)
self.r_subtb_stru(cl)
self.get_timespan(cl)
cl.close()
conn.close()
@ -127,9 +140,21 @@ class ConcurrentInquiry:
for i in range(random.randint(0,len(tlist))):
c = random.choice(where_list)
if c == '_c0>now-10d':
l.append(c)
rdate = self.min_ts + (self.max_ts - self.min_ts)/10 * random.randint(-11,11)
conlist = ' _c0 ' + random.choice(['<','>','>=','<=','<>']) + "'" + str(rdate) + "'"
if self.random_pick():
l.append(conlist)
else: l.append(c)
elif '<50' in c:
conlist = ' ' + random.choice(tlist) + random.choice(['<','>','>=','<=','<>']) + str(random.randrange(-100,100))
l.append(conlist)
elif 'is null' in c:
conlist = ' ' + random.choice(tlist) + random.choice([' is null',' is not null'])
l.append(conlist)
else:
l.append(random.choice(tlist)+c)
s_all = string.ascii_letters
conlist = ' ' + random.choice(tlist) + " like \'%" + random.choice(s_all) + "%\' "
l.append(conlist)
return 'where '+random.choice([' and ',' or ']).join(l)
def con_interval(self,tlist,col_list,tag_list):
@ -195,8 +220,10 @@ class ConcurrentInquiry:
if bool(random.getrandbits(1)):
pick_func+=alias
sel_col_list.append(pick_func)
sql=sql+','.join(sel_col_list) #select col & func
if col_rand == 0:
sql = sql + '*'
else:
sql=sql+','.join(sel_col_list) #select col & func
if self.mix_table == 0:
sql = sql + ' from '+random.choice(self.stb_list+self.subtb_list)+' '
elif self.mix_table == 1:
@ -262,7 +289,26 @@ class ConcurrentInquiry:
else:
sel_col_tag.append('t1.' + str(random.choice(col_list[0] + tag_list[0])))
sel_col_tag.append('t2.' + str(random.choice(col_list[1] + tag_list[1])))
sql += ','.join(sel_col_tag)
sel_col_list = []
random.shuffle(func_list)
if self.random_pick():
loop = 0
for i,j in zip(sel_col_tag,func_list): #决定每个被查询col的函数
alias = ' as '+ 'taos%d ' % loop
loop += 1
pick_func = ''
if j == 'leastsquares':
pick_func=j+'('+i+',1,1)'
elif j == 'top' or j == 'bottom' or j == 'percentile' or j == 'apercentile':
pick_func=j+'('+i+',1)'
else:
pick_func=j+'('+i+')'
if bool(random.getrandbits(1)):
pick_func+=alias
sel_col_list.append(pick_func)
sql += ','.join(sel_col_list)
else:
sql += ','.join(sel_col_tag)
sql = sql + ' from '+ str(tbname[0]) +' t1,' + str(tbname[1]) + ' t2 ' #select col & func
join_section = None
@ -274,7 +320,6 @@ class ConcurrentInquiry:
else:
temp = random.choices(col_intersection+tag_intersection)
join_section = temp.pop()
print(random.choices(col_intersection))
sql += 'where t1._c0 = t2._c0 and ' + 't1.' + str(join_section) + '=t2.' + str(join_section)
return sql

View File

@ -175,6 +175,7 @@ python3 ./test.py -f query/bug2119.py
python3 ./test.py -f query/isNullTest.py
python3 ./test.py -f query/queryWithTaosdKilled.py
python3 ./test.py -f query/floatCompare.py
python3 ./test.py -f query/queryGroupbySort.py
#stream
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
# wal
python3 ./test.py -f wal/addOldWalTest.py
python3 ./test.py -f wal/addOldWalTest.py
# account
python3 ./test.py -f account/account_create.py

View File

@ -47,11 +47,38 @@ class TDTestCase:
tdSql.query("select first(col1) - avg(col1) from stb where ts > '2018-09-17 08:00:00.000' and ts < '2018-09-23 04:36:40.000' interval(1h)")
tdSql.checkRows(139)
tdSql.checkData(0, 1, -1.5)
tdSql.checkData(138, 1, -1.0)
tdSql.query("select first(col1) - avg(col1) from stb where ts > '2018-09-17 08:00:00.000' and ts < '2018-09-23 04:36:40.000' interval(1h) fill(none)")
tdSql.checkRows(139)
tdSql.checkData(0, 1, -1.5)
tdSql.checkData(138, 1, -1.0)
tdSql.query("select first(col1) - avg(col1) from stb where ts > '2018-09-17 08:00:00.000' and ts < '2018-09-23 04:36:40.000' interval(1h) fill(value, 2.0)")
tdSql.checkRows(141)
tdSql.checkData(0, 1, 2.0)
tdSql.checkData(140, 1, 2.0)
tdSql.query("select first(col1) - avg(col1) from stb where ts > '2018-09-17 08:00:00.000' and ts < '2018-09-23 04:36:40.000' interval(1h) fill(prev)")
tdSql.checkRows(141)
tdSql.checkData(0, 1, None)
tdSql.checkData(140, 1, -1.0)
tdSql.query("select first(col1) - avg(col1) from stb where ts > '2018-09-17 08:00:00.000' and ts < '2018-09-23 04:36:40.000' interval(1h) fill(null)")
tdSql.checkRows(141)
tdSql.checkData(0, 1, None)
tdSql.checkData(140, 1, None)
tdSql.checkData(140, 1, None)
tdSql.query("select first(col1) - avg(col1) from stb where ts > '2018-09-17 08:00:00.000' and ts < '2018-09-23 04:36:40.000' interval(1h) fill(linear)")
tdSql.checkRows(141)
tdSql.checkData(0, 1, None)
tdSql.checkData(140, 1, None)
tdSql.query("select first(col1) - avg(col1) from stb where ts > '2018-09-17 08:00:00.000' and ts < '2018-09-23 04:36:40.000' interval(1h) fill(next)")
tdSql.checkRows(141)
tdSql.checkData(0, 1, -1.5)
tdSql.checkData(140, 1, None)
tdSql.query("select max(col1) - min(col1) from stb where ts > '2018-09-17 08:00:00.000' and ts < '2018-09-23 04:36:40.000' and id = 1 group by loc, id")
rows = tdSql.queryRows

View File

@ -28,19 +28,24 @@ class TDTestCase:
def run(self):
tdSql.prepare()
tdSql.execute(
"create table stb(ts timestamp,i int) tags (p_id nchar(20));")
tdSql.execute(
"insert into tb using stb tags('11231') values (%d, %d) (%d, %d) (%d, %d) (%d, %d)"
% (self.ts, 12, self.ts + 1, 15, self.ts + 2, 15, self.ts + 3, 12))
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.execute("CREATE TABLE meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int)")
tdSql.execute("CREATE TABLE D1001 USING meters TAGS ('Beijing.Chaoyang', 2)")
tdSql.execute("CREATE TABLE D1002 USING meters TAGS ('Beijing.Chaoyang', 3)")
tdSql.execute("INSERT INTO D1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6, 218, 0.33) (1538548696800, 12.3, 221, 0.31)")
tdSql.execute("INSERT INTO D1002 VALUES (1538548685001, 10.5, 220, 0.28) (1538548696800, 12.3, 221, 0.31)")
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):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)

View File

@ -52,7 +52,15 @@ class TDTestCase:
tdSql.query("select count(*) from meters group by loc")
tdSql.checkRows(2)
tdSql.error("select * from meters group by loc sliding(5s)")
tdSql.error("select * from meters group by loc sliding(5s)")
# Fix defect: https://jira.taosdata.com:18080/browse/TD-2700
tdSql.execute("create database test")
tdSql.execute("use test")
tdSql.execute("create table t1(ts timestamp, k int)")
tdSql.execute("insert into t1 values(1500000001000, 0)")
tdSql.query("select sum(k) from t1 interval(1d) sliding(1h)")
tdSql.checkRows(24)
def stop(self):
tdSql.close()

View File

@ -78,23 +78,10 @@ if $data5_db != 1 then
return -1
endi
sql alter database db quorum 2
sql show databases
print quorum $data5_db
if $data5_db != 2 then
return -1
endi
sql_error alter database db quorum 2
sql alter database db quorum 3
sql show databases
print quorum $data5_db
if $data5_db != 3 then
return -1
endi
sql_error alter database db quorum 3
sql alter database db quorum 3
sql alter database db quorum 2
sql alter database db quorum 1
sql_error alter database db quorum 0
sql_error alter database db quorum 4
sql_error alter database db quorum 5

View File

@ -0,0 +1,97 @@
system sh/stop_dnodes.sh
system sh/deploy.sh -n dnode1 -i 1
system sh/cfg.sh -n dnode1 -c walLevel -v 0
system sh/exec.sh -n dnode1 -s start
sleep 100
sql connect
print ======================== dnode1 start
$dbPrefix = fi_in_db
$tbPrefix = fi_in_tb
$stbPrefix = fi_in_stb
$mtPrefix = fi_in_mt
$tbNum = 10
$rowNum = 20
$totalNum = 200
print create_tb test
print =============== set up
$i = 0
$db = $dbPrefix . $i
$mt = $mtPrefix . $i
$tb = $tbPrefix . $i
$stb = $stbPrefix . $i
sql create database $db
sql use $db
# case1: create stable test
print =========== stableOp.sim case1: create/alter/drop stable test
sql CREATE STABLE $stb (TS TIMESTAMP, COL1 INT) TAGS (ID INT);
sql show stables
if $rows != 1 then
return -1
endi
print data00 = $data00
if $data00 != $stb then
return -1
endi
sql_error CREATE STABLE $tb using $stb tags (1);
sql create table $tb using $stb tags (2);
sql show tables
if $rows != 1 then
return -1
endi
sql alter stable $stb add column COL2 DOUBLE;
sql insert into $tb values (now, 1, 2.0);
sql select * from $tb ;
if $rows != 1 then
return -1
endi
sql alter stable $stb drop column COL2;
sql_error insert into $tb values (now, 1, 2.0);
sql alter stable $stb add tag tag2 int;
sql alter stable $stb change tag tag2 tag3;
sql_error drop stable $tb
sql drop table $tb ;
sql show tables
if $rows != 0 then
return -1
endi
sql DROP STABLE $stb
sql show stables
if $rows != 0 then
return -1
endi
print create/alter/drop stable test passed
sql drop database $db
sql show databases
if $rows != 0 then
return -1
endi
system sh/exec.sh -n dnode1 -s stop -x SIGINT

View File

@ -0,0 +1,46 @@
system sh/stop_dnodes.sh
system sh/deploy.sh -n dnode1 -i 1
system sh/exec.sh -n dnode1 -s start
sleep 3000
sql connect
print =============== create database
sql create database db
sql show databases
if $rows != 1 then
return -1
endi
print $data00 $data01 $data02
print =============== create super table
sql create table db.st1 (ts timestamp, i int) tags (j int)
sql create table db.st2 (ts timestamp, i int, j int) tags (t1 int, t2 int, t3 int)
sql show db.stables
if $rows != 2 then
return -1
endi
print $data00 $data01 $data02
print =============== create multiple child tables
sql create table db.ct1 using db.st1 tags(1) db.ct2 using db.st1 tags(2);
sql show db.tables
if $rows != 2 then
return -1
endi
sql create table db.ct3 using db.st2 tags(1, 1, 1) db.ct4 using db.st2 tags(2, 2, 2);
sql show db.tables
if $rows != 4 then
return -1
endi
sql create table db.ct5 using db.st1 tags(3) db.ct6 using db.st2 tags(3, 3, 3);
sql show db.tables
if $rows != 6 then
return -1
endi
system sh/exec.sh -n dnode1 -s stop -x SIGINT

View File

@ -10,7 +10,7 @@ cd ../../../debug; make
./test.sh -f general/tag/binary_binary.sim
./test.sh -f general/tag/binary.sim
./test.sh -f general/tag/bool_binary.sim
./test.sh -f general/tag/bool_int.sim
#./test.sh -f general/tag/bool_int.sim
./test.sh -f general/tag/bool.sim
./test.sh -f general/tag/change.sim
./test.sh -f general/tag/column.sim
@ -99,6 +99,5 @@ cd ../../../debug; make
./test.sh -f unique/dnode/m2.sim
./test.sh -f unique/dnode/m3.sim
./test.sh -f unique/dnode/offline3.sim
./test.sh -f general/wal/sync.sim
./test.sh -f general/wal/kill.sim
./test.sh -f general/wal/maxtables.sim

View File

@ -32,6 +32,9 @@ NODE_DIR=$SIM_DIR/$NODE_NAME
rm -rf $SIM_DIR/dnode1
rm -rf $SIM_DIR/dnode2
rm -rf $SIM_DIR/dnode3
rm -rf $SIM_DIR/tsim
tar zxf $SCRIPT_DIR/general/connection/sim.tar.gz -C $SIM_DIR/../
cd $SIM_DIR/../sim
fqdn=`hostname -f || hostname`
grep 'test4' -l -r ./* | xargs sed -i "s/test4/${fqdn}/g"
grep 'dataDir' -l -r ./* | xargs sed -i "s#/root/TDengine#${TAOS_DIR}#g"

View File

@ -321,7 +321,7 @@ step9:
endi
sql show dnodes
if $rows != 2 then
if $rows != 3 then
goto step9
endi

View File

@ -60,7 +60,7 @@ print dnode1 $data4_2
if $data4_1 != ready then
return -1
endi
if $data4_2 != offline then
if $data4_2 == ready then
return -1
endi

View File

@ -159,7 +159,7 @@ if $loopCnt == 20 then
endi
sql show dnodes -x wait_dnode1_ready
if $rows != 2 then
if $rows != 3 then
sleep 2000
goto wait_dnode1_ready
endi
@ -232,7 +232,7 @@ if $loopCnt == 10 then
endi
sql show dnodes
if $rows != 2 then
if $rows != 3 then
sleep 2000
goto wait_dnode2_offline
endi

View File

@ -20,11 +20,22 @@ function runSimCaseOneByOne {
while read -r line; do
if [[ $line =~ ^./test.sh* ]] || [[ $line =~ ^run* ]]; then
case=`echo $line | grep sim$ |awk '{print $NF}'`
IN_TDINTERNAL="community"
start_time=`date +%s`
./test.sh -f $case > /dev/null 2>&1 && \
echo -e "${GREEN}$case success${NC}" | tee -a out.log || \
echo -e "${RED}$case failed${NC}" | tee -a out.log
IN_TDINTERNAL="community"
if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]]; then
echo -n $case
./test.sh -f $case > /dev/null 2>&1 && \
( grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \
( grep -q 'script.*success.*m$' ../../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \
echo -e "${RED} failed${NC}" | tee -a out.log
else
echo -n $case
./test.sh -f $case > /dev/null 2>&1 && \
( grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \
( grep -q 'script.*success.*m$' ../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \
echo -e "${RED} failed${NC}" | tee -a out.log
fi
out_log=`tail -1 out.log `
# if [[ $out_log =~ 'failed' ]];then
# exit 8
@ -42,13 +53,17 @@ function runSimCaseOneByOnefq {
start_time=`date +%s`
IN_TDINTERNAL="community"
if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]]; then
echo -n $case
./test.sh -f $case > /dev/null 2>&1 && \
echo -e "${GREEN}$case success${NC}" | tee -a out.log || \
( grep 'script.*success.*m$' ../../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN}$case success${NC}" | tee -a out.log ) || echo -e "${RED}$case failed${NC}" | tee -a out.log
( grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \
( grep -q 'script.*success.*m$' ../../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \
echo -e "${RED} failed${NC}" | tee -a out.log
else
echo -n $case
./test.sh -f $case > /dev/null 2>&1 && \
echo -e "${GREEN}$case success${NC}" | tee -a out.log || \
( grep 'script.*success.*m$' ../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN}$case success${NC}" | tee -a out.log ) || echo -e "${RED}$case failed${NC}" | tee -a out.log
( grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \
( grep -q 'script.*success.*m$' ../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \
echo -e "${RED} failed${NC}" | tee -a out.log
fi
out_log=`tail -1 out.log `
@ -77,9 +92,10 @@ function runPyCaseOneByOne {
case=`echo $line|awk '{print $NF}'`
fi
start_time=`date +%s`
echo -n $case
$line > /dev/null 2>&1 && \
echo -e "${GREEN}$case success${NC}" | tee -a pytest-out.log || \
echo -e "${RED}$case failed${NC}" | tee -a pytest-out.log
echo -e "${GREEN} success${NC}" | tee -a pytest-out.log || \
echo -e "${RED} failed${NC}" | tee -a pytest-out.log
end_time=`date +%s`
out_log=`tail -1 pytest-out.log `
# if [[ $out_log =~ 'failed' ]];then
@ -103,9 +119,10 @@ function runPyCaseOneByOnefq {
case=`echo $line|awk '{print $NF}'`
fi
start_time=`date +%s`
echo -n $case
$line > /dev/null 2>&1 && \
echo -e "${GREEN}$case success${NC}" | tee -a pytest-out.log || \
echo -e "${RED}$case failed${NC}" | tee -a pytest-out.log
echo -e "${GREEN} success${NC}" | tee -a pytest-out.log || \
echo -e "${RED} failed${NC}" | tee -a pytest-out.log
end_time=`date +%s`
out_log=`tail -1 pytest-out.log `
if [[ $out_log =~ 'failed' ]];then
@ -138,7 +155,7 @@ if [ "$2" != "python" ]; then
elif [ "$1" == "b1" ]; then
echo "### run TSIM b1 test ###"
runSimCaseOneByOne jenkins/basic_1.txt
runSimCaseOneByOne jenkins/basic_4.txt
# runSimCaseOneByOne jenkins/basic_4.txt
elif [ "$1" == "b2" ]; then
echo "### run TSIM b2 test ###"
runSimCaseOneByOne jenkins/basic_2.txt

View File

@ -20,6 +20,7 @@
#undef TAOS_MEM_CHECK
bool simAsyncQuery = false;
bool simExecSuccess = false;
void simHandleSignal(int32_t signo) {
simSystemCleanUp();
@ -62,5 +63,8 @@ int32_t main(int32_t argc, char *argv[]) {
simScriptList[++simScriptPos] = script;
simExecuteScript(script);
return 0;
int32_t ret = simExecSuccess ? 0 : -1;
simError("execute result %d", ret);
return ret;
}

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