提交 6fd2c923 编写于 作者: W wenzhouwww

[TD-12388]<test>(query)

[submodule "src/connector/go"] [submodule "src/connector/go"]
path = src/connector/go path = src/connector/go
url = https://github.com/taosdata/driver-go.git url = https://github.com/taosdata/driver-go.git
[submodule "src/connector/hivemq-tdengine-extension"] [submodule "src/connector/hivemq-tdengine-extension"]
path = src/connector/hivemq-tdengine-extension path = src/connector/hivemq-tdengine-extension
url = https://github.com/taosdata/hivemq-tdengine-extension.git url = https://github.com/taosdata/hivemq-tdengine-extension.git
......
...@@ -4,8 +4,10 @@ import jenkins.model.CauseOfInterruption ...@@ -4,8 +4,10 @@ import jenkins.model.CauseOfInterruption
node { node {
} }
def skipbuild=0 def skipbuild = 0
def win_stop=0 def win_stop = 0
def scope = []
def mod = [0,1,2,3,4]
def abortPreviousBuilds() { def abortPreviousBuilds() {
def currentJobName = env.JOB_NAME def currentJobName = env.JOB_NAME
...@@ -349,7 +351,7 @@ pipeline { ...@@ -349,7 +351,7 @@ pipeline {
} }
stages { stages {
stage('pre_build'){ stage('pre_build'){
agent{label 'master'} agent{label 'catalina'}
options { skipDefaultCheckout() } options { skipDefaultCheckout() }
when { when {
changeRequest() changeRequest()
...@@ -358,44 +360,33 @@ pipeline { ...@@ -358,44 +360,33 @@ pipeline {
script{ script{
abort_previous() abort_previous()
abortPreviousBuilds() abortPreviousBuilds()
} println env.CHANGE_BRANCH
// sh''' if(env.CHANGE_FORK){
// rm -rf ${WORKSPACE}.tes scope = ['connector','query','insert','other','tools','taosAdapter']
// cp -r ${WORKSPACE} ${WORKSPACE}.tes }
// cd ${WORKSPACE}.tes else{
// git fetch sh'''
// ''' cd ${WKC}
// script { git reset --hard HEAD~10
// if (env.CHANGE_TARGET == 'master') { git fetch
// sh ''' git checkout ${CHANGE_BRANCH}
// git checkout master git pull
// ''' '''
// } dir('/var/lib/jenkins/workspace/TDinternal/community'){
// else if(env.CHANGE_TARGET == '2.0'){ gitlog = sh(script: "git log -1 --pretty=%B ", returnStdout:true)
// sh ''' println gitlog
// git checkout 2.0 if (!(gitlog =~ /\((.*?)\)/)){
// ''' autoCancelled = true
// } error('Aborting the build.')
// else{ }
// sh ''' temp = (gitlog =~ /\((.*?)\)/)
// git checkout develop temp = temp[0].remove(1)
// ''' scope = temp.split(",")
// } Collections.shuffle mod
// } }
// sh'''
// git fetch origin +refs/pull/${CHANGE_ID}/merge
// git checkout -qf FETCH_HEAD
// '''
// script{ }
// skipbuild='2' }
// skipbuild=sh(script: "git log -2 --pretty=%B | fgrep -ie '[skip ci]' -e '[ci skip]' && echo 1 || echo 2", returnStdout:true)
// println skipbuild
// }
// sh'''
// rm -rf ${WORKSPACE}.tes
// '''
// }
} }
} }
stage('Parallel test stage') { stage('Parallel test stage') {
...@@ -408,239 +399,90 @@ pipeline { ...@@ -408,239 +399,90 @@ pipeline {
} }
} }
parallel { parallel {
stage('python_1_s1') { stage('python_1') {
agent{label " slave1 || slave11 "} agent{label " slave1 || slave6 || slave11 || slave16 "}
steps { steps {
pre_test() pre_test()
timeout(time: 55, unit: 'MINUTES'){ timeout(time: 55, unit: 'MINUTES'){
sh ''' script{
date scope.each {
cd ${WKC}/tests sh """
./test-all.sh p1 date
date''' cd ${WKC}/tests
} ./test-CI.sh ${it} 5 ${mod[0]}
date"""
}
}
}
} }
} }
stage('python_2_s5') { stage('python_2') {
agent{label " slave5 || slave15 "} agent{label " slave2 || slave7 || slave12 || slave17 "}
steps { steps {
pre_test() pre_test()
timeout(time: 55, unit: 'MINUTES'){ timeout(time: 55, unit: 'MINUTES'){
sh ''' script{
date scope.each {
cd ${WKC}/tests sh """
./test-all.sh p2 date
date''' cd ${WKC}/tests
} ./test-CI.sh ${it} 5 ${mod[1]}
} date"""
} }
stage('python_3_s6') { }
agent{label " slave6 || slave16 "}
steps {
timeout(time: 55, unit: 'MINUTES'){
pre_test()
sh '''
date
cd ${WKC}/tests
./test-all.sh p3
date'''
} }
} }
} }
stage('test_b1_s2') { stage('python_3') {
agent{label " slave2 || slave12 "} agent{label " slave3 || slave8 || slave13 ||slave18 "}
steps { steps {
timeout(time: 105, unit: 'MINUTES'){ timeout(time: 105, unit: 'MINUTES'){
pre_test() pre_test()
sh ''' script{
rm -rf /var/lib/taos/* scope.each {
rm -rf /var/log/taos/* sh """
nohup taosd >/dev/null & date
sleep 10 cd ${WKC}/tests
''' ./test-CI.sh ${it} 5 ${mod[2]}
date"""
sh ''' }
cd ${WKC}/src/connector/python
export PYTHONPATH=$PWD/
export LD_LIBRARY_PATH=${WKC}/debug/build/lib
pip3 install pytest
pytest tests/
python3 examples/bind-multi.py
python3 examples/bind-row.py
python3 examples/demo.py
python3 examples/insert-lines.py
python3 examples/pep-249.py
python3 examples/query-async.py
python3 examples/query-objectively.py
python3 examples/subscribe-sync.py
python3 examples/subscribe-async.py
'''
sh '''
cd ${WKC}/src/connector/nodejs
npm install
npm run test
cd ${WKC}/tests/examples/nodejs
npm install td2.0-connector > /dev/null 2>&1
node nodejsChecker.js host=localhost
node test1970.js
cd ${WKC}/tests/connectorTest/nodejsTest/nanosupport
npm install td2.0-connector > /dev/null 2>&1
node nanosecondTest.js
'''
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh '''
cd ${WKC}/src/connector/C#
dotnet test
dotnet run --project src/test/Cases/Cases.csproj
cd ${WKC}/tests/examples/C#
dotnet run --project C#checker/C#checker.csproj
dotnet run --project TDengineTest/TDengineTest.csproj
dotnet run --project schemaless/schemaless.csproj
cd ${WKC}/tests/examples/C#/taosdemo
dotnet build -c Release
tree | true
./bin/Release/net5.0/taosdemo -c /etc/taos -y
'''
} }
sh '''
cd ${WKC}/tests/gotest
bash batchtest.sh
'''
sh '''
cd ${WKC}/tests
./test-all.sh b1fq
date'''
} }
} }
} }
stage('test_crash_gen_s3') { stage('python_4') {
agent{label " slave3 || slave13 "} agent{label " slave4 || slave9 || slave14 || slave19 "}
steps { steps {
pre_test()
timeout(time: 60, unit: 'MINUTES'){
sh '''
cd ${WKC}/tests/pytest
./crash_gen.sh -a -p -t 4 -s 2000
'''
}
timeout(time: 60, unit: 'MINUTES'){
sh '''
cd ${WKC}/tests/pytest
rm -rf /var/lib/taos/*
rm -rf /var/log/taos/*
./handle_crash_gen_val_log.sh
'''
sh '''
cd ${WKC}/tests/pytest
rm -rf /var/lib/taos/*
rm -rf /var/log/taos/*
./handle_taosd_val_log.sh
'''
}
timeout(time: 55, unit: 'MINUTES'){ timeout(time: 55, unit: 'MINUTES'){
sh '''
date
cd ${WKC}/tests
./test-all.sh b2fq
date
'''
}
}
}
stage('test_valgrind_s4') {
agent{label " slave4 || slave14 "}
steps {
pre_test()
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh '''
cd ${WKC}/tests/pytest
./valgrind-test.sh 2>&1 > mem-error-out.log
./handle_val_log.sh
'''
}
timeout(time: 55, unit: 'MINUTES'){
sh '''
date
cd ${WKC}/tests
./test-all.sh b3fq
date'''
sh '''
date
cd ${WKC}/tests
./test-all.sh full example
date'''
}
}
}
stage('test_b4_s7') {
agent{label " slave7 || slave17 "}
steps {
timeout(time: 105, unit: 'MINUTES'){
pre_test() pre_test()
sh ''' script{
date scope.each {
cd ${WKC}/tests sh """
./test-all.sh b4fq date
cd ${WKC}/tests cd ${WKC}/tests
./test-all.sh p4 ./test-CI.sh ${it} 5 ${mod[3]}
''' date"""
// cd ${WKC}/tests }
// ./test-all.sh full jdbc }
// cd ${WKC}/tests
// ./test-all.sh full unit
}
}
}
stage('test_b5_s8') {
agent{label " slave8 || slave18 "}
steps {
timeout(time: 55, unit: 'MINUTES'){
pre_test()
sh '''
date
cd ${WKC}/tests
./test-all.sh b5fq
date'''
}
}
}
stage('test_b6_s9') {
agent{label " slave9 || slave19 "}
steps {
timeout(time: 55, unit: 'MINUTES'){
pre_test()
sh '''
cd ${WKC}/tests
./test-all.sh develop-test
'''
sh '''
date
cd ${WKC}/tests
./test-all.sh b6fq
date'''
} }
} }
} }
stage('test_b7_s10') { stage('python_5') {
agent{label " slave10 || slave20 "} agent{label " slave5 || slave10 || slave15 || slave20 "}
steps { steps {
timeout(time: 55, unit: 'MINUTES'){ timeout(time: 55, unit: 'MINUTES'){
pre_test() pre_test()
sh ''' script{
cd ${WKC}/tests scope.each {
./test-all.sh system-test sh """
''' date
sh ''' cd ${WKC}/tests
date ./test-CI.sh ${it} 5 ${mod[4]}
cd ${WKC}/tests date"""
./test-all.sh b7fq }
date''' }
} }
} }
} }
...@@ -813,3 +655,4 @@ pipeline { ...@@ -813,3 +655,4 @@ pipeline {
} }
} }
} }
...@@ -136,7 +136,6 @@ IF (TD_ALPINE) ...@@ -136,7 +136,6 @@ IF (TD_ALPINE)
MESSAGE(STATUS "aplhine is defined") MESSAGE(STATUS "aplhine is defined")
ENDIF () ENDIF ()
IF ("${BUILD_HTTP}" STREQUAL "") IF ("${BUILD_HTTP}" STREQUAL "")
IF (TD_LINUX) IF (TD_LINUX)
IF (TD_ARM_32) IF (TD_ARM_32)
...@@ -153,6 +152,9 @@ ELSEIF (${BUILD_HTTP} MATCHES "false") ...@@ -153,6 +152,9 @@ ELSEIF (${BUILD_HTTP} MATCHES "false")
SET(TD_BUILD_HTTP FALSE) SET(TD_BUILD_HTTP FALSE)
ELSEIF (${BUILD_HTTP} MATCHES "true") ELSEIF (${BUILD_HTTP} MATCHES "true")
SET(TD_BUILD_HTTP TRUE) SET(TD_BUILD_HTTP TRUE)
ELSEIF (${BUILD_HTTP} MATCHES "internal")
SET(TD_BUILD_HTTP FALSE)
SET(TD_BUILD_TAOSA_INTERNAL TRUE)
ELSE () ELSE ()
SET(TD_BUILD_HTTP TRUE) SET(TD_BUILD_HTTP TRUE)
ENDIF () ENDIF ()
......
...@@ -4,7 +4,7 @@ PROJECT(TDengine) ...@@ -4,7 +4,7 @@ PROJECT(TDengine)
IF (DEFINED VERNUMBER) IF (DEFINED VERNUMBER)
SET(TD_VER_NUMBER ${VERNUMBER}) SET(TD_VER_NUMBER ${VERNUMBER})
ELSE () ELSE ()
SET(TD_VER_NUMBER "2.3.2.0") SET(TD_VER_NUMBER "2.4.0.0")
ENDIF () ENDIF ()
IF (DEFINED VERCOMPATIBLE) IF (DEFINED VERCOMPATIBLE)
......
Subproject commit 9015e129bd7de389afa4196495451669700904d0 Subproject commit ea6b3e973b477b8061e0076bb257dbd7f3faa756
...@@ -210,7 +210,7 @@ TDengine 分布式架构的逻辑结构图如下: ...@@ -210,7 +210,7 @@ TDengine 分布式架构的逻辑结构图如下:
![TDengine典型的操作流程](../images/architecture/message.png) ![TDengine典型的操作流程](../images/architecture/message.png)
<center> 图 2 TDengine 典型的操作流程 </center> <center> 图 2 TDengine 典型的操作流程 </center>
1. 应用通过 JDBC、ODBC 或其他API接口发起插入数据的请求。 1. 应用通过 JDBC 或其他API接口发起插入数据的请求。
2. taosc 会检查缓存,看是否保存有该表的 meta data。如果有,直接到第 4 步。如果没有,taosc 将向 mnode 发出 get meta-data 请求。 2. taosc 会检查缓存,看是否保存有该表的 meta data。如果有,直接到第 4 步。如果没有,taosc 将向 mnode 发出 get meta-data 请求。
3. mnode 将该表的 meta-data 返回给 taosc。Meta-data 包含有该表的 schema, 而且还有该表所属的 vgroup信息(vnode ID 以及所在的 dnode 的 End Point,如果副本数为 N,就有 N 组 End Point)。如果 taosc 迟迟得不到 mnode 回应,而且存在多个 mnode, taosc 将向下一个 mnode 发出请求。 3. mnode 将该表的 meta-data 返回给 taosc。Meta-data 包含有该表的 schema, 而且还有该表所属的 vgroup信息(vnode ID 以及所在的 dnode 的 End Point,如果副本数为 N,就有 N 组 End Point)。如果 taosc 迟迟得不到 mnode 回应,而且存在多个 mnode, taosc 将向下一个 mnode 发出请求。
4. taosc 向 master vnode 发起插入请求。 4. taosc 向 master vnode 发起插入请求。
...@@ -301,20 +301,6 @@ Master Vnode 遵循下面的写入流程: ...@@ -301,20 +301,6 @@ Master Vnode 遵循下面的写入流程:
与 master vnode 相比,slave vnode 不存在转发环节,也不存在回复确认环节,少了两步。但写内存与 WAL 是完全一样的。 与 master vnode 相比,slave vnode 不存在转发环节,也不存在回复确认环节,少了两步。但写内存与 WAL 是完全一样的。
### 异地容灾、IDC迁移
从上述 master 和 slave 流程可以看出,TDengine 采用的是异步复制的方式进行数据同步。这种方式能够大幅提高写入性能,网络延时对写入速度不会有大的影响。通过配置每个物理节点的IDC和机架号,可以保证对于一个虚拟节点组,虚拟节点由来自不同 IDC、不同机架的物理节点组成,从而实现异地容灾。因此 TDengine 原生支持异地容灾,无需再使用其他工具。
另一方面,TDengine 支持动态修改副本数,一旦副本数增加,新加入的虚拟节点将立即进入数据同步流程,同步结束后,新加入的虚拟节点即可提供服务。而在同步过程中,master 以及其他已经同步的虚拟节点都可以对外提供服务。利用这一特性,TDengine 可以实现无服务中断的 IDC 机房迁移。只需要将新 IDC 的物理节点加入现有集群,等数据同步完成后,再将老的 IDC 的物理节点从集群中剔除即可。
但是,这种异步复制的方式,存在极小的时间窗口,丢失写入的数据。具体场景如下:
1. master vnode 完成了它的 5 步操作,已经给 APP 确认写入成功,然后宕机
2. slave vnode 收到写入请求后,在第 2 步写入日志之前,处理失败
3. slave vnode 将成为新的 master,从而丢失了一条记录
理论上,只要是异步复制,就无法保证 100% 不丢失。但是这个窗口极小,master 与 slave 要同时发生故障,而且发生在刚给应用确认写入成功之后。
### 主从选择 ### 主从选择
Vnode 会保持一个数据版本号(version),对内存数据进行持久化存储时,对该版本号也进行持久化存储。每个数据更新操作,无论是采集的时序数据还是元数据,这个版本号将增加 1。 Vnode 会保持一个数据版本号(version),对内存数据进行持久化存储时,对该版本号也进行持久化存储。每个数据更新操作,无论是采集的时序数据还是元数据,这个版本号将增加 1。
......
...@@ -53,33 +53,38 @@ INSERT INTO test.t1 USING test.weather (ts, temperature) TAGS('beijing') VALUES( ...@@ -53,33 +53,38 @@ INSERT INTO test.t1 USING test.weather (ts, temperature) TAGS('beijing') VALUES(
## <a class="anchor" id="version"></a>TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本 ## <a class="anchor" id="version"></a>TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本
| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 | | taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
| -------------------- | ----------------- | -------- | |--------------------|--------------------| -------- |
| 2.0.33 - 2.0.34 | 2.0.3.0 及以上 | 1.8.x | | 2.0.36 | 2.4.0 及以上 | 1.8.x |
| 2.0.31 - 2.0.32 | 2.1.3.0 及以上 | 1.8.x | | 2.0.35 | 2.3.0 及以上 | 1.8.x |
| 2.0.33 - 2.0.34 | 2.0.3.0 及以上 | 1.8.x |
| 2.0.31 - 2.0.32 | 2.1.3.0 及以上 | 1.8.x |
| 2.0.22 - 2.0.30 | 2.0.18.0 - 2.1.2.x | 1.8.x | | 2.0.22 - 2.0.30 | 2.0.18.0 - 2.1.2.x | 1.8.x |
| 2.0.12 - 2.0.21 | 2.0.8.0 - 2.0.17.x | 1.8.x | | 2.0.12 - 2.0.21 | 2.0.8.0 - 2.0.17.x | 1.8.x |
| 2.0.4 - 2.0.11 | 2.0.0.0 - 2.0.7.x | 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.3 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.2 | 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 | | 1.0.1 | 1.6.1.x 及以上 | 1.8.x |
## TDengine DataType 和 Java DataType ## TDengine DataType 和 Java DataType
TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下: TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下:
| TDengine DataType | JDBCType (driver 版本 < 2.0.24) | JDBCType driver 版本 >= 2.0.24) | | TDengine DataType | JDBCType (driver 版本 < 2.0.24) | JDBCType driver 版本 >= 2.0.24) |
| ----------------- | ------------------ | ------------------ | |-------------------|-------------------------------| ------------------ |
| TIMESTAMP | java.lang.Long | java.sql.Timestamp | | TIMESTAMP | java.lang.Long | java.sql.Timestamp |
| INT | java.lang.Integer | java.lang.Integer | | INT | java.lang.Integer | java.lang.Integer |
| BIGINT | java.lang.Long | java.lang.Long | | BIGINT | java.lang.Long | java.lang.Long |
| FLOAT | java.lang.Float | java.lang.Float | | FLOAT | java.lang.Float | java.lang.Float |
| DOUBLE | java.lang.Double | java.lang.Double | | DOUBLE | java.lang.Double | java.lang.Double |
| SMALLINT | java.lang.Short | java.lang.Short | | SMALLINT | java.lang.Short | java.lang.Short |
| TINYINT | java.lang.Byte | java.lang.Byte | | TINYINT | java.lang.Byte | java.lang.Byte |
| BOOL | java.lang.Boolean | java.lang.Boolean | | BOOL | java.lang.Boolean | java.lang.Boolean |
| BINARY | java.lang.String | byte array | | BINARY | java.lang.String | byte array |
| NCHAR | java.lang.String | java.lang.String | | NCHAR | java.lang.String | java.lang.String |
| JSON | - | java.lang.String |
注意:JSON类型仅在tag中支持。
## 安装Java Connector ## 安装Java Connector
...@@ -594,6 +599,65 @@ public void setString(int columnIndex, ArrayList<String> list, int size) throws ...@@ -594,6 +599,65 @@ public void setString(int columnIndex, ArrayList<String> list, int size) throws
public void setNString(int columnIndex, ArrayList<String> list, int size) throws SQLException public void setNString(int columnIndex, ArrayList<String> list, int size) throws SQLException
``` ```
### <a class="anchor" id="set-client-configuration"></a>设置客户端参数
从TDengine-2.3.5.0版本开始,jdbc driver支持在应用的第一次连接中,设置TDengine的客户端参数。Driver支持JDBC-JNI方式中,通过jdbcUrl和properties两种方式设置client parameter。
注意:
* JDBC-RESTful不支持设置client parameter的功能。
* 应用中设置的client parameter为进程级别的,即如果要更新client的参数,需要重启应用。这是因为client parameter是全局参数,仅在应用程序的第一次设置生效。
* 以下示例代码基于taos-jdbcdriver-2.0.36。
示例代码:
```java
public class ClientParameterSetting {
private static final String host = "127.0.0.1";
public static void main(String[] args) throws SQLException {
setParameterInJdbcUrl();
setParameterInProperties();
}
private static void setParameterInJdbcUrl() throws SQLException {
String jdbcUrl = "jdbc:TAOS://" + host + ":6030/?debugFlag=135&asyncLog=0";
Connection connection = DriverManager.getConnection(jdbcUrl, "root", "taosdata");
printDatabase(connection);
connection.close();
}
private static void setParameterInProperties() throws SQLException {
String jdbcUrl = "jdbc:TAOS://" + host + ":6030/";
Properties properties = new Properties();
properties.setProperty("user", "root");
properties.setProperty("password", "taosdata");
properties.setProperty("debugFlag", "135");
properties.setProperty("asyncLog", "0");
properties.setProperty("maxSQLLength", "1048576");
try (Connection conn = DriverManager.getConnection(jdbcUrl, properties)) {
printDatabase(conn);
}
}
private static void printDatabase(Connection connection) throws SQLException {
try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("show databases");
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();
}
}
}
}
```
## <a class="anchor" id="subscribe"></a>订阅 ## <a class="anchor" id="subscribe"></a>订阅
### 创建 ### 创建
...@@ -741,17 +805,16 @@ Query OK, 1 row(s) in set (0.000141s) ...@@ -741,17 +805,16 @@ Query OK, 1 row(s) in set (0.000141s)
请参考:[JDBC example](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC) 请参考:[JDBC example](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC)
## 常见问题 ## 常见问题
* 使用Statement的addBatch和executeBatch来执行“批量写入/更行”,为什么没有带来性能上的提升?
**原因**:TDengine的JDBC实现中,通过addBatch方法提交的sql语句,会按照添加的顺序,依次执行,这种方式没有减少与服务端的交互次数,不会带来性能上的提升。
**解决方法**:1. 在一条insert语句中拼接多个values值;2. 使用多线程的方式并发插入;3. 使用参数绑定的写入方式
* java.lang.UnsatisfiedLinkError: no taos in java.library.path * java.lang.UnsatisfiedLinkError: no taos in java.library.path
**原因**:程序没有找到依赖的本地函数库 taos。 **原因**:程序没有找到依赖的本地函数库 taos。
**解决方法**:Windows 下可以将 C:\TDengine\driver\taos.dll 拷贝到 C:\Windows\System32\ 目录下,Linux 下将建立如下软链 `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` 即可。 **解决方法**:Windows 下可以将 C:\TDengine\driver\taos.dll 拷贝到 C:\Windows\System32\ 目录下,Linux 下将建立如下软链 `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` 即可。
* java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform * java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform
**原因**:目前 TDengine 只支持 64 位 JDK。 **原因**:目前 TDengine 只支持 64 位 JDK。
**解决方法**:重新安装 64 位 JDK。 **解决方法**:重新安装 64 位 JDK。
* 其它问题请参考 [Issues](https://github.com/taosdata/TDengine/issues) * 其它问题请参考 [Issues](https://github.com/taosdata/TDengine/issues)
......
...@@ -749,6 +749,49 @@ conn.execute("drop database pytest") ...@@ -749,6 +749,49 @@ conn.execute("drop database pytest")
conn.close() conn.close()
``` ```
#### JSON 类型
`taospy` `v2.2.0` 开始,Python连接器开始支持 JSON 数据类型的标签(TDengine版本要求 Beta 版 2.3.5+, 稳定版 2.4.0+)。
创建一个使用JSON类型标签的超级表及其子表:
```python
# encoding:UTF-8
import taos
conn = taos.connect()
conn.execute("create database if not exists py_test_json_type")
conn.execute("use py_test_json_type")
conn.execute("create stable s1 (ts timestamp, v1 int) tags (info json)")
conn.execute("create table s1_1 using s1 tags ('{\"k1\": \"v1\"}')")
```
查询子表标签及表名:
```python
tags = conn.query("select info, tbname from s1").fetch_all_into_dict()
tags
```
`tags` 内容为:
```python
[{'info': '{"k1":"v1"}', 'tbname': 's1_1'}]
```
获取 JSON 中某值:
```python
k1 = conn.query("select info->'k1' as k1 from s1").fetch_all_into_dict()
"""
>>> k1
[{'k1': '"v1"'}]
"""
```
更多JSON类型的操作方式请参考 [JSON 类型使用说明](https://www.taosdata.com/cn/documentation/taos-sql)
#### 关于纳秒 (nanosecond) 在 Python 连接器中的说明 #### 关于纳秒 (nanosecond) 在 Python 连接器中的说明
由于目前 Python 对 nanosecond 支持的不完善(参见链接 1. 2. ),目前的实现方式是在 nanosecond 精度时返回整数,而不是 ms 和 us 返回的 datetime 类型,应用开发者需要自行处理,建议使用 pandas 的 to_datetime()。未来如果 Python 正式完整支持了纳秒,涛思数据可能会修改相关接口。 由于目前 Python 对 nanosecond 支持的不完善(参见链接 1. 2. ),目前的实现方式是在 nanosecond 精度时返回整数,而不是 ms 和 us 返回的 datetime 类型,应用开发者需要自行处理,建议使用 pandas 的 to_datetime()。未来如果 Python 正式完整支持了纳秒,涛思数据可能会修改相关接口。
......
...@@ -7,11 +7,21 @@ TDengine 能够与开源数据可视化系统 [Grafana](https://www.grafana.com/ ...@@ -7,11 +7,21 @@ TDengine 能够与开源数据可视化系统 [Grafana](https://www.grafana.com/
### 安装Grafana ### 安装Grafana
目前 TDengine 支持 Grafana 6.2 以上的版本。用户可以根据当前的操作系统,到 Grafana 官网下载安装包,并执行安装。下载地址如下:https://grafana.com/grafana/download 目前 TDengine 支持 Grafana 7.0 以上的版本。用户可以根据当前的操作系统,到 Grafana 官网下载安装包,并执行安装。下载地址如下:<https://grafana.com/grafana/download>
### 配置Grafana ### 配置Grafana
TDengine 的 Grafana 插件请从 <https://github.com/taosdata/grafanaplugin/releases/latest> 下载。 TDengine 的 Grafana 插件托管在GitHub,可从 <https://github.com/taosdata/grafanaplugin/releases/latest> 下载,当前最新版本为 3.1.3。
推荐使用 [`grafana-cli` 命令行工具](https://grafana.com/docs/grafana/latest/administration/cli/) 进行插件安装。
```bash
sudo -u grafana grafana-cli \
--pluginUrl https://github.com/taosdata/grafanaplugin/releases/download/v3.1.3/tdengine-datasource-3.1.3.zip \
plugins install tdengine-datasource
```
或者下载到本地并解压到 Grafana 插件目录。
```bash ```bash
GF_VERSION=3.1.3 GF_VERSION=3.1.3
...@@ -31,11 +41,18 @@ Grafana 7.3+ / 8.x 版本会对插件进行签名检查,因此还需要在 gra ...@@ -31,11 +41,18 @@ Grafana 7.3+ / 8.x 版本会对插件进行签名检查,因此还需要在 gra
allow_loading_unsigned_plugins = tdengine-datasource allow_loading_unsigned_plugins = tdengine-datasource
``` ```
在Docker环境下,可以使用如下的环境变量设置自动安装并设置 TDengine 插件:
```bash
GF_INSTALL_PLUGINS=https://github.com/taosdata/grafanaplugin/releases/download/v3.1.3/tdengine-datasource-3.1.3.zip;tdengine-datasource
GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=tdengine-datasource
```
### 使用 Grafana ### 使用 Grafana
#### 配置数据源 #### 配置数据源
用户可以直接通过 localhost:3000 的网址,登录 Grafana 服务器(用户名/密码:admin/admin),通过左侧 `Configuration -> Data Sources` 可以添加数据源,如下图所示: 用户可以直接通过 <http://localhost:3000> 的网址,登录 Grafana 服务器(用户名/密码:admin/admin),通过左侧 `Configuration -> Data Sources` 可以添加数据源,如下图所示:
![img](../images/connections/add_datasource1.jpg) ![img](../images/connections/add_datasource1.jpg)
...@@ -77,78 +94,3 @@ allow_loading_unsigned_plugins = tdengine-datasource ...@@ -77,78 +94,3 @@ allow_loading_unsigned_plugins = tdengine-datasource
在 2.3.3.0 及以上版本,您可以导入 TDinsight Dashboard (Grafana Dashboard ID: [15167](https://grafana.com/grafana/dashboards/15167)) 作为 TDengine 集群的监控可视化工具。安装和使用说明请见 [TDinsight 用户手册](https://www.taosdata.com/cn/documentation/tools/insight) 在 2.3.3.0 及以上版本,您可以导入 TDinsight Dashboard (Grafana Dashboard ID: [15167](https://grafana.com/grafana/dashboards/15167)) 作为 TDengine 集群的监控可视化工具。安装和使用说明请见 [TDinsight 用户手册](https://www.taosdata.com/cn/documentation/tools/insight)
## <a class="anchor" id="matlab"></a>MATLAB
MATLAB 可以通过安装包内提供的 JDBC Driver 直接连接到 TDengine 获取数据到本地工作空间。
### MATLAB 的 JDBC 接口适配
MATLAB 的适配有下面几个步骤,下面以 Windows 10 上适配 MATLAB2021a 为例:
- 将 TDengine 客户端安装路径下的 `\TDengine\connector\jdbc的驱动程序taos-jdbcdriver-2.0.25-dist.jar` 拷贝到 `${matlab_root}\MATLAB\R2021a\java\jar\toolbox`
- 将 TDengine 安装包内的 `taos.lib` 文件拷贝至 `${matlab_root_dir}\MATLAB\R2021\lib\win64`
- 将新添加的驱动 jar 包加入 MATLAB 的 classpath。在 `${matlab_root_dir}\MATLAB\R2021a\toolbox\local\classpath.txt` 文件中添加下面一行:
```
$matlabroot/java/jar/toolbox/taos-jdbcdriver-2.0.25-dist.jar
```
-`${user_home}\AppData\Roaming\MathWorks\MATLAB\R2021a\` 下添加一个文件 `javalibrarypath.txt`,并在该文件中添加 taos.dll 的路径,比如您的 taos.dll 是在安装时拷贝到了 `C:\Windows\System32` 下,那么就应该在 `javalibrarypath.txt` 中添加如下一行:
```
C:\Windows\System32
```
### 在 MATLAB 中连接 TDengine 获取数据
在成功进行了上述配置后,打开 MATLAB。
- 创建一个连接:
```matlab
conn = database(‘test’, ‘root’, ‘taosdata’, ‘com.taosdata.jdbc.TSDBDriver’, ‘jdbc:TSDB://192.168.1.94:6030/’)
```
- 执行一次查询:
```matlab
sql0 = [‘select * from tb’]
data = select(conn, sql0);
```
- 插入一条记录:
```matlab
sql1 = [‘insert into tb values (now, 1)’]
exec(conn, sql1)
```
更多例子细节请参考安装包内 `examples\Matlab\TDengineDemo.m` 文件。
## <a class="anchor" id="r"></a>R
R语言支持通过JDBC接口来连接TDengine数据库。首先需要安装R语言的JDBC包。启动R语言环境,然后执行以下命令安装R语言的JDBC支持库:
```R
install.packages('RJDBC', repos='http://cran.us.r-project.org')
```
安装完成以后,通过执行`library('RJDBC')`命令加载 _RJDBC_ 包:
然后加载TDengine的JDBC驱动:
```R
drv<-JDBC("com.taosdata.jdbc.TSDBDriver","JDBCDriver-2.0.0-dist.jar", identifier.quote="\"")
```
如果执行成功,不会出现任何错误信息。之后通过以下命令尝试连接数据库:
```R
conn<-dbConnect(drv,"jdbc:TSDB://192.168.0.1:0/?user=root&password=taosdata","root","taosdata")
```
注意将上述命令中的IP地址替换成正确的IP地址。如果没有任务错误的信息,则连接数据库成功,否则需要根据错误提示调整连接的命令。TDengine支持以下的 _RJDBC_ 包中函数:
- dbWriteTable(conn, "test", iris, overwrite=FALSE, append=TRUE):将数据框iris写入表test中,overwrite必须设置为false,append必须设为TRUE,且数据框iris要与表test的结构一致。
- dbGetQuery(conn, "select count(*) from test"):查询语句。
- dbSendUpdate(conn, "use db"):执行任何非查询sql语句。例如dbSendUpdate(conn, "use db"), 写入数据dbSendUpdate(conn, "insert into t1 values(now, 99)")等。
- dbReadTable(conn, "test"):读取表test中数据。
- dbDisconnect(conn):关闭连接。
- dbRemoveTable(conn, "test"):删除表test。
TDengine客户端暂不支持如下函数:
- dbExistsTable(conn, "test"):是否存在表test。
- dbListTables(conn):显示连接中的所有表。
...@@ -45,7 +45,7 @@ arbitrator ha.taosdata.com:6042 ...@@ -45,7 +45,7 @@ arbitrator ha.taosdata.com:6042
一定要修改的参数是firstEp和fqdn。在每个数据节点,firstEp需全部配置成一样,**但fqdn一定要配置成其所在数据节点的值**。其他参数可不做任何修改,除非你很清楚为什么要修改。 一定要修改的参数是firstEp和fqdn。在每个数据节点,firstEp需全部配置成一样,**但fqdn一定要配置成其所在数据节点的值**。其他参数可不做任何修改,除非你很清楚为什么要修改。
**加入到集群中的数据节点dnode,涉及集群相关的下表11项参数必须完全相同,否则不能成功加入到集群中。** **加入到集群中的数据节点dnode,涉及集群相关的下表9项参数必须完全相同,否则不能成功加入到集群中。**
| **#** | **配置参数名称** | **含义** | | **#** | **配置参数名称** | **含义** |
| ----- | ------------------ | ---------------------------------------- | | ----- | ------------------ | ---------------------------------------- |
...@@ -68,6 +68,8 @@ arbitrator ha.taosdata.com:6042 ...@@ -68,6 +68,8 @@ arbitrator ha.taosdata.com:6042
``` ```
Welcome to the TDengine shell from Linux, Client Version:2.0.0.0 Welcome to the TDengine shell from Linux, Client Version:2.0.0.0
Copyright (c) 2017 by TAOS Data, Inc. All rights reserved. Copyright (c) 2017 by TAOS Data, Inc. All rights reserved.
taos> show dnodes; taos> show dnodes;
......
...@@ -222,7 +222,11 @@ taosd -C ...@@ -222,7 +222,11 @@ taosd -C
| 104 | maxWildCardsLength | | **C** | bytes | 设定 LIKE 算子的通配符字符串允许的最大长度 | 0-16384 | 100 | 2.1.6.1 版本新增。 | | 104 | maxWildCardsLength | | **C** | bytes | 设定 LIKE 算子的通配符字符串允许的最大长度 | 0-16384 | 100 | 2.1.6.1 版本新增。 |
| 105 | compressColData | | **S** | bytes | 客户端与服务器之间进行消息通讯过程中,对服务器端查询结果进行列压缩的阈值。 | 0: 对所有查询结果均进行压缩 >0: 查询结果中任意列大小超过该值的消息才进行压缩 -1: 不压缩 | -1 | 2.3.0.0 版本新增。 | | 105 | compressColData | | **S** | bytes | 客户端与服务器之间进行消息通讯过程中,对服务器端查询结果进行列压缩的阈值。 | 0: 对所有查询结果均进行压缩 >0: 查询结果中任意列大小超过该值的消息才进行压缩 -1: 不压缩 | -1 | 2.3.0.0 版本新增。 |
| 106 | tsdbMetaCompactRatio | | **C** | | tsdb meta文件中冗余数据超过多少阈值,开启meta文件的压缩功能 | 0:不开启,[1-100]:冗余数据比例 | 0 | | | 106 | tsdbMetaCompactRatio | | **C** | | tsdb meta文件中冗余数据超过多少阈值,开启meta文件的压缩功能 | 0:不开启,[1-100]:冗余数据比例 | 0 | |
| 107 | rpcForceTcp | | **SC**| | 强制使用TCP传输 | 0: 不开启 1: 开启 | 0 | 在网络比较差的环境中,建议开启。2.0版本新增。| | 107 | rpcForceTcp | | **SC**| | 强制使用TCP传输 | 0: 不开启 1: 开启 | 0 | 在网络比较差的环境中,建议开启。2.0版本新增。|
| 108 | maxNumOfDistinctRes | | **S**| | 允许返回的distinct结果最大行数 |默认值为10万,最大值1亿 | 10万 | 2.3版本新增。|
| 109 | clientMerge | | **C**| | 是否允许客户端对写入数据去重 |0:不开启,1:开启| 0 | 2.3版本新增。|
| 110 | httpDBNameMandatory | | **S**| | 是否在URL中输入 数据库名称|0:不开启,1:开启| 0 | 2.3版本新增。|
| 111 | maxRegexStringLen | | **C**| | 正则表达式最大允许长度 |默认值128,最大长度 16384 | 128 | 2.3版本新增。|
**注意:**对于端口,TDengine会使用从serverPort起13个连续的TCP和UDP端口号,请务必在防火墙打开。因此如果是缺省配置,需要打开从6030到6042共13个端口,而且必须TCP和UDP都打开。(详细的端口情况请参见 [TDengine 2.0 端口说明](https://www.taosdata.com/cn/documentation/faq#port) **注意:**对于端口,TDengine会使用从serverPort起13个连续的TCP和UDP端口号,请务必在防火墙打开。因此如果是缺省配置,需要打开从6030到6042共13个端口,而且必须TCP和UDP都打开。(详细的端口情况请参见 [TDengine 2.0 端口说明](https://www.taosdata.com/cn/documentation/faq#port)
...@@ -615,35 +619,6 @@ COMPACT 命令对指定的一个或多个 VGroup 启动碎片重整,系统会 ...@@ -615,35 +619,6 @@ COMPACT 命令对指定的一个或多个 VGroup 启动碎片重整,系统会
需要注意的是,碎片重整操作会大幅消耗磁盘 I/O。因此在重整进行期间,有可能会影响节点的写入和查询性能,甚至在极端情况下导致短时间的阻写。 需要注意的是,碎片重整操作会大幅消耗磁盘 I/O。因此在重整进行期间,有可能会影响节点的写入和查询性能,甚至在极端情况下导致短时间的阻写。
<a class="anchor" id="tsz_compress"></a>
## 浮点数有损压缩
在车联网等物联网智能应用场景中,经常会采集和存储海量的浮点数类型数据,如果能更高效地对此类数据进行压缩,那么不但能够节省数据存储的硬件资源,也能够因降低磁盘 I/O 数据量而提升系统性能表现。
从 2.1.6.0 版本开始,TDengine 提供一种名为 TSZ 的新型数据压缩算法,无论设置为有损压缩还是无损压缩,都能够显著提升浮点数类型数据的压缩率表现。目前该功能以可选模块的方式进行发布,可以通过添加特定的编译参数来启用该功能(也即常规安装包中暂未包含该功能)。
**需要注意的是,该功能一旦启用,效果是全局的,也即会对系统中所有的 FLOAT、DOUBLE 类型的数据生效。同时,在启用了浮点数有损压缩功能后写入的数据,也无法被未启用该功能的版本载入,并有可能因此而导致数据库服务报错退出。**
### 创建支持 TSZ 压缩算法的 TDengine 版本
TSZ 模块保存在单独的代码仓库 https://github.com/taosdata/TSZ 中。可以通过以下步骤创建包含此模块的 TDengine 版本:
1. TDengine 中的插件目前只支持通过 SSH 的方式拉取和编译,所以需要自己先配置好通过 SSH 拉取 GitHub 代码的环境。
2. `git clone git@github.com:taosdata/TDengine -b your_branchname --recurse-submodules` 通过 `--recurse-submodules` 使依赖模块的源代码可以被一并下载。
3. `mkdir debug && cd debug` 进入单独的编译目录。
4. `cmake .. -DTSZ_ENABLED=true` 其中参数 `-DTSZ_ENABLED=true` 表示在编译过程中加入对 TSZ 插件功能的支持。如果成功激活对 TSZ 模块的编译,那么 CMAKE 过程中也会显示 `build with TSZ enabled` 字样。
5. 编译成功后,包含 TSZ 浮点压缩功能的插件便已经编译进了 TDengine 中了,可以通过调整 taos.cfg 中的配置参数来使用此功能了。
### 通过配置文件来启用 TSZ 压缩算法
如果要启用 TSZ 压缩算法,除了在 TDengine 的编译过程需要声明启用 TSZ 模块之外,还需要在 taos.cfg 配置文件中对以下参数进行设置:
* lossyColumns:配置要进行有损压缩的浮点数数据类型。参数值类型为字符串,含义为:空 - 关闭有损压缩;float - 只对 FLOAT 类型进行有损压缩;double - 只对 DOUBLE 类型进行有损压缩;float|double:对 FLOAT 和 DOUBLE 类型都进行有损压缩。默认值是“空”,也即关闭有损压缩。
* fPrecision:设置 float 类型浮点数压缩精度,小于此值的浮点数尾数部分将被截断。参数值类型为 FLOAT,最小值为 0.0,最大值为 100,000.0。缺省值为 0.00000001(1E-8)。
* dPrecision:设置 double 类型浮点数压缩精度,小于此值的浮点数尾数部分将被截断。参数值类型为 DOUBLE,最小值为 0.0,最大值为 100,000.0。缺省值为 0.0000000000000001(1E-16)。
* maxRange:表示数据的最大浮动范围。一般无需调整,在数据具有特定特征时可以配合 range 参数来实现极高的数据压缩率。默认值为 500。
* range:表示数据大体浮动范围。一般无需调整,在数据具有特定特征时可以配合 maxRange 参数来实现极高的数据压缩率。默认值为 100。
**注意:**对 cfg 配置文件中参数值的任何调整,都需要重新启动 taosd 才能生效。并且以上选项为全局配置选项,配置后对所有数据库中所有表的 FLOAT 及 DOUBLE 类型的字段生效。
## <a class="anchor" id="directories"></a>文件目录结构 ## <a class="anchor" id="directories"></a>文件目录结构
安装TDengine后,默认会在操作系统中生成下列目录或文件: 安装TDengine后,默认会在操作系统中生成下列目录或文件:
...@@ -900,10 +875,14 @@ taosd 服务端日志文件标志位 debugflag 默认为 131,在 debug 时往 ...@@ -900,10 +875,14 @@ taosd 服务端日志文件标志位 debugflag 默认为 131,在 debug 时往
一旦设定为 135 或 143,日志文件增长很快,特别是写入、查询请求量较大时,增长速度惊人。如合并保存日志,很容易把日志内的关键信息(如配置信息、错误信息等)冲掉。为此,服务端将重要信息日志与其他日志分开存放: 一旦设定为 135 或 143,日志文件增长很快,特别是写入、查询请求量较大时,增长速度惊人。如合并保存日志,很容易把日志内的关键信息(如配置信息、错误信息等)冲掉。为此,服务端将重要信息日志与其他日志分开存放:
- taosinfo 存放重要信息日志 - taosinfo 存放重要信息日志, 包括:INFO/ERROR/WARNING 级别的日志信息。不记录DEBUG、TRACE级别的日志。
- taosdlog 存放其他日志 - taosdlog 服务器端生成的日志,记录taosinfo中全部信息外,还根据设置的日志输出级别,记录DEBUG(日志级别135)、TRACE(日志级别是 143)。
### 客户端日志
每个独立运行的客户端(一个进程)生成一个独立的客户端日志,其命名方式采用 taoslog+<序号> 的方式命名。文件标志位 debugflag 默认为 131,在 debug 时往往需要将其提升到 135 或 143 。
- taoslog 客户端(driver)生成的日志,默认记录客户端INFO/ERROR/WARNING 级别日志,还根据设置的日志输出级别,记录DEBUG(日志级别135)、TRACE(日志级别是 143)。
其中,taosinfo 日志文件最大长度由 numOfLogLines 来进行配置,一个 taosd 实例最多保留两个文件。 其中,日志文件最大长度由 numOfLogLines 来进行配置,一个 taosd 实例最多保留两个文件。
taosd 服务端日志采用异步落盘写入机制,优点是可以避免硬盘写入压力太大,对性能造成很大影响。缺点是,在极端情况下,存在少量日志行数丢失的可能。 taosd 服务端日志采用异步落盘写入机制,优点是可以避免硬盘写入压力太大,对性能造成很大影响。缺点是,在极端情况下,存在少量日志行数丢失的可能。
...@@ -83,7 +83,7 @@ TDengine 提供 3 个 UDF 的源代码示例,分别为: ...@@ -83,7 +83,7 @@ TDengine 提供 3 个 UDF 的源代码示例,分别为:
gcc -g -O0 -fPIC -shared add_one.c -o add_one.so gcc -g -O0 -fPIC -shared add_one.c -o add_one.so
``` ```
这样就准备好了动态链接库 add_one.so 文件,可以供后文创建 UDF 时使用了。 这样就准备好了动态链接库 add_one.so 文件,可以供后文创建 UDF 时使用了。为了保证可靠的系统运行,编译器 GCC 推荐使用 7.5及以上版本。
## 在系统中管理和使用 UDF ## 在系统中管理和使用 UDF
......
此差异已折叠。
# 常见问题 # 常见问题及反馈
## 0. 怎么报告问题?
## 问题反馈
如果 FAQ 中的信息不能够帮到您,需要 TDengine 技术团队的技术支持与协助,请将以下两个目录中内容打包: 如果 FAQ 中的信息不能够帮到您,需要 TDengine 技术团队的技术支持与协助,请将以下两个目录中内容打包:
1. /var/log/taos (如果没有修改过默认路径) 1. /var/log/taos (如果没有修改过默认路径)
2. /etc/taos 2. /etc/taos
...@@ -14,7 +13,9 @@ ...@@ -14,7 +13,9 @@
``` ```
但系统正常运行时,请一定将debugFlag设置为131,否则会产生大量的日志信息,降低系统效率。 但系统正常运行时,请一定将debugFlag设置为131,否则会产生大量的日志信息,降低系统效率。
## 1. TDengine2.0之前的版本升级到2.0及以上的版本应该注意什么?☆☆☆ ## 常见问题列表
**1. TDengine2.0之前的版本升级到2.0及以上的版本应该注意什么?☆☆☆**
2.0版在之前版本的基础上,进行了完全的重构,配置文件和数据文件是不兼容的。在升级之前务必进行如下操作: 2.0版在之前版本的基础上,进行了完全的重构,配置文件和数据文件是不兼容的。在升级之前务必进行如下操作:
...@@ -24,19 +25,19 @@ ...@@ -24,19 +25,19 @@
4. 安装最新稳定版本的 TDengine 4. 安装最新稳定版本的 TDengine
5. 如果需要迁移数据或者数据文件损坏,请联系涛思数据官方技术支持团队,进行协助解决 5. 如果需要迁移数据或者数据文件损坏,请联系涛思数据官方技术支持团队,进行协助解决
## 2. Windows平台下JDBCDriver找不到动态链接库,怎么办? **2. Windows平台下JDBCDriver找不到动态链接库,怎么办?**
请看为此问题撰写的[技术博客](https://www.taosdata.com/blog/2019/12/03/950.html) 请看为此问题撰写的[技术博客](https://www.taosdata.com/blog/2019/12/03/950.html)
## 3. 创建数据表时提示more dnodes are needed **3. 创建数据表时提示more dnodes are needed**
请看为此问题撰写的[技术博客](https://www.taosdata.com/blog/2019/12/03/965.html) 请看为此问题撰写的[技术博客](https://www.taosdata.com/blog/2019/12/03/965.html)
## 4. 如何让TDengine crash时生成core文件? **4. 如何让TDengine crash时生成core文件?**
请看为此问题撰写的[技术博客](https://www.taosdata.com/blog/2019/12/06/974.html) 请看为此问题撰写的[技术博客](https://www.taosdata.com/blog/2019/12/06/974.html)
## 5. 遇到错误“Unable to establish connection”, 我怎么办? **5. 遇到错误“Unable to establish connection”, 我怎么办?**
客户端遇到连接故障,请按照下面的步骤进行检查: 客户端遇到连接故障,请按照下面的步骤进行检查:
...@@ -70,7 +71,7 @@ ...@@ -70,7 +71,7 @@
10. 也可以使用taos程序内嵌的网络连通检测功能,来验证服务器和客户端之间指定的端口连接是否通畅(包括TCP和UDP):[TDengine 内嵌网络检测工具使用指南](https://www.taosdata.com/blog/2020/09/08/1816.html) 10. 也可以使用taos程序内嵌的网络连通检测功能,来验证服务器和客户端之间指定的端口连接是否通畅(包括TCP和UDP):[TDengine 内嵌网络检测工具使用指南](https://www.taosdata.com/blog/2020/09/08/1816.html)
## 6. 遇到错误“Unexpected generic error in RPC”或者“Unable to resolve FQDN”,我怎么办? **6. 遇到错误“Unexpected generic error in RPC”或者“Unable to resolve FQDN”,我怎么办?**
产生这个错误,是由于客户端或数据节点无法解析FQDN(Fully Qualified Domain Name)导致。对于TAOS Shell或客户端应用,请做如下检查: 产生这个错误,是由于客户端或数据节点无法解析FQDN(Fully Qualified Domain Name)导致。对于TAOS Shell或客户端应用,请做如下检查:
...@@ -79,16 +80,17 @@ ...@@ -79,16 +80,17 @@
3. 如果网络没有配置DNS server,请检查客户端所在机器的hosts文件,查看该FQDN是否配置,并是否有正确的IP地址 3. 如果网络没有配置DNS server,请检查客户端所在机器的hosts文件,查看该FQDN是否配置,并是否有正确的IP地址
4. 如果网络配置OK,从客户端所在机器,你需要能Ping该连接的FQDN,否则客户端是无法连接服务器的 4. 如果网络配置OK,从客户端所在机器,你需要能Ping该连接的FQDN,否则客户端是无法连接服务器的
## 7. 虽然语法正确,为什么我还是得到 "Invalid SQL" 错误 **7. 虽然语法正确,为什么我还是得到 "Invalid SQL" 错误**
如果你确认语法正确,2.0之前版本,请检查SQL语句长度是否超过64K。如果超过,也会返回这个错误。 如果你确认语法正确,2.0之前版本,请检查SQL语句长度是否超过64K。如果超过,也会返回这个错误。
## 8. 是否支持validation queries? **8. 是否支持validation queries?**
TDengine还没有一组专用的validation queries。然而建议你使用系统监测的数据库”log"来做。 TDengine还没有一组专用的validation queries。然而建议你使用系统监测的数据库”log"来做。
<a class="anchor" id="update"></a> <a class="anchor" id="update"></a>
## 9. 我可以删除或更新一条记录吗?
**9. 我可以删除或更新一条记录吗?**
TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。 TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。
...@@ -98,15 +100,15 @@ TDengine 目前尚不支持删除功能,未来根据用户需求可能会支 ...@@ -98,15 +100,15 @@ TDengine 目前尚不支持删除功能,未来根据用户需求可能会支
此外,从 2.1.7.0 版本开始,支持将 UPDATE 参数设为 2,表示“支持部分列更新”。也即,当 UPDATE 设为 1 时,如果更新一个数据行,其中某些列没有提供取值,那么这些列会被设为 NULL;而当 UPDATE 设为 2 时,如果更新一个数据行,其中某些列没有提供取值,那么这些列会保持原有数据行中的对应值。 此外,从 2.1.7.0 版本开始,支持将 UPDATE 参数设为 2,表示“支持部分列更新”。也即,当 UPDATE 设为 1 时,如果更新一个数据行,其中某些列没有提供取值,那么这些列会被设为 NULL;而当 UPDATE 设为 2 时,如果更新一个数据行,其中某些列没有提供取值,那么这些列会保持原有数据行中的对应值。
## 10. 我怎么创建超过1024列的表? **10. 我怎么创建超过1024列的表?**
使用 2.0 及其以上版本,默认支持 1024 列;2.0 之前的版本,TDengine 最大允许创建 250 列的表。但是如果确实超过限值,建议按照数据特性,逻辑地将这个宽表分解成几个小表。(从 2.1.7.0 版本开始,表的最大列数增加到了 4096 列。) 使用 2.0 及其以上版本,默认支持 1024 列;2.0 之前的版本,TDengine 最大允许创建 250 列的表。但是如果确实超过限值,建议按照数据特性,逻辑地将这个宽表分解成几个小表。(从 2.1.7.0 版本开始,表的最大列数增加到了 4096 列。)
## 11. 最有效的写入数据的方法是什么? **11. 最有效的写入数据的方法是什么?**
批量插入。每条写入语句可以一张表同时插入多条记录,也可以同时插入多张表的多条记录。 批量插入。每条写入语句可以一张表同时插入多条记录,也可以同时插入多张表的多条记录。
## 12. Windows系统下插入的nchar类数据中的汉字被解析成了乱码如何解决? **12. Windows系统下插入的nchar类数据中的汉字被解析成了乱码如何解决?**
Windows下插入nchar类的数据中如果有中文,请先确认系统的地区设置成了中国(在Control Panel里可以设置),这时cmd中的`taos`客户端应该已经可以正常工作了;如果是在IDE里开发Java应用,比如Eclipse, Intellij,请确认IDE里的文件编码为GBK(这是Java默认的编码类型),然后在生成Connection时,初始化客户端的配置,具体语句如下: Windows下插入nchar类的数据中如果有中文,请先确认系统的地区设置成了中国(在Control Panel里可以设置),这时cmd中的`taos`客户端应该已经可以正常工作了;如果是在IDE里开发Java应用,比如Eclipse, Intellij,请确认IDE里的文件编码为GBK(这是Java默认的编码类型),然后在生成Connection时,初始化客户端的配置,具体语句如下:
```JAVA ```JAVA
...@@ -116,7 +118,7 @@ properties.setProperty(TSDBDriver.LOCALE_KEY, "UTF-8"); ...@@ -116,7 +118,7 @@ properties.setProperty(TSDBDriver.LOCALE_KEY, "UTF-8");
Connection = DriverManager.getConnection(url, properties); Connection = DriverManager.getConnection(url, properties);
``` ```
## 13.JDBC报错: the excuted SQL is not a DML or a DDL? **13.JDBC报错: the excuted SQL is not a DML or a DDL?**
请更新至最新的JDBC驱动 请更新至最新的JDBC驱动
```xml ```xml
...@@ -127,15 +129,15 @@ Connection = DriverManager.getConnection(url, properties); ...@@ -127,15 +129,15 @@ Connection = DriverManager.getConnection(url, properties);
</dependency> </dependency>
``` ```
## 14. taos connect failed, reason&#58; invalid timestamp **14. taos connect failed, reason&#58; invalid timestamp**
常见原因是服务器和客户端时间没有校准,可以通过和时间服务器同步的方式(Linux 下使用 ntpdate 命令,Windows 在系统时间设置中选择自动同步)校准。 常见原因是服务器和客户端时间没有校准,可以通过和时间服务器同步的方式(Linux 下使用 ntpdate 命令,Windows 在系统时间设置中选择自动同步)校准。
## 15. 表名显示不全 **15. 表名显示不全**
由于 taos shell 在终端中显示宽度有限,有可能比较长的表名显示不全,如果按照显示的不全的表名进行相关操作会发生 Table does not exist 错误。解决方法可以是通过修改 taos.cfg 文件中的设置项 maxBinaryDisplayWidth, 或者直接输入命令 set max_binary_display_width 100。或者在命令结尾使用 \G 参数来调整结果的显示方式。 由于 taos shell 在终端中显示宽度有限,有可能比较长的表名显示不全,如果按照显示的不全的表名进行相关操作会发生 Table does not exist 错误。解决方法可以是通过修改 taos.cfg 文件中的设置项 maxBinaryDisplayWidth, 或者直接输入命令 set max_binary_display_width 100。或者在命令结尾使用 \G 参数来调整结果的显示方式。
## 16. 如何进行数据迁移? **16. 如何进行数据迁移?**
TDengine是根据hostname唯一标志一台机器的,在数据文件从机器A移动机器B时,注意如下两件事: TDengine是根据hostname唯一标志一台机器的,在数据文件从机器A移动机器B时,注意如下两件事:
...@@ -143,7 +145,7 @@ TDengine是根据hostname唯一标志一台机器的,在数据文件从机器A ...@@ -143,7 +145,7 @@ TDengine是根据hostname唯一标志一台机器的,在数据文件从机器A
- 2.0.7.0 及以后的版本,到/var/lib/taos/dnode下,修复dnodeEps.json的dnodeId对应的FQDN,重启。确保机器内所有机器的此文件是完全相同的。 - 2.0.7.0 及以后的版本,到/var/lib/taos/dnode下,修复dnodeEps.json的dnodeId对应的FQDN,重启。确保机器内所有机器的此文件是完全相同的。
- 1.x 和 2.x 版本的存储结构不兼容,需要使用迁移工具或者自己开发应用导出导入数据。 - 1.x 和 2.x 版本的存储结构不兼容,需要使用迁移工具或者自己开发应用导出导入数据。
## 17. 如何在命令行程序 taos 中临时调整日志级别 **17. 如何在命令行程序 taos 中临时调整日志级别**
为了调试方便,从 2.0.16 版本开始,命令行程序 taos 新增了与日志记录相关的两条指令: 为了调试方便,从 2.0.16 版本开始,命令行程序 taos 新增了与日志记录相关的两条指令:
...@@ -162,7 +164,8 @@ ALTER LOCAL RESETLOG; ...@@ -162,7 +164,8 @@ ALTER LOCAL RESETLOG;
其含义是,清空本机所有由客户端生成的日志文件。 其含义是,清空本机所有由客户端生成的日志文件。
<a class="anchor" id="timezone"></a> <a class="anchor" id="timezone"></a>
## 18. 时间戳的时区信息是怎样处理的?
**18. 时间戳的时区信息是怎样处理的?**
TDengine 中时间戳的时区总是由客户端进行处理,而与服务端无关。具体来说,客户端会对 SQL 语句中的时间戳进行时区转换,转为 UTC 时区(即 Unix 时间戳——Unix Timestamp)再交由服务端进行写入和查询;在读取数据时,服务端也是采用 UTC 时区提供原始数据,客户端收到后再根据本地设置,把时间戳转换为本地系统所要求的时区进行显示。 TDengine 中时间戳的时区总是由客户端进行处理,而与服务端无关。具体来说,客户端会对 SQL 语句中的时间戳进行时区转换,转为 UTC 时区(即 Unix 时间戳——Unix Timestamp)再交由服务端进行写入和查询;在读取数据时,服务端也是采用 UTC 时区提供原始数据,客户端收到后再根据本地设置,把时间戳转换为本地系统所要求的时区进行显示。
...@@ -173,7 +176,8 @@ TDengine 中时间戳的时区总是由客户端进行处理,而与服务端 ...@@ -173,7 +176,8 @@ TDengine 中时间戳的时区总是由客户端进行处理,而与服务端
4. 在书写 SQL 语句时,也可以直接使用 Unix 时间戳(例如 `1554984068000`)或带有时区的时间戳字符串,也即以 RFC 3339 格式(例如 `2013-04-12T15:52:01.123+08:00`)或 ISO-8601 格式(例如 `2013-04-12T15:52:01.123+0800`)来书写时间戳,此时这些时间戳的取值将不再受其他时区设置的影响。 4. 在书写 SQL 语句时,也可以直接使用 Unix 时间戳(例如 `1554984068000`)或带有时区的时间戳字符串,也即以 RFC 3339 格式(例如 `2013-04-12T15:52:01.123+08:00`)或 ISO-8601 格式(例如 `2013-04-12T15:52:01.123+0800`)来书写时间戳,此时这些时间戳的取值将不再受其他时区设置的影响。
<a class="anchor" id="port"></a> <a class="anchor" id="port"></a>
## 19. TDengine 都会用到哪些网络端口?
**19. TDengine 都会用到哪些网络端口?**
在 TDengine 2.0 版本中,会用到以下这些网络端口(以默认端口 6030 为前提进行说明,如果修改了配置文件中的设置,那么这里列举的端口都会出现变化),管理员可以参考这里的信息调整防火墙设置: 在 TDengine 2.0 版本中,会用到以下这些网络端口(以默认端口 6030 为前提进行说明,如果修改了配置文件中的设置,那么这里列举的端口都会出现变化),管理员可以参考这里的信息调整防火墙设置:
...@@ -191,7 +195,7 @@ TDengine 中时间戳的时区总是由客户端进行处理,而与服务端 ...@@ -191,7 +195,7 @@ TDengine 中时间戳的时区总是由客户端进行处理,而与服务端
| UDP | 6030-6034 | 客户端与服务端之间通讯。 | 随 serverPort 端口变化。 | | UDP | 6030-6034 | 客户端与服务端之间通讯。 | 随 serverPort 端口变化。 |
| UDP | 6035-6039 | 多节点集群的节点间通讯。 | 随 serverPort 端口变化。 | | UDP | 6035-6039 | 多节点集群的节点间通讯。 | 随 serverPort 端口变化。 |
## 20. go 语言编写组件编译失败怎样解决? **20. go 语言编写组件编译失败怎样解决?**
新版本 TDengine 2.3.0.0 包含一个使用 go 语言开发的 taosAdapter 组件,取代之前内置的 httpd ,提供包含原 httpd 功能以及支持多种其他软件(Prometheus、Telegraf、collectd、StatsD等)的数据接入功能。 新版本 TDengine 2.3.0.0 包含一个使用 go 语言开发的 taosAdapter 组件,取代之前内置的 httpd ,提供包含原 httpd 功能以及支持多种其他软件(Prometheus、Telegraf、collectd、StatsD等)的数据接入功能。
使用最新 develop 分支代码编译需要先 `git submodule update --init --recursive` 下载 taosAdapter 仓库代码后再编译。 使用最新 develop 分支代码编译需要先 `git submodule update --init --recursive` 下载 taosAdapter 仓库代码后再编译。
...@@ -205,3 +209,5 @@ go env -w GOPROXY=https://goproxy.cn,direct ...@@ -205,3 +209,5 @@ go env -w GOPROXY=https://goproxy.cn,direct
如果希望继续使用之前的内置 httpd,可以关闭 taosAdapter 编译,使用 如果希望继续使用之前的内置 httpd,可以关闭 taosAdapter 编译,使用
`cmake .. -DBUILD_HTTP=true` 使用原来内置的 httpd。 `cmake .. -DBUILD_HTTP=true` 使用原来内置的 httpd。
...@@ -33,8 +33,8 @@ IT 运维监测数据通常都是对时间特性比较敏感的数据,例如 ...@@ -33,8 +33,8 @@ IT 运维监测数据通常都是对时间特性比较敏感的数据,例如
### 下载 TDengine 插件到 grafana 插件目录 ### 下载 TDengine 插件到 grafana 插件目录
```bash ```bash
1. wget -c https://github.com/taosdata/grafanaplugin/releases/download/v3.1.1/tdengine-datasource-3.1.1.zip 1. wget -c https://github.com/taosdata/grafanaplugin/releases/download/v3.1.3/tdengine-datasource-3.1.3.zip
2. sudo unzip tdengine-datasource-3.1.1.zip -d /var/lib/grafana/plugins/ 2. sudo unzip tdengine-datasource-3.1.3.zip -d /var/lib/grafana/plugins/
3. sudo chown grafana:grafana -R /var/lib/grafana/plugins/tdengine 3. sudo chown grafana:grafana -R /var/lib/grafana/plugins/tdengine
4. echo -e "[plugins]\nallow_loading_unsigned_plugins = tdengine-datasource\n" | sudo tee -a /etc/grafana/grafana.ini 4. echo -e "[plugins]\nallow_loading_unsigned_plugins = tdengine-datasource\n" | sudo tee -a /etc/grafana/grafana.ini
5. sudo systemctl restart grafana-server.service 5. sudo systemctl restart grafana-server.service
......
...@@ -32,8 +32,8 @@ IT 运维监测数据通常都是对时间特性比较敏感的数据,例如 ...@@ -32,8 +32,8 @@ IT 运维监测数据通常都是对时间特性比较敏感的数据,例如
### 复制 TDengine 插件到 grafana 插件目录 ### 复制 TDengine 插件到 grafana 插件目录
```bash ```bash
1. wget -c https://github.com/taosdata/grafanaplugin/releases/download/v3.1.1/tdengine-datasource-3.1.1.zip 1. wget -c https://github.com/taosdata/grafanaplugin/releases/download/v3.1.3/tdengine-datasource-3.1.3.zip
2. sudo unzip tdengine-datasource-3.1.1.zip -d /var/lib/grafana/plugins/ 2. sudo unzip tdengine-datasource-3.1.3.zip -d /var/lib/grafana/plugins/
3. sudo chown grafana:grafana -R /var/lib/grafana/plugins/tdengine 3. sudo chown grafana:grafana -R /var/lib/grafana/plugins/tdengine
4. echo -e "[plugins]\nallow_loading_unsigned_plugins = tdengine-datasource\n" | sudo tee -a /etc/grafana/grafana.ini 4. echo -e "[plugins]\nallow_loading_unsigned_plugins = tdengine-datasource\n" | sudo tee -a /etc/grafana/grafana.ini
5. sudo systemctl restart grafana-server.service 5. sudo systemctl restart grafana-server.service
......
...@@ -54,23 +54,25 @@ INSERT INTO test.t1 USING test.weather (ts, temperature) TAGS('beijing') VALUES( ...@@ -54,23 +54,25 @@ INSERT INTO test.t1 USING test.weather (ts, temperature) TAGS('beijing') VALUES(
## JDBC driver version and supported TDengine and JDK versions ## JDBC driver version and supported TDengine and JDK versions
| taos-jdbcdriver | TDengine | JDK | | taos-jdbcdriver | TDengine | JDK |
| --------------- | ------------------ | ----- | | --------------- |--------------------|--------|
| 2.0.33 - 2.0.34 | 2.0.3.0 and above | 1.8.x | | 2.0.36 | 2.4.0 and above | 1.8.x |
| 2.0.31 - 2.0.32 | 2.1.3.0 and above | 1.8.x | | 2.0.35 | 2.3.0 and above | 1.8.x |
| 2.0.22 - 2.0.30 | 2.0.18.0 - 2.1.2.x | 1.8.x | | 2.0.33 - 2.0.34 | 2.0.3.0 and above | 1.8.x |
| 2.0.12 - 2.0.21 | 2.0.8.0 - 2.0.17.x | 1.8.x | | 2.0.31 - 2.0.32 | 2.1.3.0 and above | 1.8.x |
| 2.0.4 - 2.0.11 | 2.0.0.0 - 2.0.7.x | 1.8.x | | 2.0.22 - 2.0.30 | 2.0.18.0 - 2.1.2.x | 1.8.x |
| 1.0.3 | 1.6.1.x and above | 1.8.x | | 2.0.12 - 2.0.21 | 2.0.8.0 - 2.0.17.x | 1.8.x |
| 1.0.2 | 1.6.1.x and above | 1.8.x | | 2.0.4 - 2.0.11 | 2.0.0.0 - 2.0.7.x | 1.8.x |
| 1.0.1 | 1.6.1.x and above | 1.8.x | | 1.0.3 | 1.6.1.x and above | 1.8.x |
| 1.0.2 | 1.6.1.x and above | 1.8.x |
| 1.0.1 | 1.6.1.x and above | 1.8.x |
## DataType in TDengine and Java connector ## DataType in TDengine and Java connector
The TDengine supports the following data types and Java data types: The TDengine supports the following data types and Java data types:
| TDengine DataType | JDBCType (driver version < 2.0.24) | JDBCType (driver version >= 2.0.24) | | TDengine DataType | JDBCType (driver version < 2.0.24) | JDBCType (driver version >= 2.0.24) |
| ----------------- | ---------------------------------- | ----------------------------------- | |-------------------|------------------------------------| ----------------------------------- |
| TIMESTAMP | java.lang.Long | java.sql.Timestamp | | TIMESTAMP | java.lang.Long | java.sql.Timestamp |
| INT | java.lang.Integer | java.lang.Integer | | INT | java.lang.Integer | java.lang.Integer |
| BIGINT | java.lang.Long | java.lang.Long | | BIGINT | java.lang.Long | java.lang.Long |
...@@ -81,7 +83,8 @@ The TDengine supports the following data types and Java data types: ...@@ -81,7 +83,8 @@ The TDengine supports the following data types and Java data types:
| BOOL | java.lang.Boolean | java.lang.Boolean | | BOOL | java.lang.Boolean | java.lang.Boolean |
| BINARY | java.lang.String | byte array | | BINARY | java.lang.String | byte array |
| NCHAR | java.lang.String | java.lang.String | | NCHAR | java.lang.String | java.lang.String |
| JSON | - | java.lang.String |
**Note**: JSON type can only be used in tag.
## Install Java connector ## Install Java connector
### Runtime Requirements ### Runtime Requirements
...@@ -575,8 +578,67 @@ public void setShort(int columnIndex, ArrayList<Short> list) throws SQLException ...@@ -575,8 +578,67 @@ public void setShort(int columnIndex, ArrayList<Short> list) throws SQLException
public void setString(int columnIndex, ArrayList<String> list, int size) throws SQLException public void setString(int columnIndex, ArrayList<String> list, int size) throws SQLException
public void setNString(int columnIndex, ArrayList<String> list, int size) throws SQLException public void setNString(int columnIndex, ArrayList<String> list, int size) throws SQLException
``` ```
### Set client configuration in JDBC
Starting with TDEngine-2.3.5.0, JDBC Driver supports setting TDengine client parameters on the first connection of a Java application. The Driver supports jdbcUrl and Properties to set client parameters in JDBC-JNI mode.
Note:
* JDBC-RESTful does not support setting client parameters.
* The client parameters set in the java application are process-level. To update the client parameters, the application needs to be restarted. This is because these client parameters are global that take effect the first time the application is set up.
* The following sample code is based on taos-jdbcdriver-2.0.36.
Sample Code:
```java
public class ClientParameterSetting {
private static final String host = "127.0.0.1";
public static void main(String[] args) throws SQLException {
setParameterInJdbcUrl();
setParameterInProperties();
}
private static void setParameterInJdbcUrl() throws SQLException {
String jdbcUrl = "jdbc:TAOS://" + host + ":6030/?debugFlag=135&asyncLog=0";
Connection connection = DriverManager.getConnection(jdbcUrl, "root", "taosdata");
printDatabase(connection);
connection.close();
}
private static void setParameterInProperties() throws SQLException {
String jdbcUrl = "jdbc:TAOS://" + host + ":6030/";
Properties properties = new Properties();
properties.setProperty("user", "root");
properties.setProperty("password", "taosdata");
properties.setProperty("debugFlag", "135");
properties.setProperty("asyncLog", "0");
properties.setProperty("maxSQLLength", "1048576");
try (Connection conn = DriverManager.getConnection(jdbcUrl, properties)) {
printDatabase(conn);
}
}
private static void printDatabase(Connection connection) throws SQLException {
try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("show databases");
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();
}
}
}
}
```
### Data Subscription
## Data Subscription
#### Subscribe #### Subscribe
...@@ -699,17 +761,16 @@ Query OK, 1 row(s) in set (0.000141s) ...@@ -699,17 +761,16 @@ Query OK, 1 row(s) in set (0.000141s)
you see sample code here: [JDBC example](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC) you see sample code here: [JDBC example](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC)
## FAQ ## FAQ
- Why does not addBatch and executeBatch provide a performance benefit for executing "batch writes/updates"?
**Cause**:In TDengine's JDBC implementation, SQL statements submitted through the addBatch method are executed in the order in which they are added. This method does not reduce the number of interactions with the server and does not improve performance.
**Answer**:1. Concatenate multiple values in an INSERT statement; 2. Use multi-threaded concurrent insertion; 3. Use the parameter-binding to write
- java.lang.UnsatisfiedLinkError: no taos in java.library.path - java.lang.UnsatisfiedLinkError: no taos in java.library.path
**Cause**:The application program cannot find Library function *taos* **Cause**:The application program cannot find Library function *taos*
**Answer**:Copy `C:\TDengine\driver\taos.dll` to `C:\Windows\System32\` on Windows and make a soft link through `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` on Linux. **Answer**:Copy `C:\TDengine\driver\taos.dll` to `C:\Windows\System32\` on Windows and make a soft link through `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` on Linux.
- java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform - java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform
**Cause**:Currently TDengine only support 64bit JDK **Cause**:Currently TDengine only support 64bit JDK
**Answer**:re-install 64bit JDK. **Answer**:re-install 64bit JDK.
- For other questions, please refer to [Issues](https://github.com/taosdata/TDengine/issues) - For other questions, please refer to [Issues](https://github.com/taosdata/TDengine/issues)
......
...@@ -575,6 +575,49 @@ Close connection. ...@@ -575,6 +575,49 @@ Close connection.
conn.close() conn.close()
``` ```
#### JSON Type Support
Python connector `taospy` starts supporting JSON type as tags since `v2.2.0` (requires TDengine beta v2.3.5+, or stable v2.4.0+).
Create stable and table with JSON tag.
```python
# encoding:UTF-8
import taos
conn = taos.connect()
conn.execute("create database if not exists py_test_json_type")
conn.execute("use py_test_json_type")
conn.execute("create stable s1 (ts timestamp, v1 int) tags (info json)")
conn.execute("create table s1_1 using s1 tags ('{\"k1\": \"v1\"}')")
```
Query JSON tag and table name from a stable.
```python
tags = conn.query("select info, tbname from s1").fetch_all_into_dict()
tags
```
The `tags` value is:
```python
[{'info': '{"k1":"v1"}', 'tbname': 's1_1'}]
```
To get value from JSON tag by key:
```python
k1 = conn.query("select info->'k1' as k1 from s1").fetch_all_into_dict()
"""
>>> k1
[{'k1': '"v1"'}]
"""
```
Refer to [JSON type instructions](https://www.taosdata.com/en/documentation/taos-sql) for more usage of JSON type.
#### Using nanosecond in Python connector #### Using nanosecond in Python connector
So far Python still does not completely support nanosecond type. Please refer to the link 1 and 2. The implementation of the python connector is to return an integer number for nanosecond value rather than datatime type as what ms and us do. The developer needs to handle it themselves. We recommend using pandas to_datetime() function. If Python officially support nanosecond in the future, TAOS Data might be possible to change the interface accordingly, which mean the application need change too. So far Python still does not completely support nanosecond type. Please refer to the link 1 and 2. The implementation of the python connector is to return an integer number for nanosecond value rather than datatime type as what ms and us do. The developer needs to handle it themselves. We recommend using pandas to_datetime() function. If Python officially support nanosecond in the future, TAOS Data might be possible to change the interface accordingly, which mean the application need change too.
......
...@@ -6,25 +6,47 @@ TDengine can be quickly integrated with [Grafana](https://www.grafana.com/), an ...@@ -6,25 +6,47 @@ TDengine can be quickly integrated with [Grafana](https://www.grafana.com/), an
### Install Grafana ### Install Grafana
TDengine currently supports Grafana 6.2 and above. You can download and install the package from Grafana website according to the current operating system. The download address is as follows: TDengine currently supports Grafana 7.0 and above. You can download and install the package from Grafana website according to the current operating system. The download address is as follows: <https://grafana.com/grafana/download>.
https://grafana.com/grafana/download.
### Configure Grafana ### Configure Grafana
Download grafana plugin from <https://github.com/taosdata/grafanaplugin/releases/latest> . TDengine data source plugin for Grafana is hosted on GitHub, refer to GitHub latest release page <https://github.com/taosdata/grafanaplugin/releases/latest> to download the latest plugin package. Currently it's version 3.1.3 .
It is recommended to use [`grafana-cli` command line tool](https://grafana.com/docs/grafana/latest/administration/cli/) to install the plugin.
```bash
sudo -u grafana grafana-cli \
--pluginUrl https://github.com/taosdata/grafanaplugin/releases/download/v3.1.3/tdengine-datasource-3.1.3.zip \
plugins install tdengine-datasource
```
Users could manually download the plugin package and install it to Grafana plugins directory.
```bash ```bash
GF_VERSION=3.1.3 GF_VERSION=3.1.3
wget https://github.com/taosdata/grafanaplugin/releases/download/v$GF_VERSION/tdengine-datasource-$GF_VERSION.zip wget https://github.com/taosdata/grafanaplugin/releases/download/v$GF_VERSION/tdengine-datasource-$GF_VERSION.zip
``` ```
Taking Centos 7.2 as an example, just copy grafanaplugin directory to /var/lib/grafana/plugins directory and restart Grafana. Taking Centos 7.2 as an example, just unpack the package to /var/lib/grafana/plugins directory and restart Grafana.
```bash ```bash
sudo unzip tdengine-datasource-$GF_VERSION.zip /var/lib/grafana/plugins/ sudo unzip tdengine-datasource-$GF_VERSION.zip /var/lib/grafana/plugins/
``` ```
Grafana will check the signature after 7.3 and 8.x for security. Users need additional configurations in `grafana.ini` file to allow unsigned plugins like TDengine data source.
```ini
[plugins]
allow_loading_unsigned_plugins = tdengine-datasource
```
In docker/compose/k8s, simply setting the two environment variables will take it all for you.
```bash
GF_INSTALL_PLUGINS=https://github.com/taosdata/grafanaplugin/releases/download/v3.1.3/tdengine-datasource-3.1.3.zip;tdengine-datasource
GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=tdengine-datasource
```
### Use Grafana ### Use Grafana
#### Configure data source #### Configure data source
......
...@@ -53,13 +53,14 @@ In TDengine, the following 10 data types can be used in data model of an ordinar ...@@ -53,13 +53,14 @@ In TDengine, the following 10 data types can be used in data model of an ordinar
| 8 | TINYINT | 1 | A nullable integer type with a range of [-127, 127] | | 8 | TINYINT | 1 | A nullable integer type with a range of [-127, 127] |
| 9 | BOOL | 1 | Boolean type,{true, false} | | 9 | BOOL | 1 | Boolean type,{true, false} |
| 10 | NCHAR | Custom | Used to record non-ASCII strings, such as Chinese characters. Each nchar character takes up 4 bytes of storage space. Single quotation marks are used at both ends of the string, and escape characters are required for single quotation marks in the string, that is \’. When nchar is used, the string size must be specified. A column of type nchar (10) indicates that the string of this column stores up to 10 nchar characters, which will take up 40 bytes of space. If the length of the user string exceeds the declared length, an error will be reported. | | 10 | NCHAR | Custom | Used to record non-ASCII strings, such as Chinese characters. Each nchar character takes up 4 bytes of storage space. Single quotation marks are used at both ends of the string, and escape characters are required for single quotation marks in the string, that is \’. When nchar is used, the string size must be specified. A column of type nchar (10) indicates that the string of this column stores up to 10 nchar characters, which will take up 40 bytes of space. If the length of the user string exceeds the declared length, an error will be reported. |
| 11 | JSON | | Json type,only support for tag |
**Tips**: **Tips**:
1. TDengine is case-insensitive to English characters in SQL statements and automatically converts them to lowercase for execution. Therefore, the user's case-sensitive strings and passwords need to be enclosed in single quotation marks. 1. TDengine is case-insensitive to English characters in SQL statements and automatically converts them to lowercase for execution. Therefore, the user's case-sensitive strings and passwords need to be enclosed in single quotation marks.
2. Avoid using BINARY type to save non-ASCII type strings, which will easily lead to errors such as garbled data. The correct way is to use NCHAR type to save Chinese characters. 2. Avoid using BINARY type to save non-ASCII type strings, which will easily lead to errors such as garbled data. The correct way is to use NCHAR type to save Chinese characters.
3. The numerical values in SQL statements are treated as floating or integer numbers, depends on if the value contains decimal point or is in scientific notation format. Therefore, caution is needed since overflow might happen for corresponding data types. E.g., 9999999999999999999 is overflowed as the number is greater than the largest integer number. However, 9999999999999999999.0 is treated as a valid floating number.
## <a class="anchor" id="management"></a>Database Management ## <a class="anchor" id="management"></a>Database Management
...@@ -1245,3 +1246,92 @@ TAOS SQL supports join columns of two tables by Primary Key timestamp between th ...@@ -1245,3 +1246,92 @@ TAOS SQL supports join columns of two tables by Primary Key timestamp between th
**Availability of is no null** **Availability of is no null**
Is not null supports all types of columns. Non-null expression is < > "" and only applies to columns of non-numeric types. Is not null supports all types of columns. Non-null expression is < > "" and only applies to columns of non-numeric types.
**Restrictions on order by**
- A non super table can only have one order by.
- The super table can have at most two order by expression, and the second must be ts.
- Order by tag must be the same tag as group by tag. TBNAME is as logical as tag.
- Order by ordinary column must be the same ordinary column as group by or top/bottom. If both group by and top / bottom exist, order by must be in the same column as group by.
- There are both order by and group by. The internal of the group is sorted by ts
- Order by ts.
## JSON type instructions
- Syntax description
1. Create JSON type tag
```mysql
create stable s1 (ts timestamp, v1 int) tags (info json)
create table s1_1 using s1 tags ('{"k1": "v1"}')
```
3. JSON value operator(->)
```mysql
select * from s1 where info->'k1' = 'v1'
select info->'k1' from s1
```
4. JSON key existence operator(contains)
```mysql
select * from s1 where info contains 'k2'
select * from s1 where info contains 'k1'
```
- Supported operations
1. In where condition,support match/nmatch/between and/like/and/or/is null/is no null,in operator is not support.
```mysql
select * from s1 where info→'k1' match 'v*';
select * from s1 where info→'k1' like 'v%' and info contains 'k2';
select * from s1 where info is null;
select * from s1 where info->'k1' is not null
```
2. JSON tag is supported in group by、order by、join clause、union all and subquery,like group by json->'key'
3. Support distinct operator.
```mysql
select distinct info→'k1' from s1
```
5. Tag
Support change JSON tag(full coverage)
Support change the name of JSON tag
Not support add JSON tag, delete JSON tag
- Other constraints
1. Only tag columns can use JSON type. If JSON tag is used, there can only be one tag column.
2. Length limit:The length of the key in JSON cannot exceed 256, and the key must be printable ASCII characters; The total length of JSON string does not exceed 4096 bytes.
3. JSON format restrictions:
1. JSON input string can be empty (""," ","\t" or null) or object, and cannot be nonempty string, boolean or array.
2. Object can be {}, if the object is {}, the whole JSON string is marked as empty. The key can be "", if the key is "", the K-V pair will be ignored in the JSON string.
3. Value can be a number (int/double) or string, bool or null, not an array. Nesting is not allowed.
4. If two identical keys appear in the JSON string, the first one will take effect.
5. Escape is not supported in JSON string.
4. Null is returned when querying the key that does not exist in JSON.
5. When JSON tag is used as the sub query result, parsing and querying the JSON string in the sub query is no longer supported in the upper level query.
The following query is not supported:
```mysql
select jtag→'key' from (select jtag from stable)
select jtag->'key' from (select jtag from stable) where jtag->'key'>0
```
...@@ -33,8 +33,8 @@ Please download TDengine 2.3.0.0 or the above version from TAOS Data's [official ...@@ -33,8 +33,8 @@ Please download TDengine 2.3.0.0 or the above version from TAOS Data's [official
### Download TDengine plugin to Grafana plugin's directory ### Download TDengine plugin to Grafana plugin's directory
```bash ```bash
1. wget -c https://github.com/taosdata/grafanaplugin/releases/download/v3.1.1/tdengine-datasource-3.1.1.zip 1. wget -c https://github.com/taosdata/grafanaplugin/releases/download/v3.1.3/tdengine-datasource-3.1.3.zip
2. sudo unzip tdengine-datasource-3.1.1.zip -d /var/lib/grafana/plugins/ 2. sudo unzip tdengine-datasource-3.1.3.zip -d /var/lib/grafana/plugins/
3. sudo chown grafana:grafana -R /var/lib/grafana/plugins/tdengine 3. sudo chown grafana:grafana -R /var/lib/grafana/plugins/tdengine
4. echo -e "[plugins]\nallow_loading_unsigned_plugins = tdengine-datasource\n" | sudo tee -a /etc/grafana/grafana.ini 4. echo -e "[plugins]\nallow_loading_unsigned_plugins = tdengine-datasource\n" | sudo tee -a /etc/grafana/grafana.ini
5. sudo systemctl restart grafana-server.service 5. sudo systemctl restart grafana-server.service
......
...@@ -32,8 +32,8 @@ Please download TDengine 2.3.0.0 or the above version from TAOS Data's [official ...@@ -32,8 +32,8 @@ Please download TDengine 2.3.0.0 or the above version from TAOS Data's [official
### Download TDengine plugin to Grafana plugin's directory ### Download TDengine plugin to Grafana plugin's directory
```bash ```bash
1. wget -c https://github.com/taosdata/grafanaplugin/releases/download/v3.1.1/tdengine-datasource-3.1.1.zip 1. wget -c https://github.com/taosdata/grafanaplugin/releases/download/v3.1.3/tdengine-datasource-3.1.3.zip
2. sudo unzip tdengine-datasource-3.1.1.zip -d /var/lib/grafana/plugins/ 2. sudo unzip tdengine-datasource-3.1.3.zip -d /var/lib/grafana/plugins/
3. sudo chown grafana:grafana -R /var/lib/grafana/plugins/tdengine 3. sudo chown grafana:grafana -R /var/lib/grafana/plugins/tdengine
4. echo -e "[plugins]\nallow_loading_unsigned_plugins = tdengine-datasource\n" | sudo tee -a /etc/grafana/grafana.ini 4. echo -e "[plugins]\nallow_loading_unsigned_plugins = tdengine-datasource\n" | sudo tee -a /etc/grafana/grafana.ini
5. sudo systemctl restart grafana-server.service 5. sudo systemctl restart grafana-server.service
......
...@@ -418,6 +418,10 @@ else ...@@ -418,6 +418,10 @@ else
BUILD_HTTP=false BUILD_HTTP=false
fi fi
if [[ "$verMode" == "cluster" ]]; then
BUILD_HTTP=internal
fi
if [[ "$pagMode" == "full" ]]; then if [[ "$pagMode" == "full" ]]; then
BUILD_TOOLS=true BUILD_TOOLS=true
else else
...@@ -494,11 +498,13 @@ else ...@@ -494,11 +498,13 @@ else
exit 1 exit 1
fi fi
CORES=`grep -c ^processor /proc/cpuinfo`
if [[ "$allocator" == "jemalloc" ]]; then if [[ "$allocator" == "jemalloc" ]]; then
# jemalloc need compile first, so disable parallel build # jemalloc need compile first, so disable parallel build
make -j 8 && ${csudo}make install make -j ${CORES} && ${csudo}make install
else else
make -j 8 && ${csudo}make install make -j ${CORES} && ${csudo}make install
fi fi
cd ${curr_dir} cd ${curr_dir}
......
...@@ -43,9 +43,11 @@ if [ "$osType" != "Darwin" ]; then ...@@ -43,9 +43,11 @@ if [ "$osType" != "Darwin" ]; then
if [ "$pagMode" == "lite" ]; then if [ "$pagMode" == "lite" ]; then
#strip ${build_dir}/bin/taosd #strip ${build_dir}/bin/taosd
strip ${build_dir}/bin/taos strip ${build_dir}/bin/taos
bin_files="${build_dir}/bin/taos ${script_dir}/remove_client.sh" bin_files="${build_dir}/bin/taos \
${script_dir}/remove_client.sh"
else else
bin_files="${script_dir}/remove_client.sh \ bin_files="${build_dir}/bin/taos \
${script_dir}/remove_client.sh \
${script_dir}/set_core.sh \ ${script_dir}/set_core.sh \
${script_dir}/get_client.sh" ${script_dir}/get_client.sh"
#${script_dir}/get_client.sh ${script_dir}/taosd-dump-cfg.gdb" #${script_dir}/get_client.sh ${script_dir}/taosd-dump-cfg.gdb"
......
name: tdengine name: tdengine
base: core20 base: core20
version: '2.3.2.0' version: '2.4.0.0'
icon: snap/gui/t-dengine.svg icon: snap/gui/t-dengine.svg
summary: an open-source big data platform designed and optimized for IoT. summary: an open-source big data platform designed and optimized for IoT.
description: | description: |
......
...@@ -9,3 +9,8 @@ INCLUDE_DIRECTORIES(inc) ...@@ -9,3 +9,8 @@ INCLUDE_DIRECTORIES(inc)
AUX_SOURCE_DIRECTORY(src SRC) AUX_SOURCE_DIRECTORY(src SRC)
ADD_LIBRARY(balance ${SRC}) ADD_LIBRARY(balance ${SRC})
IF (TD_LINUX_64 AND JEMALLOC_ENABLED)
ADD_DEPENDENCIES(balance jemalloc)
ENDIF ()
...@@ -128,12 +128,13 @@ static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) { ...@@ -128,12 +128,13 @@ static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) {
// type length // type length
int32_t bytes = pSchema[i].bytes; int32_t bytes = pSchema[i].bytes;
pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 2); pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 2);
if (pSchema[i].type == TSDB_DATA_TYPE_BINARY || pSchema[i].type == TSDB_DATA_TYPE_NCHAR) {
if (pSchema[i].type == TSDB_DATA_TYPE_BINARY){
bytes -= VARSTR_HEADER_SIZE; bytes -= VARSTR_HEADER_SIZE;
}
if (pSchema[i].type == TSDB_DATA_TYPE_NCHAR) { else if(pSchema[i].type == TSDB_DATA_TYPE_NCHAR || pSchema[i].type == TSDB_DATA_TYPE_JSON) {
bytes = bytes / TSDB_NCHAR_SIZE; bytes -= VARSTR_HEADER_SIZE;
} bytes = bytes / TSDB_NCHAR_SIZE;
} }
*(int32_t *)(pRes->data + tscFieldInfoGetOffset(pQueryInfo, 2) * totalNumOfRows + pField->bytes * i) = bytes; *(int32_t *)(pRes->data + tscFieldInfoGetOffset(pQueryInfo, 2) * totalNumOfRows + pField->bytes * i) = bytes;
......
...@@ -360,7 +360,7 @@ int32_t tsParseOneColumn(SSchema *pSchema, SStrToken *pToken, char *payload, cha ...@@ -360,7 +360,7 @@ int32_t tsParseOneColumn(SSchema *pSchema, SStrToken *pToken, char *payload, cha
return tscInvalidOperationMsg(msg, "json tag length too long", pToken->z); return tscInvalidOperationMsg(msg, "json tag length too long", pToken->z);
} }
if (pToken->type == TK_NULL) { if (pToken->type == TK_NULL) {
*(int8_t *)payload = TSDB_DATA_TINYINT_NULL; *(int8_t *)payload = TSDB_DATA_JSON_PLACEHOLDER;
} else if (pToken->type != TK_STRING){ } else if (pToken->type != TK_STRING){
tscInvalidOperationMsg(msg, "invalid json data", pToken->z); tscInvalidOperationMsg(msg, "invalid json data", pToken->z);
} else{ } else{
...@@ -1063,7 +1063,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql, char** boundC ...@@ -1063,7 +1063,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql, char** boundC
sToken.n -= 2; sToken.n -= 2;
} }
char tagVal[TSDB_MAX_TAGS_LEN]; char tagVal[TSDB_MAX_TAGS_LEN] = {0};
code = tsParseOneColumn(pSchema, &sToken, tagVal, pInsertParam->msg, &sql, false, tinfo.precision); code = tsParseOneColumn(pSchema, &sToken, tagVal, pInsertParam->msg, &sql, false, tinfo.precision);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
tdDestroyKVRowBuilder(&kvRowBuilder); tdDestroyKVRowBuilder(&kvRowBuilder);
......
...@@ -517,8 +517,8 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf ...@@ -517,8 +517,8 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf
static int32_t destroySmlSTableSchema(SSmlSTableSchema* schema) { static int32_t destroySmlSTableSchema(SSmlSTableSchema* schema) {
taosHashCleanup(schema->tagHash); taosHashCleanup(schema->tagHash);
taosHashCleanup(schema->fieldHash); taosHashCleanup(schema->fieldHash);
taosArrayDestroy(schema->tags); taosArrayDestroy(&schema->tags);
taosArrayDestroy(schema->fields); taosArrayDestroy(&schema->fields);
return 0; return 0;
} }
...@@ -1009,13 +1009,13 @@ static int32_t applyChildTableDataPointsWithStmt(TAOS* taos, char* cTableName, c ...@@ -1009,13 +1009,13 @@ static int32_t applyChildTableDataPointsWithStmt(TAOS* taos, char* cTableName, c
} }
free(colBinds); free(colBinds);
} }
taosArrayDestroy(rowsBind); taosArrayDestroy(&rowsBind);
//free tag bind //free tag bind
for (int i = 0; i < taosArrayGetSize(tagBinds); ++i) { for (int i = 0; i < taosArrayGetSize(tagBinds); ++i) {
TAOS_BIND* bind = taosArrayGet(tagBinds, i); TAOS_BIND* bind = taosArrayGet(tagBinds, i);
free(bind->length); free(bind->length);
} }
taosArrayDestroy(tagBinds); taosArrayDestroy(&tagBinds);
return code; return code;
} }
...@@ -1060,8 +1060,8 @@ static int32_t insertChildTablePointsBatch(TAOS* taos, char* cTableName, char* s ...@@ -1060,8 +1060,8 @@ static int32_t insertChildTablePointsBatch(TAOS* taos, char* cTableName, char* s
tscDebug("SML:0x%"PRIx64" insert child table table %s of super table %s : %s", info->id, cTableName, sTableName, sql); tscDebug("SML:0x%"PRIx64" insert child table table %s of super table %s : %s", info->id, cTableName, sTableName, sql);
size_t maxBatchSize = TSDB_MAX_WAL_SIZE/rowSize * 2 / 3;
size_t rows = taosArrayGetSize(rowsBind); size_t rows = taosArrayGetSize(rowsBind);
size_t maxBatchSize = TSDB_MAX_WAL_SIZE/rowSize * 4 / 5;
size_t batchSize = MIN(maxBatchSize, rows); size_t batchSize = MIN(maxBatchSize, rows);
tscDebug("SML:0x%"PRIx64" insert rows into child table %s. num of rows: %zu, batch size: %zu", tscDebug("SML:0x%"PRIx64" insert rows into child table %s. num of rows: %zu, batch size: %zu",
info->id, cTableName, rows, batchSize); info->id, cTableName, rows, batchSize);
...@@ -1076,7 +1076,7 @@ static int32_t insertChildTablePointsBatch(TAOS* taos, char* cTableName, char* s ...@@ -1076,7 +1076,7 @@ static int32_t insertChildTablePointsBatch(TAOS* taos, char* cTableName, char* s
tscDebug("SML:0x%"PRIx64" insert child table batch from line %d to line %d.", info->id, i, j - 1); tscDebug("SML:0x%"PRIx64" insert child table batch from line %d to line %d.", info->id, i, j - 1);
code = doInsertChildTablePoints(taos, sql, cTableName, tagsBind, batchBind, info); code = doInsertChildTablePoints(taos, sql, cTableName, tagsBind, batchBind, info);
if (code != 0) { if (code != 0) {
taosArrayDestroy(batchBind); taosArrayDestroy(&batchBind);
tfree(sql); tfree(sql);
return code; return code;
} }
...@@ -1084,7 +1084,7 @@ static int32_t insertChildTablePointsBatch(TAOS* taos, char* cTableName, char* s ...@@ -1084,7 +1084,7 @@ static int32_t insertChildTablePointsBatch(TAOS* taos, char* cTableName, char* s
} }
i = j; i = j;
} }
taosArrayDestroy(batchBind); taosArrayDestroy(&batchBind);
tfree(sql); tfree(sql);
return code; return code;
...@@ -1236,7 +1236,7 @@ cleanup: ...@@ -1236,7 +1236,7 @@ cleanup:
pCTablePoints = taosHashIterate(cname2points, NULL); pCTablePoints = taosHashIterate(cname2points, NULL);
while (pCTablePoints) { while (pCTablePoints) {
SArray* pPoints = *pCTablePoints; SArray* pPoints = *pCTablePoints;
taosArrayDestroy(pPoints); taosArrayDestroy(&pPoints);
pCTablePoints = taosHashIterate(cname2points, pCTablePoints); pCTablePoints = taosHashIterate(cname2points, pCTablePoints);
} }
taosHashCleanup(cname2points); taosHashCleanup(cname2points);
...@@ -1336,10 +1336,10 @@ int tscSmlInsert(TAOS* taos, TAOS_SML_DATA_POINT* points, int numPoint, SSmlLine ...@@ -1336,10 +1336,10 @@ int tscSmlInsert(TAOS* taos, TAOS_SML_DATA_POINT* points, int numPoint, SSmlLine
clean_up: clean_up:
for (int i = 0; i < taosArrayGetSize(stableSchemas); ++i) { for (int i = 0; i < taosArrayGetSize(stableSchemas); ++i) {
SSmlSTableSchema* schema = taosArrayGet(stableSchemas, i); SSmlSTableSchema* schema = taosArrayGet(stableSchemas, i);
taosArrayDestroy(schema->fields); taosArrayDestroy(&schema->fields);
taosArrayDestroy(schema->tags); taosArrayDestroy(&schema->tags);
} }
taosArrayDestroy(stableSchemas); taosArrayDestroy(&stableSchemas);
return code; return code;
} }
...@@ -2536,7 +2536,7 @@ cleanup: ...@@ -2536,7 +2536,7 @@ cleanup:
destroySmlDataPoint(points+i); destroySmlDataPoint(points+i);
} }
taosArrayDestroy(lpPoints); taosArrayDestroy(&lpPoints);
tfree(info); tfree(info);
return code; return code;
......
...@@ -472,7 +472,7 @@ cleanup: ...@@ -472,7 +472,7 @@ cleanup:
destroySmlDataPoint(points+i); destroySmlDataPoint(points+i);
} }
taosArrayDestroy(lpPoints); taosArrayDestroy(&lpPoints);
tfree(info); tfree(info);
return code; return code;
...@@ -1106,7 +1106,7 @@ cleanup: ...@@ -1106,7 +1106,7 @@ cleanup:
destroySmlDataPoint(points+i); destroySmlDataPoint(points+i);
} }
taosArrayDestroy(lpPoints); taosArrayDestroy(&lpPoints);
tfree(info); tfree(info);
return code; return code;
......
...@@ -1933,7 +1933,7 @@ int taos_stmt_close(TAOS_STMT* stmt) { ...@@ -1933,7 +1933,7 @@ int taos_stmt_close(TAOS_STMT* stmt) {
pStmt->pSql->cmd.insertParam.pTableBlockHashList = NULL; pStmt->pSql->cmd.insertParam.pTableBlockHashList = NULL;
} }
taosArrayDestroy(pStmt->mtb.tags); taosArrayDestroy(&pStmt->mtb.tags);
tfree(pStmt->mtb.sqlstr); tfree(pStmt->mtb.sqlstr);
} }
} }
......
...@@ -996,9 +996,16 @@ int32_t tscValidateSqlInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { ...@@ -996,9 +996,16 @@ int32_t tscValidateSqlInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
return code; return code;
} }
// set the command/global limit parameters from the first subclause to the sqlcmd object // set the command/global limit parameters from the first not empty subclause to the sqlcmd object
pCmd->active = pCmd->pQueryInfo; SQueryInfo* queryInfo = pCmd->pQueryInfo;
pCmd->command = pCmd->pQueryInfo->command; int16_t command = queryInfo->command;
while (command == TSDB_SQL_RETRIEVE_EMPTY_RESULT && queryInfo->sibling != NULL) {
queryInfo = queryInfo->sibling;
command = queryInfo->command;
}
pCmd->active = queryInfo;
pCmd->command = command;
STableMetaInfo* pTableMetaInfo1 = tscGetMetaInfo(pCmd->active, 0); STableMetaInfo* pTableMetaInfo1 = tscGetMetaInfo(pCmd->active, 0);
if (pTableMetaInfo1->pTableMeta != NULL) { if (pTableMetaInfo1->pTableMeta != NULL) {
...@@ -1836,7 +1843,7 @@ static int32_t handleScalarTypeExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32 ...@@ -1836,7 +1843,7 @@ static int32_t handleScalarTypeExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32
int32_t ret = exprTreeFromSqlExpr(pCmd, &pNode, pItem->pNode, pQueryInfo, colList, NULL); int32_t ret = exprTreeFromSqlExpr(pCmd, &pNode, pItem->pNode, pQueryInfo, colList, NULL);
if (ret != TSDB_CODE_SUCCESS) { if (ret != TSDB_CODE_SUCCESS) {
taosArrayDestroy(colList); taosArrayDestroy(&colList);
tExprTreeDestroy(pNode, NULL); tExprTreeDestroy(pNode, NULL);
if (tscGetErrorMsgLength(pCmd) > 0) { if (tscGetErrorMsgLength(pCmd) > 0) {
return ret; return ret;
...@@ -1851,7 +1858,7 @@ static int32_t handleScalarTypeExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32 ...@@ -1851,7 +1858,7 @@ static int32_t handleScalarTypeExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32
SColIndex* pIndex = taosArrayGet(colList, k); SColIndex* pIndex = taosArrayGet(colList, k);
if (TSDB_COL_IS_TAG(pIndex->flag)) { if (TSDB_COL_IS_TAG(pIndex->flag)) {
tExprTreeDestroy(pNode, NULL); tExprTreeDestroy(pNode, NULL);
taosArrayDestroy(colList); taosArrayDestroy(&colList);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
} }
...@@ -1859,7 +1866,7 @@ static int32_t handleScalarTypeExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32 ...@@ -1859,7 +1866,7 @@ static int32_t handleScalarTypeExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32
ret = exprTreeValidateTree(tscGetErrorMsgPayload(pCmd), pNode); ret = exprTreeValidateTree(tscGetErrorMsgPayload(pCmd), pNode);
if (ret != TSDB_CODE_SUCCESS) { if (ret != TSDB_CODE_SUCCESS) {
taosArrayDestroy(colList); taosArrayDestroy(&colList);
tExprTreeDestroy(pNode, NULL); tExprTreeDestroy(pNode, NULL);
if (tscGetErrorMsgLength(pCmd) > 0) { if (tscGetErrorMsgLength(pCmd) > 0) {
return ret; return ret;
...@@ -1900,7 +1907,7 @@ static int32_t handleScalarTypeExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32 ...@@ -1900,7 +1907,7 @@ static int32_t handleScalarTypeExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32
tscInsertPrimaryTsSourceColumn(pQueryInfo, pExpr->base.uid); tscInsertPrimaryTsSourceColumn(pQueryInfo, pExpr->base.uid);
tbufCloseWriter(&bw); tbufCloseWriter(&bw);
taosArrayDestroy(colList); taosArrayDestroy(&colList);
tExprTreeDestroy(pNode, NULL); tExprTreeDestroy(pNode, NULL);
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
...@@ -4296,7 +4303,7 @@ static int32_t getColQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlEx ...@@ -4296,7 +4303,7 @@ static int32_t getColQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlEx
SArray* colList = taosArrayInit(10, sizeof(SColIndex)); SArray* colList = taosArrayInit(10, sizeof(SColIndex));
ret = exprTreeFromSqlExpr(pCmd, &p, p1, pQueryInfo, colList, NULL); ret = exprTreeFromSqlExpr(pCmd, &p, p1, pQueryInfo, colList, NULL);
taosArrayDestroy(colList); taosArrayDestroy(&colList);
SBufferWriter bw = tbufInitWriter(NULL, false); SBufferWriter bw = tbufInitWriter(NULL, false);
...@@ -4512,13 +4519,16 @@ static int32_t validateSQLExprItemSQLFunc(SSqlCmd* pCmd, tSqlExpr* pExpr, ...@@ -4512,13 +4519,16 @@ static int32_t validateSQLExprItemSQLFunc(SSqlCmd* pCmd, tSqlExpr* pExpr,
if (TSDB_FUNC_IS_SCALAR(functionId)) { if (TSDB_FUNC_IS_SCALAR(functionId)) {
code = validateSQLExprItem(pCmd, pParamElem->pNode, pQueryInfo, pList, childrenTypes + i, uid, childrenHeight+i); code = validateSQLExprItem(pCmd, pParamElem->pNode, pQueryInfo, pList, childrenTypes + i, uid, childrenHeight+i);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
free(childrenTypes); tfree(childrenTypes);
tfree(childrenHeight);
return code; return code;
} }
} }
if (!TSDB_FUNC_IS_SCALAR(functionId) && if (!TSDB_FUNC_IS_SCALAR(functionId) &&
(pParamElem->pNode->type == SQL_NODE_EXPR || pParamElem->pNode->type == SQL_NODE_SQLFUNCTION)) { (pParamElem->pNode->type == SQL_NODE_EXPR || pParamElem->pNode->type == SQL_NODE_SQLFUNCTION)) {
tfree(childrenTypes);
tfree(childrenHeight);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
} }
...@@ -4540,6 +4550,8 @@ static int32_t validateSQLExprItemSQLFunc(SSqlCmd* pCmd, tSqlExpr* pExpr, ...@@ -4540,6 +4550,8 @@ static int32_t validateSQLExprItemSQLFunc(SSqlCmd* pCmd, tSqlExpr* pExpr,
*height = maxChildrenHeight + 1; *height = maxChildrenHeight + 1;
if (anyChildAgg && anyChildScalar) { if (anyChildAgg && anyChildScalar) {
tfree(childrenTypes);
tfree(childrenHeight);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
} }
if (anyChildAgg) { if (anyChildAgg) {
...@@ -4551,7 +4563,8 @@ static int32_t validateSQLExprItemSQLFunc(SSqlCmd* pCmd, tSqlExpr* pExpr, ...@@ -4551,7 +4563,8 @@ static int32_t validateSQLExprItemSQLFunc(SSqlCmd* pCmd, tSqlExpr* pExpr,
*type = SQLEXPR_TYPE_AGG; *type = SQLEXPR_TYPE_AGG;
} }
} }
free(childrenTypes); tfree(childrenTypes);
tfree(childrenHeight);
//end if param list is not null //end if param list is not null
} else { } else {
if (TSDB_FUNC_IS_SCALAR(functionId)) { if (TSDB_FUNC_IS_SCALAR(functionId)) {
...@@ -5756,7 +5769,7 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE ...@@ -5756,7 +5769,7 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE
tSqlExprDestroy(p1); tSqlExprDestroy(p1);
tExprTreeDestroy(p, NULL); //TODO tExprTreeDestroy(p, NULL); //TODO
taosArrayDestroy(colList); taosArrayDestroy(&colList);
if (pQueryInfo->tagCond.pCond != NULL && taosArrayGetSize(pQueryInfo->tagCond.pCond) > 0 && !UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { if (pQueryInfo->tagCond.pCond != NULL && taosArrayGetSize(pQueryInfo->tagCond.pCond) > 0 && !UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "filter on tag not supported for normal table"); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "filter on tag not supported for normal table");
} }
...@@ -5878,7 +5891,7 @@ static int32_t getQueryTimeRange(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr ...@@ -5878,7 +5891,7 @@ static int32_t getQueryTimeRange(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr
SArray* colList = taosArrayInit(10, sizeof(SColIndex)); SArray* colList = taosArrayInit(10, sizeof(SColIndex));
ret = exprTreeFromSqlExpr(pCmd, &p, *pExpr, pQueryInfo, colList, NULL); ret = exprTreeFromSqlExpr(pCmd, &p, *pExpr, pQueryInfo, colList, NULL);
taosArrayDestroy(colList); taosArrayDestroy(&colList);
if (ret != TSDB_CODE_SUCCESS) { if (ret != TSDB_CODE_SUCCESS) {
goto _ret; goto _ret;
...@@ -6077,7 +6090,7 @@ int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t t ...@@ -6077,7 +6090,7 @@ int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t t
// todo error !!!! // todo error !!!!
int32_t tsRewriteFieldNameIfNecessary(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) { int32_t tsRewriteFieldNameIfNecessary(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
const char rep[] = {'(', ')', '*', ',', '.', '/', '\\', '+', '-', '%', ' '}; const char rep[] = {'(', ')', '*', ',', '.', '/', '\\', '+', '-', '%', ' ', '`'};
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) { for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
char* fieldName = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i)->name; char* fieldName = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i)->name;
...@@ -6312,7 +6325,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq ...@@ -6312,7 +6325,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
const char* msg0 = "only one column allowed in orderby"; const char* msg0 = "only one column allowed in orderby";
const char* msg1 = "invalid column name in orderby clause"; const char* msg1 = "invalid column name in orderby clause";
const char* msg2 = "too many order by columns"; const char* msg2 = "too many order by columns";
const char* msg3 = "only primary timestamp, first tag/tbname in groupby clause allowed as order column"; const char* msg3 = "only primary timestamp, tag/tbname in groupby clause allowed as order column";
const char* msg4 = "only tag in groupby clause allowed in order clause"; const char* msg4 = "only tag in groupby clause allowed in order clause";
const char* msg5 = "only primary timestamp/column in top/bottom function allowed as order column"; const char* msg5 = "only primary timestamp/column in top/bottom function allowed as order column";
const char* msg6 = "only primary timestamp allowed as the second order column"; const char* msg6 = "only primary timestamp allowed as the second order column";
...@@ -6334,8 +6347,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq ...@@ -6334,8 +6347,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
SArray* pSortOrder = pSqlNode->pSortOrder; SArray* pSortOrder = pSqlNode->pSortOrder;
/* /*
* for table query, there is only one or none order option is allowed, which is the * for table query, there is only one or none order option is allowed
* ts or values(top/bottom) order is supported.
* *
* for super table query, the order option must be less than 3 and the second must be ts. * for super table query, the order option must be less than 3 and the second must be ts.
* *
...@@ -6410,7 +6422,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq ...@@ -6410,7 +6422,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
return invalidOperationMsg(pMsgBuf, msg4); return invalidOperationMsg(pMsgBuf, msg4);
} }
SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, 0); SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, 0);
if (relTagIndex == pColIndex->colIndex) { if (relTagIndex == pColIndex->colIndex && pColIndex->flag == TSDB_COL_TAG) {
if (tscGetColumnSchemaById(pTableMetaInfo->pTableMeta, pColIndex->colId)->type == TSDB_DATA_TYPE_JSON){ if (tscGetColumnSchemaById(pTableMetaInfo->pTableMeta, pColIndex->colId)->type == TSDB_DATA_TYPE_JSON){
if(!pItem->isJsonExp){ if(!pItem->isJsonExp){
return invalidOperationMsg(pMsgBuf, msg14); return invalidOperationMsg(pMsgBuf, msg14);
...@@ -6859,11 +6871,11 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { ...@@ -6859,11 +6871,11 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
} }
SKVRowBuilder kvRowBuilder = {0}; SKVRowBuilder kvRowBuilder = {0};
if (pTagsSchema->type == TSDB_DATA_TYPE_JSON) { if (pTagsSchema->type == TSDB_DATA_TYPE_JSON) {
if (pItem->pVar.nType != TSDB_DATA_TYPE_BINARY) { if (pItem->pVar.nType != TSDB_DATA_TYPE_BINARY && pItem->pVar.nType != TSDB_DATA_TYPE_NULL) {
tscError("json type error, should be string"); tscError("json type error, should be string");
return invalidOperationMsg(pMsg, msg25); return invalidOperationMsg(pMsg, msg25);
} }
if (pItem->pVar.nType > TSDB_MAX_JSON_TAGS_LEN / TSDB_NCHAR_SIZE) { if (pItem->pVar.nLen > TSDB_MAX_JSON_TAGS_LEN / TSDB_NCHAR_SIZE) {
tscError("json tag too long"); tscError("json tag too long");
return invalidOperationMsg(pMsg, msg14); return invalidOperationMsg(pMsg, msg14);
} }
...@@ -8702,7 +8714,7 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) { ...@@ -8702,7 +8714,7 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
} }
tVariantListItem* pItem = taosArrayGet(pValList, 0); tVariantListItem* pItem = taosArrayGet(pValList, 0);
if(pItem->pVar.nType != TSDB_DATA_TYPE_BINARY){ if(pItem->pVar.nType != TSDB_DATA_TYPE_BINARY && pItem->pVar.nType != TSDB_DATA_TYPE_NULL){
tscError("json type error, should be string"); tscError("json type error, should be string");
tdDestroyKVRowBuilder(&kvRowBuilder); tdDestroyKVRowBuilder(&kvRowBuilder);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
...@@ -8712,6 +8724,7 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) { ...@@ -8712,6 +8724,7 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
tdDestroyKVRowBuilder(&kvRowBuilder); tdDestroyKVRowBuilder(&kvRowBuilder);
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
} }
ret = parseJsontoTagData(pItem->pVar.pz, &kvRowBuilder, tscGetErrorMsgPayload(pCmd), pTagSchema[0].colId); ret = parseJsontoTagData(pItem->pVar.pz, &kvRowBuilder, tscGetErrorMsgPayload(pCmd), pTagSchema[0].colId);
if (ret != TSDB_CODE_SUCCESS) { if (ret != TSDB_CODE_SUCCESS) {
tdDestroyKVRowBuilder(&kvRowBuilder); tdDestroyKVRowBuilder(&kvRowBuilder);
...@@ -9490,15 +9503,15 @@ int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) { ...@@ -9490,15 +9503,15 @@ int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) {
_end: _end:
if (plist != NULL) { if (plist != NULL) {
taosArrayDestroyEx(plist, freeElem); taosArrayDestroyEx(&plist, freeElem);
} }
if (pVgroupList != NULL) { if (pVgroupList != NULL) {
taosArrayDestroyEx(pVgroupList, freeElem); taosArrayDestroyEx(&pVgroupList, freeElem);
} }
if (tableNameList != NULL) { if (tableNameList != NULL) {
taosArrayDestroy(tableNameList); taosArrayDestroy(&tableNameList);
} }
tfree(pTableMeta); tfree(pTableMeta);
......
...@@ -1175,8 +1175,8 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { ...@@ -1175,8 +1175,8 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
_end: _end:
freeQueryAttr(&query); freeQueryAttr(&query);
taosArrayDestroy(tableScanOperator); taosArrayDestroy(&tableScanOperator);
taosArrayDestroy(queryOperator); taosArrayDestroy(&queryOperator);
return code; return code;
} }
...@@ -2259,7 +2259,7 @@ int tscProcessRetrieveFuncRsp(SSqlObj* pSql) { ...@@ -2259,7 +2259,7 @@ int tscProcessRetrieveFuncRsp(SSqlObj* pSql) {
SQueryInfo* parQueryInfo = tscGetQueryInfo(&parent->cmd); SQueryInfo* parQueryInfo = tscGetQueryInfo(&parent->cmd);
assert(parent->signature == parent && (int64_t)pSql->param == parent->self); assert(parent->signature == parent && (int64_t)pSql->param == parent->self);
taosArrayDestroy(parQueryInfo->pUdfInfo); taosArrayDestroy(&parQueryInfo->pUdfInfo);
parQueryInfo->pUdfInfo = pQueryInfo->pUdfInfo; // assigned to parent sql obj. parQueryInfo->pUdfInfo = pQueryInfo->pUdfInfo; // assigned to parent sql obj.
pQueryInfo->pUdfInfo = NULL; pQueryInfo->pUdfInfo = NULL;
...@@ -2371,7 +2371,7 @@ int tscProcessMultiTableMetaRsp(SSqlObj *pSql) { ...@@ -2371,7 +2371,7 @@ int tscProcessMultiTableMetaRsp(SSqlObj *pSql) {
int32_t size = 0; int32_t size = 0;
if (p->vgroupIdList!= NULL) { if (p->vgroupIdList!= NULL) {
taosArrayDestroy(p->vgroupIdList); taosArrayDestroy(&p->vgroupIdList);
} }
p->vgroupIdList = createVgroupIdListFromMsg(pParentSql, pMsg, pSet, fname, &size, pSql->self); p->vgroupIdList = createVgroupIdListFromMsg(pParentSql, pMsg, pSet, fname, &size, pSql->self);
...@@ -3124,13 +3124,14 @@ int tscRenewTableMeta(SSqlObj *pSql) { ...@@ -3124,13 +3124,14 @@ int tscRenewTableMeta(SSqlObj *pSql) {
pSql->rootObj->retryReason = pSql->retryReason; pSql->rootObj->retryReason = pSql->retryReason;
SSqlObj *tmpSql = pSql->rootObj; SSqlObj *rootSql = pSql->rootObj;
tscFreeSubobj(pSql->rootObj); tscFreeSubobj(rootSql);
tfree(tmpSql->pSubs); tfree(rootSql->pSubs);
tscResetSqlCmd(&rootSql->cmd, true, rootSql->self);
code = getMultiTableMetaFromMnode(tmpSql, pNameList, vgroupList, NULL, tscTableMetaCallBack, true); code = getMultiTableMetaFromMnode(rootSql, pNameList, vgroupList, NULL, tscTableMetaCallBack, true);
taosArrayDestroyEx(pNameList, freeElem); taosArrayDestroyEx(&pNameList, freeElem);
taosArrayDestroyEx(vgroupList, freeElem); taosArrayDestroyEx(&vgroupList, freeElem);
return code; return code;
} }
......
...@@ -1006,7 +1006,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) { ...@@ -1006,7 +1006,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
SArray* vgroupList = taosArrayInit(4, POINTER_BYTES); SArray* vgroupList = taosArrayInit(4, POINTER_BYTES);
if (vgroupList == NULL) { if (vgroupList == NULL) {
taosArrayDestroy(plist); taosArrayDestroy(&plist);
tfree(str); tfree(str);
return TSDB_CODE_TSC_OUT_OF_MEMORY; return TSDB_CODE_TSC_OUT_OF_MEMORY;
} }
...@@ -1023,8 +1023,8 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) { ...@@ -1023,8 +1023,8 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
tscFreeSqlObj(pSql); tscFreeSqlObj(pSql);
taosArrayDestroyEx(plist, freeElem); taosArrayDestroyEx(&plist, freeElem);
taosArrayDestroyEx(vgroupList, freeElem); taosArrayDestroyEx(&vgroupList, freeElem);
return code; return code;
} }
...@@ -1037,8 +1037,8 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) { ...@@ -1037,8 +1037,8 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
code = TSDB_CODE_SUCCESS; code = TSDB_CODE_SUCCESS;
} }
taosArrayDestroyEx(plist, freeElem); taosArrayDestroyEx(&plist, freeElem);
taosArrayDestroyEx(vgroupList, freeElem); taosArrayDestroyEx(&vgroupList, freeElem);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
tscFreeRegisteredSqlObj(pSql); tscFreeRegisteredSqlObj(pSql);
......
...@@ -194,7 +194,7 @@ fail: ...@@ -194,7 +194,7 @@ fail:
} }
if (pSub != NULL) { if (pSub != NULL) {
taosArrayDestroy(pSub->progress); taosArrayDestroy(&pSub->progress);
tsem_destroy(&pSub->sem); tsem_destroy(&pSub->sem);
free(pSub); free(pSub);
pSub = NULL; pSub = NULL;
...@@ -300,7 +300,7 @@ static int tscUpdateSubscription(STscObj* pObj, SSub* pSub) { ...@@ -300,7 +300,7 @@ static int tscUpdateSubscription(STscObj* pObj, SSub* pSub) {
} }
taosArraySort(progress, tscCompareSubscriptionProgress); taosArraySort(progress, tscCompareSubscriptionProgress);
taosArrayDestroy(pSub->progress); taosArrayDestroy(&pSub->progress);
pSub->progress = progress; pSub->progress = progress;
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
...@@ -308,7 +308,7 @@ static int tscUpdateSubscription(STscObj* pObj, SSub* pSub) { ...@@ -308,7 +308,7 @@ static int tscUpdateSubscription(STscObj* pObj, SSub* pSub) {
tscFreeVgroupTableInfo(pTableMetaInfo->pVgroupTables); tscFreeVgroupTableInfo(pTableMetaInfo->pVgroupTables);
tscBuildVgroupTableInfo(pSql, pTableMetaInfo, tables); tscBuildVgroupTableInfo(pSql, pTableMetaInfo, tables);
} }
taosArrayDestroy(tables); taosArrayDestroy(&tables);
if (pTableMetaInfo->pVgroupTables && taosArrayGetSize(pTableMetaInfo->pVgroupTables) > 0) { if (pTableMetaInfo->pVgroupTables && taosArrayGetSize(pTableMetaInfo->pVgroupTables) > 0) {
TSDB_QUERY_SET_TYPE(tscGetQueryInfo(pCmd)->type, TSDB_QUERY_TYPE_MULTITABLE_QUERY); TSDB_QUERY_SET_TYPE(tscGetQueryInfo(pCmd)->type, TSDB_QUERY_TYPE_MULTITABLE_QUERY);
...@@ -626,7 +626,7 @@ void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress) { ...@@ -626,7 +626,7 @@ void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress) {
} }
} }
taosArrayDestroy(pSub->progress); taosArrayDestroy(&pSub->progress);
tsem_destroy(&pSub->sem); tsem_destroy(&pSub->sem);
memset(pSub, 0, sizeof(*pSub)); memset(pSub, 0, sizeof(*pSub));
free(pSub); free(pSub);
......
...@@ -431,7 +431,7 @@ static void tscDestroyJoinSupporter(SJoinSupporter* pSupporter) { ...@@ -431,7 +431,7 @@ static void tscDestroyJoinSupporter(SJoinSupporter* pSupporter) {
// tscFieldInfoClear(&pSupporter->fieldsInfo); // tscFieldInfoClear(&pSupporter->fieldsInfo);
if (pSupporter->fieldsInfo.internalField != NULL) { if (pSupporter->fieldsInfo.internalField != NULL) {
taosArrayDestroy(pSupporter->fieldsInfo.internalField); taosArrayDestroy(&pSupporter->fieldsInfo.internalField);
} }
if (pSupporter->pTSBuf != NULL) { if (pSupporter->pTSBuf != NULL) {
tsBufDestroy(pSupporter->pTSBuf); tsBufDestroy(pSupporter->pTSBuf);
...@@ -446,7 +446,7 @@ static void tscDestroyJoinSupporter(SJoinSupporter* pSupporter) { ...@@ -446,7 +446,7 @@ static void tscDestroyJoinSupporter(SJoinSupporter* pSupporter) {
} }
if (pSupporter->pVgroupTables != NULL) { if (pSupporter->pVgroupTables != NULL) {
//taosArrayDestroy(pSupporter->pVgroupTables); //taosArrayDestroy(&pSupporter->pVgroupTables);
tscFreeVgroupTableInfo(pSupporter->pVgroupTables); tscFreeVgroupTableInfo(pSupporter->pVgroupTables);
pSupporter->pVgroupTables = NULL; pSupporter->pVgroupTables = NULL;
} }
...@@ -804,7 +804,7 @@ void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArr ...@@ -804,7 +804,7 @@ void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArr
if (taosArrayGetSize(result) <= 0) { if (taosArrayGetSize(result) <= 0) {
pTableMetaInfo->pVgroupTables = NULL; pTableMetaInfo->pVgroupTables = NULL;
taosArrayDestroy(result); taosArrayDestroy(&result);
} else { } else {
pTableMetaInfo->pVgroupTables = result; pTableMetaInfo->pVgroupTables = result;
...@@ -967,7 +967,7 @@ static int32_t getIntersectionOfTableTuple(SQueryInfo* pQueryInfo, SSqlObj* pPar ...@@ -967,7 +967,7 @@ static int32_t getIntersectionOfTableTuple(SQueryInfo* pQueryInfo, SSqlObj* pPar
if (!checkForDuplicateTagVal(pColSchema, p, pParentSql)) { if (!checkForDuplicateTagVal(pColSchema, p, pParentSql)) {
for (int32_t j = 0; j <= i; j++) { for (int32_t j = 0; j <= i; j++) {
taosArrayDestroy(ctxlist[j].res); taosArrayDestroy(&ctxlist[j].res);
} }
return TSDB_CODE_QRY_DUP_JOIN_KEY; return TSDB_CODE_QRY_DUP_JOIN_KEY;
} }
...@@ -1269,7 +1269,7 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow ...@@ -1269,7 +1269,7 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
pParentSql->res.code = code; pParentSql->res.code = code;
tscAsyncResultOnError(pParentSql); tscAsyncResultOnError(pParentSql);
taosArrayDestroy(resList); taosArrayDestroy(&resList);
goto _return; goto _return;
} }
...@@ -1309,11 +1309,11 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow ...@@ -1309,11 +1309,11 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
for (int32_t i = 0; i < rsize; ++i) { for (int32_t i = 0; i < rsize; ++i) {
SArray** s = taosArrayGet(resList, i); SArray** s = taosArrayGet(resList, i);
if (*s) { if (*s) {
taosArrayDestroy(*s); taosArrayDestroy(s);
} }
} }
taosArrayDestroy(resList); taosArrayDestroy(&resList);
_return: _return:
taosReleaseRef(tscObjRef, handle); taosReleaseRef(tscObjRef, handle);
...@@ -1993,7 +1993,7 @@ int32_t tscCreateJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter ...@@ -1993,7 +1993,7 @@ int32_t tscCreateJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter
pNewQueryInfo->limit.limit = -1; pNewQueryInfo->limit.limit = -1;
pNewQueryInfo->limit.offset = 0; pNewQueryInfo->limit.offset = 0;
taosArrayDestroy(pNewQueryInfo->pUpstream); taosArrayDestroy(&pNewQueryInfo->pUpstream);
pNewQueryInfo->order.orderColId = INT32_MIN; pNewQueryInfo->order.orderColId = INT32_MIN;
...@@ -2255,8 +2255,8 @@ void doAppendData(SInterResult* pInterResult, TAOS_ROW row, int32_t numOfCols, S ...@@ -2255,8 +2255,8 @@ void doAppendData(SInterResult* pInterResult, TAOS_ROW row, int32_t numOfCols, S
static void tscFreeFirstRoundSup(void **param) { static void tscFreeFirstRoundSup(void **param) {
if (*param) { if (*param) {
SFirstRoundQuerySup* pSup = (SFirstRoundQuerySup*)*param; SFirstRoundQuerySup* pSup = (SFirstRoundQuerySup*)*param;
taosArrayDestroyEx(pSup->pResult, freeInterResult); taosArrayDestroyEx(&pSup->pResult, freeInterResult);
taosArrayDestroy(pSup->pColsInfo); taosArrayDestroy(&pSup->pColsInfo);
tfree(*param); tfree(*param);
} }
} }
...@@ -3903,7 +3903,7 @@ void* createQInfoFromQueryNode(SQueryInfo* pQueryInfo, STableGroupInfo* pTableGr ...@@ -3903,7 +3903,7 @@ void* createQInfoFromQueryNode(SQueryInfo* pQueryInfo, STableGroupInfo* pTableGr
STsBufInfo bufInfo = {0}; STsBufInfo bufInfo = {0};
SQueryParam param = {.pOperator = pa}; SQueryParam param = {.pOperator = pa};
/*int32_t code = */initQInfo(&bufInfo, NULL, pSourceOperator, pQInfo, &param, NULL, 0, merger); /*int32_t code = */initQInfo(&bufInfo, NULL, pSourceOperator, pQInfo, &param, NULL, 0, merger);
taosArrayDestroy(pa); taosArrayDestroy(&pa);
return pQInfo; return pQInfo;
......
...@@ -774,11 +774,12 @@ static void setResRawPtrImpl(SSqlRes* pRes, SInternalField* pInfo, int32_t i, bo ...@@ -774,11 +774,12 @@ static void setResRawPtrImpl(SSqlRes* pRes, SInternalField* pInfo, int32_t i, bo
memcpy(dst, p, varDataTLen(p)); memcpy(dst, p, varDataTLen(p));
} else if (varDataLen(p) > 0) { } else if (varDataLen(p) > 0) {
int32_t length = taosUcs4ToMbs(varDataVal(p), varDataLen(p), varDataVal(dst)); int32_t length = taosUcs4ToMbs(varDataVal(p), varDataLen(p), varDataVal(dst));
varDataSetLen(dst, length); if (length <= 0) {
if (length == 0) {
tscError("charset:%s to %s. val:%s convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)p); tscError("charset:%s to %s. val:%s convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)p);
} }
if (length >= 0){
varDataSetLen(dst, length);
}
} else { } else {
varDataSetLen(dst, 0); varDataSetLen(dst, 0);
} }
...@@ -809,18 +810,23 @@ static void setResRawPtrImpl(SSqlRes* pRes, SInternalField* pInfo, int32_t i, bo ...@@ -809,18 +810,23 @@ static void setResRawPtrImpl(SSqlRes* pRes, SInternalField* pInfo, int32_t i, bo
varDataSetLen(dst, strlen(varDataVal(dst))); varDataSetLen(dst, strlen(varDataVal(dst)));
}else if (type == TSDB_DATA_TYPE_JSON) { }else if (type == TSDB_DATA_TYPE_JSON) {
int32_t length = taosUcs4ToMbs(varDataVal(realData), varDataLen(realData), varDataVal(dst)); int32_t length = taosUcs4ToMbs(varDataVal(realData), varDataLen(realData), varDataVal(dst));
varDataSetLen(dst, length);
if (length == 0) { if (length <= 0) {
tscError("charset:%s to %s. val:%s convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)p); tscError("charset:%s to %s. val:%s convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)p);
} }
if (length >= 0){
varDataSetLen(dst, length);
}
}else if (type == TSDB_DATA_TYPE_NCHAR) { // value -> "value" }else if (type == TSDB_DATA_TYPE_NCHAR) { // value -> "value"
*(char*)varDataVal(dst) = '\"'; *(char*)varDataVal(dst) = '\"';
int32_t length = taosUcs4ToMbs(varDataVal(realData), varDataLen(realData), POINTER_SHIFT(varDataVal(dst), CHAR_BYTES)); int32_t length = taosUcs4ToMbs(varDataVal(realData), varDataLen(realData), POINTER_SHIFT(varDataVal(dst), CHAR_BYTES));
*(char*)(POINTER_SHIFT(varDataVal(dst), length + CHAR_BYTES)) = '\"'; if (length <= 0) {
varDataSetLen(dst, length + CHAR_BYTES*2);
if (length == 0) {
tscError("charset:%s to %s. val:%s convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)p); tscError("charset:%s to %s. val:%s convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)p);
} }
if (length >= 0){
varDataSetLen(dst, length + CHAR_BYTES*2);
*(char*)(POINTER_SHIFT(varDataVal(dst), length + CHAR_BYTES)) = '\"';
}
}else if (type == TSDB_DATA_TYPE_DOUBLE) { }else if (type == TSDB_DATA_TYPE_DOUBLE) {
double jsonVd = *(double*)(realData); double jsonVd = *(double*)(realData);
sprintf(varDataVal(dst), "%.9lf", jsonVd); sprintf(varDataVal(dst), "%.9lf", jsonVd);
...@@ -1539,7 +1545,7 @@ void tscFreeQueryInfo(SSqlCmd* pCmd, bool removeCachedMeta, uint64_t id) { ...@@ -1539,7 +1545,7 @@ void tscFreeQueryInfo(SSqlCmd* pCmd, bool removeCachedMeta, uint64_t id) {
} }
if (pQueryInfo->udfCopy) { if (pQueryInfo->udfCopy) {
pQueryInfo->pUdfInfo = taosArrayDestroy(pQueryInfo->pUdfInfo); pQueryInfo->pUdfInfo = taosArrayDestroy(&pQueryInfo->pUdfInfo);
} else { } else {
pQueryInfo->pUdfInfo = tscDestroyUdfArrayList(pQueryInfo->pUdfInfo); pQueryInfo->pUdfInfo = tscDestroyUdfArrayList(pQueryInfo->pUdfInfo);
} }
...@@ -1601,7 +1607,7 @@ void* tscCleanupTableMetaMap(SHashObj* pTableMetaMap) { ...@@ -1601,7 +1607,7 @@ void* tscCleanupTableMetaMap(SHashObj* pTableMetaMap) {
STableMetaVgroupInfo* p = taosHashIterate(pTableMetaMap, NULL); STableMetaVgroupInfo* p = taosHashIterate(pTableMetaMap, NULL);
while (p) { while (p) {
taosArrayDestroy(p->vgroupIdList); taosArrayDestroy(&p->vgroupIdList);
tfree(p->pTableMeta); tfree(p->pTableMeta);
p = taosHashIterate(pTableMetaMap, p); p = taosHashIterate(pTableMetaMap, p);
} }
...@@ -1794,7 +1800,7 @@ void* tscDestroyBlockArrayList(SSqlObj *pSql, SArray* pDataBlockList) { ...@@ -1794,7 +1800,7 @@ void* tscDestroyBlockArrayList(SSqlObj *pSql, SArray* pDataBlockList) {
tscDestroyDataBlock(pSql, d, false); tscDestroyDataBlock(pSql, d, false);
} }
taosArrayDestroy(pDataBlockList); taosArrayDestroy(&pDataBlockList);
return NULL; return NULL;
} }
...@@ -1833,7 +1839,7 @@ void* tscDestroyUdfArrayList(SArray* pUdfList) { ...@@ -1833,7 +1839,7 @@ void* tscDestroyUdfArrayList(SArray* pUdfList) {
freeUdfInfo(udf); freeUdfInfo(udf);
} }
taosArrayDestroy(pUdfList); taosArrayDestroy(&pUdfList);
return NULL; return NULL;
} }
...@@ -2469,7 +2475,7 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo) { ...@@ -2469,7 +2475,7 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo) {
} }
} }
taosArrayDestroy(pFieldInfo->internalField); taosArrayDestroy(&pFieldInfo->internalField);
tfree(pFieldInfo->final); tfree(pFieldInfo->final);
memset(pFieldInfo, 0, sizeof(SFieldInfo)); memset(pFieldInfo, 0, sizeof(SFieldInfo));
...@@ -2674,7 +2680,7 @@ void tscExprDestroy(SArray* pExprInfo) { ...@@ -2674,7 +2680,7 @@ void tscExprDestroy(SArray* pExprInfo) {
sqlExprDestroy(pExpr); sqlExprDestroy(pExpr);
} }
taosArrayDestroy(pExprInfo); taosArrayDestroy(&pExprInfo);
} }
int32_t tscExprCopy(SArray* dst, const SArray* src, uint64_t uid, bool deepcopy) { int32_t tscExprCopy(SArray* dst, const SArray* src, uint64_t uid, bool deepcopy) {
...@@ -2882,7 +2888,7 @@ void tscColumnListDestroy(SArray* pColumnList) { ...@@ -2882,7 +2888,7 @@ void tscColumnListDestroy(SArray* pColumnList) {
tscColumnDestroy(pCol); tscColumnDestroy(pCol);
} }
taosArrayDestroy(pColumnList); taosArrayDestroy(&pColumnList);
} }
/* /*
...@@ -3262,7 +3268,7 @@ void tscColCondRelease(SArray** pCond) { ...@@ -3262,7 +3268,7 @@ void tscColCondRelease(SArray** pCond) {
tfree(p->cond); tfree(p->cond);
} }
taosArrayDestroy(*pCond); taosArrayDestroy(pCond);
*pCond = NULL; *pCond = NULL;
} }
...@@ -3276,7 +3282,7 @@ void tscTagCondRelease(STagCond* pTagCond) { ...@@ -3276,7 +3282,7 @@ void tscTagCondRelease(STagCond* pTagCond) {
tfree(p->cond); tfree(p->cond);
} }
taosArrayDestroy(pTagCond->pCond); taosArrayDestroy(&pTagCond->pCond);
} }
for (int32_t i = 0; i < TSDB_MAX_JOIN_TABLE_NUM; ++i) { for (int32_t i = 0; i < TSDB_MAX_JOIN_TABLE_NUM; ++i) {
...@@ -3286,11 +3292,11 @@ void tscTagCondRelease(STagCond* pTagCond) { ...@@ -3286,11 +3292,11 @@ void tscTagCondRelease(STagCond* pTagCond) {
} }
if (node->tsJoin != NULL) { if (node->tsJoin != NULL) {
taosArrayDestroy(node->tsJoin); taosArrayDestroy(&node->tsJoin);
} }
if (node->tagJoin != NULL) { if (node->tagJoin != NULL) {
taosArrayDestroy(node->tagJoin); taosArrayDestroy(&node->tagJoin);
} }
tfree(node); tfree(node);
...@@ -3473,7 +3479,7 @@ static void freeQueryInfoImpl(SQueryInfo* pQueryInfo) { ...@@ -3473,7 +3479,7 @@ static void freeQueryInfoImpl(SQueryInfo* pQueryInfo) {
pQueryInfo->colList = NULL; pQueryInfo->colList = NULL;
if (pQueryInfo->groupbyExpr.columnInfo != NULL) { if (pQueryInfo->groupbyExpr.columnInfo != NULL) {
taosArrayDestroy(pQueryInfo->groupbyExpr.columnInfo); taosArrayDestroy(&pQueryInfo->groupbyExpr.columnInfo);
pQueryInfo->groupbyExpr.columnInfo = NULL; pQueryInfo->groupbyExpr.columnInfo = NULL;
pQueryInfo->groupbyExpr.numOfGroupCols = 0; pQueryInfo->groupbyExpr.numOfGroupCols = 0;
} }
...@@ -3485,7 +3491,7 @@ static void freeQueryInfoImpl(SQueryInfo* pQueryInfo) { ...@@ -3485,7 +3491,7 @@ static void freeQueryInfoImpl(SQueryInfo* pQueryInfo) {
pQueryInfo->fillType = 0; pQueryInfo->fillType = 0;
tfree(pQueryInfo->buf); tfree(pQueryInfo->buf);
taosArrayDestroy(pQueryInfo->pUpstream); taosArrayDestroy(&pQueryInfo->pUpstream);
pQueryInfo->pUpstream = NULL; pQueryInfo->pUpstream = NULL;
pQueryInfo->bufLen = 0; pQueryInfo->bufLen = 0;
} }
...@@ -3620,10 +3626,10 @@ void tscFreeVgroupTableInfo(SArray* pVgroupTables) { ...@@ -3620,10 +3626,10 @@ void tscFreeVgroupTableInfo(SArray* pVgroupTables) {
tfree(pInfo->vgInfo.epAddr[j].fqdn); tfree(pInfo->vgInfo.epAddr[j].fqdn);
} }
#endif #endif
taosArrayDestroy(pInfo->itemList); taosArrayDestroy(&pInfo->itemList);
} }
taosArrayDestroy(pVgroupTables); taosArrayDestroy(&pVgroupTables);
} }
void tscRemoveVgroupTableGroup(SArray* pVgroupTable, int32_t index) { void tscRemoveVgroupTableGroup(SArray* pVgroupTable, int32_t index) {
...@@ -3637,7 +3643,7 @@ void tscRemoveVgroupTableGroup(SArray* pVgroupTable, int32_t index) { ...@@ -3637,7 +3643,7 @@ void tscRemoveVgroupTableGroup(SArray* pVgroupTable, int32_t index) {
// tfree(pInfo->vgInfo.epAddr[j].fqdn); // tfree(pInfo->vgInfo.epAddr[j].fqdn);
// } // }
taosArrayDestroy(pInfo->itemList); taosArrayDestroy(&pInfo->itemList);
taosArrayRemove(pVgroupTable, index); taosArrayRemove(pVgroupTable, index);
} }
...@@ -5186,7 +5192,8 @@ int32_t tscCreateQueryFromQueryInfo(SQueryInfo* pQueryInfo, SQueryAttr* pQueryAt ...@@ -5186,7 +5192,8 @@ int32_t tscCreateQueryFromQueryInfo(SQueryInfo* pQueryInfo, SQueryAttr* pQueryAt
} }
// global aggregate query // global aggregate query
if (pQueryAttr->stableQuery && (pQueryAttr->simpleAgg || pQueryAttr->interval.interval > 0) && tscIsTwoStageSTableQuery(pQueryInfo, 0)) { if (pQueryAttr->stableQuery && (pQueryAttr->simpleAgg || pQueryAttr->interval.interval > 0 || pQueryAttr->sw.gap > 0)
&& tscIsTwoStageSTableQuery(pQueryInfo, 0)) {
createGlobalAggregateExpr(pQueryAttr, pQueryInfo); createGlobalAggregateExpr(pQueryAttr, pQueryInfo);
} }
...@@ -5452,7 +5459,7 @@ int parseJsontoTagData(char* json, SKVRowBuilder* kvRowBuilder, char* errMsg, in ...@@ -5452,7 +5459,7 @@ int parseJsontoTagData(char* json, SKVRowBuilder* kvRowBuilder, char* errMsg, in
varDataSetLen(nullTypeVal + CHAR_BYTES, INT_BYTES); varDataSetLen(nullTypeVal + CHAR_BYTES, INT_BYTES);
*(uint32_t*)(varDataVal(nullTypeKey)) = jsonNULL; *(uint32_t*)(varDataVal(nullTypeKey)) = jsonNULL;
tdAddColToKVRow(kvRowBuilder, jsonIndex++, TSDB_DATA_TYPE_NCHAR, nullTypeKey, false); // add json null type tdAddColToKVRow(kvRowBuilder, jsonIndex++, TSDB_DATA_TYPE_NCHAR, nullTypeKey, false); // add json null type
if (strtrim(json) == 0 || strcasecmp(json, "null") == 0){ if (!json || strtrim(json) == 0 || strcasecmp(json, "null") == 0){
*(uint32_t*)(varDataVal(nullTypeVal + CHAR_BYTES)) = jsonNULL; *(uint32_t*)(varDataVal(nullTypeVal + CHAR_BYTES)) = jsonNULL;
tdAddColToKVRow(kvRowBuilder, jsonIndex++, TSDB_DATA_TYPE_NCHAR, nullTypeVal, true); // add json null value tdAddColToKVRow(kvRowBuilder, jsonIndex++, TSDB_DATA_TYPE_NCHAR, nullTypeVal, true); // add json null value
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
...@@ -5514,10 +5521,10 @@ int parseJsontoTagData(char* json, SKVRowBuilder* kvRowBuilder, char* errMsg, in ...@@ -5514,10 +5521,10 @@ int parseJsontoTagData(char* json, SKVRowBuilder* kvRowBuilder, char* errMsg, in
char *tagVal = calloc(strlen(jsonValue) * TSDB_NCHAR_SIZE + TSDB_NCHAR_SIZE, 1); char *tagVal = calloc(strlen(jsonValue) * TSDB_NCHAR_SIZE + TSDB_NCHAR_SIZE, 1);
*tagVal = jsonType2DbType(0, item->type); // type *tagVal = jsonType2DbType(0, item->type); // type
char* tagData = POINTER_SHIFT(tagVal,CHAR_BYTES); char* tagData = POINTER_SHIFT(tagVal,CHAR_BYTES);
if (!taosMbsToUcs4(jsonValue, strlen(jsonValue), varDataVal(tagData), if (strlen(jsonValue) > 0 && !taosMbsToUcs4(jsonValue, strlen(jsonValue), varDataVal(tagData),
(int32_t)(strlen(jsonValue) * TSDB_NCHAR_SIZE), &outLen)) { (int32_t)(strlen(jsonValue) * TSDB_NCHAR_SIZE), &outLen)) {
tscError("json string error:%s|%s", strerror(errno), jsonValue); tscError("charset:%s to %s. val:%s, errno:%s, convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, jsonValue, strerror(errno));
retCode = tscSQLSyntaxErrMsg(errMsg, "serizelize json error", NULL); retCode = tscSQLSyntaxErrMsg(errMsg, "charset convert json error", NULL);
free(tagVal); free(tagVal);
goto end; goto end;
} }
......
...@@ -894,6 +894,6 @@ SMemRow mergeTwoMemRows(void *buffer, SMemRow row1, SMemRow row2, STSchema *pSch ...@@ -894,6 +894,6 @@ SMemRow mergeTwoMemRows(void *buffer, SMemRow row1, SMemRow row2, STSchema *pSch
} }
ASSERT(kvLen == memRowTLen(tRow)); ASSERT(kvLen == memRowTLen(tRow));
} }
taosArrayDestroy(stashRow); taosArrayDestroy(&stashRow);
return buffer; return buffer;
} }
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "tskiplist.h" #include "tskiplist.h"
#include "texpr.h" #include "texpr.h"
#include "tarithoperator.h" #include "tarithoperator.h"
#include "tulog.h"
static int32_t exprValidateMathNode(tExprNode *pExpr); static int32_t exprValidateMathNode(tExprNode *pExpr);
static int32_t exprValidateStringConcatNode(tExprNode *pExpr); static int32_t exprValidateStringConcatNode(tExprNode *pExpr);
...@@ -1274,6 +1275,11 @@ void castConvert(int16_t inputType, int16_t inputBytes, char *input, int16_t Out ...@@ -1274,6 +1275,11 @@ void castConvert(int16_t inputType, int16_t inputBytes, char *input, int16_t Out
} else if (inputType == TSDB_DATA_TYPE_NCHAR) { } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
char *newColData = calloc(1, outputBytes * TSDB_NCHAR_SIZE + 1); char *newColData = calloc(1, outputBytes * TSDB_NCHAR_SIZE + 1);
int len = taosUcs4ToMbs(varDataVal(input), varDataLen(input), newColData); int len = taosUcs4ToMbs(varDataVal(input), varDataLen(input), newColData);
if (len < 0){
uError("castConvert taosUcs4ToMbs error 1");
tfree(newColData);
return;
}
newColData[len] = 0; newColData[len] = 0;
*(int64_t *)output = strtoll(newColData, NULL, 10); *(int64_t *)output = strtoll(newColData, NULL, 10);
tfree(newColData); tfree(newColData);
...@@ -1291,6 +1297,11 @@ void castConvert(int16_t inputType, int16_t inputBytes, char *input, int16_t Out ...@@ -1291,6 +1297,11 @@ void castConvert(int16_t inputType, int16_t inputBytes, char *input, int16_t Out
} else if (inputType == TSDB_DATA_TYPE_NCHAR) { } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
char *newColData = calloc(1, outputBytes * TSDB_NCHAR_SIZE + 1); char *newColData = calloc(1, outputBytes * TSDB_NCHAR_SIZE + 1);
int len = taosUcs4ToMbs(varDataVal(input), varDataLen(input), newColData); int len = taosUcs4ToMbs(varDataVal(input), varDataLen(input), newColData);
if (len < 0){
uError("castConvert taosUcs4ToMbs error 2");
tfree(newColData);
return;
}
newColData[len] = 0; newColData[len] = 0;
*(int64_t *)output = strtoull(newColData, NULL, 10); *(int64_t *)output = strtoull(newColData, NULL, 10);
tfree(newColData); tfree(newColData);
...@@ -1332,11 +1343,19 @@ void castConvert(int16_t inputType, int16_t inputBytes, char *input, int16_t Out ...@@ -1332,11 +1343,19 @@ void castConvert(int16_t inputType, int16_t inputBytes, char *input, int16_t Out
if (inputType == TSDB_DATA_TYPE_BOOL) { if (inputType == TSDB_DATA_TYPE_BOOL) {
char tmp[8] = {0}; char tmp[8] = {0};
int32_t len = sprintf(tmp, "%.*s", ncharSize, *(int8_t*)input ? "true" : "false"); int32_t len = sprintf(tmp, "%.*s", ncharSize, *(int8_t*)input ? "true" : "false");
taosMbsToUcs4(tmp, len, varDataVal(output), outputBytes - VARSTR_HEADER_SIZE, &len); bool ret = taosMbsToUcs4(tmp, len, varDataVal(output), outputBytes - VARSTR_HEADER_SIZE, &len);
if(!ret) {
uError("castConvert1 taosMbsToUcs4 error");
return;
}
varDataSetLen(output, len); varDataSetLen(output, len);
} else if (inputType == TSDB_DATA_TYPE_BINARY) { } else if (inputType == TSDB_DATA_TYPE_BINARY) {
int32_t len = ncharSize > varDataLen(input) ? varDataLen(input) : ncharSize; int32_t len = ncharSize > varDataLen(input) ? varDataLen(input) : ncharSize;
taosMbsToUcs4(input + VARSTR_HEADER_SIZE, len, varDataVal(output), outputBytes - VARSTR_HEADER_SIZE, &len); bool ret = taosMbsToUcs4(input + VARSTR_HEADER_SIZE, len, varDataVal(output), outputBytes - VARSTR_HEADER_SIZE, &len);
if(!ret) {
uError("castConvert2 taosMbsToUcs4 error");
return;
}
varDataSetLen(output, len); varDataSetLen(output, len);
} else if (inputType == TSDB_DATA_TYPE_TIMESTAMP) { } else if (inputType == TSDB_DATA_TYPE_TIMESTAMP) {
assert(0); assert(0);
...@@ -1348,7 +1367,11 @@ void castConvert(int16_t inputType, int16_t inputBytes, char *input, int16_t Out ...@@ -1348,7 +1367,11 @@ void castConvert(int16_t inputType, int16_t inputBytes, char *input, int16_t Out
char tmp[400] = {0}; char tmp[400] = {0};
NUM_TO_STRING(inputType, input, sizeof(tmp), tmp); NUM_TO_STRING(inputType, input, sizeof(tmp), tmp);
int32_t len = (int32_t)(ncharSize > strlen(tmp) ? strlen(tmp) : ncharSize); int32_t len = (int32_t)(ncharSize > strlen(tmp) ? strlen(tmp) : ncharSize);
taosMbsToUcs4(tmp, len, varDataVal(output), outputBytes - VARSTR_HEADER_SIZE, &len); bool ret = taosMbsToUcs4(tmp, len, varDataVal(output), outputBytes - VARSTR_HEADER_SIZE, &len);
if(!ret) {
uError("castConvert3 taosMbsToUcs4 error");
return;
}
varDataSetLen(output, len); varDataSetLen(output, len);
} }
break; break;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "ttype.h" #include "ttype.h"
#include "tutil.h" #include "tutil.h"
#include "tvariant.h" #include "tvariant.h"
#include "tulog.h"
#define SET_EXT_INFO(converted, res, minv, maxv, exti) do { \ #define SET_EXT_INFO(converted, res, minv, maxv, exti) do { \
if (converted == NULL || exti == NULL || *converted == false) { break; } \ if (converted == NULL || exti == NULL || *converted == false) { break; } \
...@@ -222,11 +223,9 @@ void tVariantDestroy(tVariant *pVar) { ...@@ -222,11 +223,9 @@ void tVariantDestroy(tVariant *pVar) {
void* p = taosArrayGetP(pVar->arr, i); void* p = taosArrayGetP(pVar->arr, i);
free(p); free(p);
} }
taosArrayDestroy(pVar->arr); taosArrayDestroy(&pVar->arr);
pVar->arr = NULL;
} else if (pVar->nType == TSDB_DATA_TYPE_VALUE_ARRAY) { } else if (pVar->nType == TSDB_DATA_TYPE_VALUE_ARRAY) {
taosArrayDestroy(pVar->arr); taosArrayDestroy(&pVar->arr);
pVar->arr = NULL;
} }
} }
...@@ -361,8 +360,12 @@ int32_t tVariantToString(tVariant *pVar, char *dst) { ...@@ -361,8 +360,12 @@ int32_t tVariantToString(tVariant *pVar, char *dst) {
case TSDB_DATA_TYPE_NCHAR: { case TSDB_DATA_TYPE_NCHAR: {
dst[0] = '\''; dst[0] = '\'';
taosUcs4ToMbs(pVar->wpz, (twcslen(pVar->wpz) + 1) * TSDB_NCHAR_SIZE, dst + 1); int32_t len = taosUcs4ToMbs(pVar->wpz, (twcslen(pVar->wpz) + 1) * TSDB_NCHAR_SIZE, dst + 1);
int32_t len = (int32_t)strlen(dst); if (len < 0){
uError("castConvert1 taosUcs4ToMbs error");
return 0 ;
}
len = (int32_t)strlen(dst);
dst[len] = '\''; dst[len] = '\'';
dst[len + 1] = 0; dst[len + 1] = 0;
return len + 1; return len + 1;
...@@ -430,11 +433,17 @@ static int32_t toBinary(tVariant *pVariant, char **pDest, int32_t *pDestSize) { ...@@ -430,11 +433,17 @@ static int32_t toBinary(tVariant *pVariant, char **pDest, int32_t *pDestSize) {
pBuf = realloc(pBuf, newSize + 1); pBuf = realloc(pBuf, newSize + 1);
} }
taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, pBuf); int32_t len = taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, pBuf);
if (len < 0){
uError("castConvert1 taosUcs4ToMbs error");
}
free(pVariant->wpz); free(pVariant->wpz);
pBuf[newSize] = 0; pBuf[newSize] = 0;
} else { } else {
taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, *pDest); int32_t len = taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, *pDest);
if (len < 0){
uError("castConvert1 taosUcs4ToMbs error");
}
} }
} else { } else {
...@@ -944,7 +953,7 @@ int32_t tVariantDumpEx(tVariant *pVariant, char *payload, int16_t type, bool inc ...@@ -944,7 +953,7 @@ int32_t tVariantDumpEx(tVariant *pVariant, char *payload, int16_t type, bool inc
break; break;
} }
case TSDB_DATA_TYPE_JSON:{ case TSDB_DATA_TYPE_JSON:{
if (pVariant->nType == TSDB_DATA_TYPE_BINARY){ if (pVariant->nType == TSDB_DATA_TYPE_BINARY || pVariant->nType == TSDB_DATA_TYPE_NULL){
*((int8_t *)payload) = TSDB_DATA_JSON_PLACEHOLDER; *((int8_t *)payload) = TSDB_DATA_JSON_PLACEHOLDER;
} else if (pVariant->nType == TSDB_DATA_TYPE_JSON){ // select * from stable, set tag type to json,from setTagValue/tag_project_function } else if (pVariant->nType == TSDB_DATA_TYPE_JSON){ // select * from stable, set tag type to json,from setTagValue/tag_project_function
memcpy(payload, pVariant->pz, pVariant->nLen); memcpy(payload, pVariant->pz, pVariant->nLen);
......
...@@ -398,5 +398,8 @@ namespace TDengineDriver ...@@ -398,5 +398,8 @@ namespace TDengineDriver
IntPtr stmtErrPrt = StmtErrPtr(stmt); IntPtr stmtErrPrt = StmtErrPtr(stmt);
return Marshal.PtrToStringAnsi(stmtErrPrt); return Marshal.PtrToStringAnsi(stmtErrPrt);
} }
[DllImport("taos", EntryPoint = "taos_fetch_lengths", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr FetchLengths(IntPtr taos);
} }
} }
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
namespace TDengineDriver namespace TDengineDriver
...@@ -249,7 +250,8 @@ namespace TDengineDriver ...@@ -249,7 +250,8 @@ namespace TDengineDriver
TAOS_BIND bind = new TAOS_BIND(); TAOS_BIND bind = new TAOS_BIND();
IntPtr umanageBinary = Marshal.StringToHGlobalAnsi(val); IntPtr umanageBinary = Marshal.StringToHGlobalAnsi(val);
int leng = val.Length; var strToBytes = System.Text.Encoding.Default.GetBytes(val);
int leng = strToBytes.Length;
IntPtr lenPtr = Marshal.AllocHGlobal(sizeof(ulong)); IntPtr lenPtr = Marshal.AllocHGlobal(sizeof(ulong));
Marshal.WriteInt64(lenPtr, leng); Marshal.WriteInt64(lenPtr, leng);
...@@ -264,9 +266,11 @@ namespace TDengineDriver ...@@ -264,9 +266,11 @@ namespace TDengineDriver
public static TAOS_BIND BindNchar(String val) public static TAOS_BIND BindNchar(String val)
{ {
TAOS_BIND bind = new TAOS_BIND(); TAOS_BIND bind = new TAOS_BIND();
var strToBytes = System.Text.Encoding.Default.GetBytes(val);
IntPtr umanageNchar = (IntPtr)Marshal.StringToHGlobalAnsi(val); IntPtr umanageNchar = (IntPtr)Marshal.StringToHGlobalAnsi(val);
int leng = val.Length;
int leng = strToBytes.Length;
IntPtr lenPtr = Marshal.AllocHGlobal(sizeof(ulong)); IntPtr lenPtr = Marshal.AllocHGlobal(sizeof(ulong));
Marshal.WriteInt64(lenPtr, leng); Marshal.WriteInt64(lenPtr, leng);
......
...@@ -449,28 +449,27 @@ namespace TDengineDriver ...@@ -449,28 +449,27 @@ namespace TDengineDriver
for (int i = 0; i < elementCount; i++) for (int i = 0; i < elementCount; i++)
{ {
int itemLength = 0; int itemLength = 0;
byte[] decodeByte = GetStringEncodeByte(arr[i]);
itemLength = decodeByte.Length;
// if element if not null and element length is less then typeSize // if element if not null and element length is less then typeSize
// fill the memory with default char.Since arr element memory need align. // fill the memory with default char.Since arr element memory need align.
if (!String.IsNullOrEmpty(arr[i]) && typeSize <= arr[i].Length) if (!String.IsNullOrEmpty(arr[i]) && typeSize == itemLength)
{ {
itemLength = arr[i].Length;
arrStrBuilder.Append(arr[i]); arrStrBuilder.Append(arr[i]);
} }
else if (!String.IsNullOrEmpty(arr[i]) && typeSize > arr[i].Length) else if (!String.IsNullOrEmpty(arr[i]) && typeSize > itemLength)
{ {
itemLength = arr[i].Length;
arrStrBuilder.Append(arr[i]); arrStrBuilder.Append(arr[i]);
arrStrBuilder.Append(AlignCharArr(typeSize - arr[i].Length)); arrStrBuilder.Append(AlignCharArr(typeSize - itemLength));
} }
else else
{ {
// if is null value,fill the memory with default values. // if is null value,fill the memory with default values.
itemLength = 0;
arrStrBuilder.Append(AlignCharArr(typeSize)); arrStrBuilder.Append(AlignCharArr(typeSize));
} }
//set TAOS_MULTI_BIND.length //set TAOS_MULTI_BIND.length
Marshal.WriteInt32(lengthArr, intSize * i, itemLength); Marshal.WriteInt32(lengthArr, intSize * i, typeSize);
//set TAOS_MULTI_BIND.is_null //set TAOS_MULTI_BIND.is_null
Marshal.WriteByte(nullArr, byteSize * i, Convert.ToByte(String.IsNullOrEmpty(arr[i]) ? 1 : 0)); Marshal.WriteByte(nullArr, byteSize * i, Convert.ToByte(String.IsNullOrEmpty(arr[i]) ? 1 : 0));
} }
...@@ -505,28 +504,27 @@ namespace TDengineDriver ...@@ -505,28 +504,27 @@ namespace TDengineDriver
for (int i = 0; i < elementCount; i++) for (int i = 0; i < elementCount; i++)
{ {
int itemLength = 0; int itemLength = 0;
byte[] decodeByte = GetStringEncodeByte(arr[i]);
itemLength = decodeByte.Length;
// if element if not null and element length is less then typeSize // if element if not null and element length is less then typeSize
// fill the memory with default char.Since arr element memory need align. // fill the memory with default char.Since arr element memory need align.
if (!String.IsNullOrEmpty(arr[i]) && typeSize <= arr[i].Length) if (!String.IsNullOrEmpty(arr[i]) && typeSize == itemLength)
{ {
itemLength = arr[i].Length;
arrStrBuilder.Append(arr[i]); arrStrBuilder.Append(arr[i]);
} }
else if (!String.IsNullOrEmpty(arr[i]) && typeSize > arr[i].Length) else if (!String.IsNullOrEmpty(arr[i]) && typeSize > itemLength)
{ {
itemLength = arr[i].Length;
arrStrBuilder.Append(arr[i]); arrStrBuilder.Append(arr[i]);
arrStrBuilder.Append(AlignCharArr(typeSize - arr[i].Length)); arrStrBuilder.Append(AlignCharArr(typeSize - itemLength));
} }
else else
{ {
// if is null value,fill the memory with default values. // if is null value,fill the memory with default values.
itemLength = 0;
arrStrBuilder.Append(AlignCharArr(typeSize)); arrStrBuilder.Append(AlignCharArr(typeSize));
} }
//set TAOS_MULTI_BIND.length //set TAOS_MULTI_BIND.length
Marshal.WriteInt32(lengthArr, intSize * i, itemLength); Marshal.WriteInt32(lengthArr, intSize * i, typeSize);
//set TAOS_MULTI_BIND.is_null //set TAOS_MULTI_BIND.is_null
Marshal.WriteByte(nullArr, byteSize * i, Convert.ToByte(String.IsNullOrEmpty(arr[i]) ? 1 : 0)); Marshal.WriteByte(nullArr, byteSize * i, Convert.ToByte(String.IsNullOrEmpty(arr[i]) ? 1 : 0));
} }
...@@ -604,13 +602,28 @@ namespace TDengineDriver ...@@ -604,13 +602,28 @@ namespace TDengineDriver
int max = 0; int max = 0;
for (int i = 0; i < strArr.Length; i++) for (int i = 0; i < strArr.Length; i++)
{ {
if (!String.IsNullOrEmpty(strArr[i]) && max < strArr[i].Length) int tmpLength = GetStringEncodeByte(strArr[i]).Length;
if (!String.IsNullOrEmpty(strArr[i]) && max < tmpLength)
{ {
max = strArr[i].Length; max = tmpLength;
} }
} }
return max; return max;
} }
private static Byte[] GetStringEncodeByte(string str)
{
Byte[] strToBytes = null;
if(String.IsNullOrEmpty(str))
{
strToBytes = System.Text.Encoding.Default.GetBytes(String.Empty);
}
else
{
strToBytes = System.Text.Encoding.Default.GetBytes(str);
}
return strToBytes;
}
} }
} }
\ No newline at end of file
...@@ -9,4 +9,8 @@ ...@@ -9,4 +9,8 @@
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<DocumentationFile>..\doc\FunctionTest.XML</DocumentationFile>
</PropertyGroup>
</Project> </Project>
...@@ -21,7 +21,8 @@ namespace Test.UtilsTools.DataSource ...@@ -21,7 +21,8 @@ namespace Test.UtilsTools.DataSource
public static string[] binaryArr = new string[5] { "1234567890~!@#$%^&*()_+=-`[]{}:,./<>?", String.Empty, null, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890~!@#$%^&*()_+=-`[]{}:,./<>?" }; public static string[] binaryArr = new string[5] { "1234567890~!@#$%^&*()_+=-`[]{}:,./<>?", String.Empty, null, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890~!@#$%^&*()_+=-`[]{}:,./<>?" };
public static string[] ncharArr = new string[5] { "1234567890~!@#$%^&*()_+=-`[]{}:,./<>?", null, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890~!@#$%^&*()_+=-`[]{}:,./<>?", string.Empty }; public static string[] ncharArr = new string[5] { "1234567890~!@#$%^&*()_+=-`[]{}:,./<>?", null, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890~!@#$%^&*()_+=-`[]{}:,./<>?", string.Empty };
public static string[] binaryArrCn = new string[5] { "涛思数据", String.Empty, null, "taosdata涛思数据", "涛思数据TDengine" };
public static string[] NcharArrCn = new string[5] { "涛思数据", null, "taosdata涛思数据", "涛思数据TDengine", String.Empty };
public static TAOS_BIND[] getTags() public static TAOS_BIND[] getTags()
{ {
TAOS_BIND[] binds = new TAOS_BIND[13]; TAOS_BIND[] binds = new TAOS_BIND[13];
...@@ -40,6 +41,47 @@ namespace Test.UtilsTools.DataSource ...@@ -40,6 +41,47 @@ namespace Test.UtilsTools.DataSource
binds[12] = TaosBind.BindNchar("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKZXCVBNM`1234567890-=+_)(*&^%$#@!~[];,./<>?:{}"); binds[12] = TaosBind.BindNchar("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKZXCVBNM`1234567890-=+_)(*&^%$#@!~[];,./<>?:{}");
return binds; return binds;
} }
public static TAOS_BIND[] getCNTags()
{
TAOS_BIND[] binds = new TAOS_BIND[13];
binds[0] = TaosBind.BindBool(true);
binds[1] = TaosBind.BindTinyInt(-2);
binds[2] = TaosBind.BindSmallInt(short.MaxValue - 1);
binds[3] = TaosBind.BindInt(int.MaxValue - 1);
binds[4] = TaosBind.BindBigInt(Int64.MaxValue - 1);
binds[5] = TaosBind.BindUTinyInt(byte.MaxValue - 1);
binds[6] = TaosBind.BindUSmallInt(UInt16.MaxValue - 1);
binds[7] = TaosBind.BindUInt(uint.MinValue + 1);
binds[8] = TaosBind.BindUBigInt(UInt64.MinValue + 1);
binds[9] = TaosBind.BindFloat(11.11F);
binds[10] = TaosBind.BindDouble(22.22D);
binds[11] = TaosBind.BindBinary("TDengine涛思数据");
binds[12] = TaosBind.BindNchar("涛思");
return binds;
}
public static TAOS_BIND[] getNtableCNRow()
{
TAOS_BIND[] binds = new TAOS_BIND[15];
binds[0] = TaosBind.BindTimestamp(1637064040000);
binds[1] = TaosBind.BindTinyInt(-2);
binds[2] = TaosBind.BindSmallInt(short.MaxValue);
binds[3] = TaosBind.BindInt(int.MaxValue);
binds[4] = TaosBind.BindBigInt(Int64.MaxValue);
binds[5] = TaosBind.BindUTinyInt(byte.MaxValue - 1);
binds[6] = TaosBind.BindUSmallInt(UInt16.MaxValue - 1);
binds[7] = TaosBind.BindUInt(uint.MinValue + 1);
binds[8] = TaosBind.BindUBigInt(UInt64.MinValue + 1);
binds[9] = TaosBind.BindFloat(11.11F);
binds[10] = TaosBind.BindDouble(22.22D);
binds[11] = TaosBind.BindBinary("TDengine数据");
binds[12] = TaosBind.BindNchar("taosdata涛思数据");
binds[13] = TaosBind.BindBool(true);
binds[14] = TaosBind.BindNil();
return binds;
}
public static TAOS_BIND[] getNtableRow() public static TAOS_BIND[] getNtableRow()
{ {
TAOS_BIND[] binds = new TAOS_BIND[15]; TAOS_BIND[] binds = new TAOS_BIND[15];
...@@ -60,7 +102,6 @@ namespace Test.UtilsTools.DataSource ...@@ -60,7 +102,6 @@ namespace Test.UtilsTools.DataSource
binds[14] = TaosBind.BindNil(); binds[14] = TaosBind.BindNil();
return binds; return binds;
} }
public static TAOS_MULTI_BIND[] GetMultiBindArr() public static TAOS_MULTI_BIND[] GetMultiBindArr()
{ {
TAOS_MULTI_BIND[] mBinds = new TAOS_MULTI_BIND[14]; TAOS_MULTI_BIND[] mBinds = new TAOS_MULTI_BIND[14];
...@@ -80,6 +121,26 @@ namespace Test.UtilsTools.DataSource ...@@ -80,6 +121,26 @@ namespace Test.UtilsTools.DataSource
mBinds[13] = TaosMultiBind.MultiBindNchar(ncharArr); mBinds[13] = TaosMultiBind.MultiBindNchar(ncharArr);
return mBinds; return mBinds;
} }
public static TAOS_MULTI_BIND[] GetMultiBindCNArr()
{
TAOS_MULTI_BIND[] mBinds = new TAOS_MULTI_BIND[14];
mBinds[0] = TaosMultiBind.MultiBindTimestamp(tsArr);
mBinds[1] = TaosMultiBind.MultiBindBool(boolArr);
mBinds[2] = TaosMultiBind.MultiBindTinyInt(tinyIntArr);
mBinds[3] = TaosMultiBind.MultiBindSmallInt(shortArr);
mBinds[4] = TaosMultiBind.MultiBindInt(intArr);
mBinds[5] = TaosMultiBind.MultiBindBigint(longArr);
mBinds[6] = TaosMultiBind.MultiBindFloat(floatArr);
mBinds[7] = TaosMultiBind.MultiBindDouble(doubleArr);
mBinds[8] = TaosMultiBind.MultiBindUTinyInt(uTinyIntArr);
mBinds[9] = TaosMultiBind.MultiBindUSmallInt(uShortArr);
mBinds[10] = TaosMultiBind.MultiBindUInt(uIntArr);
mBinds[11] = TaosMultiBind.MultiBindUBigInt(uLongArr);
mBinds[12] = TaosMultiBind.MultiBindBinary(binaryArrCn);
mBinds[13] = TaosMultiBind.MultiBindNchar(NcharArrCn);
return mBinds;
}
public static TAOS_BIND[] GetQueryCondition() public static TAOS_BIND[] GetQueryCondition()
{ {
TAOS_BIND[] queryCondition = new TAOS_BIND[2]; TAOS_BIND[] queryCondition = new TAOS_BIND[2];
......
using System;
using Test.UtilsTools;
using System.Collections.Generic;
namespace Cases
{
public class FetchLengthCase
{
/// <author>xiaolei</author>
/// <Name>TestRetrieveBinary</Name>
/// <describe>TD-12103 C# connector fetch_row with binary data retrieving error</describe>
/// <filename>FetchLength.cs</filename>
/// <result>pass or failed </result>
public void TestRetrieveBinary(IntPtr conn)
{
string sql1 = "create stable stb1 (ts timestamp, name binary(10)) tags(n int);";
string sql2 = "insert into tb1 using stb1 tags(1) values(now, 'log');";
string sql3 = "insert into tb2 using stb1 tags(2) values(now, 'test');";
string sql4 = "insert into tb3 using stb1 tags(3) values(now, 'db02');";
string sql5 = "insert into tb4 using stb1 tags(4) values(now, 'db3');";
string sql6 = "select distinct(name) from stb1;";//
UtilsTools.ExecuteQuery(conn, sql1);
UtilsTools.ExecuteQuery(conn, sql2);
UtilsTools.ExecuteQuery(conn, sql3);
UtilsTools.ExecuteQuery(conn, sql4);
UtilsTools.ExecuteQuery(conn, sql5);
IntPtr resPtr = IntPtr.Zero;
resPtr = UtilsTools.ExecuteQuery(conn, sql6);
List<List<string>> result = UtilsTools.GetResultSet(resPtr);
List<string> colname = result[0];
List<string> data = result[1];
UtilsTools.AssertEqual("db3", data[0]);
UtilsTools.AssertEqual("log", data[1]);
UtilsTools.AssertEqual("db02", data[2]);
UtilsTools.AssertEqual("test", data[3]);
}
}
}
using System; using System;
using Test.UtilsTools; using Test.UtilsTools;
using Cases; using Cases;
namespace Cases.EntryPoint namespace Cases.EntryPoint
{ {
class Program class Program
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
IntPtr conn = IntPtr.Zero; IntPtr conn = IntPtr.Zero;
IntPtr stmt = IntPtr.Zero; IntPtr stmt = IntPtr.Zero;
IntPtr res = IntPtr.Zero; IntPtr res = IntPtr.Zero;
conn = UtilsTools.TDConnection("127.0.0.1", "root", "taosdata", "", 0); conn = UtilsTools.TDConnection("127.0.0.1", "root", "taosdata", "", 0);
UtilsTools.ExecuteQuery(conn, "drop database if exists csharp"); UtilsTools.ExecuteUpdate(conn, "drop database if exists csharp");
UtilsTools.ExecuteQuery(conn, "create database if not exists csharp keep 3650"); UtilsTools.ExecuteUpdate(conn, "create database if not exists csharp keep 3650");
UtilsTools.ExecuteQuery(conn, "use csharp"); UtilsTools.ExecuteUpdate(conn, "use csharp");
Console.WriteLine("====================StableColumnByColumn==================="); Console.WriteLine("====================StableColumnByColumn===================");
StableColumnByColumn columnByColumn = new StableColumnByColumn(); StableColumnByColumn columnByColumn = new StableColumnByColumn();
columnByColumn.Test(conn, "stablecolumnbycolumn"); columnByColumn.Test(conn, "stablecolumnbycolumn");
Console.WriteLine("====================StmtStableQuery==================="); Console.WriteLine("====================StmtStableQuery===================");
StmtStableQuery stmtStableQuery = new StmtStableQuery(); StmtStableQuery stmtStableQuery = new StmtStableQuery();
stmtStableQuery.Test(conn, "stablecolumnbycolumn"); stmtStableQuery.Test(conn, "stablecolumnbycolumn");
Console.WriteLine("====================StableMutipleLine==================="); Console.WriteLine("====================StableMutipleLine===================");
StableMutipleLine mutipleLine = new StableMutipleLine(); StableMutipleLine mutipleLine = new StableMutipleLine();
mutipleLine.Test(conn, "stablemutipleline"); mutipleLine.Test(conn, "stablemutipleline");
//================================================================================ //================================================================================
Console.WriteLine("====================NtableSingleLine==================="); Console.WriteLine("====================NtableSingleLine===================");
NtableSingleLine ntableSingleLine = new NtableSingleLine(); NtableSingleLine ntableSingleLine = new NtableSingleLine();
ntableSingleLine.Test(conn, "stablesingleline"); ntableSingleLine.Test(conn, "stablesingleline");
IntPtr resPtr = UtilsTools.ExecuteQuery(conn, "select * from stablesingleline ");
Console.WriteLine("====================NtableMutipleLine==================="); UtilsTools.DisplayRes(resPtr);
NtableMutipleLine ntableMutipleLine = new NtableMutipleLine();
ntableMutipleLine.Test(conn, "ntablemutipleline"); Console.WriteLine("====================NtableMutipleLine===================");
Console.WriteLine("====================StmtNtableQuery==================="); NtableMutipleLine ntableMutipleLine = new NtableMutipleLine();
StmtNtableQuery stmtNtableQuery = new StmtNtableQuery(); ntableMutipleLine.Test(conn, "ntablemutipleline");
stmtNtableQuery.Test(conn, "ntablemutipleline"); Console.WriteLine("====================StmtNtableQuery===================");
StmtNtableQuery stmtNtableQuery = new StmtNtableQuery();
Console.WriteLine("====================NtableColumnByColumn==================="); stmtNtableQuery.Test(conn, "ntablemutipleline");
NtableColumnByColumn ntableColumnByColumn = new NtableColumnByColumn();
ntableColumnByColumn.Test(conn, "ntablecolumnbycolumn"); Console.WriteLine("====================NtableColumnByColumn===================");
NtableColumnByColumn ntableColumnByColumn = new NtableColumnByColumn();
Console.WriteLine("====================fetchfeilds==================="); ntableColumnByColumn.Test(conn, "ntablecolumnbycolumn");
FetchFields fetchFields = new FetchFields();
fetchFields.Test(conn,"fetchfeilds"); Console.WriteLine("====================fetchfeilds===================");
FetchFields fetchFields = new FetchFields();
Console.WriteLine("===================JsonTagTest===================="); fetchFields.Test(conn, "fetchfeilds");
JsonTagTest jsonTagTest = new JsonTagTest();
jsonTagTest.Test(conn);
StableStmtCases stableStmtCases = new StableStmtCases();
// UtilsTools.ExecuteQuery(conn, "drop database if exists csharp"); Console.WriteLine("====================stableStmtCases.TestBindSingleLineCn===================");
UtilsTools.CloseConnection(conn); stableStmtCases.TestBindSingleLineCn(conn, "stablestmtcasestestbindsinglelinecn");
UtilsTools.ExitProgram();
Console.WriteLine("====================stableStmtCases.TestBindColumnCn===================");
stableStmtCases.TestBindColumnCn(conn, " stablestmtcasestestbindcolumncn");
}
} Console.WriteLine("====================stableStmtCases.TestBindMultiLineCn===================");
} stableStmtCases.TestBindMultiLineCn(conn, "stablestmtcasestestbindmultilinecn");
NormalTableStmtCases normalTableStmtCases = new NormalTableStmtCases();
Console.WriteLine("====================normalTableStmtCases.TestBindSingleLineCn===================");
normalTableStmtCases.TestBindSingleLineCn(conn, "normaltablestmtcasestestbindsinglelinecn");
Console.WriteLine("====================normalTableStmtCases.TestBindColumnCn===================");
normalTableStmtCases.TestBindColumnCn(conn, "normaltablestmtcasestestbindcolumncn");
Console.WriteLine("====================normalTableStmtCases.TestBindMultiLineCn===================");
normalTableStmtCases.TestBindMultiLineCn(conn, "normaltablestmtcasestestbindmultilinecn");
Console.WriteLine("===================JsonTagTest====================");
JsonTagTest jsonTagTest = new JsonTagTest();
jsonTagTest.Test(conn);
Console.WriteLine("====================fetchLengthCase===================");
FetchLengthCase fetchLengthCase = new FetchLengthCase();
fetchLengthCase.TestRetrieveBinary(conn);
UtilsTools.ExecuteQuery(conn, "drop database if exists csharp");
UtilsTools.CloseConnection(conn);
UtilsTools.ExitProgram();
}
}
}
...@@ -7,7 +7,11 @@ namespace Cases ...@@ -7,7 +7,11 @@ namespace Cases
{ {
public class NtableSingleLine public class NtableSingleLine
{ {
/// <author>xiaolei</author>
/// <Name>NtableSingleLine.Test</Name>
/// <describe>Test stmt insert sinle line data into normal table</describe>
/// <filename>StmtNormalTable.cs</filename>
/// <result>pass or failed </result>
public void Test(IntPtr conn, string tableName) public void Test(IntPtr conn, string tableName)
{ {
String createTb = "create table " + tableName + "(ts timestamp,tt tinyint,si smallint,ii int,bi bigint,tu tinyint unsigned,su smallint unsigned,iu int unsigned,bu bigint unsigned,ff float ,dd double ,bb binary(200),nc nchar(200),bo bool,nullVal int);"; String createTb = "create table " + tableName + "(ts timestamp,tt tinyint,si smallint,ii int,bi bigint,tu tinyint unsigned,su smallint unsigned,iu int unsigned,bu bigint unsigned,ff float ,dd double ,bb binary(200),nc nchar(200),bo bool,nullVal int);";
...@@ -23,21 +27,26 @@ namespace Cases ...@@ -23,21 +27,26 @@ namespace Cases
StmtUtilTools.StmtExecute(stmt); StmtUtilTools.StmtExecute(stmt);
StmtUtilTools.StmtClose(stmt); StmtUtilTools.StmtClose(stmt);
DataSource.FreeTaosBind(valuesRow); DataSource.FreeTaosBind(valuesRow);
} }
} }
public class NtableMutipleLine public class NtableMutipleLine
{ {
TAOS_MULTI_BIND[] mbind = DataSource.GetMultiBindArr(); /// <author>xiaolei</author>
/// <Name>NtableMutipleLine.Test</Name>
/// <describe>Test stmt insert multiple rows of data into normal table</describe>
/// <filename>StmtNormalTable.cs</filename>
/// <result>pass or failed </result>
public void Test(IntPtr conn, string tableName) public void Test(IntPtr conn, string tableName)
{ {
TAOS_MULTI_BIND[] mbind = DataSource.GetMultiBindArr();
String createTb = "create table " + tableName + " (ts timestamp ,b bool,v1 tinyint,v2 smallint,v4 int,v8 bigint,f4 float,f8 double,u1 tinyint unsigned,u2 smallint unsigned,u4 int unsigned,u8 bigint unsigned,bin binary(200),blob nchar(200));"; String createTb = "create table " + tableName + " (ts timestamp ,b bool,v1 tinyint,v2 smallint,v4 int,v8 bigint,f4 float,f8 double,u1 tinyint unsigned,u2 smallint unsigned,u4 int unsigned,u8 bigint unsigned,bin binary(200),blob nchar(200));";
String insertSql = "insert into ? values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; String insertSql = "insert into ? values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
UtilsTools.ExecuteQuery(conn, createTb); UtilsTools.ExecuteUpdate(conn, createTb);
String[] loadList = { tableName };
IntPtr stmt = StmtUtilTools.StmtInit(conn); IntPtr stmt = StmtUtilTools.StmtInit(conn);
StmtUtilTools.loadTableInfo(conn, loadList);
StmtUtilTools.StmtPrepare(stmt, insertSql); StmtUtilTools.StmtPrepare(stmt, insertSql);
StmtUtilTools.SetTableName(stmt, tableName); StmtUtilTools.SetTableName(stmt, tableName);
StmtUtilTools.BindParamBatch(stmt, mbind); StmtUtilTools.BindParamBatch(stmt, mbind);
...@@ -49,15 +58,20 @@ namespace Cases ...@@ -49,15 +58,20 @@ namespace Cases
} }
public class NtableColumnByColumn public class NtableColumnByColumn
{ {
DataSource data = new DataSource(); /// <author>xiaolei</author>
TAOS_MULTI_BIND[] mbind = DataSource.GetMultiBindArr(); /// <Name>NtableColumnByColumn.Test</Name>
/// <describe>Test stmt insert multiple rows of data into normal table by column after column </describe>
/// <filename>StmtNormalTable.cs</filename>
/// <result>pass or failed </result>
public void Test(IntPtr conn, string tableName) public void Test(IntPtr conn, string tableName)
{ {
DataSource data = new DataSource();
TAOS_MULTI_BIND[] mbind = DataSource.GetMultiBindArr();
String createTb = "create table " + tableName + " (ts timestamp ,b bool,v1 tinyint,v2 smallint,v4 int,v8 bigint,f4 float,f8 double,u1 tinyint unsigned,u2 smallint unsigned,u4 int unsigned,u8 bigint unsigned,bin binary(200),blob nchar(200));"; String createTb = "create table " + tableName + " (ts timestamp ,b bool,v1 tinyint,v2 smallint,v4 int,v8 bigint,f4 float,f8 double,u1 tinyint unsigned,u2 smallint unsigned,u4 int unsigned,u8 bigint unsigned,bin binary(200),blob nchar(200));";
String insertSql = "insert into ? values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; String insertSql = "insert into ? values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
UtilsTools.ExecuteQuery(conn, createTb); UtilsTools.ExecuteUpdate(conn, createTb);
IntPtr stmt = StmtUtilTools.StmtInit(conn); IntPtr stmt = StmtUtilTools.StmtInit(conn);
StmtUtilTools.StmtPrepare(stmt, insertSql); StmtUtilTools.StmtPrepare(stmt, insertSql);
...@@ -86,4 +100,106 @@ namespace Cases ...@@ -86,4 +100,106 @@ namespace Cases
} }
} }
public class NormalTableStmtCases
{
/// <author>xiaolei</author>
/// <Name>NormalTableStmtCases.TestBindSingleLineCn</Name>
/// <describe>Test stmt insert single line of chinese character into normal table by column after column </describe>
/// <filename>StmtNormalTable.cs</filename>
/// <result>pass or failed </result>
public void TestBindSingleLineCn(IntPtr conn, string tableName)
{
String createTb = "create table " + tableName + "(ts timestamp,tt tinyint,si smallint,ii int,bi bigint,tu tinyint unsigned,su smallint unsigned,iu int unsigned,bu bigint unsigned,ff float ,dd double ,bb binary(200),nc nchar(200),bo bool,nullVal int);";
String insertSql = "insert into ? values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
TAOS_BIND[] valuesRow = DataSource.getNtableCNRow();
UtilsTools.ExecuteUpdate(conn, createTb);
IntPtr stmt = StmtUtilTools.StmtInit(conn);
StmtUtilTools.StmtPrepare(stmt, insertSql);
StmtUtilTools.SetTableName(stmt, tableName);
StmtUtilTools.BindParam(stmt, valuesRow);
StmtUtilTools.AddBatch(stmt);
StmtUtilTools.StmtExecute(stmt);
StmtUtilTools.StmtClose(stmt);
DataSource.FreeTaosBind(valuesRow);
string querySql = "select * from " + tableName;
IntPtr res = UtilsTools.ExecuteQuery(conn, querySql);
UtilsTools.DisplayRes(res);
}
/// <author>xiaolei</author>
/// <Name>NormalTableStmtCases.TestBindColumnCn</Name>
/// <describe>Test stmt insert single line of chinese character into normal table by column after column </describe>
/// <filename>StmtNormalTable.cs</filename>
/// <result>pass or failed </result>
public void TestBindColumnCn(IntPtr conn,string tableName)
{
DataSource data = new DataSource();
TAOS_MULTI_BIND[] mbind = DataSource.GetMultiBindCNArr();
String createTb = "create table " + tableName + " (ts timestamp ,b bool,v1 tinyint,v2 smallint,v4 int,v8 bigint,f4 float,f8 double,u1 tinyint unsigned,u2 smallint unsigned,u4 int unsigned,u8 bigint unsigned,bin binary(200),blob nchar(200));";
String insertSql = "insert into ? values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
UtilsTools.ExecuteUpdate(conn, createTb);
IntPtr stmt = StmtUtilTools.StmtInit(conn);
StmtUtilTools.StmtPrepare(stmt, insertSql);
StmtUtilTools.SetTableName(stmt, tableName);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[0], 0);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[1], 1);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[2], 2);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[3], 3);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[4], 4);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[5], 5);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[6], 6);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[7], 7);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[8], 8);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[9], 9);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[10], 10);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[11], 11);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[12], 12);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[13], 13);
StmtUtilTools.AddBatch(stmt);
StmtUtilTools.StmtExecute(stmt);
StmtUtilTools.StmtClose(stmt);
DataSource.FreeTaosMBind(mbind);
string querySql = "select * from " + tableName;
IntPtr res = UtilsTools.ExecuteQuery(conn, querySql);
UtilsTools.DisplayRes(res);
}
/// <author>xiaolei</author>
/// <Name>NormalTableStmtCases.TestBindMultiLineCn</Name>
/// <describe>Test stmt insert single line of chinese character into normal table by column after column </describe>
/// <filename>StmtNormalTable.cs</filename>
/// <result>pass or failed </result>
public void TestBindMultiLineCn(IntPtr conn, string tableName)
{
TAOS_MULTI_BIND[] mbind = DataSource.GetMultiBindCNArr();
String createTb = "create table " + tableName + " (ts timestamp ,b bool,v1 tinyint,v2 smallint,v4 int,v8 bigint,f4 float,f8 double,u1 tinyint unsigned,u2 smallint unsigned,u4 int unsigned,u8 bigint unsigned,bin binary(200),blob nchar(200));";
String insertSql = "insert into ? values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
UtilsTools.ExecuteUpdate(conn, createTb);
IntPtr stmt = StmtUtilTools.StmtInit(conn);
StmtUtilTools.StmtPrepare(stmt, insertSql);
StmtUtilTools.SetTableName(stmt, tableName);
StmtUtilTools.BindParamBatch(stmt, mbind);
StmtUtilTools.AddBatch(stmt);
StmtUtilTools.StmtExecute(stmt);
StmtUtilTools.StmtClose(stmt);
DataSource.FreeTaosMBind(mbind);
string querySql = "select * from " + tableName;
IntPtr res = UtilsTools.ExecuteQuery(conn, querySql);
UtilsTools.DisplayRes(res);
}
}
} }
\ No newline at end of file
...@@ -15,10 +15,8 @@ namespace Cases ...@@ -15,10 +15,8 @@ namespace Cases
String createTb = "create stable " + tableName + " (ts timestamp ,b bool,v1 tinyint,v2 smallint,v4 int,v8 bigint,f4 float,f8 double,u1 tinyint unsigned,u2 smallint unsigned,u4 int unsigned,u8 bigint unsigned,bin binary(200),blob nchar(200))tags(bo bool,tt tinyint,si smallint,ii int,bi bigint,tu tinyint unsigned,su smallint unsigned,iu int unsigned,bu bigint unsigned,ff float ,dd double ,bb binary(200),nc nchar(200));"; String createTb = "create stable " + tableName + " (ts timestamp ,b bool,v1 tinyint,v2 smallint,v4 int,v8 bigint,f4 float,f8 double,u1 tinyint unsigned,u2 smallint unsigned,u4 int unsigned,u8 bigint unsigned,bin binary(200),blob nchar(200))tags(bo bool,tt tinyint,si smallint,ii int,bi bigint,tu tinyint unsigned,su smallint unsigned,iu int unsigned,bu bigint unsigned,ff float ,dd double ,bb binary(200),nc nchar(200));";
String insertSql = "insert into ? using " + tableName + " tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; String insertSql = "insert into ? using " + tableName + " tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
UtilsTools.ExecuteQuery(conn, createTb); UtilsTools.ExecuteUpdate(conn, createTb);
String[] loadList = { tableName };
IntPtr stmt = StmtUtilTools.StmtInit(conn); IntPtr stmt = StmtUtilTools.StmtInit(conn);
StmtUtilTools.loadTableInfo(conn, loadList);
StmtUtilTools.StmtPrepare(stmt, insertSql); StmtUtilTools.StmtPrepare(stmt, insertSql);
StmtUtilTools.SetTableNameTags(stmt, tableName + "_t1", tags); StmtUtilTools.SetTableNameTags(stmt, tableName + "_t1", tags);
...@@ -43,9 +41,8 @@ namespace Cases ...@@ -43,9 +41,8 @@ namespace Cases
String insertSql = "insert into ? using " + tableName + " tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; String insertSql = "insert into ? using " + tableName + " tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
UtilsTools.ExecuteQuery(conn, createTb); UtilsTools.ExecuteUpdate(conn, createTb);
IntPtr stmt = StmtUtilTools.StmtInit(conn); IntPtr stmt = StmtUtilTools.StmtInit(conn);
StmtUtilTools.StmtPrepare(stmt, insertSql); StmtUtilTools.StmtPrepare(stmt, insertSql);
StmtUtilTools.SetTableNameTags(stmt, tableName + "_t1", tags); StmtUtilTools.SetTableNameTags(stmt, tableName + "_t1", tags);
...@@ -73,4 +70,119 @@ namespace Cases ...@@ -73,4 +70,119 @@ namespace Cases
} }
} }
public class StableStmtCases
{
/// <author>xiaolei</author>
/// <Name>StableStmtCases.TestBindSingleLineCn</Name>
/// <describe>Test stmt insert single line of chinese character into stable by column after column </describe>
/// <filename>StmtSTable.cs</filename>
/// <result>pass or failed </result>
public void TestBindSingleLineCn(IntPtr conn, string tableName)
{
TAOS_BIND[] tags = DataSource.getCNTags();
TAOS_BIND[] binds = DataSource.getNtableCNRow();
String createTb = "create stable " + tableName + " (ts timestamp,v1 tinyint,v2 smallint,v4 int,v8 bigint,u1 tinyint unsigned,u2 smallint unsigned,u4 int unsigned,u8 bigint unsigned,f4 float,f8 double,bin binary(200),blob nchar(200),b bool,nilcol int)tags(bo bool,tt tinyint,si smallint,ii int,bi bigint,tu tinyint unsigned,su smallint unsigned,iu int unsigned,bu bigint unsigned,ff float ,dd double ,bb binary(200),nc nchar(200));";
String insertSql = "insert into ? using " + tableName + " tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
UtilsTools.ExecuteUpdate(conn, createTb);
IntPtr stmt = StmtUtilTools.StmtInit(conn);
StmtUtilTools.StmtPrepare(stmt, insertSql);
StmtUtilTools.SetTableNameTags(stmt, tableName + "_t1", tags);
StmtUtilTools.BindParam(stmt, binds);
StmtUtilTools.AddBatch(stmt);
StmtUtilTools.StmtExecute(stmt);
StmtUtilTools.StmtClose(stmt);
DataSource.FreeTaosBind(tags);
DataSource.FreeTaosBind(binds);
string querySql = "select * from " + tableName;
IntPtr res = UtilsTools.ExecuteQuery(conn, querySql);
UtilsTools.DisplayRes(res);
}
/// <author>xiaolei</author>
/// <Name>StableStmtCases.TestBindColumnCn</Name>
/// <describe>Test stmt insert single line of chinese character into stable by column after column </describe>
/// <filename>StmtSTable.cs</filename>
/// <result>pass or failed </result>
public void TestBindColumnCn(IntPtr conn, string tableName)
{
DataSource data = new DataSource();
TAOS_BIND[] tags = DataSource.getCNTags();
TAOS_MULTI_BIND[] mbind = DataSource.GetMultiBindCNArr();
String createTb = "create stable " + tableName + " (ts timestamp ,b bool,v1 tinyint,v2 smallint,v4 int,v8 bigint,f4 float,f8 double,u1 tinyint unsigned,u2 smallint unsigned,u4 int unsigned,u8 bigint unsigned,bin binary(200),blob nchar(200))tags(bo bool,tt tinyint,si smallint,ii int,bi bigint,tu tinyint unsigned,su smallint unsigned,iu int unsigned,bu bigint unsigned,ff float ,dd double ,bb binary(200),nc nchar(200));";
String insertSql = "insert into ? using " + tableName + " tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
UtilsTools.ExecuteUpdate(conn, createTb);
IntPtr stmt = StmtUtilTools.StmtInit(conn);
StmtUtilTools.StmtPrepare(stmt, insertSql);
StmtUtilTools.SetTableNameTags(stmt, tableName + "_t1", tags);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[0], 0);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[1], 1);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[2], 2);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[3], 3);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[4], 4);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[5], 5);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[6], 6);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[7], 7);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[8], 8);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[9], 9);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[10], 10);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[11], 11);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[12], 12);
StmtUtilTools.BindSingleParamBatch(stmt, mbind[13], 13);
StmtUtilTools.AddBatch(stmt);
StmtUtilTools.StmtExecute(stmt);
StmtUtilTools.StmtClose(stmt);
DataSource.FreeTaosBind(tags);
DataSource.FreeTaosMBind(mbind);
string querySql = "select * from " + tableName;
IntPtr res = UtilsTools.ExecuteQuery(conn, querySql);
UtilsTools.DisplayRes(res);
}
/// <author>xiaolei</author>
/// <Name>StableStmtCases.TestBindMultiLineCn</Name>
/// <describe>Test stmt insert single line of chinese character into stable by column after column </describe>
/// <filename>StmtSTable.cs</filename>
/// <result>pass or failed </result>
public void TestBindMultiLineCn(IntPtr conn, string tableName)
{
TAOS_BIND[] tags = DataSource.getCNTags();
TAOS_MULTI_BIND[] mbind = DataSource.GetMultiBindCNArr();
String createTb = "create stable " + tableName + " (ts timestamp ,b bool,v1 tinyint,v2 smallint,v4 int,v8 bigint,f4 float,f8 double,u1 tinyint unsigned,u2 smallint unsigned,u4 int unsigned,u8 bigint unsigned,bin binary(200),blob nchar(200))tags(bo bool,tt tinyint,si smallint,ii int,bi bigint,tu tinyint unsigned,su smallint unsigned,iu int unsigned,bu bigint unsigned,ff float ,dd double ,bb binary(200),nc nchar(200));";
String insertSql = "insert into ? using " + tableName + " tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
UtilsTools.ExecuteUpdate(conn, createTb);
IntPtr stmt = StmtUtilTools.StmtInit(conn);
StmtUtilTools.StmtPrepare(stmt, insertSql);
StmtUtilTools.SetTableNameTags(stmt, tableName + "_t1", tags);
StmtUtilTools.BindParamBatch(stmt, mbind);
StmtUtilTools.AddBatch(stmt);
StmtUtilTools.StmtExecute(stmt);
StmtUtilTools.StmtClose(stmt);
DataSource.FreeTaosBind(tags);
DataSource.FreeTaosMBind(mbind);
string querySql = "select * from " + tableName;
IntPtr res = UtilsTools.ExecuteQuery(conn, querySql);
UtilsTools.DisplayRes(res);
}
}
} }
\ No newline at end of file
...@@ -8,7 +8,7 @@ namespace Test.UtilsTools ...@@ -8,7 +8,7 @@ namespace Test.UtilsTools
public class UtilsTools public class UtilsTools
{ {
static string configDir = "C:/TDengine/cfg"; static string configDir = "/etc/taos";//"C:/TDengine/cfg";
public static IntPtr TDConnection(string ip, string user, string password, string db, short port) public static IntPtr TDConnection(string ip, string user, string password, string db, short port)
{ {
...@@ -35,7 +35,6 @@ namespace Test.UtilsTools ...@@ -35,7 +35,6 @@ namespace Test.UtilsTools
else else
{ {
Console.WriteLine(sql.ToString() + " success"); Console.WriteLine(sql.ToString() + " success");
} }
return res; return res;
} }
...@@ -61,6 +60,28 @@ namespace Test.UtilsTools ...@@ -61,6 +60,28 @@ namespace Test.UtilsTools
return res; return res;
} }
public static void ExecuteUpdate(IntPtr conn, String sql)
{
IntPtr res = TDengine.Query(conn, sql);
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
else
{
Console.WriteLine(sql.ToString() + " success");
}
TDengine.FreeResult(res);
}
public static void DisplayRes(IntPtr res) public static void DisplayRes(IntPtr res)
{ {
long queryRows = 0; long queryRows = 0;
...@@ -83,9 +104,13 @@ namespace Test.UtilsTools ...@@ -83,9 +104,13 @@ namespace Test.UtilsTools
IntPtr rowdata; IntPtr rowdata;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero) while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero)
{ {
queryRows++; queryRows++;
IntPtr colLengthPtr = TDengine.FetchLengths(res);
int[] colLengthArr = new int[fieldCount];
Marshal.Copy(colLengthPtr, colLengthArr, 0, fieldCount);
for (int fields = 0; fields < fieldCount; ++fields) for (int fields = 0; fields < fieldCount; ++fields)
{ {
TDengineMeta meta = metas[fields]; TDengineMeta meta = metas[fields];
...@@ -131,7 +156,7 @@ namespace Test.UtilsTools ...@@ -131,7 +156,7 @@ namespace Test.UtilsTools
builder.Append(v7); builder.Append(v7);
break; break;
case TDengineDataType.TSDB_DATA_TYPE_BINARY: case TDengineDataType.TSDB_DATA_TYPE_BINARY:
string v8 = Marshal.PtrToStringAnsi(data); string v8 = Marshal.PtrToStringAnsi(data, colLengthArr[fields]);
builder.Append(v8); builder.Append(v8);
break; break;
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP: case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
...@@ -139,7 +164,7 @@ namespace Test.UtilsTools ...@@ -139,7 +164,7 @@ namespace Test.UtilsTools
builder.Append(v9); builder.Append(v9);
break; break;
case TDengineDataType.TSDB_DATA_TYPE_NCHAR: case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
string v10 = Marshal.PtrToStringAnsi(data); string v10 = Marshal.PtrToStringAnsi(data, colLengthArr[fields]);
builder.Append(v10); builder.Append(v10);
break; break;
case TDengineDataType.TSDB_DATA_TYPE_JSONTAG: case TDengineDataType.TSDB_DATA_TYPE_JSONTAG:
...@@ -164,6 +189,117 @@ namespace Test.UtilsTools ...@@ -164,6 +189,117 @@ namespace Test.UtilsTools
TDengine.FreeResult(res); Console.WriteLine(""); TDengine.FreeResult(res); Console.WriteLine("");
} }
public static List<List<string>> GetResultSet(IntPtr res)
{
List<List<string>> result = new List<List<string>>();
List<string> colName = new List<string>();
List<string> dataRaw = new List<string>();
long queryRows = 0;
if (!IsValidResult(res))
{
ExitProgram();
}
int fieldCount = TDengine.FieldCount(res);
List<TDengineMeta> metas = TDengine.FetchFields(res);
for (int j = 0; j < metas.Count; j++)
{
TDengineMeta meta = (TDengineMeta)metas[j];
colName.Add(meta.name);
}
result.Add(colName);
IntPtr rowdata;
while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero)
{
queryRows++;
IntPtr colLengthPtr = TDengine.FetchLengths(res);
int[] colLengthArr = new int[fieldCount];
Marshal.Copy(colLengthPtr, colLengthArr, 0, fieldCount);
for (int fields = 0; fields < fieldCount; ++fields)
{
TDengineMeta meta = metas[fields];
int offset = IntPtr.Size * fields;
IntPtr data = Marshal.ReadIntPtr(rowdata, offset);
if (data == IntPtr.Zero)
{
dataRaw.Add("NULL");
continue;
}
switch ((TDengineDataType)meta.type)
{
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
bool v1 = Marshal.ReadByte(data) == 0 ? false : true;
dataRaw.Add(v1.ToString());
break;
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
byte v2 = Marshal.ReadByte(data);
dataRaw.Add(v2.ToString());
break;
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
short v3 = Marshal.ReadInt16(data);
dataRaw.Add(v3.ToString());
break;
case TDengineDataType.TSDB_DATA_TYPE_INT:
int v4 = Marshal.ReadInt32(data);
dataRaw.Add(v4.ToString());
break;
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
long v5 = Marshal.ReadInt64(data);
dataRaw.Add(v5.ToString());
break;
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
float v6 = (float)Marshal.PtrToStructure(data, typeof(float));
dataRaw.Add(v6.ToString());
break;
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
double v7 = (double)Marshal.PtrToStructure(data, typeof(double));
dataRaw.Add(v7.ToString());
break;
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
string v8 = Marshal.PtrToStringAnsi(data, colLengthArr[fields]);
dataRaw.Add(v8);
break;
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
long v9 = Marshal.ReadInt64(data);
dataRaw.Add(v9.ToString());
break;
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
string v10 = Marshal.PtrToStringAnsi(data, colLengthArr[fields]);
dataRaw.Add(v10);
break;
}
}
}
result.Add(dataRaw);
if (TDengine.ErrorNo(res) != 0)
{
Console.Write("Query is not complete, Error {0:G}", TDengine.ErrorNo(res), TDengine.Error(res));
}
TDengine.FreeResult(res); Console.WriteLine("");
return result;
}
public static bool IsValidResult(IntPtr res)
{
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
return false;
}
Console.WriteLine("");
return false;
}
return true;
}
public static void CloseConnection(IntPtr conn) public static void CloseConnection(IntPtr conn)
{ {
if (conn != IntPtr.Zero) if (conn != IntPtr.Zero)
...@@ -183,6 +319,18 @@ namespace Test.UtilsTools ...@@ -183,6 +319,18 @@ namespace Test.UtilsTools
List<TDengineMeta> metas = TDengine.FetchFields(res); List<TDengineMeta> metas = TDengine.FetchFields(res);
return metas; return metas;
} }
public static void AssertEqual(string expectVal, string actualVal)
{
if (expectVal == actualVal)
{
Console.WriteLine("{0}=={1} pass", expectVal, actualVal);
}
else
{
Console.WriteLine("{0}=={1} failed", expectVal, actualVal);
ExitProgram();
}
}
public static void ExitProgram() public static void ExitProgram()
{ {
TDengine.Cleanup(); TDengine.Cleanup();
......
...@@ -652,8 +652,8 @@ namespace TDengineDriver.Test ...@@ -652,8 +652,8 @@ namespace TDengineDriver.Test
{ {
int bufferType = 8; int bufferType = 8;
String buffer = "qwertyuiopasdghjklzxcvbnm<>?:\"{}+_)(*&^%$#@!~QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./`1234567890-="; String buffer = "qwertyuiopasdghjklzxcvbnm<>?:\"{}+_)(*&^%$#@!~QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./`1234567890-=";
int bufferLength = buffer.Length; int bufferLength = System.Text.Encoding.Default.GetBytes(buffer).Length;
int length = buffer.Length; int length = System.Text.Encoding.Default.GetBytes(buffer).Length;
TDengineDriver.TAOS_BIND bind = TaosBind.BindBinary("qwertyuiopasdghjklzxcvbnm<>?:\"{}+_)(*&^%$#@!~QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./`1234567890-="); TDengineDriver.TAOS_BIND bind = TaosBind.BindBinary("qwertyuiopasdghjklzxcvbnm<>?:\"{}+_)(*&^%$#@!~QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./`1234567890-=");
int BindLengPtr = Marshal.ReadInt32(bind.length); int BindLengPtr = Marshal.ReadInt32(bind.length);
...@@ -674,8 +674,8 @@ namespace TDengineDriver.Test ...@@ -674,8 +674,8 @@ namespace TDengineDriver.Test
{ {
int bufferType = 8; int bufferType = 8;
String buffer = "一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./"; String buffer = "一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./";
int bufferLength = buffer.Length; int bufferLength = System.Text.Encoding.Default.GetBytes(buffer).Length;
int length = buffer.Length; int length = System.Text.Encoding.Default.GetBytes(buffer).Length;
TDengineDriver.TAOS_BIND bind = TaosBind.BindBinary("一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./"); TDengineDriver.TAOS_BIND bind = TaosBind.BindBinary("一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./");
int BindLengPtr = Marshal.ReadInt32(bind.length); int BindLengPtr = Marshal.ReadInt32(bind.length);
...@@ -696,8 +696,8 @@ namespace TDengineDriver.Test ...@@ -696,8 +696,8 @@ namespace TDengineDriver.Test
{ {
int bufferType = 8; int bufferType = 8;
String buffer = "一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; String buffer = "一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
int bufferLength = buffer.Length; int bufferLength = System.Text.Encoding.Default.GetBytes(buffer).Length;
int length = buffer.Length; int length = System.Text.Encoding.Default.GetBytes(buffer).Length;
TDengineDriver.TAOS_BIND bind = TaosBind.BindBinary("一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"); TDengineDriver.TAOS_BIND bind = TaosBind.BindBinary("一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM");
int BindLengPtr = Marshal.ReadInt32(bind.length); int BindLengPtr = Marshal.ReadInt32(bind.length);
...@@ -718,8 +718,8 @@ namespace TDengineDriver.Test ...@@ -718,8 +718,8 @@ namespace TDengineDriver.Test
{ {
int bufferType = 10; int bufferType = 10;
String buffer = "qwertyuiopasdghjklzxcvbnm<>?:\"{}+_)(*&^%$#@!~QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./`1234567890-="; String buffer = "qwertyuiopasdghjklzxcvbnm<>?:\"{}+_)(*&^%$#@!~QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./`1234567890-=";
int bufferLength = buffer.Length; int bufferLength = System.Text.Encoding.Default.GetBytes(buffer).Length;
int length = buffer.Length; int length = System.Text.Encoding.Default.GetBytes(buffer).Length;
TDengineDriver.TAOS_BIND bind = TaosBind.BindNchar("qwertyuiopasdghjklzxcvbnm<>?:\"{}+_)(*&^%$#@!~QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./`1234567890-="); TDengineDriver.TAOS_BIND bind = TaosBind.BindNchar("qwertyuiopasdghjklzxcvbnm<>?:\"{}+_)(*&^%$#@!~QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./`1234567890-=");
int BindLengPtr = Marshal.ReadInt32(bind.length); int BindLengPtr = Marshal.ReadInt32(bind.length);
...@@ -739,8 +739,8 @@ namespace TDengineDriver.Test ...@@ -739,8 +739,8 @@ namespace TDengineDriver.Test
{ {
int bufferType = 10; int bufferType = 10;
String buffer = "一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./"; String buffer = "一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./";
int bufferLength = buffer.Length; int bufferLength = System.Text.Encoding.Default.GetBytes(buffer).Length;
int length = buffer.Length; int length = System.Text.Encoding.Default.GetBytes(buffer).Length;
TDengineDriver.TAOS_BIND bind = TaosBind.BindNchar("一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./"); TDengineDriver.TAOS_BIND bind = TaosBind.BindNchar("一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./");
int BindLengPtr = Marshal.ReadInt32(bind.length); int BindLengPtr = Marshal.ReadInt32(bind.length);
...@@ -760,8 +760,8 @@ namespace TDengineDriver.Test ...@@ -760,8 +760,8 @@ namespace TDengineDriver.Test
{ {
int bufferType = 10; int bufferType = 10;
String buffer = "一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; String buffer = "一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
int bufferLength = buffer.Length; int bufferLength = System.Text.Encoding.Default.GetBytes(buffer).Length;
int length = buffer.Length; int length = System.Text.Encoding.Default.GetBytes(buffer).Length;
TDengineDriver.TAOS_BIND bind = TaosBind.BindNchar("一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"); TDengineDriver.TAOS_BIND bind = TaosBind.BindNchar("一二两三四五六七八九十廿毛另壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分零整1234567890`~!@#$%^&*()_+[]{};':<>?,./qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM");
int BindLengPtr = Marshal.ReadInt32(bind.length); int BindLengPtr = Marshal.ReadInt32(bind.length);
......
...@@ -2,10 +2,14 @@ ...@@ -2,10 +2,14 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<DocumentationFile>..\doc\UnitTest.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="3.1.0"> <PackageReference Include="coverlet.msbuild" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
......
...@@ -443,16 +443,29 @@ public class TSDBResultSetRowData { ...@@ -443,16 +443,29 @@ public class TSDBResultSetRowData {
case 0: { case 0: {
milliseconds = ts; milliseconds = ts;
fracNanoseconds = (int) (ts * 1_000_000 % 1_000_000_000); fracNanoseconds = (int) (ts * 1_000_000 % 1_000_000_000);
fracNanoseconds = fracNanoseconds < 0 ? 1_000_000_000 + fracNanoseconds : fracNanoseconds;
break; break;
} }
case 1: { case 1: {
milliseconds = ts / 1_000; milliseconds = ts / 1_000;
fracNanoseconds = (int) (ts * 1_000 % 1_000_000_000); fracNanoseconds = (int) (ts * 1_000 % 1_000_000_000);
if (fracNanoseconds < 0) {
if (milliseconds == 0 ){
milliseconds = -1;
}
fracNanoseconds += 1_000_000_000;
}
break; break;
} }
case 2: { case 2: {
milliseconds = ts / 1_000_000; milliseconds = ts / 1_000_000;
fracNanoseconds = (int) (ts % 1_000_000_000); fracNanoseconds = (int) (ts % 1_000_000_000);
if (fracNanoseconds < 0) {
if (milliseconds == 0 ){
milliseconds = -1;
}
fracNanoseconds += 1_000_000_000;
}
break; break;
} }
default: { default: {
......
package com.taosdata.jdbc.cases; package com.taosdata.jdbc.cases;
import com.taosdata.jdbc.annotation.CatalogRunner;
import com.taosdata.jdbc.annotation.Description;
import com.taosdata.jdbc.annotation.TestTarget;
import com.taosdata.jdbc.utils.TimestampUtil; import com.taosdata.jdbc.utils.TimestampUtil;
import org.junit.*; import org.junit.*;
import org.junit.runner.RunWith;
import java.sql.*; import java.sql.*;
@RunWith(CatalogRunner.class)
@TestTarget(alias = "negative value convert to timestamp", author = "huolibo", version = "2.0.37")
public class DatetimeBefore1970Test { public class DatetimeBefore1970Test {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
private Connection conn; private Connection conn;
@Test @Test
public void test() throws SQLException { @Description("millisecond")
public void msTest() throws SQLException {
conn = createEnvironment("ms");
long now = System.currentTimeMillis();
try (Statement stmt = conn.createStatement()) { try (Statement stmt = conn.createStatement()) {
// given // given
// before
stmt.executeUpdate("insert into weather(ts) values('1969-12-31 00:00:00.001')");
stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999')"); stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999')");
// zero
stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000')"); stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000')");
stmt.executeUpdate("insert into weather(ts) values('1970-01-01 08:00:00.000')"); //after
stmt.executeUpdate("insert into weather(ts) values('1970-01-01 07:59:59.999')"); stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.001')");
stmt.executeUpdate("insert into weather(ts) values(" + now + ")");
ResultSet rs = stmt.executeQuery("select * from weather order by ts asc"); ResultSet rs = stmt.executeQuery("select * from weather order by ts asc");
ResultSetMetaData metaData = rs.getMetaData(); ResultSetMetaData metaData = rs.getMetaData();
Assert.assertEquals(2, metaData.getColumnCount()); Assert.assertEquals(2, metaData.getColumnCount());
...@@ -26,44 +39,221 @@ public class DatetimeBefore1970Test { ...@@ -26,44 +39,221 @@ public class DatetimeBefore1970Test {
rs.next(); rs.next();
// then // then
Timestamp ts = rs.getTimestamp("ts"); Timestamp ts = rs.getTimestamp("ts");
Assert.assertEquals("1969-12-31 23:59:59.999", TimestampUtil.longToDatetime(ts.getTime())); Assert.assertEquals(-24 * 60 * 60 * 1000 + 1, ts.getTime());
// when // when
rs.next(); rs.next();
// then // then
ts = rs.getTimestamp("ts"); ts = rs.getTimestamp("ts");
Assert.assertEquals("1970-01-01 00:00:00.000", TimestampUtil.longToDatetime(ts.getTime())); Assert.assertEquals(-1, ts.getTime());
// when // when
rs.next(); rs.next();
// then // then
ts = rs.getTimestamp("ts"); ts = rs.getTimestamp("ts");
Assert.assertEquals("1970-01-01 08:00:00.000", TimestampUtil.longToDatetime(ts.getTime())); Assert.assertEquals(0, ts.getTime());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals(1, ts.getTime());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals(now, ts.getTime());
}
}
@Test
@Description("microsecond")
public void usTest() throws SQLException {
conn = createEnvironment("us");
long now = System.currentTimeMillis();
try (Statement stmt = conn.createStatement()) {
// given
stmt.executeUpdate("insert into weather(ts) values('1969-12-31 00:00:00.000001')");
stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999999')");
stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000000')");
stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000001')");
stmt.executeUpdate("insert into weather(ts) values(" + now + ")");
ResultSet rs = stmt.executeQuery("select * from weather order by ts asc");
ResultSetMetaData metaData = rs.getMetaData();
Assert.assertEquals(2, metaData.getColumnCount());
// when
rs.next();
// then
Timestamp ts = rs.getTimestamp("ts");
Assert.assertEquals(-24 * 60 * 60 * 1000, ts.getTime());
Assert.assertEquals(1_000, ts.getNanos());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals(-1, ts.getTime());
Assert.assertEquals(999_999_000, ts.getNanos());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals(0, ts.getTime());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals(0, ts.getTime());
Assert.assertEquals(1_000, ts.getNanos());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
String s = String.valueOf(now);
Assert.assertEquals(Long.parseLong(s.substring(0, s.length() - 3)), ts.getTime());
Assert.assertEquals(Long.parseLong(s.substring(s.length() - 6) + "000"), ts.getNanos());
}
}
@Test
@Description("nanosecond")
public void nanoTest() throws SQLException {
conn = createEnvironment("ns");
long now = System.currentTimeMillis() * 1000_000L + System.nanoTime() % 1000_000L;
try (Statement stmt = conn.createStatement()) {
// given
stmt.executeUpdate("insert into weather(ts) values('1969-12-31 00:00:00.000000123')");
stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999999999')");
stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000')");
stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000000001')");
stmt.executeUpdate("insert into weather(ts) values(" + now + ")");
ResultSet rs = stmt.executeQuery("select * from weather order by ts asc");
ResultSetMetaData metaData = rs.getMetaData();
Assert.assertEquals(2, metaData.getColumnCount());
// when
rs.next();
// then
Timestamp ts = rs.getTimestamp("ts");
Assert.assertEquals(-24 * 60 * 60 * 1_000, ts.getTime());
Assert.assertEquals(123, ts.getNanos());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals(-1, ts.getTime());
Assert.assertEquals(999999999, ts.getNanos());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals(0, ts.getNanos());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals(1, ts.getNanos());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
String s = String.valueOf(now);
Assert.assertEquals(Long.parseLong(s.substring(0, s.length() - 6)), ts.getTime());
Assert.assertEquals(Long.parseLong(s.substring(s.length() - 9)), ts.getNanos());
}
}
@Test
@Ignore
@Description("nanosecond convert timestamp when timezone is asia shanghai")
public void asiaShanghaiTest() throws SQLException {
conn = createEnvironment("ns");
long now = System.currentTimeMillis() * 1000_000L + System.nanoTime() % 1000_000L;
try (Statement stmt = conn.createStatement()) {
// given
stmt.executeUpdate("insert into weather(ts) values('1969-12-31 00:00:00.000000123')");
stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999999999')");
stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000')");
stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000000001')");
stmt.executeUpdate("insert into weather(ts) values(" + now + ")");
ResultSet rs = stmt.executeQuery("select * from weather order by ts asc");
ResultSetMetaData metaData = rs.getMetaData();
Assert.assertEquals(2, metaData.getColumnCount());
// when
rs.next();
// then
Timestamp ts = rs.getTimestamp("ts");
Assert.assertEquals("1969-12-31 08:00:00.000", TimestampUtil.longToDatetime(ts.getTime()));
Assert.assertEquals(123, ts.getNanos());
// when // when
rs.next(); rs.next();
// then // then
ts = rs.getTimestamp("ts"); ts = rs.getTimestamp("ts");
Assert.assertEquals("1970-01-01 07:59:59.999", TimestampUtil.longToDatetime(ts.getTime())); Assert.assertEquals("1970-01-01 07:59:59.999", TimestampUtil.longToDatetime(ts.getTime()));
Assert.assertEquals(999999999, ts.getNanos());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals("1970-01-01 08:00:00.000", TimestampUtil.longToDatetime(ts.getTime()));
Assert.assertEquals(0, ts.getNanos());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
Assert.assertEquals("1970-01-01 08:00:00.000", TimestampUtil.longToDatetime(ts.getTime()));
Assert.assertEquals(1, ts.getNanos());
// when
rs.next();
// then
ts = rs.getTimestamp("ts");
String s = String.valueOf(now);
Assert.assertEquals(Long.parseLong(s.substring(0, s.length() - 6)), ts.getTime());
Assert.assertEquals(Long.parseLong(s.substring(s.length() - 9)), ts.getNanos());
} }
} }
@Before private Connection createEnvironment(String precision) throws SQLException {
public void before() throws SQLException { String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata&timezone=UTC";
conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); String createSql = "create database if not exists test_timestamp keep 36500";
if (!isEmpty(precision)) {
createSql += " precision '" + precision + "'";
}
conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
stmt.execute("drop database if exists test_timestamp"); stmt.execute("drop database if exists test_timestamp");
stmt.execute("create database if not exists test_timestamp keep 36500"); stmt.execute(createSql);
stmt.execute("use test_timestamp"); stmt.execute("use test_timestamp");
stmt.execute("create table weather(ts timestamp,f1 float)"); stmt.execute("create table weather(ts timestamp,f1 float)");
stmt.close(); stmt.close();
return conn;
}
private boolean isEmpty(String string) {
return null == string || string.trim().equals("");
} }
@After @After
public void after() throws SQLException { public void after() throws SQLException {
Statement stmt = conn.createStatement(); if (conn != null) {
stmt.execute("drop database if exists test_timestamp"); Statement stmt = conn.createStatement();
if (conn != null) stmt.execute("drop database if exists test_timestamp");
stmt.close();
conn.close(); conn.close();
}
} }
} }
package com.taosdata.jdbc.confprops; package com.taosdata.jdbc.confprops;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import java.sql.Connection; import java.sql.Connection;
...@@ -13,6 +14,7 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -13,6 +14,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream; import java.util.stream.IntStream;
@Ignore
public class HttpKeepAliveTest { public class HttpKeepAliveTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
......
node_modules
\ No newline at end of file
This repositry create a custom Node-Red node for configing TDEngine server connection and execute SQL from preview node msg.payload
## Design
Use Taos data restful API to commit SQL, API call like
```
curl -H 'Authorization: Basic <TOKEN>' -d '<SQL>' <ip>:<PORT>/rest/sql/[db_name]
```
Input options:
* DB Server: Setup server connection or select a exist server
* DB Name: Database to execute SQL
Use [axios](https://axios-http.com/) to call http request
## Usage
1. Start Node-Red
2. Install TDEngine node
3. Add "taos query" node to workspace from palette
4. Setup a TDEngine server and database name
5. Add function or other node to create SQL, put SQL into msg.payload
6. Link to "taos query" node
### Demo
1. Start Node-Red by docker
```
docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red
```
2. Import sample flow "demo/flow.json"
![import-flow](demo/ImportFlow.png)
3. Install TDEngine node by name "node-red-contrib-tdengine", current version is 0.0.2
![alt](demo/InstallTDEngineNode.png)
4. Modify your TDEngine server config
![alt](demo/ModifyServerConfig.png)
5. Edit test SQL
![alt](demo/EditTestSQL.png)
6. Start flow by click Inject node
[
{
"id": "01ad89bea2c249f6",
"type": "tab",
"label": "流程 1",
"disabled": false,
"info": "",
"env": [
{
"name": "test",
"value": "abc",
"type": "str"
},
{
"name": "path",
"value": "{\"codes\":\"/usr/local/processing/codes\",\"parameters\":\"/usr/local/processing/parameters\"}",
"type": "json"
}
]
},
{
"id": "0ab8aa0c7f1b7522",
"type": "taos-query",
"z": "01ad89bea2c249f6",
"server": "e385222cd91994dc",
"database": "demo",
"x": 780,
"y": 400,
"wires": [
[
"f9c4f70dc2d79548"
]
]
},
{
"id": "ba09b80a40b65780",
"type": "inject",
"z": "01ad89bea2c249f6",
"name": "",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "INSERT INTO t VALUES (NOW, 23)",
"payloadType": "str",
"x": 490,
"y": 400,
"wires": [
[
"0ab8aa0c7f1b7522"
]
]
},
{
"id": "f9c4f70dc2d79548",
"type": "debug",
"z": "01ad89bea2c249f6",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1050,
"y": 400,
"wires": []
},
{
"id": "e385222cd91994dc",
"type": "taos-config",
"host": "localhost",
"port": "6030",
"username": "root",
"password": "taosdata"
}
]
\ No newline at end of file
{
"name": "node-red-contrib-tdengine",
"version": "0.0.2",
"description": "",
"main": "tdengine.js",
"repository": {
"type": "git",
"url": "git+https://github.com/kevinpan45/node-red-contrib-tdengine.git"
},
"author": "kevinpan45@163.com",
"license": "ISC",
"dependencies": {
"axios": "^0.24.0",
"mocha": "^9.1.3"
},
"node-red": {
"nodes": {
"tdengine": "tdengine.js"
}
},
"keywords": [
"node-red",
"tdengine"
],
"devDependencies": {
"node-red": "^2.1.4",
"node-red-node-test-helper": "^0.2.7"
}
}
<script type="text/javascript">
"use strict";
/*global RED*/
RED.nodes.registerType('taos-config', {
category: 'config',
defaults: {
host: {
value: "localhost",
required: true
},
port: {
value: "6030",
required: true
},
username: {
value: "",
required: false
},
password: {
value: "",
required: false
}
},
label: function () {
return this.host || "TDEngine host";
}
});
</script>
<script type="text/x-red" data-template-name="taos-config">
<div class="form-row">
<label for="node-config-input-host"><i class="fa fa-server"></i> Host</label>
<input type="text" id="node-config-input-host">
</div>
<div class="form-row">
<label for="node-config-input-port"><i class="fa fa-server"></i> Port</label>
<input type="text" id="node-config-input-port">
</div>
<div class="form-row">
<label for="node-config-input-username"><i class="fa fa-server"></i> User Name</label>
<input type="text" id="node-config-input-username">
</div>
<div class="form-row">
<label for="node-config-input-password"><i class="fa fa-server"></i> Password</label>
<input type="text" id="node-config-input-password">
</div>
</script>
<script type="text/javascript">
/*global RED*/
RED.nodes.registerType('taos-query', {
category: 'TDEngine',
inputs: 1,
outputs: 1,
color: "#ffffff",
paletteLabel: "taos query",
defaults: {
server: {
value: "",
type: "taos-config"
},
database: {
value: ""
},
sql: {
value: ""
}
},
label: function () {
return this.name || "taos " + this.database;
}
});
</script>
<script type="text/x-red" data-template-name="taos-query">
<div class="form-row">
<label for="node-input-server"><i class="fa fa-globe"></i> Server</label>
<input type="text" id="node-input-server" placeholder="Server">
</div>
<div class="form-row">
<label for="node-input-database"><i class="fa fa-tag"></i> Database</label>
<input type="text" id="node-input-database" placeholder="Database">
</div>
</script>
<script type="text/x-red" data-help-name="taos-query">
<p>TDEngine Query</p>
<p>Execute SQL on remote TDEngine server by restful API</p>
</script>
\ No newline at end of file
module.exports = function (RED) {
"use strict";
const axios = require('axios');
function TaosConfig(n) {
RED.nodes.createNode(this, n);
this.host = n.host;
this.port = n.port;
this.username = n.username;
this.password = n.password;
}
RED.nodes.registerType("taos-config", TaosConfig);
function TaosQuery(n) {
RED.nodes.createNode(this, n);
this.server = RED.nodes.getNode(n.server);
this.database = n.database;
var node = this;
node.on("close", function (done) {
node.status({});
client = null;
done();
});
node.on("input", async function (msg, send, done) {
send = send || function () { node.send.apply(node, arguments) }
done = done || function (err) { if (err) node.error(err, msg); }
let sql = msg.payload;
if (!msg.payload || msg.payload == "") {
throw new Error("Execute SQL must be set.");
}
try {
msg.payload = await query(this.server, sql);
send(msg);
done();
} catch (error) {
done(error);
}
});
}
RED.nodes.registerType("taos-query", TaosQuery);
function query(server, sql) {
console.log("Start to execute SQL : " + sql);
let url = generateUrl(server);
return axios.post(url, sql, {
headers: { 'Authorization': token(server) }
}).then(function (response) {
console.log('Get http response from taos : ' + response.data.data);
return response.data.data;
}).catch(function (error) {
console.error("Request Failed " + e);
throw new Error(response.desc);
});
}
function generateUrl(server) {
return "http://" + server.host + ":" + server.port + '/rest/sql';
}
function token(server) {
return 'Basic ' + Buffer.from(server.username + ":" + server.password).toString('base64')
}
};
...@@ -41,6 +41,7 @@ cursor.execute("show databases") ...@@ -41,6 +41,7 @@ cursor.execute("show databases")
results = cursor.fetchall() results = cursor.fetchall()
for row in results: for row in results:
print(row) print(row)
cursor.close() cursor.close()
conn.close() conn.close()
``` ```
...@@ -57,8 +58,10 @@ result = conn.query("show databases") ...@@ -57,8 +58,10 @@ result = conn.query("show databases")
num_of_fields = result.field_count num_of_fields = result.field_count
for field in result.fields: for field in result.fields:
print(field) print(field)
for row in result: for row in result:
print(row) print(row)
result.close() result.close()
conn.execute("drop database pytest") conn.execute("drop database pytest")
conn.close() conn.close()
...@@ -75,12 +78,13 @@ def fetch_callback(p_param, p_result, num_of_rows): ...@@ -75,12 +78,13 @@ def fetch_callback(p_param, p_result, num_of_rows):
print("fetched ", num_of_rows, "rows") print("fetched ", num_of_rows, "rows")
p = cast(p_param, POINTER(Counter)) p = cast(p_param, POINTER(Counter))
result = TaosResult(p_result) result = TaosResult(p_result)
if num_of_rows == 0: if num_of_rows == 0:
print("fetching completed") print("fetching completed")
p.contents.done = True p.contents.done = True
result.close() result.close()
return return
if num_of_rows < 0: if num_of_rows < 0:
p.contents.done = True p.contents.done = True
result.check_error(num_of_rows) result.check_error(num_of_rows)
...@@ -90,6 +94,7 @@ def fetch_callback(p_param, p_result, num_of_rows): ...@@ -90,6 +94,7 @@ def fetch_callback(p_param, p_result, num_of_rows):
for row in result.rows_iter(num_of_rows): for row in result.rows_iter(num_of_rows):
# print(row) # print(row)
None None
p.contents.count += result.row_count p.contents.count += result.row_count
result.fetch_rows_a(fetch_callback, p_param) result.fetch_rows_a(fetch_callback, p_param)
...@@ -97,17 +102,19 @@ def fetch_callback(p_param, p_result, num_of_rows): ...@@ -97,17 +102,19 @@ def fetch_callback(p_param, p_result, num_of_rows):
def query_callback(p_param, p_result, code): def query_callback(p_param, p_result, code):
# type: (c_void_p, c_void_p, c_int) -> None # type: (c_void_p, c_void_p, c_int) -> None
if p_result == None: if p_result is None:
return return
result = TaosResult(p_result) result = TaosResult(p_result)
if code == 0: if code == 0:
result.fetch_rows_a(fetch_callback, p_param) result.fetch_rows_a(fetch_callback, p_param)
result.check_error(code) result.check_error(code)
class Counter(Structure): class Counter(Structure):
_fields_ = [("count", c_int), ("done", c_bool)] _fields_ = [("count", c_int), ("done", c_bool)]
def __str__(self): def __str__(self):
return "{ count: %d, done: %s }" % (self.count, self.done) return "{ count: %d, done: %s }" % (self.count, self.done)
...@@ -116,10 +123,11 @@ def test_query(conn): ...@@ -116,10 +123,11 @@ def test_query(conn):
# type: (TaosConnection) -> None # type: (TaosConnection) -> None
counter = Counter(count=0) counter = Counter(count=0)
conn.query_a("select * from log.log", query_callback, byref(counter)) conn.query_a("select * from log.log", query_callback, byref(counter))
while not counter.done: while not counter.done:
print("wait query callback") print("wait query callback")
time.sleep(1) time.sleep(1)
print(counter) print(counter)
conn.close() conn.close()
...@@ -182,6 +190,7 @@ result = conn.query("select * from log") ...@@ -182,6 +190,7 @@ result = conn.query("select * from log")
for row in result: for row in result:
print(row) print(row)
result.close() result.close()
stmt.close() stmt.close()
conn.close() conn.close()
...@@ -237,18 +246,20 @@ result.close() ...@@ -237,18 +246,20 @@ result.close()
result = conn.query("select * from log") result = conn.query("select * from log")
for row in result: for row in result:
print(row) print(row)
result.close() result.close()
stmt.close() stmt.close()
conn.close() conn.close()
``` ```
### Statement API - Subscribe ### Subscription
```python ```python
import taos import taos
import random
conn = taos.connect() conn = taos.connect()
dbname = "pytest_taos_subscribe_callback" dbname = "pytest_taos_subscribe"
conn.execute("drop database if exists %s" % dbname) conn.execute("drop database if exists %s" % dbname)
conn.execute("create database if not exists %s" % dbname) conn.execute("create database if not exists %s" % dbname)
conn.select_db(dbname) conn.select_db(dbname)
...@@ -256,7 +267,7 @@ conn.execute("create table if not exists log(ts timestamp, n int)") ...@@ -256,7 +267,7 @@ conn.execute("create table if not exists log(ts timestamp, n int)")
for i in range(10): for i in range(10):
conn.execute("insert into log values(now, %d)" % i) conn.execute("insert into log values(now, %d)" % i)
sub = conn.subscribe(True, "test", "select * from log", 1000) sub = conn.subscribe(False, "test", "select * from log", 1000)
print("# consume from begin") print("# consume from begin")
for ts, n in sub.consume(): for ts, n in sub.consume():
print(ts, n) print(ts, n)
...@@ -268,9 +279,18 @@ for i in range(5): ...@@ -268,9 +279,18 @@ for i in range(5):
for ts, n in result: for ts, n in result:
print(ts, n) print(ts, n)
sub.close(True)
print("# keep progress consume")
sub = conn.subscribe(False, "test", "select * from log", 1000)
result = sub.consume()
rows = result.fetch_all()
# consume from latest subscription needs root privilege(for /var/lib/taos).
assert result.row_count == 0
print("## consumed ", len(rows), "rows")
print("# consume with a stop condition") print("# consume with a stop condition")
for i in range(10): for i in range(10):
conn.execute("insert into log values(now, %d)" % int(random() * 10)) conn.execute("insert into log values(now, %d)" % random.randint(0, 10))
result = sub.consume() result = sub.consume()
try: try:
ts, n = next(result) ts, n = next(result)
...@@ -283,12 +303,13 @@ for i in range(10): ...@@ -283,12 +303,13 @@ for i in range(10):
continue continue
sub.close() sub.close()
# sub.close()
conn.execute("drop database if exists %s" % dbname) conn.execute("drop database if exists %s" % dbname)
conn.close() # conn.close()
``` ```
### Statement API - Subscribe asynchronously with callback ### Subscription asynchronously with callback
```python ```python
from taos import * from taos import *
...@@ -300,7 +321,7 @@ import time ...@@ -300,7 +321,7 @@ import time
def subscribe_callback(p_sub, p_result, p_param, errno): def subscribe_callback(p_sub, p_result, p_param, errno):
# type: (c_void_p, c_void_p, c_void_p, c_int) -> None # type: (c_void_p, c_void_p, c_void_p, c_int) -> None
print("# fetch in callback") print("# fetch in callback")
result = TaosResult(p_result) result = TaosResult(c_void_p(p_result))
result.check_error(errno) result.check_error(errno)
for row in result.rows_iter(): for row in result.rows_iter():
ts, n = row() ts, n = row()
...@@ -311,42 +332,45 @@ def test_subscribe_callback(conn): ...@@ -311,42 +332,45 @@ def test_subscribe_callback(conn):
# type: (TaosConnection) -> None # type: (TaosConnection) -> None
dbname = "pytest_taos_subscribe_callback" dbname = "pytest_taos_subscribe_callback"
try: try:
print("drop if exists")
conn.execute("drop database if exists %s" % dbname) conn.execute("drop database if exists %s" % dbname)
print("create database")
conn.execute("create database if not exists %s" % dbname) conn.execute("create database if not exists %s" % dbname)
conn.select_db(dbname) print("create table")
conn.execute("create table if not exists log(ts timestamp, n int)") # conn.execute("use %s" % dbname)
conn.execute("create table if not exists %s.log(ts timestamp, n int)" % dbname)
print("# subscribe with callback") print("# subscribe with callback")
sub = conn.subscribe(False, "test", "select * from log", 1000, subscribe_callback) sub = conn.subscribe(False, "test", "select * from %s.log" % dbname, 1000, subscribe_callback)
for i in range(10): for i in range(10):
conn.execute("insert into log values(now, %d)" % i) conn.execute("insert into %s.log values(now, %d)" % (dbname, i))
time.sleep(0.7) time.sleep(0.7)
sub.close() sub.close()
conn.execute("drop database if exists %s" % dbname) conn.execute("drop database if exists %s" % dbname)
conn.close() # conn.close()
except Exception as err: except Exception as err:
conn.execute("drop database if exists %s" % dbname) conn.execute("drop database if exists %s" % dbname)
conn.close() # conn.close()
raise err raise err
if __name__ == "__main__": if __name__ == "__main__":
test_subscribe_callback(connect()) test_subscribe_callback(connect())
``` ```
### Statement API - Stream ### Stream
```python ```python
from taos import * from taos import *
from ctypes import * from ctypes import *
import time
def stream_callback(p_param, p_result, p_row): def stream_callback(p_param, p_result, p_row):
# type: (c_void_p, c_void_p, c_void_p) -> None # type: (c_void_p, c_void_p, c_void_p) -> None
if p_result is None or p_row is None:
if p_result == None or p_row == None:
return return
result = TaosResult(p_result) result = TaosResult(p_result)
row = TaosRow(result, p_row) row = TaosRow(result, p_row)
...@@ -355,13 +379,12 @@ def stream_callback(p_param, p_result, p_row): ...@@ -355,13 +379,12 @@ def stream_callback(p_param, p_result, p_row):
p = cast(p_param, POINTER(Counter)) p = cast(p_param, POINTER(Counter))
p.contents.count += count p.contents.count += count
print("[%s] inserted %d in 5s, total count: %d" % (ts.strftime("%Y-%m-%d %H:%M:%S"), count, p.contents.count)) print("[%s] inserted %d in 5s, total count: %d" % (ts.strftime("%Y-%m-%d %H:%M:%S"), count, p.contents.count))
except Exception as err: except Exception as err:
print(err) print(err)
raise err raise err
class Counter(ctypes.Structure): class Counter(Structure):
_fields_ = [ _fields_ = [
("count", c_int), ("count", c_int),
] ]
...@@ -378,16 +401,17 @@ def test_stream(conn): ...@@ -378,16 +401,17 @@ def test_stream(conn):
conn.execute("create database if not exists %s" % dbname) conn.execute("create database if not exists %s" % dbname)
conn.select_db(dbname) conn.select_db(dbname)
conn.execute("create table if not exists log(ts timestamp, n int)") conn.execute("create table if not exists log(ts timestamp, n int)")
result = conn.query("select count(*) from log interval(5s)") result = conn.query("select count(*) from log interval(5s)")
assert result.field_count == 2 assert result.field_count == 2
counter = Counter() counter = Counter()
counter.count = 0 counter.count = 0
stream = conn.stream("select count(*) from log interval(5s)", stream_callback, param=byref(counter)) stream = conn.stream("select count(*) from log interval(5s)", stream_callback, param=byref(counter))
for _ in range(0, 20): for _ in range(0, 20):
conn.execute("insert into log values(now,0)(now+1s, 1)(now + 2s, 2)") conn.execute("insert into log values(now,0)(now+1s, 1)(now + 2s, 2)")
time.sleep(2) time.sleep(2)
stream.close() stream.close()
conn.execute("drop database if exists %s" % dbname) conn.execute("drop database if exists %s" % dbname)
conn.close() conn.close()
...@@ -399,12 +423,14 @@ def test_stream(conn): ...@@ -399,12 +423,14 @@ def test_stream(conn):
if __name__ == "__main__": if __name__ == "__main__":
test_stream(connect()) test_stream(connect())
``` ```
### Insert with line protocol ### Insert with line protocol
```python ```python
import taos import taos
from taos import SmlProtocol, SmlPrecision
conn = taos.connect() conn = taos.connect()
dbname = "pytest_line" dbname = "pytest_line"
...@@ -413,29 +439,22 @@ conn.execute("create database if not exists %s precision 'us'" % dbname) ...@@ -413,29 +439,22 @@ conn.execute("create database if not exists %s precision 'us'" % dbname)
conn.select_db(dbname) conn.select_db(dbname)
lines = [ lines = [
'st,t1=3i64,t2=4f64,t3="t3" c1=3i64,c3=L"pass",c2=false,c4=4f64 1626006833639000000ns', 'st,t1=3i64,t2=4f64,t3="t3" c1=3i64,c3=L"pass",c2=false,c4=4f64 1626006833639000000',
'st,t1=4i64,t3="t4",t2=5f64,t4=5f64 c1=3i64,c3=L"pass it again",c2=true,c4=5f64,c5=5f64,c6=7u64 1626006933640000000',
'stf,t1=4i64,t3="t4",t2=5f64,t4=5f64 c1=3i64,c3=L"pass it again_stf",c2=false,c5=5f64,c6=7u64 1626006933641000000',
] ]
conn.schemaless_insert(lines, 0, "ns") conn.schemaless_insert(lines, taos.SmlProtocol.LINE_PROTOCOL, taos.SmlPrecision.NOT_CONFIGURED)
print("inserted") print("inserted")
lines = [ conn.schemaless_insert(lines, taos.SmlProtocol.LINE_PROTOCOL, taos.SmlPrecision.NOT_CONFIGURED)
'stf,t1=5i64,t3="t4",t2=5f64,t4=5f64 c1=3i64,c3=L"pass it again_stf",c2=false,c5=5f64,c6=7u64 1626006933641000000',
]
conn.schemaless_insert(lines, 0, "ns")
result = conn.query("show tables") result = conn.query("show tables")
for row in result: for row in result:
print(row) print(row)
result.close()
conn.execute("drop database if exists %s" % dbname) conn.execute("drop database if exists %s" % dbname)
conn.close()
``` ```
## License - AGPL-3.0 ## License
Keep same with [TDengine](https://github.com/taosdata/TDengine). We use MIT license for Python connector.
...@@ -29,7 +29,7 @@ def fetch_callback(p_param, p_result, num_of_rows): ...@@ -29,7 +29,7 @@ def fetch_callback(p_param, p_result, num_of_rows):
def query_callback(p_param, p_result, code): def query_callback(p_param, p_result, code):
# type: (c_void_p, c_void_p, c_int) -> None # type: (c_void_p, c_void_p, c_int) -> None
if p_result == None: if p_result is None:
return return
result = TaosResult(p_result) result = TaosResult(p_result)
if code == 0: if code == 0:
......
from taos import *
from ctypes import *
import time
def stream_callback(p_param, p_result, p_row):
# type: (c_void_p, c_void_p, c_void_p) -> None
if p_result is None or p_row is None:
return
result = TaosResult(p_result)
row = TaosRow(result, p_row)
try:
ts, count = row()
p = cast(p_param, POINTER(Counter))
p.contents.count += count
print("[%s] inserted %d in 5s, total count: %d" % (ts.strftime("%Y-%m-%d %H:%M:%S"), count, p.contents.count))
except Exception as err:
print(err)
raise err
class Counter(Structure):
_fields_ = [
("count", c_int),
]
def __str__(self):
return "%d" % self.count
def test_stream(conn):
# type: (TaosConnection) -> None
dbname = "pytest_taos_stream"
try:
conn.execute("drop database if exists %s" % dbname)
conn.execute("create database if not exists %s" % dbname)
conn.select_db(dbname)
conn.execute("create table if not exists log(ts timestamp, n int)")
result = conn.query("select count(*) from log interval(5s)")
assert result.field_count == 2
counter = Counter()
counter.count = 0
stream = conn.stream("select count(*) from log interval(5s)", stream_callback, param=byref(counter))
for _ in range(0, 20):
conn.execute("insert into log values(now,0)(now+1s, 1)(now + 2s, 2)")
time.sleep(2)
stream.close()
conn.execute("drop database if exists %s" % dbname)
conn.close()
except Exception as err:
conn.execute("drop database if exists %s" % dbname)
conn.close()
raise err
if __name__ == "__main__":
test_stream(connect())
...@@ -86,7 +86,7 @@ def fetch_callback(p_param, p_result, num_of_rows): ...@@ -86,7 +86,7 @@ def fetch_callback(p_param, p_result, num_of_rows):
def query_callback(p_param, p_result, code): def query_callback(p_param, p_result, code):
# type: (c_void_p, c_void_p, c_int) -> None # type: (c_void_p, c_void_p, c_int) -> None
if p_result == None: if p_result is None:
return return
result = TaosResult(p_result) result = TaosResult(p_result)
if code == 0: if code == 0:
...@@ -335,7 +335,7 @@ from ctypes import * ...@@ -335,7 +335,7 @@ from ctypes import *
def stream_callback(p_param, p_result, p_row): def stream_callback(p_param, p_result, p_row):
# type: (c_void_p, c_void_p, c_void_p) -> None # type: (c_void_p, c_void_p, c_void_p) -> None
if p_result == None or p_row == None: if p_result is None or p_row is None:
return return
result = TaosResult(p_result) result = TaosResult(p_result)
row = TaosRow(result, p_row) row = TaosRow(result, p_row)
......
...@@ -317,7 +317,7 @@ class TaosMultiBind(ctypes.Structure): ...@@ -317,7 +317,7 @@ class TaosMultiBind(ctypes.Structure):
def _str_to_buffer(self, values): def _str_to_buffer(self, values):
self.num = len(values) self.num = len(values)
is_null = [1 if v == None else 0 for v in values] is_null = [1 if v is None else 0 for v in values]
self.is_null = cast((c_byte * self.num)(*is_null), c_char_p) self.is_null = cast((c_byte * self.num)(*is_null), c_char_p)
if sum(is_null) == self.num: if sum(is_null) == self.num:
......
...@@ -373,9 +373,9 @@ def taos_fetch_block(result, fields=None, field_count=None): ...@@ -373,9 +373,9 @@ def taos_fetch_block(result, fields=None, field_count=None):
if num_of_rows == 0: if num_of_rows == 0:
return None, 0 return None, 0
precision = taos_result_precision(result) precision = taos_result_precision(result)
if fields == None: if fields is None:
fields = taos_fetch_fields(result) fields = taos_fetch_fields(result)
if field_count == None: if field_count is None:
field_count = taos_field_count(result) field_count = taos_field_count(result)
blocks = [None] * field_count blocks = [None] * field_count
fieldLen = taos_fetch_lengths(result, field_count) fieldLen = taos_fetch_lengths(result, field_count)
...@@ -466,7 +466,7 @@ def taos_fetch_lengths(result, field_count=None): ...@@ -466,7 +466,7 @@ def taos_fetch_lengths(result, field_count=None):
# type: (c_void_p, int) -> Array[int] # type: (c_void_p, int) -> Array[int]
"""Make sure to call taos_fetch_row or taos_fetch_block before fetch_lengths""" """Make sure to call taos_fetch_row or taos_fetch_block before fetch_lengths"""
lens = _libtaos.taos_fetch_lengths(result) lens = _libtaos.taos_fetch_lengths(result)
if field_count == None: if field_count is None:
field_count = taos_field_count(result) field_count = taos_field_count(result)
if not lens: if not lens:
raise OperationalError("field length empty, use taos_fetch_row/block before it") raise OperationalError("field length empty, use taos_fetch_row/block before it")
...@@ -823,7 +823,7 @@ def taos_stmt_use_result(stmt): ...@@ -823,7 +823,7 @@ def taos_stmt_use_result(stmt):
@stmt: TAOS_STMT* @stmt: TAOS_STMT*
""" """
result = c_void_p(_libtaos.taos_stmt_use_result(stmt)) result = c_void_p(_libtaos.taos_stmt_use_result(stmt))
if result == None: if result is None:
raise StatementError(taos_stmt_errstr(stmt)) raise StatementError(taos_stmt_errstr(stmt))
return result return result
......
...@@ -41,7 +41,7 @@ class TaosResult(object): ...@@ -41,7 +41,7 @@ class TaosResult(object):
if self._result is None or self.fields is None: if self._result is None or self.fields is None:
raise OperationalError("Invalid use of fetch iterator") raise OperationalError("Invalid use of fetch iterator")
if self._block == None or self._block_iter >= self._block_length: if self._block is None or self._block_iter >= self._block_length:
self._block, self._block_length = self.fetch_block() self._block, self._block_length = self.fetch_block()
self._block_iter = 0 self._block_iter = 0
# self._row_count += self._block_length # self._row_count += self._block_length
...@@ -55,7 +55,7 @@ class TaosResult(object): ...@@ -55,7 +55,7 @@ class TaosResult(object):
"""fields definitions of the current result""" """fields definitions of the current result"""
if self._result is None: if self._result is None:
raise ResultError("no result object setted") raise ResultError("no result object setted")
if self._fields == None: if self._fields is None:
self._fields = taos_fetch_fields(self._result) self._fields = taos_fetch_fields(self._result)
return self._fields return self._fields
...@@ -72,7 +72,7 @@ class TaosResult(object): ...@@ -72,7 +72,7 @@ class TaosResult(object):
@property @property
def precision(self): def precision(self):
if self._precision == None: if self._precision is None:
self._precision = taos_result_precision(self._result) self._precision = taos_result_precision(self._result)
return self._precision return self._precision
...@@ -114,7 +114,7 @@ class TaosResult(object): ...@@ -114,7 +114,7 @@ class TaosResult(object):
if self._result is None: if self._result is None:
raise OperationalError("Invalid use of fetchall") raise OperationalError("Invalid use of fetchall")
if self._fields == None: if self._fields is None:
self._fields = taos_fetch_fields(self._result) self._fields = taos_fetch_fields(self._result)
buffer = [[] for i in range(len(self._fields))] buffer = [[] for i in range(len(self._fields))]
self._row_count = 0 self._row_count = 0
...@@ -150,7 +150,7 @@ class TaosResult(object): ...@@ -150,7 +150,7 @@ class TaosResult(object):
return taos_errstr(self._result) return taos_errstr(self._result)
def check_error(self, errno=None, close=True): def check_error(self, errno=None, close=True):
if errno == None: if errno is None:
errno = self.errno() errno = self.errno()
if errno != 0: if errno != 0:
msg = self.errstr() msg = self.errstr()
......
...@@ -274,7 +274,6 @@ int32_t* taosGetErrno(); ...@@ -274,7 +274,6 @@ int32_t* taosGetErrno();
#define TSDB_CODE_TDB_IVLD_TAG_VAL TAOS_DEF_ERROR_CODE(0, 0x0615) //"TSDB invalid tag value") #define TSDB_CODE_TDB_IVLD_TAG_VAL TAOS_DEF_ERROR_CODE(0, 0x0615) //"TSDB invalid tag value")
#define TSDB_CODE_TDB_NO_CACHE_LAST_ROW TAOS_DEF_ERROR_CODE(0, 0x0616) //"TSDB no cache last row data") #define TSDB_CODE_TDB_NO_CACHE_LAST_ROW TAOS_DEF_ERROR_CODE(0, 0x0616) //"TSDB no cache last row data")
#define TSDB_CODE_TDB_INCOMPLETE_DFILESET TAOS_DEF_ERROR_CODE(0, 0x0617) //"TSDB incomplete DFileSet") #define TSDB_CODE_TDB_INCOMPLETE_DFILESET TAOS_DEF_ERROR_CODE(0, 0x0617) //"TSDB incomplete DFileSet")
#define TSDB_CODE_TDB_NO_JSON_TAG_KEY TAOS_DEF_ERROR_CODE(0, 0x0618) //"TSDB no tag json key")
// query // query
#define TSDB_CODE_QRY_INVALID_QHANDLE TAOS_DEF_ERROR_CODE(0, 0x0700) //"Invalid handle") #define TSDB_CODE_QRY_INVALID_QHANDLE TAOS_DEF_ERROR_CODE(0, 0x0700) //"Invalid handle")
......
...@@ -32,6 +32,10 @@ ELSEIF (TD_WINDOWS) ...@@ -32,6 +32,10 @@ ELSEIF (TD_WINDOWS)
LIST(APPEND SRC ./src/shellMain.c) LIST(APPEND SRC ./src/shellMain.c)
LIST(APPEND SRC ./src/shellWindows.c) LIST(APPEND SRC ./src/shellWindows.c)
ADD_EXECUTABLE(shell ${SRC}) ADD_EXECUTABLE(shell ${SRC})
IF (TD_LINUX_64 AND JEMALLOC_ENABLED)
ADD_DEPENDENCIES(shell jemalloc)
ENDIF ()
TARGET_LINK_LIBRARIES(shell taos_static cJson) TARGET_LINK_LIBRARIES(shell taos_static cJson)
IF (TD_POWER) IF (TD_POWER)
......
...@@ -448,9 +448,29 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) { ...@@ -448,9 +448,29 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) {
tt = 0; tt = 0;
} }
*/ */
#ifdef WINDOWS #ifdef WINDOWS
if (tt < 0) tt = 0; if (tt < 0) {
SYSTEMTIME a={1970,1,5,1,0,0,0,0}; // SYSTEMTIME struct support 1601-01-01. set 1970 to compatible with Epoch time.
FILETIME b; // unit is 100ns
ULARGE_INTEGER c;
SystemTimeToFileTime(&a,&b);
c.LowPart = b.dwLowDateTime;
c.HighPart = b.dwHighDateTime;
c.QuadPart+=tt*10000000;
b.dwLowDateTime=c.LowPart;
b.dwHighDateTime=c.HighPart;
FileTimeToLocalFileTime(&b,&b);
FileTimeToSystemTime(&b,&a);
int pos = sprintf(buf,"%02d-%02d-%02d %02d:%02d:%02d", a.wYear, a.wMonth,a.wDay, a.wHour, a.wMinute, a.wSecond);
if (precision == TSDB_TIME_PRECISION_NANO) {
sprintf(buf + pos, ".%09d", ms);
} else if (precision == TSDB_TIME_PRECISION_MICRO) {
sprintf(buf + pos, ".%06d", ms);
} else {
sprintf(buf + pos, ".%03d", ms);
}
return buf;
}
#endif #endif
if (tt <= 0 && ms < 0) { if (tt <= 0 && ms < 0) {
tt--; tt--;
......
Subproject commit beca4813316f254624d8dbecf54d45a5a232c61d Subproject commit 27751ba9ca17407425fb50a52cd68295794dedc3
...@@ -8,3 +8,8 @@ INCLUDE_DIRECTORIES(inc) ...@@ -8,3 +8,8 @@ INCLUDE_DIRECTORIES(inc)
AUX_SOURCE_DIRECTORY(src SRC) AUX_SOURCE_DIRECTORY(src SRC)
ADD_LIBRARY(mnode ${SRC}) ADD_LIBRARY(mnode ${SRC})
IF (TD_LINUX_64 AND JEMALLOC_ENABLED)
ADD_DEPENDENCIES(mnode jemalloc)
ENDIF ()
...@@ -3155,7 +3155,7 @@ static int32_t mnodeProcessMultiTableMetaMsg(SMnodeMsg *pMsg) { ...@@ -3155,7 +3155,7 @@ static int32_t mnodeProcessMultiTableMetaMsg(SMnodeMsg *pMsg) {
_end: _end:
tfree(str); tfree(str);
tfree(nameList); tfree(nameList);
taosArrayDestroy(pList); taosArrayDestroy(&pList);
pMsg->pTable = NULL; pMsg->pTable = NULL;
pMsg->pVgroup = NULL; pMsg->pVgroup = NULL;
tfree(pMultiMeta); tfree(pMultiMeta);
......
...@@ -11,6 +11,11 @@ ADD_LIBRARY(os ${SRC}) ...@@ -11,6 +11,11 @@ ADD_LIBRARY(os ${SRC})
IF (TD_LINUX) IF (TD_LINUX)
TARGET_LINK_LIBRARIES(os oslinux) TARGET_LINK_LIBRARIES(os oslinux)
IF (TD_LINUX_64 AND JEMALLOC_ENABLED)
ADD_DEPENDENCIES(os jemalloc)
ENDIF ()
IF (TD_ARM_32 OR TD_LINUX_32) IF (TD_ARM_32 OR TD_LINUX_32)
TARGET_LINK_LIBRARIES(os atomic) TARGET_LINK_LIBRARIES(os atomic)
ENDIF () ENDIF ()
......
...@@ -4,4 +4,9 @@ PROJECT(TDengine) ...@@ -4,4 +4,9 @@ PROJECT(TDengine)
AUX_SOURCE_DIRECTORY(. SRC) AUX_SOURCE_DIRECTORY(. SRC)
ADD_LIBRARY(oslinux ${SRC}) ADD_LIBRARY(oslinux ${SRC})
TARGET_LINK_LIBRARIES(oslinux m rt z dl) TARGET_LINK_LIBRARIES(oslinux m rt z dl)
\ No newline at end of file
IF (TD_LINUX_64 AND JEMALLOC_ENABLED)
ADD_DEPENDENCIES(oslinux jemalloc)
ENDIF ()
...@@ -8,6 +8,8 @@ IF (TD_BUILD_HTTP) ...@@ -8,6 +8,8 @@ IF (TD_BUILD_HTTP)
MESSAGE("${Yellow} use original embedded httpd ${ColourReset}") MESSAGE("${Yellow} use original embedded httpd ${ColourReset}")
MESSAGE("") MESSAGE("")
ADD_SUBDIRECTORY(http) ADD_SUBDIRECTORY(http)
ELSEIF(TD_BUILD_TAOSA_INTERNAL)
MESSAGE("${Yellow} use taosa internal as httpd ${ColourReset}")
ELSE () ELSE ()
MESSAGE("") MESSAGE("")
MESSAGE("${Green} use taosadapter as httpd ${ColourReset}") MESSAGE("${Green} use taosadapter as httpd ${ColourReset}")
......
...@@ -601,6 +601,10 @@ static void monSaveSystemInfo() { ...@@ -601,6 +601,10 @@ static void monSaveSystemInfo() {
} }
static int32_t monGetRowElemCharLen(TAOS_FIELD field, char *rowElem) { static int32_t monGetRowElemCharLen(TAOS_FIELD field, char *rowElem) {
if (field.type != TSDB_DATA_TYPE_BINARY && field.type != TSDB_DATA_TYPE_NCHAR) {
return -1;
}
int32_t charLen = varDataLen(rowElem - VARSTR_HEADER_SIZE); int32_t charLen = varDataLen(rowElem - VARSTR_HEADER_SIZE);
if (field.type == TSDB_DATA_TYPE_BINARY) { if (field.type == TSDB_DATA_TYPE_BINARY) {
assert(charLen <= field.bytes && charLen >= 0); assert(charLen <= field.bytes && charLen >= 0);
...@@ -629,12 +633,14 @@ static int32_t monBuildMasterUptimeSql(char *sql) { ...@@ -629,12 +633,14 @@ static int32_t monBuildMasterUptimeSql(char *sql) {
while ((row = taos_fetch_row(result))) { while ((row = taos_fetch_row(result))) {
for (int i = 0; i < num_fields; ++i) { for (int i = 0; i < num_fields; ++i) {
int32_t charLen = monGetRowElemCharLen(fields[i], (char *)row[i]); if (strcmp(fields[i].name, "role") == 0) {
if (strcmp(fields[i].name, "role") == 0 && strncmp((char *)row[i], "master", charLen) == 0) { int32_t charLen = monGetRowElemCharLen(fields[i], (char *)row[i]);
if (strcmp(fields[i + 1].name, "role_time") == 0) { if (strncmp((char *)row[i], "master", charLen) == 0) {
int64_t now = taosGetTimestamp(TSDB_TIME_PRECISION_MILLI); if (strcmp(fields[i + 1].name, "role_time") == 0) {
//master uptime in seconds int64_t now = taosGetTimestamp(TSDB_TIME_PRECISION_MILLI);
masterUptime = (now - *(int64_t *)row[i + 1]) / 1000; //master uptime in seconds
masterUptime = (now - *(int64_t *)row[i + 1]) / 1000;
}
} }
} }
} }
...@@ -1139,12 +1145,16 @@ static uint32_t monBuildVgroupsInfoSql(char *sql, char *dbName) { ...@@ -1139,12 +1145,16 @@ static uint32_t monBuildVgroupsInfoSql(char *sql, char *dbName) {
pos += snprintf(sql, SQL_LENGTH, "insert into %s.vgroup_%d values(%" PRId64 ", "SQL_STR_FMT, pos += snprintf(sql, SQL_LENGTH, "insert into %s.vgroup_%d values(%" PRId64 ", "SQL_STR_FMT,
tsMonitorDbName, vgId, ts, dbName); tsMonitorDbName, vgId, ts, dbName);
} else { } else {
return TSDB_CODE_SUCCESS; goto DONE;
} }
} else if (strcmp(fields[i].name, "tables") == 0) { } else if (strcmp(fields[i].name, "tables") == 0) {
pos += snprintf(sql + pos, SQL_LENGTH, ", %d", *(int32_t *)row[i]); pos += snprintf(sql + pos, SQL_LENGTH, ", %d", *(int32_t *)row[i]);
} else if (strcmp(fields[i].name, "status") == 0) { } else if (strcmp(fields[i].name, "status") == 0) {
charLen = monGetRowElemCharLen(fields[i], (char *)row[i]); charLen = monGetRowElemCharLen(fields[i], (char *)row[i]);
if (charLen < 0) {
monError("failed to save vgroup_%d info, reason: invalid row %s len, sql:%s", vgId, (char *)row[i], tsMonitor.sql);
goto DONE;
}
pos += snprintf(sql + pos, strlen(SQL_STR_FMT) + charLen + 1, ", "SQL_STR_FMT, (char *)row[i]); pos += snprintf(sql + pos, strlen(SQL_STR_FMT) + charLen + 1, ", "SQL_STR_FMT, (char *)row[i]);
} else if (strcmp(fields[i].name, "onlines") == 0) { } else if (strcmp(fields[i].name, "onlines") == 0) {
pos += snprintf(sql + pos, SQL_LENGTH, ", %d", *(int32_t *)row[i]); pos += snprintf(sql + pos, SQL_LENGTH, ", %d", *(int32_t *)row[i]);
...@@ -1152,6 +1162,10 @@ static uint32_t monBuildVgroupsInfoSql(char *sql, char *dbName) { ...@@ -1152,6 +1162,10 @@ static uint32_t monBuildVgroupsInfoSql(char *sql, char *dbName) {
snprintf(v_dnode_ids, sizeof(v_dnode_ids), "%d;", *(int16_t *)row[i]); snprintf(v_dnode_ids, sizeof(v_dnode_ids), "%d;", *(int16_t *)row[i]);
} else if (v_dnode_str && strcmp(v_dnode_str, "_status") == 0) { } else if (v_dnode_str && strcmp(v_dnode_str, "_status") == 0) {
charLen = monGetRowElemCharLen(fields[i], (char *)row[i]); charLen = monGetRowElemCharLen(fields[i], (char *)row[i]);
if (charLen < 0) {
monError("failed to save vgroup_%d info, reason: invalid row %s len, sql:%s", vgId, (char *)row[i], tsMonitor.sql);
goto DONE;
}
snprintf(v_dnode_status, charLen + 1, "%s;", (char *)row[i]); snprintf(v_dnode_status, charLen + 1, "%s;", (char *)row[i]);
} else if (strcmp(fields[i].name, "compacting") == 0) { } else if (strcmp(fields[i].name, "compacting") == 0) {
//flush dnode_ids and dnode_role in to sql //flush dnode_ids and dnode_role in to sql
...@@ -1169,8 +1183,9 @@ static uint32_t monBuildVgroupsInfoSql(char *sql, char *dbName) { ...@@ -1169,8 +1183,9 @@ static uint32_t monBuildVgroupsInfoSql(char *sql, char *dbName) {
monDebug("successfully to save vgroup_%d info, sql:%s", vgId, tsMonitor.sql); monDebug("successfully to save vgroup_%d info, sql:%s", vgId, tsMonitor.sql);
} }
} }
taos_free_result(result);
DONE:
taos_free_result(result);
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
...@@ -1220,12 +1235,24 @@ static void monSaveSlowQueryInfo() { ...@@ -1220,12 +1235,24 @@ static void monSaveSlowQueryInfo() {
if (strcmp(fields[i].name, "query_id") == 0) { if (strcmp(fields[i].name, "query_id") == 0) {
has_slowquery = true; has_slowquery = true;
charLen = monGetRowElemCharLen(fields[i], (char *)row[i]); charLen = monGetRowElemCharLen(fields[i], (char *)row[i]);
if (charLen < 0) {
monError("failed to save slow_query info, reason: invalid row %s len, sql:%s", (char *)row[i], tsMonitor.sql);
goto DONE;
}
pos += snprintf(sql + pos, strlen(SQL_STR_FMT) + charLen + 1, ", "SQL_STR_FMT, (char *)row[i]); pos += snprintf(sql + pos, strlen(SQL_STR_FMT) + charLen + 1, ", "SQL_STR_FMT, (char *)row[i]);
} else if (strcmp(fields[i].name, "user") == 0) { } else if (strcmp(fields[i].name, "user") == 0) {
charLen = monGetRowElemCharLen(fields[i], (char *)row[i]); charLen = monGetRowElemCharLen(fields[i], (char *)row[i]);
if (charLen < 0) {
monError("failed to save slow_query info, reason: invalid row %s len, sql:%s", (char *)row[i], tsMonitor.sql);
goto DONE;
}
pos += snprintf(sql + pos, strlen(SQL_STR_FMT) + charLen + 1, ", "SQL_STR_FMT, (char *)row[i]); pos += snprintf(sql + pos, strlen(SQL_STR_FMT) + charLen + 1, ", "SQL_STR_FMT, (char *)row[i]);
} else if (strcmp(fields[i].name, "qid") == 0) { } else if (strcmp(fields[i].name, "qid") == 0) {
charLen = monGetRowElemCharLen(fields[i], (char *)row[i]); charLen = monGetRowElemCharLen(fields[i], (char *)row[i]);
if (charLen < 0) {
monError("failed to save slow_query info, reason: invalid row %s len, sql:%s", (char *)row[i], tsMonitor.sql);
goto DONE;
}
pos += snprintf(sql + pos, strlen(SQL_STR_FMT) + charLen + 1, ", "SQL_STR_FMT, (char *)row[i]); pos += snprintf(sql + pos, strlen(SQL_STR_FMT) + charLen + 1, ", "SQL_STR_FMT, (char *)row[i]);
} else if (strcmp(fields[i].name, "created_time") == 0) { } else if (strcmp(fields[i].name, "created_time") == 0) {
int64_t create_time = *(int64_t *)row[i]; int64_t create_time = *(int64_t *)row[i];
...@@ -1235,18 +1262,25 @@ static void monSaveSlowQueryInfo() { ...@@ -1235,18 +1262,25 @@ static void monSaveSlowQueryInfo() {
pos += snprintf(sql + pos, SQL_LENGTH, ", %" PRId64 "", *(int64_t *)row[i]); pos += snprintf(sql + pos, SQL_LENGTH, ", %" PRId64 "", *(int64_t *)row[i]);
} else if (strcmp(fields[i].name, "ep") == 0) { } else if (strcmp(fields[i].name, "ep") == 0) {
charLen = monGetRowElemCharLen(fields[i], (char *)row[i]); charLen = monGetRowElemCharLen(fields[i], (char *)row[i]);
if (charLen < 0) {
monError("failed to save slow_query info, reason: invalid row %s len, sql:%s", (char *)row[i], tsMonitor.sql);
goto DONE;
}
pos += snprintf(sql + pos, strlen(SQL_STR_FMT) + charLen + 1, ", "SQL_STR_FMT, (char *)row[i]); pos += snprintf(sql + pos, strlen(SQL_STR_FMT) + charLen + 1, ", "SQL_STR_FMT, (char *)row[i]);
} else if (strcmp(fields[i].name, "sql") == 0) { } else if (strcmp(fields[i].name, "sql") == 0) {
charLen = monGetRowElemCharLen(fields[i], (char *)row[i]); charLen = monGetRowElemCharLen(fields[i], (char *)row[i]);
if (charLen < 0) {
monError("failed to save slow_query info, reason: invalid row %s len, sql:%s", (char *)row[i], tsMonitor.sql);
goto DONE;
}
pos += snprintf(sql + pos, strlen(SQL_STR_FMT) + charLen + 2, ", "SQL_STR_FMT")", (char *)row[i]); pos += snprintf(sql + pos, strlen(SQL_STR_FMT) + charLen + 2, ", "SQL_STR_FMT")", (char *)row[i]);
} }
} }
} }
monDebug("save slow query, sql:%s", sql); monDebug("save slow query, sql:%s", sql);
taos_free_result(result);
if (!has_slowquery) { if (!has_slowquery) {
return; goto DONE;
} }
void *res = taos_query(tsMonitor.conn, tsMonitor.sql); void *res = taos_query(tsMonitor.conn, tsMonitor.sql);
code = taos_errno(res); code = taos_errno(res);
...@@ -1259,6 +1293,9 @@ static void monSaveSlowQueryInfo() { ...@@ -1259,6 +1293,9 @@ static void monSaveSlowQueryInfo() {
monDebug("successfully to save slowquery info, sql:%s", tsMonitor.sql); monDebug("successfully to save slowquery info, sql:%s", tsMonitor.sql);
} }
DONE:
taos_free_result(result);
return;
} }
static void monSaveDisksInfo() { static void monSaveDisksInfo() {
......
Subproject commit 826f3d3b7820a5c007d301854d56db003b424d0a Subproject commit 273b5219f8bcc604e43beebc6f1f95abed85170a
...@@ -66,7 +66,7 @@ typedef struct SDiskbasedResultBuf { ...@@ -66,7 +66,7 @@ typedef struct SDiskbasedResultBuf {
SHashObj* groupSet; // id hash table SHashObj* groupSet; // id hash table
SHashObj* all; SHashObj* all;
SList* lruList; SList* lruList;
void* emptyDummyIdList; // dummy id list SArray * emptyDummyIdList; // dummy id list
void* assistBuf; // assistant buffer for compress/decompress data void* assistBuf; // assistant buffer for compress/decompress data
SArray* pFree; // free area in file SArray* pFree; // free area in file
bool comp; // compressed before flushed to disk bool comp; // compressed before flushed to disk
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -1040,7 +1040,10 @@ void tColModelDisplay(SColumnModel *pModel, void *pData, int32_t numOfRows, int3 ...@@ -1040,7 +1040,10 @@ void tColModelDisplay(SColumnModel *pModel, void *pData, int32_t numOfRows, int3
break; break;
case TSDB_DATA_TYPE_NCHAR: { case TSDB_DATA_TYPE_NCHAR: {
char buf[4096] = {0}; char buf[4096] = {0};
taosUcs4ToMbs(val, pModel->pFields[j].field.bytes, buf); int32_t len = taosUcs4ToMbs(val, pModel->pFields[j].field.bytes, buf);
if (len < 0){
qError("castConvert1 taosUcs4ToMbs error");
}
printf("%s\t", buf); printf("%s\t", buf);
break; break;
} }
...@@ -1092,7 +1095,10 @@ void tColModelDisplayEx(SColumnModel *pModel, void *pData, int32_t numOfRows, in ...@@ -1092,7 +1095,10 @@ void tColModelDisplayEx(SColumnModel *pModel, void *pData, int32_t numOfRows, in
break; break;
case TSDB_DATA_TYPE_NCHAR: { case TSDB_DATA_TYPE_NCHAR: {
char buf[128] = {0}; char buf[128] = {0};
taosUcs4ToMbs(val, pModel->pFields[j].field.bytes, buf); int32_t len = taosUcs4ToMbs(val, pModel->pFields[j].field.bytes, buf);
if (len < 0){
qError("castConvert1 taosUcs4ToMbs error");
}
printf("%s\t", buf); printf("%s\t", buf);
break; break;
} }
......
此差异已折叠。
...@@ -183,7 +183,7 @@ bool likeOperator(SColumnFilterElem *pFilter, const char *minval, const char *ma ...@@ -183,7 +183,7 @@ bool likeOperator(SColumnFilterElem *pFilter, const char *minval, const char *ma
return patternMatch((char *)pFilter->filterInfo.pz, varDataVal(minval), varDataLen(minval), &info) == TSDB_PATTERN_MATCH; return patternMatch((char *)pFilter->filterInfo.pz, varDataVal(minval), varDataLen(minval), &info) == TSDB_PATTERN_MATCH;
} else if (type == TSDB_DATA_TYPE_NCHAR) { } else if (type == TSDB_DATA_TYPE_NCHAR) {
SPatternCompareInfo info = PATTERN_COMPARE_INFO_INITIALIZER; SPatternCompareInfo info = PATTERN_COMPARE_INFO_INITIALIZER;
return WCSPatternMatch((wchar_t*)pFilter->filterInfo.pz, varDataVal(minval), varDataLen(minval)/TSDB_NCHAR_SIZE, &info) == TSDB_PATTERN_MATCH; return WCSPatternMatch((uint32_t *) pFilter->filterInfo.pz, (uint32_t *) varDataVal(minval), varDataLen(minval)/TSDB_NCHAR_SIZE, &info) == TSDB_PATTERN_MATCH;
} else { } else {
return false; return false;
} }
......
...@@ -224,7 +224,7 @@ SArray* createQueryPlanImpl(SQueryInfo* pQueryInfo) { ...@@ -224,7 +224,7 @@ SArray* createQueryPlanImpl(SQueryInfo* pQueryInfo) {
if (pQueryInfo->numOfTables > 1) { // it is a join query if (pQueryInfo->numOfTables > 1) { // it is a join query
// 1. separate the select clause according to table // 1. separate the select clause according to table
taosArrayDestroy(upstream); taosArrayDestroy(&upstream);
upstream = taosArrayInit(5, POINTER_BYTES); upstream = taosArrayInit(5, POINTER_BYTES);
for(int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { for(int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
...@@ -279,7 +279,7 @@ SQueryNode* qCreateQueryPlan(SQueryInfo* pQueryInfo) { ...@@ -279,7 +279,7 @@ SQueryNode* qCreateQueryPlan(SQueryInfo* pQueryInfo) {
assert(taosArrayGetSize(upstream) == 1); assert(taosArrayGetSize(upstream) == 1);
SQueryNode* p = taosArrayGetP(upstream, 0); SQueryNode* p = taosArrayGetP(upstream, 0);
taosArrayDestroy(upstream); taosArrayDestroy(&upstream);
return p; return p;
} }
...@@ -300,7 +300,7 @@ static void doDestroyQueryNode(SQueryNode* pQueryNode) { ...@@ -300,7 +300,7 @@ static void doDestroyQueryNode(SQueryNode* pQueryNode) {
doDestroyQueryNode(p); doDestroyQueryNode(p);
} }
taosArrayDestroy(pQueryNode->pPrevNodes); taosArrayDestroy(&pQueryNode->pPrevNodes);
} }
tfree(pQueryNode); tfree(pQueryNode);
......
...@@ -433,12 +433,12 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf) { ...@@ -433,12 +433,12 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf) {
tfree(pi); tfree(pi);
} }
taosArrayDestroy(*p); taosArrayDestroy(p);
p = taosHashIterate(pResultBuf->groupSet, p); p = taosHashIterate(pResultBuf->groupSet, p);
} }
tdListFree(pResultBuf->lruList); tdListFree(pResultBuf->lruList);
taosArrayDestroy(pResultBuf->emptyDummyIdList); taosArrayDestroy(&pResultBuf->emptyDummyIdList);
taosHashCleanup(pResultBuf->groupSet); taosHashCleanup(pResultBuf->groupSet);
taosHashCleanup(pResultBuf->all); taosHashCleanup(pResultBuf->all);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册