提交 0d4da6a7 编写于 作者: C Cary Xu

Merge branch 'develop' into fix/TD-6044

...@@ -180,7 +180,7 @@ IF (TD_WINDOWS) ...@@ -180,7 +180,7 @@ IF (TD_WINDOWS)
ADD_DEFINITIONS(-D_MBCS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) ADD_DEFINITIONS(-D_MBCS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
SET(CMAKE_GENERATOR "NMake Makefiles" CACHE INTERNAL "" FORCE) SET(CMAKE_GENERATOR "NMake Makefiles" CACHE INTERNAL "" FORCE)
IF (NOT TD_GODLL) IF (NOT TD_GODLL)
SET(COMMON_FLAGS "/nologo /WX /wd4018 /wd2220 /Oi /Oy- /Gm- /EHsc /MT /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Gd /errorReport:prompt /analyze-") SET(COMMON_FLAGS "/nologo /WX /wd4018 /wd5999 /Oi /Oy- /Gm- /EHsc /MT /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Gd /errorReport:prompt /analyze-")
IF (MSVC AND (MSVC_VERSION GREATER_EQUAL 1900)) IF (MSVC AND (MSVC_VERSION GREATER_EQUAL 1900))
SET(COMMON_FLAGS "${COMMON_FLAGS} /Wv:18") SET(COMMON_FLAGS "${COMMON_FLAGS} /Wv:18")
ENDIF () ENDIF ()
......
...@@ -34,12 +34,22 @@ ENDIF () ...@@ -34,12 +34,22 @@ ENDIF ()
# #
# Set compiler options # Set compiler options
SET(COMMON_C_FLAGS "${COMMON_FLAGS} -std=gnu99") IF (TD_LINUX)
SET(COMMON_C_FLAGS "${COMMON_FLAGS} -std=gnu99")
ELSE ()
SET(COMMON_C_FLAGS "${COMMON_FLAGS} ")
ENDIF ()
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${COMMON_C_FLAGS} ${DEBUG_FLAGS}") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${COMMON_C_FLAGS} ${DEBUG_FLAGS}")
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${COMMON_C_FLAGS} ${RELEASE_FLAGS}") SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${COMMON_C_FLAGS} ${RELEASE_FLAGS}")
# Set c++ compiler options # Set c++ compiler options
SET(COMMON_CXX_FLAGS "${COMMON_FLAGS} -std=c++11 -Wno-unused-function") IF (TD_WINDOWS)
SET(COMMON_CXX_FLAGS "${COMMON_FLAGS} -std=c++11")
ELSE ()
SET(COMMON_CXX_FLAGS "${COMMON_FLAGS} -std=c++11 -Wno-unused-function")
ENDIF ()
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS} ${DEBUG_FLAGS}") SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS} ${DEBUG_FLAGS}")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS} ${RELEASE_FLAGS}") SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS} ${RELEASE_FLAGS}")
......
...@@ -138,7 +138,7 @@ select * from meters where ts > now - 1d and current > 10; ...@@ -138,7 +138,7 @@ select * from meters where ts > now - 1d and current > 10;
订阅的`topic`实际上是它的名字,因为订阅功能是在客户端API中实现的,所以没必要保证它全局唯一,但需要它在一台客户端机器上唯一。 订阅的`topic`实际上是它的名字,因为订阅功能是在客户端API中实现的,所以没必要保证它全局唯一,但需要它在一台客户端机器上唯一。
如果名`topic`的订阅不存在,参数`restart`没有意义;但如果用户程序创建这个订阅后退出,当它再次启动并重新使用这个`topic`时,`restart`就会被用于决定是从头开始读取数据,还是接续上次的位置进行读取。本例中,如果`restart`**true**(非零值),用户程序肯定会读到所有数据。但如果这个订阅之前就存在了,并且已经读取了一部分数据,且`restart`**false****0**),用户程序就不会读到之前已经读取的数据了。 如果名`topic`的订阅不存在,参数`restart`没有意义;但如果用户程序创建这个订阅后退出,当它再次启动并重新使用这个`topic`时,`restart`就会被用于决定是从头开始读取数据,还是接续上次的位置进行读取。本例中,如果`restart`**true**(非零值),用户程序肯定会读到所有数据。但如果这个订阅之前就存在了,并且已经读取了一部分数据,且`restart`**false****0**),用户程序就不会读到之前已经读取的数据了。
`taos_subscribe`的最后一个参数是以毫秒为单位的轮询周期。在同步模式下,如果前后两次调用`taos_consume`的时间间隔小于此时间,`taos_consume`会阻塞,直到间隔超过此时间。异步模式下,这个时间是两次调用回调函数的最小时间间隔。 `taos_subscribe`的最后一个参数是以毫秒为单位的轮询周期。在同步模式下,如果前后两次调用`taos_consume`的时间间隔小于此时间,`taos_consume`会阻塞,直到间隔超过此时间。异步模式下,这个时间是两次调用回调函数的最小时间间隔。
...@@ -179,7 +179,8 @@ void print_result(TAOS_RES* res, int blockFetch) { ...@@ -179,7 +179,8 @@ void print_result(TAOS_RES* res, int blockFetch) {
  } else {   } else {
    while ((row = taos_fetch_row(res))) {     while ((row = taos_fetch_row(res))) {
      char temp[256];       char temp[256];
      taos_print_row(temp, row, fields, num_fields);puts(temp);       taos_print_row(temp, row, fields, num_fields);
      puts(temp);
      nRows++;       nRows++;
    }     }
  }   }
...@@ -211,14 +212,14 @@ taos_unsubscribe(tsub, keep); ...@@ -211,14 +212,14 @@ taos_unsubscribe(tsub, keep);
则可以在示例代码所在目录执行以下命令来编译并启动示例程序: 则可以在示例代码所在目录执行以下命令来编译并启动示例程序:
```shell ```bash
$ make $ make
$ ./subscribe -sql='select * from meters where current > 10;' $ ./subscribe -sql='select * from meters where current > 10;'
``` ```
示例程序启动后,打开另一个终端窗口,启动 TDengine 的 shell 向 **D1001** 插入一条电流为 12A 的数据: 示例程序启动后,打开另一个终端窗口,启动 TDengine 的 shell 向 **D1001** 插入一条电流为 12A 的数据:
```shell ```sql
$ taos $ taos
> use test; > use test;
> insert into D1001 values(now, 12, 220, 1); > insert into D1001 values(now, 12, 220, 1);
...@@ -313,7 +314,7 @@ public class SubscribeDemo { ...@@ -313,7 +314,7 @@ public class SubscribeDemo {
运行示例程序,首先,它会消费符合查询条件的所有历史数据: 运行示例程序,首先,它会消费符合查询条件的所有历史数据:
```shell ```bash
# java -jar subscribe.jar # java -jar subscribe.jar
ts: 1597464000000 current: 12.0 voltage: 220 phase: 1 location: Beijing.Chaoyang groupid : 2 ts: 1597464000000 current: 12.0 voltage: 220 phase: 1 location: Beijing.Chaoyang groupid : 2
...@@ -333,16 +334,16 @@ taos> insert into d1001 values("2020-08-15 12:40:00.000", 12.4, 220, 1); ...@@ -333,16 +334,16 @@ taos> insert into d1001 values("2020-08-15 12:40:00.000", 12.4, 220, 1);
因为这条数据的电流大于10A,示例程序会将其消费: 因为这条数据的电流大于10A,示例程序会将其消费:
```shell ```
ts: 1597466400000 current: 12.4 voltage: 220 phase: 1 location: Beijing.Chaoyang groupid: 2 ts: 1597466400000 current: 12.4 voltage: 220 phase: 1 location: Beijing.Chaoyang groupid: 2
``` ```
## <a class="anchor" id="cache"></a>缓存(Cache) ## <a class="anchor" id="cache"></a>缓存(Cache)
TDengine采用时间驱动缓存管理策略(First-In-First-Out,FIFO),又称为写驱动的缓存管理机制。这种策略有别于读驱动的数据缓存模式(Least-Recent-Use,LRU),直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候,将最早的数据批量写入磁盘。一般意义上来说,对于物联网数据的使用,用户最为关心最近产生的数据,即当前状态。TDengine充分利用了这一特性,将最近到达的(当前状态)数据保存在缓存中。 TDengine采用时间驱动缓存管理策略(First-In-First-Out,FIFO),又称为写驱动的缓存管理机制。这种策略有别于读驱动的数据缓存模式(Least-Recent-Used,LRU),直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候,将最早的数据批量写入磁盘。一般意义上来说,对于物联网数据的使用,用户最为关心最近产生的数据,即当前状态。TDengine充分利用了这一特性,将最近到达的(当前状态)数据保存在缓存中。
TDengine通过查询函数向用户提供毫秒级的数据获取能力。直接将最近到达的数据保存在缓存中,可以更加快速地响应用户针对最近一条或一批数据的查询分析,整体上提供更快的数据库查询响应能力。从这个意义上来说,可通过设置合适的配置参数将TDengine作为数据缓存来使用,而不需要再部署额外的缓存系统,可有效地简化系统架构,降低运维的成本。需要注意的是,TDengine重启以后系统的缓存将被清空,之前缓存的数据均会被批量写入磁盘,缓存的数据将不会像专门的Key-value缓存系统再将之前缓存的数据重新加载到缓存中。 TDengine通过查询函数向用户提供毫秒级的数据获取能力。直接将最近到达的数据保存在缓存中,可以更加快速地响应用户针对最近一条或一批数据的查询分析,整体上提供更快的数据库查询响应能力。从这个意义上来说,可通过设置合适的配置参数将TDengine作为数据缓存来使用,而不需要再部署额外的缓存系统,可有效地简化系统架构,降低运维的成本。需要注意的是,TDengine重启以后系统的缓存将被清空,之前缓存的数据均会被批量写入磁盘,缓存的数据将不会像专门的key-value缓存系统再将之前缓存的数据重新加载到缓存中。
TDengine分配固定大小的内存空间作为缓存空间,缓存空间可根据应用的需求和硬件资源配置。通过适当的设置缓存空间,TDengine可以提供极高性能的写入和查询的支持。TDengine中每个虚拟节点(virtual node)创建时分配独立的缓存池。每个虚拟节点管理自己的缓存池,不同虚拟节点间不共享缓存池。每个虚拟节点内部所属的全部表共享该虚拟节点的缓存池。 TDengine分配固定大小的内存空间作为缓存空间,缓存空间可根据应用的需求和硬件资源配置。通过适当的设置缓存空间,TDengine可以提供极高性能的写入和查询的支持。TDengine中每个虚拟节点(virtual node)创建时分配独立的缓存池。每个虚拟节点管理自己的缓存池,不同虚拟节点间不共享缓存池。每个虚拟节点内部所属的全部表共享该虚拟节点的缓存池。
......
# Java Connector # Java Connector
TDengine 提供了遵循 JDBC 标准(3.0)API 规范的 `taos-jdbcdriver` 实现,可在 maven 的中央仓库 [Sonatype Repository][1] 搜索下载。 ## 安装
Java连接器支持的系统有: Linux 64/Windows x64/Windows x86。
**安装前准备:**
- 已安装TDengine服务器端
- 已安装好TDengine应用驱动,具体请参照 [安装连接器驱动步骤](https://www.taosdata.com/cn/documentation/connector#driver) 章节
TDengine 为了方便 Java 应用使用,提供了遵循 JDBC 标准(3.0)API 规范的 `taos-jdbcdriver` 实现。目前可以通过 [Sonatype Repository](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver) 搜索并下载。
由于 TDengine 的应用驱动是使用C语言开发的,使用 taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库。
- libtaos.so 在 Linux 系统中成功安装 TDengine 后,依赖的本地函数库 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so,该目录包含在 Linux 自动扫描路径上,无需单独指定。
- taos.dll 在 Windows 系统中安装完客户端之后,驱动包依赖的 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。
注意:在 Windows 环境开发时需要安装 TDengine 对应的 [windows 客户端](https://www.taosdata.com/cn/all-downloads/#TDengine-Windows-Client),Linux 服务器安装完 TDengine 之后默认已安装 client,也可以单独安装 [Linux 客户端](https://www.taosdata.com/cn/getting-started/#快速上手) 连接远程 TDengine Server。
### 如何获取 TAOS-JDBCDriver
**maven仓库**
目前 taos-jdbcdriver 已经发布到 [Sonatype Repository](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver) 仓库,且各大仓库都已同步。
- [sonatype](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver)
- [mvnrepository](https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver)
- [maven.aliyun](https://maven.aliyun.com/mvn/search)
maven 项目中使用如下 pom.xml 配置即可:
```xml-dtd
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.18</version>
</dependency>
```
**源码编译打包**
下载 TDengine 源码之后,进入 taos-jdbcdriver 源码目录 `src/connector/jdbc` 执行 `mvn clean package -Dmaven.test.skip=true` 即可生成相应 jar 包。
### 示例程序
示例程序源码位于install_directory/examples/JDBC,有如下目录:
JDBCDemo JDBC示例源程序
JDBCConnectorChecker JDBC安装校验源程序及jar包
Springbootdemo springboot示例源程序
SpringJdbcTemplate SpringJDBC模板
### 安装验证
运行如下指令:
```Bash
cd {install_directory}/examples/JDBC/JDBCConnectorChecker
java -jar JDBCConnectorChecker.jar -host <fqdn>
```
验证通过将打印出成功信息。
## Java连接器的使用
`taos-jdbcdriver` 的实现包括 2 种形式: JDBC-JNI 和 JDBC-RESTful(taos-jdbcdriver-2.0.18 开始支持 JDBC-RESTful)。 JDBC-JNI 通过调用客户端 libtaos.so(或 taos.dll )的本地方法实现, JDBC-RESTful 则在内部封装了 RESTful 接口实现。 `taos-jdbcdriver` 的实现包括 2 种形式: JDBC-JNI 和 JDBC-RESTful(taos-jdbcdriver-2.0.18 开始支持 JDBC-RESTful)。 JDBC-JNI 通过调用客户端 libtaos.so(或 taos.dll )的本地方法实现, JDBC-RESTful 则在内部封装了 RESTful 接口实现。
...@@ -20,7 +86,7 @@ TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致 ...@@ -20,7 +86,7 @@ TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致
* 对每个 Connection 的实例,至多只能有一个打开的 ResultSet 实例;如果在 ResultSet 还没关闭的情况下执行了新的查询,taos-jdbcdriver 会自动关闭上一个 ResultSet。 * 对每个 Connection 的实例,至多只能有一个打开的 ResultSet 实例;如果在 ResultSet 还没关闭的情况下执行了新的查询,taos-jdbcdriver 会自动关闭上一个 ResultSet。
## JDBC-JNI和JDBC-RESTful的对比 ### JDBC-JNI和JDBC-RESTful的对比
<table > <table >
<tr align="center"><th>对比项</th><th>JDBC-JNI</th><th>JDBC-RESTful</th></tr> <tr align="center"><th>对比项</th><th>JDBC-JNI</th><th>JDBC-RESTful</th></tr>
...@@ -51,33 +117,34 @@ TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致 ...@@ -51,33 +117,34 @@ TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致
注意:与 JNI 方式不同,RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,RESTful 下所有对表名、超级表名的引用都需要指定数据库名前缀。 注意:与 JNI 方式不同,RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,RESTful 下所有对表名、超级表名的引用都需要指定数据库名前缀。
## 如何获取 taos-jdbcdriver ### <a class="anchor" id="version"></a>TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本
### maven 仓库
目前 taos-jdbcdriver 已经发布到 [Sonatype Repository][1] 仓库,且各大仓库都已同步。 | taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
| -------------------- | ----------------- | -------- |
* [sonatype][8] | 2.0.31 | 2.1.3.0 及以上 | 1.8.x |
* [mvnrepository][9] | 2.0.22 - 2.0.30 | 2.0.18.0 - 2.1.2.x | 1.8.x |
* [maven.aliyun][10] | 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 |
maven 项目中使用如下 pom.xml 配置即可: | 1.0.3 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
```xml | 1.0.1 | 1.6.1.x 及以上 | 1.8.x |
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.18</version>
</dependency>
```
### 源码编译打包
下载 [TDengine][3] 源码之后,进入 taos-jdbcdriver 源码目录 `src/connector/jdbc` 执行 `mvn clean package -Dmaven.test.skip=true` 即可生成相应 jar 包。
### TDengine DataType 和 Java DataType
TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下:
## JDBC的使用说明 | TDengine DataType | Java DataType |
| ----------------- | ------------------ |
| TIMESTAMP | java.sql.Timestamp |
| INT | java.lang.Integer |
| BIGINT | java.lang.Long |
| FLOAT | java.lang.Float |
| DOUBLE | java.lang.Double |
| SMALLINT | java.lang.Short |
| TINYINT | java.lang.Byte |
| BOOL | java.lang.Boolean |
| BINARY | byte array |
| NCHAR | java.lang.String |
### 获取连接 ### 获取连接
...@@ -112,12 +179,12 @@ Connection conn = DriverManager.getConnection(jdbcUrl); ...@@ -112,12 +179,12 @@ Connection conn = DriverManager.getConnection(jdbcUrl);
**注意**:使用 JDBC-JNI 的 driver,taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库。 **注意**:使用 JDBC-JNI 的 driver,taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库。
* libtaos.so * libtaos.so
linux 系统中成功安装 TDengine 后,依赖的本地函数库 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so,该目录包含在 Linux 自动扫描路径上,无需单独指定。 Linux 系统中成功安装 TDengine 后,依赖的本地函数库 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so,该目录包含在 Linux 自动扫描路径上,无需单独指定。
* taos.dll * taos.dll
windows 系统中安装完客户端之后,驱动包依赖的 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。 Windows 系统中安装完客户端之后,驱动包依赖的 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。
> 在 windows 环境开发时需要安装 TDengine 对应的 [windows 客户端][14],Linux 服务器安装完 TDengine 之后默认已安装 client,也可以单独安装 [Linux 客户端][15] 连接远程 TDengine Server。 > 在 Windows 环境开发时需要安装 TDengine 对应的 [windows 客户端][14],Linux 服务器安装完 TDengine 之后默认已安装 client,也可以单独安装 [Linux 客户端][15] 连接远程 TDengine Server。
JDBC-JNI 的使用请参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1955.html) JDBC-JNI 的使用请参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1955.html)
...@@ -166,8 +233,7 @@ properties 中的配置参数如下: ...@@ -166,8 +233,7 @@ properties 中的配置参数如下:
#### 使用客户端配置文件建立连接 #### 使用客户端配置文件建立连接
当使用 JDBC-JNI 连接 TDengine 集群时,可以使用客户端配置文件,在客户端配置文件中指定集群的 firstEp、secondEp参数。 当使用 JDBC-JNI 连接 TDengine 集群时,可以使用客户端配置文件,在客户端配置文件中指定集群的 firstEp、secondEp参数。如下所示:
如下所示:
1. 在 Java 应用中不指定 hostname 和 port 1. 在 Java 应用中不指定 hostname 和 port
...@@ -214,7 +280,7 @@ TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可 ...@@ -214,7 +280,7 @@ TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可
例如:在 url 中指定了 password 为 taosdata,在 Properties 中指定了 password 为 taosdemo,那么,JDBC 会使用 url 中的 password 建立连接。 例如:在 url 中指定了 password 为 taosdata,在 Properties 中指定了 password 为 taosdemo,那么,JDBC 会使用 url 中的 password 建立连接。
> 更多详细配置请参考[客户端配置][13] > 更多详细配置请参考[客户端配置](https://www.taosdata.com/cn/documentation/administrator/#client)
### 创建数据库和表 ### 创建数据库和表
...@@ -242,8 +308,8 @@ int affectedRows = stmt.executeUpdate("insert into tb values(now, 23, 10.3) (now ...@@ -242,8 +308,8 @@ int affectedRows = stmt.executeUpdate("insert into tb values(now, 23, 10.3) (now
System.out.println("insert " + affectedRows + " rows."); System.out.println("insert " + affectedRows + " rows.");
``` ```
> now 为系统内部函数,默认为服务器当前时间。 > now 为系统内部函数,默认为客户端所在计算机当前时间。
> `now + 1s` 代表服务器当前时间往后加 1 秒,数字后面代表时间单位:a(毫秒), s(秒), m(分), h(小时), d(天),w(周), n(月), y(年)。 > `now + 1s` 代表客户端当前时间往后加 1 秒,数字后面代表时间单位:a(毫秒),s(秒),m(分),h(小时),d(天),w(周),n(月),y(年)。
### 查询数据 ### 查询数据
...@@ -464,7 +530,7 @@ conn.close(); ...@@ -464,7 +530,7 @@ conn.close();
``` ```
> 通过 HikariDataSource.getConnection() 获取连接后,使用完成后需要调用 close() 方法,实际上它并不会关闭连接,只是放回连接池中。 > 通过 HikariDataSource.getConnection() 获取连接后,使用完成后需要调用 close() 方法,实际上它并不会关闭连接,只是放回连接池中。
> 更多 HikariCP 使用问题请查看[官方说明][5] > 更多 HikariCP 使用问题请查看[官方说明](https://github.com/brettwooldridge/HikariCP)
**Druid** **Druid**
...@@ -505,13 +571,13 @@ public static void main(String[] args) throws Exception { ...@@ -505,13 +571,13 @@ public static void main(String[] args) throws Exception {
} }
``` ```
> 更多 druid 使用问题请查看[官方说明][6] > 更多 druid 使用问题请查看[官方说明](https://github.com/alibaba/druid)
**注意事项** **注意事项**
* TDengine `v1.6.4.1` 版本开始提供了一个专门用于心跳检测的函数 `select server_status()`,所以在使用连接池时推荐使用 `select server_status()` 进行 Validation Query。 * TDengine `v1.6.4.1` 版本开始提供了一个专门用于心跳检测的函数 `select server_status()`,所以在使用连接池时推荐使用 `select server_status()` 进行 Validation Query。
如下所示,`select server_status()` 执行成功会返回 `1` 如下所示,`select server_status()` 执行成功会返回 `1`
```shell ```sql
taos> select server_status(); taos> select server_status();
server_status()| server_status()|
================ ================
...@@ -521,43 +587,10 @@ Query OK, 1 row(s) in set (0.000141s) ...@@ -521,43 +587,10 @@ Query OK, 1 row(s) in set (0.000141s)
## 与框架使用 ## 在框架中使用
* Spring JdbcTemplate 中使用 taos-jdbcdriver,可参考 [SpringJdbcTemplate][11] * Spring JdbcTemplate 中使用 taos-jdbcdriver,可参考 [SpringJdbcTemplate](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/SpringJdbcTemplate)
* Springboot + Mybatis 中使用,可参考 [springbootdemo][12] * Springboot + Mybatis 中使用,可参考 [springbootdemo](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/springbootdemo)
## <a class="anchor" id="version"></a>TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本
| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
| -------------------- | ----------------- | -------- |
| 2.0.31 | 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.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 |
| 1.0.3 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.1 | 1.6.1.x 及以上 | 1.8.x |
## TDengine DataType 和 Java DataType
TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下:
| TDengine DataType | Java DataType |
| ----------------- | ------------------ |
| TIMESTAMP | java.sql.Timestamp |
| INT | java.lang.Integer |
| BIGINT | java.lang.Long |
| FLOAT | java.lang.Float |
| DOUBLE | java.lang.Double |
| SMALLINT | java.lang.Short |
| TINYINT | java.lang.Byte |
| BOOL | java.lang.Boolean |
| BINARY | byte array |
| NCHAR | java.lang.String |
...@@ -567,7 +600,7 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对 ...@@ -567,7 +600,7 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对
**原因**:程序没有找到依赖的本地函数库 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
...@@ -575,21 +608,5 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对 ...@@ -575,21 +608,5 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对
**解决方法**:重新安装 64 位 JDK。 **解决方法**:重新安装 64 位 JDK。
* 其它问题请参考 [Issues][7] * 其它问题请参考 [Issues](https://github.com/taosdata/TDengine/issues)
[1]: https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver
[2]: https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver
[3]: https://github.com/taosdata/TDengine
[4]: https://www.taosdata.com/blog/2019/12/03/jdbcdriver%e6%89%be%e4%b8%8d%e5%88%b0%e5%8a%a8%e6%80%81%e9%93%be%e6%8e%a5%e5%ba%93/
[5]: https://github.com/brettwooldridge/HikariCP
[6]: https://github.com/alibaba/druid
[7]: https://github.com/taosdata/TDengine/issues
[8]: https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver
[9]: https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver
[10]: https://maven.aliyun.com/mvn/search
[11]: https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/SpringJdbcTemplate
[12]: https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/springbootdemo
[13]: https://www.taosdata.com/cn/documentation/administrator/#client
[14]: https://www.taosdata.com/cn/all-downloads/#TDengine-Windows-Client
[15]: https://www.taosdata.com/cn/getting-started/#%E5%AE%A2%E6%88%B7%E7%AB%AF
...@@ -23,7 +23,7 @@ sudo cp -rf /usr/local/taos/connector/grafanaplugin /var/lib/grafana/plugins/tde ...@@ -23,7 +23,7 @@ sudo cp -rf /usr/local/taos/connector/grafanaplugin /var/lib/grafana/plugins/tde
#### 配置数据源 #### 配置数据源
用户可以直接通过 localhost:3000 的网址,登录 Grafana 服务器(用户名/密码:admin/admin),通过左侧 `Configuration -> Data Sources` 可以添加数据源,如下图所示: 用户可以直接通过 localhost:3000 的网址,登录 Grafana 服务器(用户名/密码:admin/admin),通过左侧 `Configuration -> Data Sources` 可以添加数据源,如下图所示:
![img](page://images/connections/add_datasource1.jpg) ![img](page://images/connections/add_datasource1.jpg)
...@@ -35,7 +35,7 @@ sudo cp -rf /usr/local/taos/connector/grafanaplugin /var/lib/grafana/plugins/tde ...@@ -35,7 +35,7 @@ sudo cp -rf /usr/local/taos/connector/grafanaplugin /var/lib/grafana/plugins/tde
![img](page://images/connections/add_datasource3.jpg) ![img](page://images/connections/add_datasource3.jpg)
* Host: TDengine 集群的中任意一台服务器的 IP 地址与 TDengine RESTful 接口的端口号(6041),默认 http://localhost:6041 * Host: TDengine 集群的中任意一台服务器的 IP 地址与 TDengine RESTful 接口的端口号(6041),默认 http://localhost:6041
* User:TDengine 用户名。 * User:TDengine 用户名。
* Password:TDengine 用户密码。 * Password:TDengine 用户密码。
...@@ -64,7 +64,7 @@ sudo cp -rf /usr/local/taos/connector/grafanaplugin /var/lib/grafana/plugins/tde ...@@ -64,7 +64,7 @@ sudo cp -rf /usr/local/taos/connector/grafanaplugin /var/lib/grafana/plugins/tde
#### 导入 Dashboard #### 导入 Dashboard
在 Grafana 插件目录 /usr/local/taos/connector/grafana/tdengine/dashboard/ 下提供了一个 `tdengine-grafana.json` 可导入的 dashboard。 在 Grafana 插件目录 /usr/local/taos/connector/grafanaplugin/dashboard 下提供了一个 `tdengine-grafana.json` 可导入的 dashboard。
点击左侧 `Import` 按钮,并上传 `tdengine-grafana.json` 文件: 点击左侧 `Import` 按钮,并上传 `tdengine-grafana.json` 文件:
...@@ -140,13 +140,13 @@ conn<-dbConnect(drv,"jdbc:TSDB://192.168.0.1:0/?user=root&password=taosdata","ro ...@@ -140,13 +140,13 @@ conn<-dbConnect(drv,"jdbc:TSDB://192.168.0.1:0/?user=root&password=taosdata","ro
- dbWriteTable(conn, "test", iris, overwrite=FALSE, append=TRUE):将数据框iris写入表test中,overwrite必须设置为false,append必须设为TRUE,且数据框iris要与表test的结构一致。 - dbWriteTable(conn, "test", iris, overwrite=FALSE, append=TRUE):将数据框iris写入表test中,overwrite必须设置为false,append必须设为TRUE,且数据框iris要与表test的结构一致。
- dbGetQuery(conn, "select count(*) from test"):查询语句 - dbGetQuery(conn, "select count(*) from test"):查询语句
- dbSendUpdate(conn, "use db"):执行任何非查询sql语句。例如dbSendUpdate(conn, "use db"), 写入数据dbSendUpdate(conn, "insert into t1 values(now, 99)")等。 - dbSendUpdate(conn, "use db"):执行任何非查询sql语句。例如dbSendUpdate(conn, "use db"), 写入数据dbSendUpdate(conn, "insert into t1 values(now, 99)")等。
- dbReadTable(conn, "test"):读取表test中数据 - dbReadTable(conn, "test"):读取表test中数据
- dbDisconnect(conn):关闭连接 - dbDisconnect(conn):关闭连接
- dbRemoveTable(conn, "test"):删除表test - dbRemoveTable(conn, "test"):删除表test
TDengine客户端暂不支持如下函数: TDengine客户端暂不支持如下函数:
- dbExistsTable(conn, "test"):是否存在表test - dbExistsTable(conn, "test"):是否存在表test
- dbListTables(conn):显示连接中的所有表 - dbListTables(conn):显示连接中的所有表
...@@ -6,7 +6,7 @@ TDengine can quickly integrate with [Grafana](https://www.grafana.com/), an open ...@@ -6,7 +6,7 @@ TDengine can quickly integrate with [Grafana](https://www.grafana.com/), an open
### Install Grafana ### Install Grafana
TDengine currently supports Grafana 5.2.4 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 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:
https://grafana.com/grafana/download. https://grafana.com/grafana/download.
...@@ -64,7 +64,7 @@ According to the default prompt, query the average system memory usage at the sp ...@@ -64,7 +64,7 @@ According to the default prompt, query the average system memory usage at the sp
#### Import Dashboard #### Import Dashboard
A `tdengine-grafana.json` importable dashboard is provided under the Grafana plug-in directory/usr/local/taos/connector/grafana/tdengine/dashboard/. A `tdengine-grafana.json` importable dashboard is provided under the Grafana plug-in directory `/usr/local/taos/connector/grafanaplugin/dashboard`.
Click the `Import` button on the left panel and upload the `tdengine-grafana.json` file: Click the `Import` button on the left panel and upload the `tdengine-grafana.json` file:
......
...@@ -218,8 +218,4 @@ use telegraf; ...@@ -218,8 +218,4 @@ use telegraf;
使用telegraf这个数据库。然后执行show tables,describe table等命令详细查询下telegraf这个库里保存了些什么数据。 使用telegraf这个数据库。然后执行show tables,describe table等命令详细查询下telegraf这个库里保存了些什么数据。
具体TDengine的查询语句可以参考[TDengine官方文档](https://www.taosdata.com/cn/documentation/taos-sql/) 具体TDengine的查询语句可以参考[TDengine官方文档](https://www.taosdata.com/cn/documentation/taos-sql/)
## 接入多个监控对象 ## 接入多个监控对象
<<<<<<< HEAD
就像前面原理介绍的,这个miniDevops的小系统,已经提供了一个时序数据库和可视化系统,对于多台机器的监控,只需要将每台机器的telegraf或prometheus配置按上面所述修改,就可以完成监控数据采集和可视化呈现了。 就像前面原理介绍的,这个miniDevops的小系统,已经提供了一个时序数据库和可视化系统,对于多台机器的监控,只需要将每台机器的telegraf或prometheus配置按上面所述修改,就可以完成监控数据采集和可视化呈现了。
=======
就像前面原理介绍的,这个miniDevops的小系统,已经提供了一个时序数据库和可视化系统,对于多台机器的监控,只需要将每台机器的telegraf或prometheus配置按上面所述修改,就可以完成监控数据采集和可视化呈现了。
>>>>>>> 740f82af58c4ecc2deecfa36fb1de4ef5ee55efc
...@@ -1944,20 +1944,6 @@ static void addPrimaryTsColIntoResult(SQueryInfo* pQueryInfo, SSqlCmd* pCmd) { ...@@ -1944,20 +1944,6 @@ static void addPrimaryTsColIntoResult(SQueryInfo* pQueryInfo, SSqlCmd* pCmd) {
pQueryInfo->type |= TSDB_QUERY_TYPE_PROJECTION_QUERY; pQueryInfo->type |= TSDB_QUERY_TYPE_PROJECTION_QUERY;
} }
bool isValidDistinctSql(SQueryInfo* pQueryInfo) {
if (pQueryInfo == NULL) {
return false;
}
if ((pQueryInfo->type & TSDB_QUERY_TYPE_STABLE_QUERY) != TSDB_QUERY_TYPE_STABLE_QUERY
&& (pQueryInfo->type & TSDB_QUERY_TYPE_TABLE_QUERY) != TSDB_QUERY_TYPE_TABLE_QUERY) {
return false;
}
if (tscNumOfExprs(pQueryInfo) == 1){
return true;
}
return false;
}
static bool hasNoneUserDefineExpr(SQueryInfo* pQueryInfo) { static bool hasNoneUserDefineExpr(SQueryInfo* pQueryInfo) {
size_t numOfExprs = taosArrayGetSize(pQueryInfo->exprList); size_t numOfExprs = taosArrayGetSize(pQueryInfo->exprList);
for (int32_t i = 0; i < numOfExprs; ++i) { for (int32_t i = 0; i < numOfExprs; ++i) {
...@@ -2047,8 +2033,11 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS ...@@ -2047,8 +2033,11 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS
const char* msg1 = "too many items in selection clause"; const char* msg1 = "too many items in selection clause";
const char* msg2 = "functions or others can not be mixed up"; const char* msg2 = "functions or others can not be mixed up";
const char* msg3 = "not support query expression"; const char* msg3 = "not support query expression";
const char* msg4 = "only support distinct one column or tag"; const char* msg4 = "not support distinct mixed with proj/agg func";
const char* msg5 = "invalid function name"; const char* msg5 = "invalid function name";
const char* msg6 = "not support distinct mixed with join";
const char* msg7 = "not support distinct mixed with groupby";
const char* msg8 = "not support distinct in nest query";
// too many result columns not support order by in query // too many result columns not support order by in query
if (taosArrayGetSize(pSelNodeList) > TSDB_MAX_COLUMNS) { if (taosArrayGetSize(pSelNodeList) > TSDB_MAX_COLUMNS) {
...@@ -2060,17 +2049,22 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS ...@@ -2060,17 +2049,22 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS
} }
bool hasDistinct = false; bool hasDistinct = false;
bool hasAgg = false;
size_t numOfExpr = taosArrayGetSize(pSelNodeList); size_t numOfExpr = taosArrayGetSize(pSelNodeList);
int32_t distIdx = -1;
for (int32_t i = 0; i < numOfExpr; ++i) { for (int32_t i = 0; i < numOfExpr; ++i) {
int32_t outputIndex = (int32_t)tscNumOfExprs(pQueryInfo); int32_t outputIndex = (int32_t)tscNumOfExprs(pQueryInfo);
tSqlExprItem* pItem = taosArrayGet(pSelNodeList, i); tSqlExprItem* pItem = taosArrayGet(pSelNodeList, i);
if (hasDistinct == false) { if (hasDistinct == false) {
hasDistinct = (pItem->distinct == true); hasDistinct = (pItem->distinct == true);
distIdx = hasDistinct ? i : -1;
} }
int32_t type = pItem->pNode->type; int32_t type = pItem->pNode->type;
if (type == SQL_NODE_SQLFUNCTION) { if (type == SQL_NODE_SQLFUNCTION) {
hasAgg = true;
if (hasDistinct) break;
pItem->pNode->functionId = isValidFunction(pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n); pItem->pNode->functionId = isValidFunction(pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n);
SUdfInfo* pUdfInfo = NULL; SUdfInfo* pUdfInfo = NULL;
if (pItem->pNode->functionId < 0) { if (pItem->pNode->functionId < 0) {
...@@ -2106,10 +2100,22 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS ...@@ -2106,10 +2100,22 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS
} }
} }
//TODO(dengyihao), refactor as function
//handle distinct func mixed with other func
if (hasDistinct == true) { if (hasDistinct == true) {
if (!isValidDistinctSql(pQueryInfo) ) { if (distIdx != 0 || hasAgg) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4);
} }
if (joinQuery) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
if (pQueryInfo->groupbyExpr.numOfGroupCols != 0) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
}
if (pQueryInfo->pDownstream != NULL) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg8);
}
pQueryInfo->distinct = true; pQueryInfo->distinct = true;
} }
...@@ -8682,12 +8688,12 @@ static int32_t doValidateSubquery(SSqlNode* pSqlNode, int32_t index, SSqlObj* pS ...@@ -8682,12 +8688,12 @@ static int32_t doValidateSubquery(SSqlNode* pSqlNode, int32_t index, SSqlObj* pS
pSub->pUdfInfo = pUdfInfo; pSub->pUdfInfo = pUdfInfo;
pSub->udfCopy = true; pSub->udfCopy = true;
pSub->pDownstream = pQueryInfo;
int32_t code = validateSqlNode(pSql, p, pSub); int32_t code = validateSqlNode(pSql, p, pSub);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
return code; return code;
} }
pSub->pDownstream = pQueryInfo;
// create dummy table meta info // create dummy table meta info
STableMetaInfo* pTableMetaInfo1 = calloc(1, sizeof(STableMetaInfo)); STableMetaInfo* pTableMetaInfo1 = calloc(1, sizeof(STableMetaInfo));
...@@ -8796,6 +8802,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf ...@@ -8796,6 +8802,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
return TSDB_CODE_TSC_INVALID_OPERATION; return TSDB_CODE_TSC_INVALID_OPERATION;
} }
if (validateSelectNodeList(pCmd, pQueryInfo, pSqlNode->pSelNodeList, false, timeWindowQuery, true) != if (validateSelectNodeList(pCmd, pQueryInfo, pSqlNode->pSelNodeList, false, timeWindowQuery, true) !=
TSDB_CODE_SUCCESS) { TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_OPERATION; return TSDB_CODE_TSC_INVALID_OPERATION;
......
...@@ -409,7 +409,7 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) { ...@@ -409,7 +409,7 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) {
if ((TSDB_QUERY_HAS_TYPE(pQueryInfo->type, (TSDB_QUERY_TYPE_STABLE_SUBQUERY | TSDB_QUERY_TYPE_SUBQUERY | if ((TSDB_QUERY_HAS_TYPE(pQueryInfo->type, (TSDB_QUERY_TYPE_STABLE_SUBQUERY | TSDB_QUERY_TYPE_SUBQUERY |
TSDB_QUERY_TYPE_TAG_FILTER_QUERY)) && TSDB_QUERY_TYPE_TAG_FILTER_QUERY)) &&
!TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_PROJECTION_QUERY)) || !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_PROJECTION_QUERY)) ||
(TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_NEST_SUBQUERY))) { (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_NEST_SUBQUERY)) || (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_STABLE_SUBQUERY) && pQueryInfo->distinct)) {
// do nothing in case of super table subquery // do nothing in case of super table subquery
} else { } else {
pSql->retry += 1; pSql->retry += 1;
...@@ -502,10 +502,22 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) { ...@@ -502,10 +502,22 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) {
} }
rpcMsg->code = (pRes->code == TSDB_CODE_SUCCESS) ? (int32_t)pRes->numOfRows : pRes->code; rpcMsg->code = (pRes->code == TSDB_CODE_SUCCESS) ? (int32_t)pRes->numOfRows : pRes->code;
if (pRes->code == TSDB_CODE_RPC_FQDN_ERROR) { if (pRes->code == TSDB_CODE_RPC_FQDN_ERROR) {
tscAllocPayload(pCmd, TSDB_FQDN_LEN + 64);
// handle three situation
// 1. epset retry, only return last failure ep
// 2. no epset retry, like 'taos -h invalidFqdn', return invalidFqdn
// 3. other situation, no expected
if (pEpSet) { if (pEpSet) {
char buf[TSDB_FQDN_LEN + 64] = {0};
tscAllocPayload(pCmd, sizeof(buf));
sprintf(tscGetErrorMsgPayload(pCmd), "%s\"%s\"", tstrerror(pRes->code),pEpSet->fqdn[(pEpSet->inUse)%(pEpSet->numOfEps)]); sprintf(tscGetErrorMsgPayload(pCmd), "%s\"%s\"", tstrerror(pRes->code),pEpSet->fqdn[(pEpSet->inUse)%(pEpSet->numOfEps)]);
} else if (pCmd->command >= TSDB_SQL_MGMT) {
SRpcEpSet tEpset;
SRpcCorEpSet *pCorEpSet = pSql->pTscObj->tscCorMgmtEpSet;
taosCorBeginRead(&pCorEpSet->version);
tEpset = pCorEpSet->epSet;
taosCorEndRead(&pCorEpSet->version);
sprintf(tscGetErrorMsgPayload(pCmd), "%s\"%s\"", tstrerror(pRes->code),tEpset.fqdn[(tEpset.inUse)%(tEpset.numOfEps)]);
} else { } else {
sprintf(tscGetErrorMsgPayload(pCmd), "%s", tstrerror(pRes->code)); sprintf(tscGetErrorMsgPayload(pCmd), "%s", tstrerror(pRes->code));
} }
......
...@@ -821,17 +821,22 @@ static void doSetupSDataBlock(SSqlRes* pRes, SSDataBlock* pBlock, SFilterInfo* p ...@@ -821,17 +821,22 @@ static void doSetupSDataBlock(SSqlRes* pRes, SSDataBlock* pBlock, SFilterInfo* p
// filter data if needed // filter data if needed
if (pFilterInfo) { if (pFilterInfo) {
//doSetFilterColumnInfo(pFilterInfo, numOfFilterCols, pBlock); //doSetFilterColumnInfo(pFilterInfo, numOfFilterCols, pBlock);
doSetFilterColInfo(pFilterInfo, pBlock); filterSetColFieldData(pFilterInfo, pBlock->info.numOfCols, pBlock->pDataBlock);
bool gotNchar = false; bool gotNchar = false;
filterConverNcharColumns(pFilterInfo, pBlock->info.rows, &gotNchar); filterConverNcharColumns(pFilterInfo, pBlock->info.rows, &gotNchar);
int8_t* p = calloc(pBlock->info.rows, sizeof(int8_t)); int8_t* p = NULL;
//bool all = doFilterDataBlock(pFilterInfo, numOfFilterCols, pBlock->info.rows, p); //bool all = doFilterDataBlock(pFilterInfo, numOfFilterCols, pBlock->info.rows, p);
bool all = filterExecute(pFilterInfo, pBlock->info.rows, p); bool all = filterExecute(pFilterInfo, pBlock->info.rows, &p, NULL, 0);
if (gotNchar) { if (gotNchar) {
filterFreeNcharColumns(pFilterInfo); filterFreeNcharColumns(pFilterInfo);
} }
if (!all) { if (!all) {
if (p) {
doCompactSDataBlock(pBlock, pBlock->info.rows, p); doCompactSDataBlock(pBlock, pBlock->info.rows, p);
} else {
pBlock->info.rows = 0;
pBlock->pBlockStatis = NULL; // clean the block statistics info
}
} }
tfree(p); tfree(p);
...@@ -1522,7 +1527,6 @@ void tscFreeSqlObj(SSqlObj* pSql) { ...@@ -1522,7 +1527,6 @@ void tscFreeSqlObj(SSqlObj* pSql) {
tscFreeSqlResult(pSql); tscFreeSqlResult(pSql);
tscResetSqlCmd(pCmd, false, pSql->self); tscResetSqlCmd(pCmd, false, pSql->self);
memset(pCmd->payload, 0, (size_t)pCmd->allocSize);
tfree(pCmd->payload); tfree(pCmd->payload);
pCmd->allocSize = 0; pCmd->allocSize = 0;
...@@ -3618,6 +3622,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, __async_cb_func_t ...@@ -3618,6 +3622,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, __async_cb_func_t
pNewQueryInfo->numOfTables = 0; pNewQueryInfo->numOfTables = 0;
pNewQueryInfo->pTableMetaInfo = NULL; pNewQueryInfo->pTableMetaInfo = NULL;
pNewQueryInfo->bufLen = pQueryInfo->bufLen; pNewQueryInfo->bufLen = pQueryInfo->bufLen;
pNewQueryInfo->distinct = pQueryInfo->distinct;
pNewQueryInfo->buf = malloc(pQueryInfo->bufLen); pNewQueryInfo->buf = malloc(pQueryInfo->bufLen);
if (pNewQueryInfo->buf == NULL) { if (pNewQueryInfo->buf == NULL) {
......
...@@ -60,6 +60,7 @@ extern char tsLocale[]; ...@@ -60,6 +60,7 @@ extern char tsLocale[];
extern char tsCharset[]; // default encode string extern char tsCharset[]; // default encode string
extern int8_t tsEnableCoreFile; extern int8_t tsEnableCoreFile;
extern int32_t tsCompressMsgSize; extern int32_t tsCompressMsgSize;
extern int32_t tsMaxNumOfDistinctResults;
extern char tsTempDir[]; extern char tsTempDir[];
//query buffer management //query buffer management
......
...@@ -87,6 +87,9 @@ int32_t tsMaxNumOfOrderedResults = 100000; ...@@ -87,6 +87,9 @@ int32_t tsMaxNumOfOrderedResults = 100000;
// 10 ms for sliding time, the value will changed in case of time precision changed // 10 ms for sliding time, the value will changed in case of time precision changed
int32_t tsMinSlidingTime = 10; int32_t tsMinSlidingTime = 10;
// the maxinum number of distict query result
int32_t tsMaxNumOfDistinctResults = 1000 * 10000;
// 1 us for interval time range, changed accordingly // 1 us for interval time range, changed accordingly
int32_t tsMinIntervalTime = 1; int32_t tsMinIntervalTime = 1;
...@@ -544,6 +547,17 @@ static void doInitGlobalConfig(void) { ...@@ -544,6 +547,17 @@ static void doInitGlobalConfig(void) {
cfg.unitType = TAOS_CFG_UTYPE_NONE; cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg); taosInitConfigOption(cfg);
cfg.option = "maxNumOfDistinctRes";
cfg.ptr = &tsMaxNumOfDistinctResults;
cfg.valType = TAOS_CFG_VTYPE_INT32;
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_SHOW | TSDB_CFG_CTYPE_B_CLIENT;
cfg.minValue = 10*10000;
cfg.maxValue = 10000*10000;
cfg.ptrLength = 0;
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
cfg.option = "numOfMnodes"; cfg.option = "numOfMnodes";
cfg.ptr = &tsNumOfMnodes; cfg.ptr = &tsNumOfMnodes;
cfg.valType = TAOS_CFG_VTYPE_INT32; cfg.valType = TAOS_CFG_VTYPE_INT32;
......
...@@ -109,6 +109,24 @@ function convertDouble(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) ...@@ -109,6 +109,24 @@ function convertDouble(data, num_of_rows, nbytes = 0, offset = 0, precision = 0)
return res; return res;
} }
function convertBinary(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) {
data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset);
let res = [];
let currOffset = 0;
while (currOffset < data.length) {
let len = data.readIntLE(currOffset, 2);
let dataEntry = data.slice(currOffset + 2, currOffset + len + 2); //one entry in a row under a column;
if (dataEntry[0] == 255) {
res.push(null)
} else {
res.push(dataEntry.toString("utf-8"));
}
currOffset += nbytes;
}
return res;
}
function convertNchar(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { function convertNchar(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) {
data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset);
let res = []; let res = [];
...@@ -117,7 +135,11 @@ function convertNchar(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) ...@@ -117,7 +135,11 @@ function convertNchar(data, num_of_rows, nbytes = 0, offset = 0, precision = 0)
while (currOffset < data.length) { while (currOffset < data.length) {
let len = data.readIntLE(currOffset, 2); let len = data.readIntLE(currOffset, 2);
let dataEntry = data.slice(currOffset + 2, currOffset + len + 2); //one entry in a row under a column; let dataEntry = data.slice(currOffset + 2, currOffset + len + 2); //one entry in a row under a column;
if (dataEntry[0] == 255 && dataEntry[1] == 255) {
res.push(null)
} else {
res.push(dataEntry.toString("utf-8")); res.push(dataEntry.toString("utf-8"));
}
currOffset += nbytes; currOffset += nbytes;
} }
return res; return res;
...@@ -132,7 +154,7 @@ let convertFunctions = { ...@@ -132,7 +154,7 @@ let convertFunctions = {
[FieldTypes.C_BIGINT]: convertBigint, [FieldTypes.C_BIGINT]: convertBigint,
[FieldTypes.C_FLOAT]: convertFloat, [FieldTypes.C_FLOAT]: convertFloat,
[FieldTypes.C_DOUBLE]: convertDouble, [FieldTypes.C_DOUBLE]: convertDouble,
[FieldTypes.C_BINARY]: convertNchar, [FieldTypes.C_BINARY]: convertBinary,
[FieldTypes.C_TIMESTAMP]: convertTimestamp, [FieldTypes.C_TIMESTAMP]: convertTimestamp,
[FieldTypes.C_NCHAR]: convertNchar [FieldTypes.C_NCHAR]: convertNchar
} }
......
const taos = require('../tdengine');
var conn = taos.connect({ host: "localhost" });
var c1 = conn.cursor();
function checkData(data, row, col, expect) {
let checkdata = data[row][col];
if (checkdata == expect) {
// console.log('check pass')
}
else {
console.log('check failed, expect ' + expect + ', but is ' + checkdata)
}
}
c1.execute('drop database if exists testnodejsnchar')
c1.execute('create database testnodejsnchar')
c1.execute('use testnodejsnchar');
c1.execute('create table tb (ts timestamp, value float, text binary(200))')
c1.execute("insert into tb values('2021-06-10 00:00:00', 24.7, '中文10000000000000000000000');") -
c1.execute('insert into tb values(1623254400150, 24.7, NULL);')
c1.execute('import into tb values(1623254400300, 24.7, "中文3中文10000000000000000000000中文10000000000000000000000中文10000000000000000000000中文10000000000000000000000");')
sql = 'select * from tb;'
console.log('*******************************************')
c1.execute(sql);
data = c1.fetchall();
console.log(data)
//check data about insert data
checkData(data, 0, 2, '中文10000000000000000000000')
checkData(data, 1, 2, null)
checkData(data, 2, 2, '中文3中文10000000000000000000000中文10000000000000000000000中文10000000000000000000000中文10000000000000000000000')
\ No newline at end of file
...@@ -56,6 +56,8 @@ typedef struct SShellArguments { ...@@ -56,6 +56,8 @@ typedef struct SShellArguments {
int abort; int abort;
int port; int port;
int pktLen; int pktLen;
int pktNum;
char* pktType;
char* netTestRole; char* netTestRole;
} SShellArguments; } SShellArguments;
......
...@@ -64,6 +64,10 @@ void printHelp() { ...@@ -64,6 +64,10 @@ void printHelp() {
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
char DARWINCLIENT_VERSION[] = "Welcome to the TDengine shell from %s, Client Version:%s\n"
"Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.\n\n";
char g_password[MAX_PASSWORD_SIZE];
void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
wordexp_t full_path; wordexp_t full_path;
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
...@@ -77,8 +81,19 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -77,8 +81,19 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
} }
} }
// for password // for password
else if (strcmp(argv[i], "-p") == 0) { else if (strncmp(argv[i], "-p", 2) == 0) {
arguments->is_use_passwd = true; strcpy(tsOsName, "Darwin");
printf(DARWINCLIENT_VERSION, tsOsName, taos_get_client_info());
if (strlen(argv[i]) == 2) {
printf("Enter password: ");
if (scanf("%s", g_password) > 1) {
fprintf(stderr, "password read error\n");
}
getchar();
} else {
tstrncpy(g_password, (char *)(argv[i] + 2), MAX_PASSWORD_SIZE);
}
arguments->password = g_password;
} }
// for management port // for management port
else if (strcmp(argv[i], "-P") == 0) { else if (strcmp(argv[i], "-P") == 0) {
......
...@@ -65,7 +65,15 @@ extern TAOS *taos_connect_auth(const char *ip, const char *user, const char *aut ...@@ -65,7 +65,15 @@ extern TAOS *taos_connect_auth(const char *ip, const char *user, const char *aut
*/ */
TAOS *shellInit(SShellArguments *_args) { TAOS *shellInit(SShellArguments *_args) {
printf("\n"); printf("\n");
if (!_args->is_use_passwd) {
#ifdef TD_WINDOWS
strcpy(tsOsName, "Windows");
#elif defined(TD_DARWIN)
strcpy(tsOsName, "Darwin");
#endif
printf(CLIENT_VERSION, tsOsName, taos_get_client_info()); printf(CLIENT_VERSION, tsOsName, taos_get_client_info());
}
fflush(stdout); fflush(stdout);
// set options before initializing // set options before initializing
...@@ -73,9 +81,7 @@ TAOS *shellInit(SShellArguments *_args) { ...@@ -73,9 +81,7 @@ TAOS *shellInit(SShellArguments *_args) {
taos_options(TSDB_OPTION_TIMEZONE, _args->timezone); taos_options(TSDB_OPTION_TIMEZONE, _args->timezone);
} }
if (_args->is_use_passwd) { if (!_args->is_use_passwd) {
if (_args->password == NULL) _args->password = getpass("Enter password: ");
} else {
_args->password = TSDB_DEFAULT_PASS; _args->password = TSDB_DEFAULT_PASS;
} }
......
...@@ -34,7 +34,7 @@ static char doc[] = ""; ...@@ -34,7 +34,7 @@ static char doc[] = "";
static char args_doc[] = ""; static char args_doc[] = "";
static struct argp_option options[] = { static struct argp_option options[] = {
{"host", 'h', "HOST", 0, "TDengine server FQDN to connect. The default host is localhost."}, {"host", 'h', "HOST", 0, "TDengine server FQDN to connect. The default host is localhost."},
{"password", 'p', "PASSWORD", OPTION_ARG_OPTIONAL, "The password to use when connecting to the server."}, {"password", 'p', 0, 0, "The password to use when connecting to the server."},
{"port", 'P', "PORT", 0, "The TCP/IP port number to use for the connection."}, {"port", 'P', "PORT", 0, "The TCP/IP port number to use for the connection."},
{"user", 'u', "USER", 0, "The user name to use when connecting to the server."}, {"user", 'u', "USER", 0, "The user name to use when connecting to the server."},
{"auth", 'A', "Auth", 0, "The auth string to use when connecting to the server."}, {"auth", 'A', "Auth", 0, "The auth string to use when connecting to the server."},
...@@ -50,6 +50,8 @@ static struct argp_option options[] = { ...@@ -50,6 +50,8 @@ static struct argp_option options[] = {
{"timezone", 't', "TIMEZONE", 0, "Time zone of the shell, default is local."}, {"timezone", 't', "TIMEZONE", 0, "Time zone of the shell, default is local."},
{"netrole", 'n', "NETROLE", 0, "Net role when network connectivity test, default is startup, options: client|server|rpc|startup|sync."}, {"netrole", 'n', "NETROLE", 0, "Net role when network connectivity test, default is startup, options: client|server|rpc|startup|sync."},
{"pktlen", 'l', "PKTLEN", 0, "Packet length used for net test, default is 1000 bytes."}, {"pktlen", 'l', "PKTLEN", 0, "Packet length used for net test, default is 1000 bytes."},
{"pktnum", 'N', "PKTNUM", 0, "Packet numbers used for net test, default is 100."},
{"pkttype", 'S', "PKTTYPE", 0, "Packet type used for net test, default is TCP."},
{0}}; {0}};
static error_t parse_opt(int key, char *arg, struct argp_state *state) { static error_t parse_opt(int key, char *arg, struct argp_state *state) {
...@@ -63,8 +65,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { ...@@ -63,8 +65,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
arguments->host = arg; arguments->host = arg;
break; break;
case 'p': case 'p':
arguments->is_use_passwd = true;
if (arg) arguments->password = arg;
break; break;
case 'P': case 'P':
if (arg) { if (arg) {
...@@ -148,6 +148,17 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { ...@@ -148,6 +148,17 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
return -1; return -1;
} }
break; break;
case 'N':
if (arg) {
arguments->pktNum = atoi(arg);
} else {
fprintf(stderr, "Invalid packet number\n");
return -1;
}
break;
case 'S':
arguments->pktType = arg;
break;
case OPT_ABORT: case OPT_ABORT:
arguments->abort = 1; arguments->abort = 1;
break; break;
...@@ -160,12 +171,41 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { ...@@ -160,12 +171,41 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
/* Our argp parser. */ /* Our argp parser. */
static struct argp argp = {options, parse_opt, args_doc, doc}; static struct argp argp = {options, parse_opt, args_doc, doc};
char LINUXCLIENT_VERSION[] = "Welcome to the TDengine shell from %s, Client Version:%s\n"
"Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.\n\n";
char g_password[MAX_PASSWORD_SIZE];
static void parse_password(
int argc, char *argv[], SShellArguments *arguments) {
for (int i = 1; i < argc; i++) {
if (strncmp(argv[i], "-p", 2) == 0) {
strcpy(tsOsName, "Linux");
printf(LINUXCLIENT_VERSION, tsOsName, taos_get_client_info());
if (strlen(argv[i]) == 2) {
printf("Enter password: ");
if (scanf("%20s", g_password) > 1) {
fprintf(stderr, "password reading error\n");
}
getchar();
} else {
tstrncpy(g_password, (char *)(argv[i] + 2), MAX_PASSWORD_SIZE);
}
arguments->password = g_password;
arguments->is_use_passwd = true;
}
}
}
void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
static char verType[32] = {0}; static char verType[32] = {0};
sprintf(verType, "version: %s\n", version); sprintf(verType, "version: %s\n", version);
argp_program_version = verType; argp_program_version = verType;
if (argc > 1) {
parse_password(argc, argv, arguments);
}
argp_parse(&argp, argc, argv, 0, 0, arguments); argp_parse(&argp, argc, argv, 0, 0, arguments);
if (arguments->abort) { if (arguments->abort) {
#ifndef _ALPINE #ifndef _ALPINE
......
...@@ -71,7 +71,9 @@ int checkVersion() { ...@@ -71,7 +71,9 @@ int checkVersion() {
// Global configurations // Global configurations
SShellArguments args = { SShellArguments args = {
.host = NULL, .host = NULL,
#ifndef TD_WINDOWS
.password = NULL, .password = NULL,
#endif
.user = NULL, .user = NULL,
.database = NULL, .database = NULL,
.timezone = NULL, .timezone = NULL,
...@@ -83,6 +85,8 @@ SShellArguments args = { ...@@ -83,6 +85,8 @@ SShellArguments args = {
.threadNum = 5, .threadNum = 5,
.commands = NULL, .commands = NULL,
.pktLen = 1000, .pktLen = 1000,
.pktNum = 100,
.pktType = "TCP",
.netTestRole = NULL .netTestRole = NULL
}; };
...@@ -116,7 +120,7 @@ int main(int argc, char* argv[]) { ...@@ -116,7 +120,7 @@ int main(int argc, char* argv[]) {
printf("Failed to init taos"); printf("Failed to init taos");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
taosNetTest(args.netTestRole, args.host, args.port, args.pktLen); taosNetTest(args.netTestRole, args.host, args.port, args.pktLen, args.pktNum, args.pktType);
exit(0); exit(0);
} }
......
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
extern char configDir[]; extern char configDir[];
char WINCLIENT_VERSION[] = "Welcome to the TDengine shell from %s, Client Version:%s\n"
"Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.\n\n";
void printVersion() { void printVersion() {
printf("version: %s\n", version); printf("version: %s\n", version);
} }
...@@ -55,12 +58,18 @@ void printHelp() { ...@@ -55,12 +58,18 @@ void printHelp() {
printf("%s%s%s\n", indent, indent, "Net role when network connectivity test, default is startup, options: client|server|rpc|startup|sync."); printf("%s%s%s\n", indent, indent, "Net role when network connectivity test, default is startup, options: client|server|rpc|startup|sync.");
printf("%s%s\n", indent, "-l"); printf("%s%s\n", indent, "-l");
printf("%s%s%s\n", indent, indent, "Packet length used for net test, default is 1000 bytes."); printf("%s%s%s\n", indent, indent, "Packet length used for net test, default is 1000 bytes.");
printf("%s%s\n", indent, "-N");
printf("%s%s%s\n", indent, indent, "Packet numbers used for net test, default is 100.");
printf("%s%s\n", indent, "-S");
printf("%s%s%s\n", indent, indent, "Packet type used for net test, default is TCP.");
printf("%s%s\n", indent, "-V"); printf("%s%s\n", indent, "-V");
printf("%s%s%s\n", indent, indent, "Print program version."); printf("%s%s%s\n", indent, indent, "Print program version.");
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
char g_password[MAX_PASSWORD_SIZE];
void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
// for host // for host
...@@ -73,11 +82,20 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -73,11 +82,20 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
} }
} }
// for password // for password
else if (strcmp(argv[i], "-p") == 0) { else if (strncmp(argv[i], "-p", 2) == 0) {
arguments->is_use_passwd = true; arguments->is_use_passwd = true;
if (i < argc - 1 && argv[i + 1][0] != '-') { strcpy(tsOsName, "Windows");
arguments->password = argv[++i]; printf(WINCLIENT_VERSION, tsOsName, taos_get_client_info());
if (strlen(argv[i]) == 2) {
printf("Enter password: ");
if (scanf("%s", g_password) > 1) {
fprintf(stderr, "password read error!\n");
}
getchar();
} else {
tstrncpy(g_password, (char *)(argv[i] + 2), MAX_PASSWORD_SIZE);
} }
arguments->password = g_password;
} }
// for management port // for management port
else if (strcmp(argv[i], "-P") == 0) { else if (strcmp(argv[i], "-P") == 0) {
...@@ -170,6 +188,22 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -170,6 +188,22 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
else if (strcmp(argv[i], "-N") == 0) {
if (i < argc - 1) {
arguments->pktNum = atoi(argv[++i]);
} else {
fprintf(stderr, "option -N requires an argument\n");
exit(EXIT_FAILURE);
}
}
else if (strcmp(argv[i], "-S") == 0) {
if (i < argc - 1) {
arguments->pktType = argv[++i];
} else {
fprintf(stderr, "option -S requires an argument\n");
exit(EXIT_FAILURE);
}
}
else if (strcmp(argv[i], "-V") == 0) { else if (strcmp(argv[i], "-V") == 0) {
printVersion(); printVersion();
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
......
...@@ -77,7 +77,7 @@ extern char configDir[]; ...@@ -77,7 +77,7 @@ extern char configDir[];
#define COL_BUFFER_LEN ((TSDB_COL_NAME_LEN + 15) * TSDB_MAX_COLUMNS) #define COL_BUFFER_LEN ((TSDB_COL_NAME_LEN + 15) * TSDB_MAX_COLUMNS)
#define MAX_USERNAME_SIZE 64 #define MAX_USERNAME_SIZE 64
#define MAX_PASSWORD_SIZE 16 #define MAX_PASSWORD_SIZE 20
#define MAX_HOSTNAME_SIZE 253 // https://man7.org/linux/man-pages/man7/hostname.7.html #define MAX_HOSTNAME_SIZE 253 // https://man7.org/linux/man-pages/man7/hostname.7.html
#define MAX_TB_NAME_SIZE 64 #define MAX_TB_NAME_SIZE 64
#define MAX_DATA_SIZE (16*TSDB_MAX_COLUMNS)+20 // max record len: 16*MAX_COLUMNS, timestamp string and ,('') need extra space #define MAX_DATA_SIZE (16*TSDB_MAX_COLUMNS)+20 // max record len: 16*MAX_COLUMNS, timestamp string and ,('') need extra space
...@@ -867,7 +867,9 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { ...@@ -867,7 +867,9 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) {
} else if (strncmp(argv[i], "-p", 2) == 0) { } else if (strncmp(argv[i], "-p", 2) == 0) {
if (strlen(argv[i]) == 2) { if (strlen(argv[i]) == 2) {
printf("Enter password:"); printf("Enter password:");
scanf("%s", arguments->password); if (scanf("%s", arguments->password) > 1) {
fprintf(stderr, "password read error!\n");
}
} else { } else {
tstrncpy(arguments->password, (char *)(argv[i] + 2), MAX_PASSWORD_SIZE); tstrncpy(arguments->password, (char *)(argv[i] + 2), MAX_PASSWORD_SIZE);
} }
...@@ -1340,8 +1342,8 @@ static char *rand_bool_str(){ ...@@ -1340,8 +1342,8 @@ static char *rand_bool_str(){
static int32_t rand_bool(){ static int32_t rand_bool(){
static int cursor; static int cursor;
cursor++; cursor++;
cursor = cursor % MAX_PREPARED_RAND; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
return g_randint[cursor] % 2; return g_randint[cursor % MAX_PREPARED_RAND] % 2;
} }
static char *rand_tinyint_str() static char *rand_tinyint_str()
...@@ -1356,8 +1358,8 @@ static int32_t rand_tinyint() ...@@ -1356,8 +1358,8 @@ static int32_t rand_tinyint()
{ {
static int cursor; static int cursor;
cursor++; cursor++;
cursor = cursor % MAX_PREPARED_RAND; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
return g_randint[cursor] % 128; return g_randint[cursor % MAX_PREPARED_RAND] % 128;
} }
static char *rand_smallint_str() static char *rand_smallint_str()
...@@ -1372,8 +1374,8 @@ static int32_t rand_smallint() ...@@ -1372,8 +1374,8 @@ static int32_t rand_smallint()
{ {
static int cursor; static int cursor;
cursor++; cursor++;
cursor = cursor % MAX_PREPARED_RAND; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
return g_randint[cursor] % 32767; return g_randint[cursor % MAX_PREPARED_RAND] % 32767;
} }
static char *rand_int_str() static char *rand_int_str()
...@@ -1388,8 +1390,8 @@ static int32_t rand_int() ...@@ -1388,8 +1390,8 @@ static int32_t rand_int()
{ {
static int cursor; static int cursor;
cursor++; cursor++;
cursor = cursor % MAX_PREPARED_RAND; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
return g_randint[cursor]; return g_randint[cursor % MAX_PREPARED_RAND];
} }
static char *rand_bigint_str() static char *rand_bigint_str()
...@@ -1404,8 +1406,8 @@ static int64_t rand_bigint() ...@@ -1404,8 +1406,8 @@ static int64_t rand_bigint()
{ {
static int cursor; static int cursor;
cursor++; cursor++;
cursor = cursor % MAX_PREPARED_RAND; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
return g_randbigint[cursor]; return g_randbigint[cursor % MAX_PREPARED_RAND];
} }
static char *rand_float_str() static char *rand_float_str()
...@@ -1421,8 +1423,8 @@ static float rand_float() ...@@ -1421,8 +1423,8 @@ static float rand_float()
{ {
static int cursor; static int cursor;
cursor++; cursor++;
cursor = cursor % MAX_PREPARED_RAND; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
return g_randfloat[cursor]; return g_randfloat[cursor % MAX_PREPARED_RAND];
} }
static char *demo_current_float_str() static char *demo_current_float_str()
...@@ -1437,8 +1439,9 @@ static float UNUSED_FUNC demo_current_float() ...@@ -1437,8 +1439,9 @@ static float UNUSED_FUNC demo_current_float()
{ {
static int cursor; static int cursor;
cursor++; cursor++;
cursor = cursor % MAX_PREPARED_RAND; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
return (float)(9.8 + 0.04 * (g_randint[cursor] % 10) + g_randfloat[cursor]/1000000000); return (float)(9.8 + 0.04 * (g_randint[cursor % MAX_PREPARED_RAND] % 10)
+ g_randfloat[cursor % MAX_PREPARED_RAND]/1000000000);
} }
static char *demo_voltage_int_str() static char *demo_voltage_int_str()
...@@ -1453,8 +1456,8 @@ static int32_t UNUSED_FUNC demo_voltage_int() ...@@ -1453,8 +1456,8 @@ static int32_t UNUSED_FUNC demo_voltage_int()
{ {
static int cursor; static int cursor;
cursor++; cursor++;
cursor = cursor % MAX_PREPARED_RAND; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
return 215 + g_randint[cursor] % 10; return 215 + g_randint[cursor % MAX_PREPARED_RAND] % 10;
} }
static char *demo_phase_float_str() { static char *demo_phase_float_str() {
...@@ -1467,8 +1470,9 @@ static char *demo_phase_float_str() { ...@@ -1467,8 +1470,9 @@ static char *demo_phase_float_str() {
static float UNUSED_FUNC demo_phase_float(){ static float UNUSED_FUNC demo_phase_float(){
static int cursor; static int cursor;
cursor++; cursor++;
cursor = cursor % MAX_PREPARED_RAND; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
return (float)((115 + g_randint[cursor] % 10 + g_randfloat[cursor]/1000000000)/360); return (float)((115 + g_randint[cursor % MAX_PREPARED_RAND] % 10
+ g_randfloat[cursor % MAX_PREPARED_RAND]/1000000000)/360);
} }
#if 0 #if 0
...@@ -5818,6 +5822,7 @@ static int32_t prepareStmtBindArrayByType( ...@@ -5818,6 +5822,7 @@ static int32_t prepareStmtBindArrayByType(
} else if (0 == strncasecmp(dataType, } else if (0 == strncasecmp(dataType,
"INT", strlen("INT"))) { "INT", strlen("INT"))) {
int32_t *bind_int = malloc(sizeof(int32_t)); int32_t *bind_int = malloc(sizeof(int32_t));
assert(bind_int);
if (value) { if (value) {
*bind_int = atoi(value); *bind_int = atoi(value);
...@@ -5832,6 +5837,7 @@ static int32_t prepareStmtBindArrayByType( ...@@ -5832,6 +5837,7 @@ static int32_t prepareStmtBindArrayByType(
} else if (0 == strncasecmp(dataType, } else if (0 == strncasecmp(dataType,
"BIGINT", strlen("BIGINT"))) { "BIGINT", strlen("BIGINT"))) {
int64_t *bind_bigint = malloc(sizeof(int64_t)); int64_t *bind_bigint = malloc(sizeof(int64_t));
assert(bind_bigint);
if (value) { if (value) {
*bind_bigint = atoll(value); *bind_bigint = atoll(value);
...@@ -5846,6 +5852,7 @@ static int32_t prepareStmtBindArrayByType( ...@@ -5846,6 +5852,7 @@ static int32_t prepareStmtBindArrayByType(
} else if (0 == strncasecmp(dataType, } else if (0 == strncasecmp(dataType,
"FLOAT", strlen("FLOAT"))) { "FLOAT", strlen("FLOAT"))) {
float *bind_float = malloc(sizeof(float)); float *bind_float = malloc(sizeof(float));
assert(bind_float);
if (value) { if (value) {
*bind_float = (float)atof(value); *bind_float = (float)atof(value);
...@@ -5860,6 +5867,7 @@ static int32_t prepareStmtBindArrayByType( ...@@ -5860,6 +5867,7 @@ static int32_t prepareStmtBindArrayByType(
} else if (0 == strncasecmp(dataType, } else if (0 == strncasecmp(dataType,
"DOUBLE", strlen("DOUBLE"))) { "DOUBLE", strlen("DOUBLE"))) {
double *bind_double = malloc(sizeof(double)); double *bind_double = malloc(sizeof(double));
assert(bind_double);
if (value) { if (value) {
*bind_double = atof(value); *bind_double = atof(value);
...@@ -5874,6 +5882,7 @@ static int32_t prepareStmtBindArrayByType( ...@@ -5874,6 +5882,7 @@ static int32_t prepareStmtBindArrayByType(
} else if (0 == strncasecmp(dataType, } else if (0 == strncasecmp(dataType,
"SMALLINT", strlen("SMALLINT"))) { "SMALLINT", strlen("SMALLINT"))) {
int16_t *bind_smallint = malloc(sizeof(int16_t)); int16_t *bind_smallint = malloc(sizeof(int16_t));
assert(bind_smallint);
if (value) { if (value) {
*bind_smallint = (int16_t)atoi(value); *bind_smallint = (int16_t)atoi(value);
...@@ -5888,6 +5897,7 @@ static int32_t prepareStmtBindArrayByType( ...@@ -5888,6 +5897,7 @@ static int32_t prepareStmtBindArrayByType(
} else if (0 == strncasecmp(dataType, } else if (0 == strncasecmp(dataType,
"TINYINT", strlen("TINYINT"))) { "TINYINT", strlen("TINYINT"))) {
int8_t *bind_tinyint = malloc(sizeof(int8_t)); int8_t *bind_tinyint = malloc(sizeof(int8_t));
assert(bind_tinyint);
if (value) { if (value) {
*bind_tinyint = (int8_t)atoi(value); *bind_tinyint = (int8_t)atoi(value);
...@@ -5902,6 +5912,7 @@ static int32_t prepareStmtBindArrayByType( ...@@ -5902,6 +5912,7 @@ static int32_t prepareStmtBindArrayByType(
} else if (0 == strncasecmp(dataType, } else if (0 == strncasecmp(dataType,
"BOOL", strlen("BOOL"))) { "BOOL", strlen("BOOL"))) {
int8_t *bind_bool = malloc(sizeof(int8_t)); int8_t *bind_bool = malloc(sizeof(int8_t));
assert(bind_bool);
if (value) { if (value) {
if (strncasecmp(value, "true", 4)) { if (strncasecmp(value, "true", 4)) {
...@@ -5921,6 +5932,7 @@ static int32_t prepareStmtBindArrayByType( ...@@ -5921,6 +5932,7 @@ static int32_t prepareStmtBindArrayByType(
} else if (0 == strncasecmp(dataType, } else if (0 == strncasecmp(dataType,
"TIMESTAMP", strlen("TIMESTAMP"))) { "TIMESTAMP", strlen("TIMESTAMP"))) {
int64_t *bind_ts2 = malloc(sizeof(int64_t)); int64_t *bind_ts2 = malloc(sizeof(int64_t));
assert(bind_ts2);
if (value) { if (value) {
if (strchr(value, ':') && strchr(value, '-')) { if (strchr(value, ':') && strchr(value, '-')) {
...@@ -5935,6 +5947,7 @@ static int32_t prepareStmtBindArrayByType( ...@@ -5935,6 +5947,7 @@ static int32_t prepareStmtBindArrayByType(
if (TSDB_CODE_SUCCESS != taosParseTime( if (TSDB_CODE_SUCCESS != taosParseTime(
value, &tmpEpoch, strlen(value), value, &tmpEpoch, strlen(value),
timePrec, 0)) { timePrec, 0)) {
free(bind_ts2);
errorPrint("Input %s, time format error!\n", value); errorPrint("Input %s, time format error!\n", value);
return -1; return -1;
} }
...@@ -6259,7 +6272,7 @@ static int32_t prepareStbStmtBindTag( ...@@ -6259,7 +6272,7 @@ static int32_t prepareStbStmtBindTag(
char *bindBuffer = calloc(1, DOUBLE_BUFF_LEN); // g_args.len_of_binary); char *bindBuffer = calloc(1, DOUBLE_BUFF_LEN); // g_args.len_of_binary);
if (bindBuffer == NULL) { if (bindBuffer == NULL) {
errorPrint("%s() LN%d, Failed to allocate %d bind buffer\n", errorPrint("%s() LN%d, Failed to allocate %d bind buffer\n",
__func__, __LINE__, g_args.len_of_binary); __func__, __LINE__, DOUBLE_BUFF_LEN);
return -1; return -1;
} }
...@@ -6291,7 +6304,7 @@ static int32_t prepareStbStmtBindRand( ...@@ -6291,7 +6304,7 @@ static int32_t prepareStbStmtBindRand(
char *bindBuffer = calloc(1, DOUBLE_BUFF_LEN); // g_args.len_of_binary); char *bindBuffer = calloc(1, DOUBLE_BUFF_LEN); // g_args.len_of_binary);
if (bindBuffer == NULL) { if (bindBuffer == NULL) {
errorPrint("%s() LN%d, Failed to allocate %d bind buffer\n", errorPrint("%s() LN%d, Failed to allocate %d bind buffer\n",
__func__, __LINE__, g_args.len_of_binary); __func__, __LINE__, DOUBLE_BUFF_LEN);
return -1; return -1;
} }
......
...@@ -206,9 +206,9 @@ static struct argp_option options[] = { ...@@ -206,9 +206,9 @@ static struct argp_option options[] = {
{"host", 'h', "HOST", 0, "Server host dumping data from. Default is localhost.", 0}, {"host", 'h', "HOST", 0, "Server host dumping data from. Default is localhost.", 0},
{"user", 'u', "USER", 0, "User name used to connect to server. Default is root.", 0}, {"user", 'u', "USER", 0, "User name used to connect to server. Default is root.", 0},
#ifdef _TD_POWER_ #ifdef _TD_POWER_
{"password", 'p', "PASSWORD", 0, "User password to connect to server. Default is powerdb.", 0}, {"password", 'p', 0, 0, "User password to connect to server. Default is powerdb.", 0},
#else #else
{"password", 'p', "PASSWORD", 0, "User password to connect to server. Default is taosdata.", 0}, {"password", 'p', 0, 0, "User password to connect to server. Default is taosdata.", 0},
#endif #endif
{"port", 'P', "PORT", 0, "Port to connect", 0}, {"port", 'P', "PORT", 0, "Port to connect", 0},
{"cversion", 'v', "CVERION", 0, "client version", 0}, {"cversion", 'v', "CVERION", 0, "client version", 0},
...@@ -248,12 +248,14 @@ static struct argp_option options[] = { ...@@ -248,12 +248,14 @@ static struct argp_option options[] = {
{0} {0}
}; };
#define MAX_PASSWORD_SIZE 20
/* Used by main to communicate with parse_opt. */ /* Used by main to communicate with parse_opt. */
typedef struct arguments { typedef struct arguments {
// connection option // connection option
char *host; char *host;
char *user; char *user;
char *password; char password[MAX_PASSWORD_SIZE];
uint16_t port; uint16_t port;
char cversion[12]; char cversion[12];
uint16_t mysqlFlag; uint16_t mysqlFlag;
...@@ -376,7 +378,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { ...@@ -376,7 +378,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
g_args.user = arg; g_args.user = arg;
break; break;
case 'p': case 'p':
g_args.password = arg;
break; break;
case 'P': case 'P':
g_args.port = atoi(arg); g_args.port = atoi(arg);
...@@ -554,6 +555,23 @@ static void parse_precision_first( ...@@ -554,6 +555,23 @@ static void parse_precision_first(
} }
} }
static void parse_password(
int argc, char *argv[], SArguments *arguments) {
for (int i = 1; i < argc; i++) {
if (strncmp(argv[i], "-p", 2) == 0) {
if (strlen(argv[i]) == 2) {
printf("Enter password: ");
if(scanf("%20s", arguments->password) > 1) {
errorPrint("%s() LN%d, password read error!\n", __func__, __LINE__);
}
} else {
tstrncpy(arguments->password, (char *)(argv[i] + 2), MAX_PASSWORD_SIZE);
}
argv[i] = "";
}
}
}
static void parse_timestamp( static void parse_timestamp(
int argc, char *argv[], SArguments *arguments) { int argc, char *argv[], SArguments *arguments) {
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
...@@ -616,9 +634,10 @@ int main(int argc, char *argv[]) { ...@@ -616,9 +634,10 @@ int main(int argc, char *argv[]) {
int ret = 0; int ret = 0;
/* Parse our arguments; every option seen by parse_opt will be /* Parse our arguments; every option seen by parse_opt will be
reflected in arguments. */ reflected in arguments. */
if (argc > 2) { if (argc > 1) {
parse_precision_first(argc, argv, &g_args); parse_precision_first(argc, argv, &g_args);
parse_timestamp(argc, argv, &g_args); parse_timestamp(argc, argv, &g_args);
parse_password(argc, argv, &g_args);
} }
argp_parse(&argp, argc, argv, 0, 0, &g_args); argp_parse(&argp, argc, argv, 0, 0, &g_args);
......
...@@ -515,13 +515,21 @@ typedef struct SStateWindowOperatorInfo { ...@@ -515,13 +515,21 @@ typedef struct SStateWindowOperatorInfo {
bool reptScan; bool reptScan;
} SStateWindowOperatorInfo; } SStateWindowOperatorInfo;
typedef struct SDistinctDataInfo {
int32_t index;
int32_t type;
int32_t bytes;
} SDistinctDataInfo;
typedef struct SDistinctOperatorInfo { typedef struct SDistinctOperatorInfo {
SHashObj *pSet; SHashObj *pSet;
SSDataBlock *pRes; SSDataBlock *pRes;
bool recordNullVal; //has already record the null value, no need to try again bool recordNullVal; //has already record the null value, no need to try again
int64_t threshold; int64_t threshold;
int64_t outputCapacity; int64_t outputCapacity;
int32_t colIndex; int32_t totalBytes;
char* buf;
SArray* pDistinctDataInfo;
} SDistinctOperatorInfo; } SDistinctOperatorInfo;
struct SGlobalMerger; struct SGlobalMerger;
...@@ -590,7 +598,6 @@ SSDataBlock* doSLimit(void* param, bool* newgroup); ...@@ -590,7 +598,6 @@ SSDataBlock* doSLimit(void* param, bool* newgroup);
int32_t doCreateFilterInfo(SColumnInfo* pCols, int32_t numOfCols, int32_t numOfFilterCols, SSingleColumnFilterInfo** pFilterInfo, uint64_t qId); int32_t doCreateFilterInfo(SColumnInfo* pCols, int32_t numOfCols, int32_t numOfFilterCols, SSingleColumnFilterInfo** pFilterInfo, uint64_t qId);
void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, SSDataBlock* pBlock); void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, SSDataBlock* pBlock);
void doSetFilterColInfo(SFilterInfo *pFilters, SSDataBlock* pBlock);
bool doFilterDataBlock(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, int32_t numOfRows, int8_t* p); bool doFilterDataBlock(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, int32_t numOfRows, int8_t* p);
void doCompactSDataBlock(SSDataBlock* pBlock, int32_t numOfRows, int8_t* p); void doCompactSDataBlock(SSDataBlock* pBlock, int32_t numOfRows, int8_t* p);
......
...@@ -31,10 +31,11 @@ extern "C" { ...@@ -31,10 +31,11 @@ extern "C" {
#define FILTER_DEFAULT_GROUP_UNIT_SIZE 2 #define FILTER_DEFAULT_GROUP_UNIT_SIZE 2
#define FILTER_DUMMY_EMPTY_OPTR 127 #define FILTER_DUMMY_EMPTY_OPTR 127
#define FILTER_DUMMY_RANGE_OPTR 126
#define MAX_NUM_STR_SIZE 40 #define MAX_NUM_STR_SIZE 40
#define FILTER_RM_UNIT_MIN_ROWS 100
enum { enum {
FLD_TYPE_COLUMN = 1, FLD_TYPE_COLUMN = 1,
FLD_TYPE_VALUE = 2, FLD_TYPE_VALUE = 2,
...@@ -70,6 +71,12 @@ enum { ...@@ -70,6 +71,12 @@ enum {
FI_STATUS_CLONED = 8, FI_STATUS_CLONED = 8,
}; };
enum {
FI_STATUS_BLK_ALL = 1,
FI_STATUS_BLK_EMPTY = 2,
FI_STATUS_BLK_ACTIVE = 4,
};
enum { enum {
RANGE_TYPE_UNIT = 1, RANGE_TYPE_UNIT = 1,
RANGE_TYPE_VAR_HASH = 2, RANGE_TYPE_VAR_HASH = 2,
...@@ -98,7 +105,7 @@ typedef struct SFilterColRange { ...@@ -98,7 +105,7 @@ typedef struct SFilterColRange {
typedef bool (*rangeCompFunc) (const void *, const void *, const void *, const void *, __compar_fn_t); typedef bool (*rangeCompFunc) (const void *, const void *, const void *, const void *, __compar_fn_t);
typedef int32_t(*filter_desc_compare_func)(const void *, const void *); typedef int32_t(*filter_desc_compare_func)(const void *, const void *);
typedef bool(*filter_exec_func)(void *, int32_t, int8_t*); typedef bool(*filter_exec_func)(void *, int32_t, int8_t**, SDataStatis *, int16_t);
typedef struct SFilterRangeCompare { typedef struct SFilterRangeCompare {
int64_t s; int64_t s;
...@@ -197,6 +204,7 @@ typedef struct SFilterComUnit { ...@@ -197,6 +204,7 @@ typedef struct SFilterComUnit {
void *colData; void *colData;
void *valData; void *valData;
void *valData2; void *valData2;
uint16_t colId;
uint16_t dataSize; uint16_t dataSize;
uint8_t dataType; uint8_t dataType;
uint8_t optr; uint8_t optr;
...@@ -225,6 +233,10 @@ typedef struct SFilterInfo { ...@@ -225,6 +233,10 @@ typedef struct SFilterInfo {
uint8_t *unitFlags; // got result uint8_t *unitFlags; // got result
SFilterRangeCtx **colRange; SFilterRangeCtx **colRange;
filter_exec_func func; filter_exec_func func;
uint8_t blkFlag;
uint16_t blkGroupNum;
uint16_t *blkUnits;
int8_t *blkUnitRes;
SFilterPCtx pctx; SFilterPCtx pctx;
} SFilterInfo; } SFilterInfo;
...@@ -265,12 +277,13 @@ typedef struct SFilterInfo { ...@@ -265,12 +277,13 @@ typedef struct SFilterInfo {
#define CHK_RET(c, r) do { if (c) { return r; } } while (0) #define CHK_RET(c, r) do { if (c) { return r; } } while (0)
#define CHK_JMP(c) do { if (c) { goto _return; } } while (0) #define CHK_JMP(c) do { if (c) { goto _return; } } while (0)
#define CHK_LRETV(c,...) do { if (c) { qError(__VA_ARGS__); return; } } while (0) #define CHK_LRETV(c,...) do { if (c) { qError(__VA_ARGS__); return; } } while (0)
#define CHK_LRET(c, r,...) do { if (c) { qError(__VA_ARGS__); return r; } } while (0) #define CHK_LRET(c, r,...) do { if (c) { if (r) {qError(__VA_ARGS__); } else { qDebug(__VA_ARGS__); } return r; } } while (0)
#define FILTER_GET_FIELD(i, id) (&((i)->fields[(id).type].fields[(id).idx])) #define FILTER_GET_FIELD(i, id) (&((i)->fields[(id).type].fields[(id).idx]))
#define FILTER_GET_COL_FIELD(i, idx) (&((i)->fields[FLD_TYPE_COLUMN].fields[idx])) #define FILTER_GET_COL_FIELD(i, idx) (&((i)->fields[FLD_TYPE_COLUMN].fields[idx]))
#define FILTER_GET_COL_FIELD_TYPE(fi) (((SSchema *)((fi)->desc))->type) #define FILTER_GET_COL_FIELD_TYPE(fi) (((SSchema *)((fi)->desc))->type)
#define FILTER_GET_COL_FIELD_SIZE(fi) (((SSchema *)((fi)->desc))->bytes) #define FILTER_GET_COL_FIELD_SIZE(fi) (((SSchema *)((fi)->desc))->bytes)
#define FILTER_GET_COL_FIELD_ID(fi) (((SSchema *)((fi)->desc))->colId)
#define FILTER_GET_COL_FIELD_DESC(fi) ((SSchema *)((fi)->desc)) #define FILTER_GET_COL_FIELD_DESC(fi) ((SSchema *)((fi)->desc))
#define FILTER_GET_COL_FIELD_DATA(fi, ri) ((char *)(fi)->data + ((SSchema *)((fi)->desc))->bytes * (ri)) #define FILTER_GET_COL_FIELD_DATA(fi, ri) ((char *)(fi)->data + ((SSchema *)((fi)->desc))->bytes * (ri))
#define FILTER_GET_VAL_FIELD_TYPE(fi) (((tVariant *)((fi)->desc))->nType) #define FILTER_GET_VAL_FIELD_TYPE(fi) (((tVariant *)((fi)->desc))->nType)
...@@ -280,10 +293,12 @@ typedef struct SFilterInfo { ...@@ -280,10 +293,12 @@ typedef struct SFilterInfo {
#define FILTER_GROUP_UNIT(i, g, uid) ((i)->units + (g)->unitIdxs[uid]) #define FILTER_GROUP_UNIT(i, g, uid) ((i)->units + (g)->unitIdxs[uid])
#define FILTER_UNIT_LEFT_FIELD(i, u) FILTER_GET_FIELD(i, (u)->left) #define FILTER_UNIT_LEFT_FIELD(i, u) FILTER_GET_FIELD(i, (u)->left)
#define FILTER_UNIT_RIGHT_FIELD(i, u) FILTER_GET_FIELD(i, (u)->right) #define FILTER_UNIT_RIGHT_FIELD(i, u) FILTER_GET_FIELD(i, (u)->right)
#define FILTER_UNIT_RIGHT2_FIELD(i, u) FILTER_GET_FIELD(i, (u)->right2)
#define FILTER_UNIT_DATA_TYPE(u) ((u)->compare.type) #define FILTER_UNIT_DATA_TYPE(u) ((u)->compare.type)
#define FILTER_UNIT_COL_DESC(i, u) FILTER_GET_COL_FIELD_DESC(FILTER_UNIT_LEFT_FIELD(i, u)) #define FILTER_UNIT_COL_DESC(i, u) FILTER_GET_COL_FIELD_DESC(FILTER_UNIT_LEFT_FIELD(i, u))
#define FILTER_UNIT_COL_DATA(i, u, ri) FILTER_GET_COL_FIELD_DATA(FILTER_UNIT_LEFT_FIELD(i, u), ri) #define FILTER_UNIT_COL_DATA(i, u, ri) FILTER_GET_COL_FIELD_DATA(FILTER_UNIT_LEFT_FIELD(i, u), ri)
#define FILTER_UNIT_COL_SIZE(i, u) FILTER_GET_COL_FIELD_SIZE(FILTER_UNIT_LEFT_FIELD(i, u)) #define FILTER_UNIT_COL_SIZE(i, u) FILTER_GET_COL_FIELD_SIZE(FILTER_UNIT_LEFT_FIELD(i, u))
#define FILTER_UNIT_COL_ID(i, u) FILTER_GET_COL_FIELD_ID(FILTER_UNIT_LEFT_FIELD(i, u))
#define FILTER_UNIT_VAL_DATA(i, u) FILTER_GET_VAL_FIELD_DATA(FILTER_UNIT_RIGHT_FIELD(i, u)) #define FILTER_UNIT_VAL_DATA(i, u) FILTER_GET_VAL_FIELD_DATA(FILTER_UNIT_RIGHT_FIELD(i, u))
#define FILTER_UNIT_COL_IDX(u) ((u)->left.idx) #define FILTER_UNIT_COL_IDX(u) ((u)->left.idx)
#define FILTER_UNIT_OPTR(u) ((u)->compare.optr) #define FILTER_UNIT_OPTR(u) ((u)->compare.optr)
...@@ -309,8 +324,8 @@ typedef struct SFilterInfo { ...@@ -309,8 +324,8 @@ typedef struct SFilterInfo {
extern int32_t filterInitFromTree(tExprNode* tree, SFilterInfo **pinfo, uint32_t options); extern int32_t filterInitFromTree(tExprNode* tree, SFilterInfo **pinfo, uint32_t options);
extern bool filterExecute(SFilterInfo *info, int32_t numOfRows, int8_t* p); extern bool filterExecute(SFilterInfo *info, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols);
extern int32_t filterSetColFieldData(SFilterInfo *info, int16_t colId, void *data); extern int32_t filterSetColFieldData(SFilterInfo *info, int32_t numOfCols, SArray* pDataBlock);
extern int32_t filterGetTimeRange(SFilterInfo *info, STimeWindow *win); extern int32_t filterGetTimeRange(SFilterInfo *info, STimeWindow *win);
extern int32_t filterConverNcharColumns(SFilterInfo* pFilterInfo, int32_t rows, bool *gotNchar); extern int32_t filterConverNcharColumns(SFilterInfo* pFilterInfo, int32_t rows, bool *gotNchar);
extern int32_t filterFreeNcharColumns(SFilterInfo* pFilterInfo); extern int32_t filterFreeNcharColumns(SFilterInfo* pFilterInfo);
......
...@@ -43,6 +43,10 @@ ...@@ -43,6 +43,10 @@
#define SDATA_BLOCK_INITIALIZER (SDataBlockInfo) {{0}, 0} #define SDATA_BLOCK_INITIALIZER (SDataBlockInfo) {{0}, 0}
#define MULTI_KEY_DELIM "-"
#define HASH_CAPACITY_LIMIT 10000000
#define TIME_WINDOW_COPY(_dst, _src) do {\ #define TIME_WINDOW_COPY(_dst, _src) do {\
(_dst).skey = (_src).skey;\ (_dst).skey = (_src).skey;\
(_dst).ekey = (_src).ekey;\ (_dst).ekey = (_src).ekey;\
...@@ -2947,11 +2951,12 @@ void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInf ...@@ -2947,11 +2951,12 @@ void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInf
void filterColRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSDataBlock* pBlock, bool ascQuery) { void filterColRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSDataBlock* pBlock, bool ascQuery) {
int32_t numOfRows = pBlock->info.rows; int32_t numOfRows = pBlock->info.rows;
int8_t *p = calloc(numOfRows, sizeof(int8_t)); int8_t *p = NULL;
bool all = true; bool all = true;
if (pRuntimeEnv->pTsBuf != NULL) { if (pRuntimeEnv->pTsBuf != NULL) {
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0); SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0);
p = calloc(numOfRows, sizeof(int8_t));
TSKEY* k = (TSKEY*) pColInfoData->pData; TSKEY* k = (TSKEY*) pColInfoData->pData;
for (int32_t i = 0; i < numOfRows; ++i) { for (int32_t i = 0; i < numOfRows; ++i) {
...@@ -2975,11 +2980,16 @@ void filterColRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSDataBlock* pBlock ...@@ -2975,11 +2980,16 @@ void filterColRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSDataBlock* pBlock
// save the cursor status // save the cursor status
pRuntimeEnv->current->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf); pRuntimeEnv->current->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
} else { } else {
all = filterExecute(pRuntimeEnv->pQueryAttr->pFilters, numOfRows, p); all = filterExecute(pRuntimeEnv->pQueryAttr->pFilters, numOfRows, &p, pBlock->pBlockStatis, pRuntimeEnv->pQueryAttr->numOfCols);
} }
if (!all) { if (!all) {
if (p) {
doCompactSDataBlock(pBlock, numOfRows, p); doCompactSDataBlock(pBlock, numOfRows, p);
} else {
pBlock->info.rows = 0;
pBlock->pBlockStatis = NULL; // clean the block statistics info
}
} }
tfree(p); tfree(p);
...@@ -3028,15 +3038,6 @@ void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFi ...@@ -3028,15 +3038,6 @@ void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFi
} }
} }
void doSetFilterColInfo(SFilterInfo * pFilters, SSDataBlock* pBlock) {
for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, j);
filterSetColFieldData(pFilters, pColInfo->info.colId, pColInfo->pData);
}
}
int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock, int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock,
uint32_t* status) { uint32_t* status) {
*status = BLK_DATA_NO_NEEDED; *status = BLK_DATA_NO_NEEDED;
...@@ -3191,7 +3192,7 @@ int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTa ...@@ -3191,7 +3192,7 @@ int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTa
} }
if (pQueryAttr->pFilters != NULL) { if (pQueryAttr->pFilters != NULL) {
doSetFilterColInfo(pQueryAttr->pFilters, pBlock); filterSetColFieldData(pQueryAttr->pFilters, pBlock->info.numOfCols, pBlock->pDataBlock);
} }
if (pQueryAttr->pFilters != NULL || pRuntimeEnv->pTsBuf != NULL) { if (pQueryAttr->pFilters != NULL || pRuntimeEnv->pTsBuf != NULL) {
...@@ -3569,6 +3570,7 @@ void setDefaultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, i ...@@ -3569,6 +3570,7 @@ void setDefaultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, i
SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo; SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo;
int64_t tid = 0; int64_t tid = 0;
pRuntimeEnv->keyBuf = realloc(pRuntimeEnv->keyBuf, sizeof(tid) + sizeof(int64_t) + POINTER_BYTES);
SResultRow* pRow = doSetResultOutBufByKey(pRuntimeEnv, pResultRowInfo, tid, (char *)&tid, sizeof(tid), true, uid); SResultRow* pRow = doSetResultOutBufByKey(pRuntimeEnv, pResultRowInfo, tid, (char *)&tid, sizeof(tid), true, uid);
for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) { for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
...@@ -6528,6 +6530,8 @@ static void destroyConditionOperatorInfo(void* param, int32_t numOfOutput) { ...@@ -6528,6 +6530,8 @@ static void destroyConditionOperatorInfo(void* param, int32_t numOfOutput) {
static void destroyDistinctOperatorInfo(void* param, int32_t numOfOutput) { static void destroyDistinctOperatorInfo(void* param, int32_t numOfOutput) {
SDistinctOperatorInfo* pInfo = (SDistinctOperatorInfo*) param; SDistinctOperatorInfo* pInfo = (SDistinctOperatorInfo*) param;
taosHashCleanup(pInfo->pSet); taosHashCleanup(pInfo->pSet);
tfree(pInfo->buf);
taosArrayDestroy(pInfo->pDistinctDataInfo);
pInfo->pRes = destroyOutputBuf(pInfo->pRes); pInfo->pRes = destroyOutputBuf(pInfo->pRes);
} }
...@@ -7069,18 +7073,64 @@ SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInf ...@@ -7069,18 +7073,64 @@ SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInf
return pOperator; return pOperator;
} }
static bool initMultiDistinctInfo(SDistinctOperatorInfo *pInfo, SOperatorInfo* pOperator, SSDataBlock *pBlock) {
if (taosArrayGetSize(pInfo->pDistinctDataInfo) == pOperator->numOfOutput) {
// distinct info already inited
return true;
}
for (int i = 0; i < pOperator->numOfOutput; i++) {
pInfo->totalBytes += pOperator->pExpr[i].base.colBytes;
}
for (int i = 0; i < pOperator->numOfOutput; i++) {
int numOfBlock = (int)(taosArrayGetSize(pBlock->pDataBlock));
assert(i < numOfBlock);
for (int j = 0; j < numOfBlock; j++) {
SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, j);
if (pColDataInfo->info.colId == pOperator->pExpr[i].base.resColId) {
SDistinctDataInfo item = {.index = j, .type = pColDataInfo->info.type, .bytes = pColDataInfo->info.bytes};
taosArrayInsert(pInfo->pDistinctDataInfo, i, &item);
}
}
}
pInfo->totalBytes += (int32_t)strlen(MULTI_KEY_DELIM) * (pOperator->numOfOutput);
pInfo->buf = calloc(1, pInfo->totalBytes);
return taosArrayGetSize(pInfo->pDistinctDataInfo) == pOperator->numOfOutput ? true : false;
}
static void buildMultiDistinctKey(SDistinctOperatorInfo *pInfo, SSDataBlock *pBlock, int32_t rowId) {
char *p = pInfo->buf;
memset(p, 0, pInfo->totalBytes);
for (int i = 0; i < taosArrayGetSize(pInfo->pDistinctDataInfo); i++) {
SDistinctDataInfo* pDistDataInfo = (SDistinctDataInfo *)taosArrayGet(pInfo->pDistinctDataInfo, i);
SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, pDistDataInfo->index);
char *val = ((char *)pColDataInfo->pData) + pColDataInfo->info.bytes * rowId;
if (isNull(val, pDistDataInfo->type)) {
p += pDistDataInfo->bytes;
continue;
}
if (IS_VAR_DATA_TYPE(pDistDataInfo->type)) {
memcpy(p, varDataVal(val), varDataLen(val));
p += varDataLen(val);
} else {
memcpy(p, val, pDistDataInfo->bytes);
p += pDistDataInfo->bytes;
}
memcpy(p, MULTI_KEY_DELIM, strlen(MULTI_KEY_DELIM));
p += strlen(MULTI_KEY_DELIM);
}
}
static SSDataBlock* hashDistinct(void* param, bool* newgroup) { static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
SOperatorInfo* pOperator = (SOperatorInfo*) param; SOperatorInfo* pOperator = (SOperatorInfo*) param;
if (pOperator->status == OP_EXEC_DONE) { if (pOperator->status == OP_EXEC_DONE) {
return NULL; return NULL;
} }
SDistinctOperatorInfo* pInfo = pOperator->info; SDistinctOperatorInfo* pInfo = pOperator->info;
SSDataBlock* pRes = pInfo->pRes; SSDataBlock* pRes = pInfo->pRes;
pRes->info.rows = 0; pRes->info.rows = 0;
SSDataBlock* pBlock = NULL; SSDataBlock* pBlock = NULL;
while(1) { while(1) {
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
...@@ -7091,63 +7141,44 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) { ...@@ -7091,63 +7141,44 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
pOperator->status = OP_EXEC_DONE; pOperator->status = OP_EXEC_DONE;
break; break;
} }
if (pInfo->colIndex == -1) { if (!initMultiDistinctInfo(pInfo, pOperator, pBlock)) {
for (int i = 0; i < taosArrayGetSize(pBlock->pDataBlock); i++) {
SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, i);
if (pColDataInfo->info.colId == pOperator->pExpr[0].base.resColId) {
pInfo->colIndex = i;
break;
}
}
}
if (pInfo->colIndex == -1) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
pOperator->status = OP_EXEC_DONE; pOperator->status = OP_EXEC_DONE;
return NULL; break;
} }
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pInfo->colIndex); // ensure result output buf
int16_t bytes = pColInfoData->info.bytes;
int16_t type = pColInfoData->info.type;
// ensure the output buffer size
SColumnInfoData* pResultColInfoData = taosArrayGet(pRes->pDataBlock, 0);
if (pRes->info.rows + pBlock->info.rows > pInfo->outputCapacity) { if (pRes->info.rows + pBlock->info.rows > pInfo->outputCapacity) {
int32_t newSize = pRes->info.rows + pBlock->info.rows; int32_t newSize = pRes->info.rows + pBlock->info.rows;
char* tmp = realloc(pResultColInfoData->pData, newSize * bytes); for (int i = 0; i < taosArrayGetSize(pRes->pDataBlock); i++) {
SColumnInfoData* pResultColInfoData = taosArrayGet(pRes->pDataBlock, i);
SDistinctDataInfo* pDistDataInfo = taosArrayGet(pInfo->pDistinctDataInfo, i);
char* tmp = realloc(pResultColInfoData->pData, newSize * pDistDataInfo->bytes);
if (tmp == NULL) { if (tmp == NULL) {
return NULL; return NULL;
} else { } else {
pResultColInfoData->pData = tmp; pResultColInfoData->pData = tmp;
pInfo->outputCapacity = newSize;
} }
} }
pInfo->outputCapacity = newSize;
for(int32_t i = 0; i < pBlock->info.rows; ++i) {
char* val = ((char*)pColInfoData->pData) + bytes * i;
if (isNull(val, type)) {
continue;
}
char* p = val;
size_t keyLen = 0;
if (IS_VAR_DATA_TYPE(pOperator->pExpr->base.colType)) {
tstr* var = (tstr*)(val);
p = var->data;
keyLen = varDataLen(var);
} else {
keyLen = bytes;
} }
int dummy; for (int32_t i = 0; i < pBlock->info.rows; i++) {
void* res = taosHashGet(pInfo->pSet, p, keyLen); buildMultiDistinctKey(pInfo, pBlock, i);
if (res == NULL) { if (taosHashGet(pInfo->pSet, pInfo->buf, pInfo->totalBytes) == NULL) {
taosHashPut(pInfo->pSet, p, keyLen, &dummy, sizeof(dummy)); int32_t dummy;
char* start = pResultColInfoData->pData + bytes * pInfo->pRes->info.rows; taosHashPut(pInfo->pSet, pInfo->buf, pInfo->totalBytes, &dummy, sizeof(dummy));
memcpy(start, val, bytes); for (int j = 0; j < taosArrayGetSize(pRes->pDataBlock); j++) {
SDistinctDataInfo* pDistDataInfo = taosArrayGet(pInfo->pDistinctDataInfo, j); // distinct meta info
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pDistDataInfo->index); //src
SColumnInfoData* pResultColInfoData = taosArrayGet(pRes->pDataBlock, j); // dist
char* val = ((char*)pColInfoData->pData) + pDistDataInfo->bytes * i;
char *start = pResultColInfoData->pData + pDistDataInfo->bytes * pInfo->pRes->info.rows;
memcpy(start, val, pDistDataInfo->bytes);
}
pRes->info.rows += 1; pRes->info.rows += 1;
} }
} }
if (pRes->info.rows >= pInfo->threshold) { if (pRes->info.rows >= pInfo->threshold) {
break; break;
} }
...@@ -7158,12 +7189,15 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) { ...@@ -7158,12 +7189,15 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
SOperatorInfo* createDistinctOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) { SOperatorInfo* createDistinctOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
SDistinctOperatorInfo* pInfo = calloc(1, sizeof(SDistinctOperatorInfo)); SDistinctOperatorInfo* pInfo = calloc(1, sizeof(SDistinctOperatorInfo));
pInfo->colIndex = -1; pInfo->totalBytes = 0;
pInfo->threshold = 10000000; // distinct result threshold pInfo->buf = NULL;
pInfo->threshold = tsMaxNumOfDistinctResults; // distinct result threshold
pInfo->outputCapacity = 4096; pInfo->outputCapacity = 4096;
pInfo->pSet = taosHashInit(64, taosGetDefaultHashFunction(pExpr->base.colType), false, HASH_NO_LOCK); pInfo->pDistinctDataInfo = taosArrayInit(numOfOutput, sizeof(SDistinctDataInfo));
pInfo->pSet = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
pInfo->pRes = createOutputBuf(pExpr, numOfOutput, (int32_t) pInfo->outputCapacity); pInfo->pRes = createOutputBuf(pExpr, numOfOutput, (int32_t) pInfo->outputCapacity);
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
pOperator->name = "DistinctOperator"; pOperator->name = "DistinctOperator";
pOperator->blockingOptr = false; pOperator->blockingOptr = false;
......
...@@ -1521,7 +1521,7 @@ void filterDumpInfoToString(SFilterInfo *info, const char *msg, int32_t options) ...@@ -1521,7 +1521,7 @@ void filterDumpInfoToString(SFilterInfo *info, const char *msg, int32_t options)
int32_t type = FILTER_UNIT_DATA_TYPE(unit); int32_t type = FILTER_UNIT_DATA_TYPE(unit);
int32_t len = 0; int32_t len = 0;
int32_t tlen = 0; int32_t tlen = 0;
char str[256] = {0}; char str[512] = {0};
SFilterField *left = FILTER_UNIT_LEFT_FIELD(info, unit); SFilterField *left = FILTER_UNIT_LEFT_FIELD(info, unit);
SSchema *sch = left->desc; SSchema *sch = left->desc;
...@@ -1540,6 +1540,24 @@ void filterDumpInfoToString(SFilterInfo *info, const char *msg, int32_t options) ...@@ -1540,6 +1540,24 @@ void filterDumpInfoToString(SFilterInfo *info, const char *msg, int32_t options)
} }
strcat(str, "]"); strcat(str, "]");
if (unit->compare.optr2) {
strcat(str, " && ");
sprintf(str + strlen(str), "[%d][%s] %s [", sch->colId, sch->name, gOptrStr[unit->compare.optr2].str);
if (unit->right2.type == FLD_TYPE_VALUE && FILTER_UNIT_OPTR(unit) != TSDB_RELATION_IN) {
SFilterField *right = FILTER_UNIT_RIGHT2_FIELD(info, unit);
char *data = right->data;
if (IS_VAR_DATA_TYPE(type)) {
tlen = varDataLen(data);
data += VARSTR_HEADER_SIZE;
}
converToStr(str + strlen(str), type, data, tlen > 32 ? 32 : tlen, &tlen);
} else {
strcat(str, "NULL");
}
strcat(str, "]");
}
qDebug("%s", str); //TODO qDebug("%s", str); //TODO
} }
...@@ -1556,6 +1574,7 @@ void filterDumpInfoToString(SFilterInfo *info, const char *msg, int32_t options) ...@@ -1556,6 +1574,7 @@ void filterDumpInfoToString(SFilterInfo *info, const char *msg, int32_t options)
return; return;
} }
if (options == 1) {
qDebug("%s - RANGE info:", msg); qDebug("%s - RANGE info:", msg);
qDebug("RANGE Num:%u", info->colRangeNum); qDebug("RANGE Num:%u", info->colRangeNum);
...@@ -1588,6 +1607,31 @@ void filterDumpInfoToString(SFilterInfo *info, const char *msg, int32_t options) ...@@ -1588,6 +1607,31 @@ void filterDumpInfoToString(SFilterInfo *info, const char *msg, int32_t options)
} }
} }
} }
return;
}
qDebug("%s - Block Filter info:", msg);
if (FILTER_GET_FLAG(info->blkFlag, FI_STATUS_BLK_ALL)) {
qDebug("Flag:%s", "ALL");
return;
} else if (FILTER_GET_FLAG(info->blkFlag, FI_STATUS_BLK_EMPTY)) {
qDebug("Flag:%s", "EMPTY");
return;
} else if (FILTER_GET_FLAG(info->blkFlag, FI_STATUS_BLK_ACTIVE)){
qDebug("Flag:%s", "ACTIVE");
}
qDebug("GroupNum:%d", info->blkGroupNum);
uint16_t *unitIdx = info->blkUnits;
for (uint16_t i = 0; i < info->blkGroupNum; ++i) {
qDebug("Group[%d] UnitNum: %d:", i, *unitIdx);
uint16_t unitNum = *(unitIdx++);
for (uint16_t m = 0; m < unitNum; ++m) {
qDebug("uidx[%d]", *(unitIdx++));
}
}
} }
} }
...@@ -1674,6 +1718,8 @@ void filterFreeInfo(SFilterInfo *info) { ...@@ -1674,6 +1718,8 @@ void filterFreeInfo(SFilterInfo *info) {
CHK_RETV(info == NULL); CHK_RETV(info == NULL);
tfree(info->cunits); tfree(info->cunits);
tfree(info->blkUnitRes);
tfree(info->blkUnits);
for (int32_t i = 0; i < FLD_TYPE_MAX; ++i) { for (int32_t i = 0; i < FLD_TYPE_MAX; ++i) {
for (uint16_t f = 0; f < info->fields[i].num; ++f) { for (uint16_t f = 0; f < info->fields[i].num; ++f) {
...@@ -2485,6 +2531,8 @@ int32_t filterGenerateComInfo(SFilterInfo *info) { ...@@ -2485,6 +2531,8 @@ int32_t filterGenerateComInfo(SFilterInfo *info) {
uint16_t n = 0; uint16_t n = 0;
info->cunits = malloc(info->unitNum * sizeof(*info->cunits)); info->cunits = malloc(info->unitNum * sizeof(*info->cunits));
info->blkUnitRes = malloc(sizeof(*info->blkUnitRes) * info->unitNum);
info->blkUnits = malloc(sizeof(*info->blkUnits) * (info->unitNum + 1) * info->groupNum);
for (uint16_t i = 0; i < info->unitNum; ++i) { for (uint16_t i = 0; i < info->unitNum; ++i) {
SFilterUnit *unit = &info->units[i]; SFilterUnit *unit = &info->units[i];
...@@ -2493,6 +2541,7 @@ int32_t filterGenerateComInfo(SFilterInfo *info) { ...@@ -2493,6 +2541,7 @@ int32_t filterGenerateComInfo(SFilterInfo *info) {
info->cunits[i].rfunc = filterGetRangeCompFuncFromOptrs(unit->compare.optr, unit->compare.optr2); info->cunits[i].rfunc = filterGetRangeCompFuncFromOptrs(unit->compare.optr, unit->compare.optr2);
info->cunits[i].optr = FILTER_UNIT_OPTR(unit); info->cunits[i].optr = FILTER_UNIT_OPTR(unit);
info->cunits[i].colData = NULL; info->cunits[i].colData = NULL;
info->cunits[i].colId = FILTER_UNIT_COL_ID(info, unit);
if (unit->right.type == FLD_TYPE_VALUE) { if (unit->right.type == FLD_TYPE_VALUE) {
info->cunits[i].valData = FILTER_UNIT_VAL_DATA(info, unit); info->cunits[i].valData = FILTER_UNIT_VAL_DATA(info, unit);
...@@ -2541,36 +2590,317 @@ int32_t filterUpdateComUnits(SFilterInfo *info) { ...@@ -2541,36 +2590,317 @@ int32_t filterUpdateComUnits(SFilterInfo *info) {
} }
static FORCE_INLINE bool filterExecuteImplAll(void *info, int32_t numOfRows, int8_t* p) { int32_t filterRmUnitByRange(SFilterInfo *info, SDataStatis *pDataStatis, int32_t numOfCols, int32_t numOfRows) {
int32_t rmUnit = 0;
memset(info->blkUnitRes, 0, sizeof(*info->blkUnitRes) * info->unitNum);
for (int32_t k = 0; k < info->unitNum; ++k) {
int32_t index = -1;
SFilterComUnit *cunit = &info->cunits[k];
if (FILTER_NO_MERGE_DATA_TYPE(cunit->dataType)) {
continue;
}
for(int32_t i = 0; i < numOfCols; ++i) {
if (pDataStatis[i].colId == cunit->colId) {
index = i;
break;
}
}
if (index == -1) {
continue;
}
if (pDataStatis[index].numOfNull <= 0) {
if (cunit->optr == TSDB_RELATION_ISNULL) {
info->blkUnitRes[k] = -1;
rmUnit = 1;
continue;
}
if (cunit->optr == TSDB_RELATION_NOTNULL) {
info->blkUnitRes[k] = 1;
rmUnit = 1;
continue;
}
} else {
if (pDataStatis[index].numOfNull == numOfRows) {
if (cunit->optr == TSDB_RELATION_ISNULL) {
info->blkUnitRes[k] = 1;
rmUnit = 1;
continue;
}
info->blkUnitRes[k] = -1;
rmUnit = 1;
continue;
}
}
if (cunit->optr == TSDB_RELATION_ISNULL || cunit->optr == TSDB_RELATION_NOTNULL
|| cunit->optr == TSDB_RELATION_IN || cunit->optr == TSDB_RELATION_LIKE
|| cunit->optr == TSDB_RELATION_NOT_EQUAL) {
continue;
}
SDataStatis* pDataBlockst = &pDataStatis[index];
void *minVal, *maxVal;
if (cunit->dataType == TSDB_DATA_TYPE_FLOAT) {
float minv = (float)(*(double *)(&pDataBlockst->min));
float maxv = (float)(*(double *)(&pDataBlockst->max));
minVal = &minv;
maxVal = &maxv;
} else {
minVal = &pDataBlockst->min;
maxVal = &pDataBlockst->max;
}
bool minRes = false, maxRes = false;
if (cunit->rfunc >= 0) {
minRes = (*gRangeCompare[cunit->rfunc])(minVal, minVal, cunit->valData, cunit->valData2, gDataCompare[cunit->func]);
maxRes = (*gRangeCompare[cunit->rfunc])(maxVal, maxVal, cunit->valData, cunit->valData2, gDataCompare[cunit->func]);
if (minRes && maxRes) {
info->blkUnitRes[k] = 1;
rmUnit = 1;
} else if ((!minRes) && (!maxRes)) {
minRes = filterDoCompare(gDataCompare[cunit->func], TSDB_RELATION_LESS_EQUAL, minVal, cunit->valData);
maxRes = filterDoCompare(gDataCompare[cunit->func], TSDB_RELATION_GREATER_EQUAL, maxVal, cunit->valData2);
if (minRes && maxRes) {
continue;
}
info->blkUnitRes[k] = -1;
rmUnit = 1;
}
} else {
minRes = filterDoCompare(gDataCompare[cunit->func], cunit->optr, minVal, cunit->valData);
maxRes = filterDoCompare(gDataCompare[cunit->func], cunit->optr, maxVal, cunit->valData);
if (minRes && maxRes) {
info->blkUnitRes[k] = 1;
rmUnit = 1;
} else if ((!minRes) && (!maxRes)) {
if (cunit->optr == TSDB_RELATION_EQUAL) {
minRes = filterDoCompare(gDataCompare[cunit->func], TSDB_RELATION_GREATER, minVal, cunit->valData);
maxRes = filterDoCompare(gDataCompare[cunit->func], TSDB_RELATION_LESS, maxVal, cunit->valData);
if (minRes || maxRes) {
info->blkUnitRes[k] = -1;
rmUnit = 1;
}
continue;
}
info->blkUnitRes[k] = -1;
rmUnit = 1;
}
}
}
CHK_LRET(rmUnit == 0, TSDB_CODE_SUCCESS, "NO Block Filter APPLY");
info->blkGroupNum = info->groupNum;
uint16_t *unitNum = info->blkUnits;
uint16_t *unitIdx = unitNum + 1;
int32_t all = 0, empty = 0;
for (uint32_t g = 0; g < info->groupNum; ++g) {
SFilterGroup *group = &info->groups[g];
*unitNum = group->unitNum;
all = 0;
empty = 0;
for (uint32_t u = 0; u < group->unitNum; ++u) {
uint16_t uidx = group->unitIdxs[u];
if (info->blkUnitRes[uidx] == 1) {
--(*unitNum);
all = 1;
continue;
} else if (info->blkUnitRes[uidx] == -1) {
*unitNum = 0;
empty = 1;
break;
}
*(unitIdx++) = uidx;
}
if (*unitNum == 0) {
--info->blkGroupNum;
assert(empty || all);
if (empty) {
FILTER_SET_FLAG(info->blkFlag, FI_STATUS_BLK_EMPTY);
} else {
FILTER_SET_FLAG(info->blkFlag, FI_STATUS_BLK_ALL);
goto _return;
}
continue;
}
unitNum = unitIdx;
++unitIdx;
}
if (info->blkGroupNum) {
FILTER_CLR_FLAG(info->blkFlag, FI_STATUS_BLK_EMPTY);
FILTER_SET_FLAG(info->blkFlag, FI_STATUS_BLK_ACTIVE);
}
_return:
filterDumpInfoToString(info, "Block Filter", 2);
return TSDB_CODE_SUCCESS;
}
bool filterExecuteBasedOnStatisImpl(void *pinfo, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) {
SFilterInfo *info = (SFilterInfo *)pinfo;
bool all = true;
uint16_t *unitIdx = NULL;
*p = calloc(numOfRows, sizeof(int8_t));
for (int32_t i = 0; i < numOfRows; ++i) {
//FILTER_UNIT_CLR_F(info);
unitIdx = info->blkUnits;
for (uint32_t g = 0; g < info->blkGroupNum; ++g) {
uint16_t unitNum = *(unitIdx++);
for (uint32_t u = 0; u < unitNum; ++u) {
SFilterComUnit *cunit = &info->cunits[*(unitIdx + u)];
void *colData = (char *)cunit->colData + cunit->dataSize * i;
//if (FILTER_UNIT_GET_F(info, uidx)) {
// p[i] = FILTER_UNIT_GET_R(info, uidx);
//} else {
uint8_t optr = cunit->optr;
if (isNull(colData, cunit->dataType)) {
(*p)[i] = optr == TSDB_RELATION_ISNULL ? true : false;
} else {
if (optr == TSDB_RELATION_NOTNULL) {
(*p)[i] = 1;
} else if (optr == TSDB_RELATION_ISNULL) {
(*p)[i] = 0;
} else if (cunit->rfunc >= 0) {
(*p)[i] = (*gRangeCompare[cunit->rfunc])(colData, colData, cunit->valData, cunit->valData2, gDataCompare[cunit->func]);
} else {
(*p)[i] = filterDoCompare(gDataCompare[cunit->func], cunit->optr, colData, cunit->valData);
}
//FILTER_UNIT_SET_R(info, uidx, p[i]);
//FILTER_UNIT_SET_F(info, uidx);
}
if ((*p)[i] == 0) {
break;
}
}
if ((*p)[i]) {
break;
}
unitIdx += unitNum;
}
if ((*p)[i] == 0) {
all = false;
}
}
return all;
}
int32_t filterExecuteBasedOnStatis(SFilterInfo *info, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols, bool* all) {
if (statis && numOfRows >= FILTER_RM_UNIT_MIN_ROWS) {
info->blkFlag = 0;
filterRmUnitByRange(info, statis, numOfCols, numOfRows);
if (info->blkFlag) {
if (FILTER_GET_FLAG(info->blkFlag, FI_STATUS_BLK_ALL)) {
*all = true;
goto _return;
} else if (FILTER_GET_FLAG(info->blkFlag, FI_STATUS_BLK_EMPTY)) {
*all = false;
goto _return;
}
assert(info->unitNum > 1);
*all = filterExecuteBasedOnStatisImpl(info, numOfRows, p, statis, numOfCols);
goto _return;
}
}
return 1;
_return:
info->blkFlag = 0;
return TSDB_CODE_SUCCESS;
}
static FORCE_INLINE bool filterExecuteImplAll(void *info, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) {
return true; return true;
} }
static FORCE_INLINE bool filterExecuteImplEmpty(void *info, int32_t numOfRows, int8_t* p) { static FORCE_INLINE bool filterExecuteImplEmpty(void *info, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) {
return false; return false;
} }
static FORCE_INLINE bool filterExecuteImplIsNull(void *pinfo, int32_t numOfRows, int8_t* p) { static FORCE_INLINE bool filterExecuteImplIsNull(void *pinfo, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) {
SFilterInfo *info = (SFilterInfo *)pinfo; SFilterInfo *info = (SFilterInfo *)pinfo;
bool all = true; bool all = true;
if (filterExecuteBasedOnStatis(info, numOfRows, p, statis, numOfCols, &all) == 0) {
return all;
}
*p = calloc(numOfRows, sizeof(int8_t));
for (int32_t i = 0; i < numOfRows; ++i) { for (int32_t i = 0; i < numOfRows; ++i) {
uint16_t uidx = info->groups[0].unitIdxs[0]; uint16_t uidx = info->groups[0].unitIdxs[0];
void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i; void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i;
p[i] = isNull(colData, info->cunits[uidx].dataType); (*p)[i] = isNull(colData, info->cunits[uidx].dataType);
if (p[i] == 0) { if ((*p)[i] == 0) {
all = false; all = false;
} }
} }
return all; return all;
} }
static FORCE_INLINE bool filterExecuteImplNotNull(void *pinfo, int32_t numOfRows, int8_t* p) { static FORCE_INLINE bool filterExecuteImplNotNull(void *pinfo, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) {
SFilterInfo *info = (SFilterInfo *)pinfo; SFilterInfo *info = (SFilterInfo *)pinfo;
bool all = true; bool all = true;
if (filterExecuteBasedOnStatis(info, numOfRows, p, statis, numOfCols, &all) == 0) {
return all;
}
*p = calloc(numOfRows, sizeof(int8_t));
for (int32_t i = 0; i < numOfRows; ++i) { for (int32_t i = 0; i < numOfRows; ++i) {
uint16_t uidx = info->groups[0].unitIdxs[0]; uint16_t uidx = info->groups[0].unitIdxs[0];
void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i; void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i;
p[i] = !isNull(colData, info->cunits[uidx].dataType); (*p)[i] = !isNull(colData, info->cunits[uidx].dataType);
if (p[i] == 0) { if ((*p)[i] == 0) {
all = false; all = false;
} }
} }
...@@ -2578,7 +2908,7 @@ static FORCE_INLINE bool filterExecuteImplNotNull(void *pinfo, int32_t numOfRows ...@@ -2578,7 +2908,7 @@ static FORCE_INLINE bool filterExecuteImplNotNull(void *pinfo, int32_t numOfRows
return all; return all;
} }
bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t* p) { bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) {
SFilterInfo *info = (SFilterInfo *)pinfo; SFilterInfo *info = (SFilterInfo *)pinfo;
bool all = true; bool all = true;
uint16_t dataSize = info->cunits[0].dataSize; uint16_t dataSize = info->cunits[0].dataSize;
...@@ -2588,6 +2918,12 @@ bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t* p) { ...@@ -2588,6 +2918,12 @@ bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t* p) {
void *valData2 = info->cunits[0].valData2; void *valData2 = info->cunits[0].valData2;
__compar_fn_t func = gDataCompare[info->cunits[0].func]; __compar_fn_t func = gDataCompare[info->cunits[0].func];
if (filterExecuteBasedOnStatis(info, numOfRows, p, statis, numOfCols, &all) == 0) {
return all;
}
*p = calloc(numOfRows, sizeof(int8_t));
for (int32_t i = 0; i < numOfRows; ++i) { for (int32_t i = 0; i < numOfRows; ++i) {
if (isNull(colData, info->cunits[0].dataType)) { if (isNull(colData, info->cunits[0].dataType)) {
all = false; all = false;
...@@ -2595,9 +2931,9 @@ bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t* p) { ...@@ -2595,9 +2931,9 @@ bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t* p) {
continue; continue;
} }
p[i] = (*rfunc)(colData, colData, valData, valData2, func); (*p)[i] = (*rfunc)(colData, colData, valData, valData2, func);
if (p[i] == 0) { if ((*p)[i] == 0) {
all = false; all = false;
} }
...@@ -2607,10 +2943,16 @@ bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t* p) { ...@@ -2607,10 +2943,16 @@ bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t* p) {
return all; return all;
} }
bool filterExecuteImplMisc(void *pinfo, int32_t numOfRows, int8_t* p) { bool filterExecuteImplMisc(void *pinfo, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) {
SFilterInfo *info = (SFilterInfo *)pinfo; SFilterInfo *info = (SFilterInfo *)pinfo;
bool all = true; bool all = true;
if (filterExecuteBasedOnStatis(info, numOfRows, p, statis, numOfCols, &all) == 0) {
return all;
}
*p = calloc(numOfRows, sizeof(int8_t));
for (int32_t i = 0; i < numOfRows; ++i) { for (int32_t i = 0; i < numOfRows; ++i) {
uint16_t uidx = info->groups[0].unitIdxs[0]; uint16_t uidx = info->groups[0].unitIdxs[0];
void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i; void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i;
...@@ -2619,9 +2961,9 @@ bool filterExecuteImplMisc(void *pinfo, int32_t numOfRows, int8_t* p) { ...@@ -2619,9 +2961,9 @@ bool filterExecuteImplMisc(void *pinfo, int32_t numOfRows, int8_t* p) {
continue; continue;
} }
p[i] = filterDoCompare(gDataCompare[info->cunits[uidx].func], info->cunits[uidx].optr, colData, info->cunits[uidx].valData); (*p)[i] = filterDoCompare(gDataCompare[info->cunits[uidx].func], info->cunits[uidx].optr, colData, info->cunits[uidx].valData);
if (p[i] == 0) { if ((*p)[i] == 0) {
all = false; all = false;
} }
} }
...@@ -2630,10 +2972,16 @@ bool filterExecuteImplMisc(void *pinfo, int32_t numOfRows, int8_t* p) { ...@@ -2630,10 +2972,16 @@ bool filterExecuteImplMisc(void *pinfo, int32_t numOfRows, int8_t* p) {
} }
bool filterExecuteImpl(void *pinfo, int32_t numOfRows, int8_t* p) { bool filterExecuteImpl(void *pinfo, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) {
SFilterInfo *info = (SFilterInfo *)pinfo; SFilterInfo *info = (SFilterInfo *)pinfo;
bool all = true; bool all = true;
if (filterExecuteBasedOnStatis(info, numOfRows, p, statis, numOfCols, &all) == 0) {
return all;
}
*p = calloc(numOfRows, sizeof(int8_t));
for (int32_t i = 0; i < numOfRows; ++i) { for (int32_t i = 0; i < numOfRows; ++i) {
//FILTER_UNIT_CLR_F(info); //FILTER_UNIT_CLR_F(info);
...@@ -2650,33 +2998,33 @@ bool filterExecuteImpl(void *pinfo, int32_t numOfRows, int8_t* p) { ...@@ -2650,33 +2998,33 @@ bool filterExecuteImpl(void *pinfo, int32_t numOfRows, int8_t* p) {
uint8_t optr = cunit->optr; uint8_t optr = cunit->optr;
if (isNull(colData, cunit->dataType)) { if (isNull(colData, cunit->dataType)) {
p[i] = optr == TSDB_RELATION_ISNULL ? true : false; (*p)[i] = optr == TSDB_RELATION_ISNULL ? true : false;
} else { } else {
if (optr == TSDB_RELATION_NOTNULL) { if (optr == TSDB_RELATION_NOTNULL) {
p[i] = 1; (*p)[i] = 1;
} else if (optr == TSDB_RELATION_ISNULL) { } else if (optr == TSDB_RELATION_ISNULL) {
p[i] = 0; (*p)[i] = 0;
} else if (cunit->rfunc >= 0) { } else if (cunit->rfunc >= 0) {
p[i] = (*gRangeCompare[cunit->rfunc])(colData, colData, cunit->valData, cunit->valData2, gDataCompare[cunit->func]); (*p)[i] = (*gRangeCompare[cunit->rfunc])(colData, colData, cunit->valData, cunit->valData2, gDataCompare[cunit->func]);
} else { } else {
p[i] = filterDoCompare(gDataCompare[cunit->func], cunit->optr, colData, cunit->valData); (*p)[i] = filterDoCompare(gDataCompare[cunit->func], cunit->optr, colData, cunit->valData);
} }
//FILTER_UNIT_SET_R(info, uidx, p[i]); //FILTER_UNIT_SET_R(info, uidx, p[i]);
//FILTER_UNIT_SET_F(info, uidx); //FILTER_UNIT_SET_F(info, uidx);
} }
if (p[i] == 0) { if ((*p)[i] == 0) {
break; break;
} }
} }
if (p[i]) { if ((*p)[i]) {
break; break;
} }
} }
if (p[i] == 0) { if ((*p)[i] == 0) {
all = false; all = false;
} }
} }
...@@ -2684,8 +3032,9 @@ bool filterExecuteImpl(void *pinfo, int32_t numOfRows, int8_t* p) { ...@@ -2684,8 +3032,9 @@ bool filterExecuteImpl(void *pinfo, int32_t numOfRows, int8_t* p) {
return all; return all;
} }
FORCE_INLINE bool filterExecute(SFilterInfo *info, int32_t numOfRows, int8_t* p) {
return (*info->func)(info, numOfRows, p); FORCE_INLINE bool filterExecute(SFilterInfo *info, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) {
return (*info->func)(info, numOfRows, p, statis, numOfCols);
} }
int32_t filterSetExecFunc(SFilterInfo *info) { int32_t filterSetExecFunc(SFilterInfo *info) {
...@@ -2767,7 +3116,7 @@ _return: ...@@ -2767,7 +3116,7 @@ _return:
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
int32_t filterSetColFieldData(SFilterInfo *info, int16_t colId, void *data) { int32_t filterSetColFieldData(SFilterInfo *info, int32_t numOfCols, SArray* pDataBlock) {
CHK_LRET(info == NULL, TSDB_CODE_QRY_APP_ERROR, "info NULL"); CHK_LRET(info == NULL, TSDB_CODE_QRY_APP_ERROR, "info NULL");
CHK_LRET(info->fields[FLD_TYPE_COLUMN].num <= 0, TSDB_CODE_QRY_APP_ERROR, "no column fileds"); CHK_LRET(info->fields[FLD_TYPE_COLUMN].num <= 0, TSDB_CODE_QRY_APP_ERROR, "no column fileds");
...@@ -2778,12 +3127,16 @@ int32_t filterSetColFieldData(SFilterInfo *info, int16_t colId, void *data) { ...@@ -2778,12 +3127,16 @@ int32_t filterSetColFieldData(SFilterInfo *info, int16_t colId, void *data) {
for (uint16_t i = 0; i < info->fields[FLD_TYPE_COLUMN].num; ++i) { for (uint16_t i = 0; i < info->fields[FLD_TYPE_COLUMN].num; ++i) {
SFilterField* fi = &info->fields[FLD_TYPE_COLUMN].fields[i]; SFilterField* fi = &info->fields[FLD_TYPE_COLUMN].fields[i];
SSchema* sch = fi->desc; SSchema* sch = fi->desc;
if (sch->colId == colId) {
fi->data = data; for (int32_t j = 0; j < numOfCols; ++j) {
SColumnInfoData* pColInfo = taosArrayGet(pDataBlock, j);
if (sch->colId == pColInfo->info.colId) {
fi->data = pColInfo->pData;
break; break;
} }
} }
}
filterUpdateComUnits(info); filterUpdateComUnits(info);
...@@ -2880,16 +3233,17 @@ bool filterRangeExecute(SFilterInfo *info, SDataStatis *pDataStatis, int32_t num ...@@ -2880,16 +3233,17 @@ bool filterRangeExecute(SFilterInfo *info, SDataStatis *pDataStatis, int32_t num
// no statistics data, load the true data block // no statistics data, load the true data block
if (index == -1) { if (index == -1) {
return true; break;
} }
// not support pre-filter operation on binary/nchar data type // not support pre-filter operation on binary/nchar data type
if (FILTER_NO_MERGE_DATA_TYPE(ctx->type)) { if (FILTER_NO_MERGE_DATA_TYPE(ctx->type)) {
return true; break;
} }
if ((pDataStatis[index].numOfNull <= 0) && (ctx->isnull && !ctx->notnull && !ctx->isrange)) { if ((pDataStatis[index].numOfNull <= 0) && (ctx->isnull && !ctx->notnull && !ctx->isrange)) {
return false; ret = false;
break;
} }
// all data in current column are NULL, no need to check its boundary value // all data in current column are NULL, no need to check its boundary value
...@@ -2897,7 +3251,8 @@ bool filterRangeExecute(SFilterInfo *info, SDataStatis *pDataStatis, int32_t num ...@@ -2897,7 +3251,8 @@ bool filterRangeExecute(SFilterInfo *info, SDataStatis *pDataStatis, int32_t num
// if isNULL query exists, load the null data column // if isNULL query exists, load the null data column
if ((ctx->notnull || ctx->isrange) && (!ctx->isnull)) { if ((ctx->notnull || ctx->isrange) && (!ctx->isnull)) {
return false; ret = false;
break;
} }
continue; continue;
......
...@@ -1133,7 +1133,7 @@ static void rpcNotifyClient(SRpcReqContext *pContext, SRpcMsg *pMsg) { ...@@ -1133,7 +1133,7 @@ static void rpcNotifyClient(SRpcReqContext *pContext, SRpcMsg *pMsg) {
} else { } else {
// for asynchronous API // for asynchronous API
SRpcEpSet *pEpSet = NULL; SRpcEpSet *pEpSet = NULL;
//if (pContext->epSet.inUse != pContext->oldInUse || pContext->redirect) if (pContext->epSet.inUse != pContext->oldInUse || pContext->redirect)
pEpSet = &pContext->epSet; pEpSet = &pContext->epSet;
(*pRpc->cfp)(pMsg, pEpSet); (*pRpc->cfp)(pMsg, pEpSet);
......
...@@ -691,6 +691,18 @@ static STableGroupInfo* trimTableGroup(STimeWindow* window, STableGroupInfo* pGr ...@@ -691,6 +691,18 @@ static STableGroupInfo* trimTableGroup(STimeWindow* window, STableGroupInfo* pGr
TsdbQueryHandleT tsdbQueryRowsInExternalWindow(STsdbRepo *tsdb, STsdbQueryCond* pCond, STableGroupInfo *groupList, uint64_t qId, SMemRef* pRef) { TsdbQueryHandleT tsdbQueryRowsInExternalWindow(STsdbRepo *tsdb, STsdbQueryCond* pCond, STableGroupInfo *groupList, uint64_t qId, SMemRef* pRef) {
STableGroupInfo* pNew = trimTableGroup(&pCond->twindow, groupList); STableGroupInfo* pNew = trimTableGroup(&pCond->twindow, groupList);
if (pNew->numOfTables == 0) {
tsdbDebug("update query time range to invalidate time window");
assert(taosArrayGetSize(pNew->pGroupList) == 0);
bool asc = ASCENDING_TRAVERSE(pCond->order);
if (asc) {
pCond->twindow.ekey = pCond->twindow.skey - 1;
} else {
pCond->twindow.skey = pCond->twindow.ekey - 1;
}
}
STsdbQueryHandle *pQueryHandle = (STsdbQueryHandle*) tsdbQueryTables(tsdb, pCond, pNew, qId, pRef); STsdbQueryHandle *pQueryHandle = (STsdbQueryHandle*) tsdbQueryTables(tsdb, pCond, pNew, qId, pRef);
pQueryHandle->loadExternalRow = true; pQueryHandle->loadExternalRow = true;
pQueryHandle->currentLoadExternalRows = true; pQueryHandle->currentLoadExternalRows = true;
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
extern "C" { extern "C" {
#endif #endif
void taosNetTest(char *role, char *host, int port, int pkgLen); void taosNetTest(char *role, char *host, int32_t port, int32_t pkgLen, int32_t pkgNum, char *pkgType);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -27,6 +27,10 @@ ...@@ -27,6 +27,10 @@
#include "syncMsg.h" #include "syncMsg.h"
#define MAX_PKG_LEN (64 * 1000) #define MAX_PKG_LEN (64 * 1000)
#define MAX_SPEED_PKG_LEN (1024 * 1024 * 1024)
#define MIN_SPEED_PKG_LEN 1024
#define MAX_SPEED_PKG_NUM 10000
#define MIN_SPEED_PKG_NUM 1
#define BUFFER_SIZE (MAX_PKG_LEN + 1024) #define BUFFER_SIZE (MAX_PKG_LEN + 1024)
extern int32_t tsRpcMaxUdpSize; extern int32_t tsRpcMaxUdpSize;
...@@ -466,6 +470,7 @@ static void taosNetTestRpc(char *host, int32_t startPort, int32_t pkgLen) { ...@@ -466,6 +470,7 @@ static void taosNetTestRpc(char *host, int32_t startPort, int32_t pkgLen) {
sendpkgLen = pkgLen; sendpkgLen = pkgLen;
} }
tsRpcForceTcp = 1;
int32_t ret = taosNetCheckRpc(host, port, sendpkgLen, spi, NULL); int32_t ret = taosNetCheckRpc(host, port, sendpkgLen, spi, NULL);
if (ret < 0) { if (ret < 0) {
printf("failed to test TCP port:%d\n", port); printf("failed to test TCP port:%d\n", port);
...@@ -479,6 +484,7 @@ static void taosNetTestRpc(char *host, int32_t startPort, int32_t pkgLen) { ...@@ -479,6 +484,7 @@ static void taosNetTestRpc(char *host, int32_t startPort, int32_t pkgLen) {
sendpkgLen = pkgLen; sendpkgLen = pkgLen;
} }
tsRpcForceTcp = 0;
ret = taosNetCheckRpc(host, port, pkgLen, spi, NULL); ret = taosNetCheckRpc(host, port, pkgLen, spi, NULL);
if (ret < 0) { if (ret < 0) {
printf("failed to test UDP port:%d\n", port); printf("failed to test UDP port:%d\n", port);
...@@ -542,12 +548,122 @@ static void taosNetTestServer(char *host, int32_t startPort, int32_t pkgLen) { ...@@ -542,12 +548,122 @@ static void taosNetTestServer(char *host, int32_t startPort, int32_t pkgLen) {
} }
} }
void taosNetTest(char *role, char *host, int32_t port, int32_t pkgLen) { static void taosNetTestFqdn(char *host) {
int code = 0;
uint64_t startTime = taosGetTimestampUs();
uint32_t ip = taosGetIpv4FromFqdn(host);
if (ip == 0xffffffff) {
uError("failed to get IP address from %s since %s", host, strerror(errno));
code = -1;
}
uint64_t endTime = taosGetTimestampUs();
uint64_t el = endTime - startTime;
printf("check convert fqdn spend, status: %d\tcost: %" PRIu64 " us\n", code, el);
return;
}
static void taosNetCheckSpeed(char *host, int32_t port, int32_t pkgLen,
int32_t pkgNum, char *pkgType) {
// record config
int32_t compressTmp = tsCompressMsgSize;
int32_t maxUdpSize = tsRpcMaxUdpSize;
int32_t forceTcp = tsRpcForceTcp;
if (0 == strcmp("tcp", pkgType)){
tsRpcForceTcp = 1;
tsRpcMaxUdpSize = 0; // force tcp
} else {
tsRpcForceTcp = 0;
tsRpcMaxUdpSize = INT_MAX;
}
tsCompressMsgSize = -1;
SRpcEpSet epSet;
SRpcMsg reqMsg;
SRpcMsg rspMsg;
void * pRpcConn;
char secretEncrypt[32] = {0};
char spi = 0;
pRpcConn = taosNetInitRpc(secretEncrypt, spi);
if (NULL == pRpcConn) {
uError("failed to init client rpc");
return;
}
printf("check net spend, host:%s port:%d pkgLen:%d pkgNum:%d pkgType:%s\n\n", host, port, pkgLen, pkgNum, pkgType);
int32_t totalSucc = 0;
uint64_t startT = taosGetTimestampUs();
for (int32_t i = 1; i <= pkgNum; i++) {
uint64_t startTime = taosGetTimestampUs();
memset(&epSet, 0, sizeof(SRpcEpSet));
epSet.inUse = 0;
epSet.numOfEps = 1;
epSet.port[0] = port;
strcpy(epSet.fqdn[0], host);
reqMsg.msgType = TSDB_MSG_TYPE_NETWORK_TEST;
reqMsg.pCont = rpcMallocCont(pkgLen);
reqMsg.contLen = pkgLen;
reqMsg.code = 0;
reqMsg.handle = NULL; // rpc handle returned to app
reqMsg.ahandle = NULL; // app handle set by client
strcpy(reqMsg.pCont, "nettest speed");
rpcSendRecv(pRpcConn, &epSet, &reqMsg, &rspMsg);
int code = 0;
if ((rspMsg.code != 0) || (rspMsg.msgType != TSDB_MSG_TYPE_NETWORK_TEST + 1)) {
uError("ret code 0x%x %s", rspMsg.code, tstrerror(rspMsg.code));
code = -1;
}else{
totalSucc ++;
}
rpcFreeCont(rspMsg.pCont);
uint64_t endTime = taosGetTimestampUs();
uint64_t el = endTime - startTime;
printf("progress:%5d/%d\tstatus:%d\tcost:%8.2lf ms\tspeed:%8.2lf MB/s\n", i, pkgNum, code, el/1000.0, pkgLen/(el/1000000.0)/1024.0/1024.0);
}
int64_t endT = taosGetTimestampUs();
uint64_t elT = endT - startT;
printf("\ntotal succ:%5d/%d\tcost:%8.2lf ms\tspeed:%8.2lf MB/s\n", totalSucc, pkgNum, elT/1000.0, pkgLen/(elT/1000000.0)/1024.0/1024.0*totalSucc);
rpcClose(pRpcConn);
// return config
tsCompressMsgSize = compressTmp;
tsRpcMaxUdpSize = maxUdpSize;
tsRpcForceTcp = forceTcp;
return;
}
static void taosNetTestSpeed(char *host, int32_t port, int32_t pkgLen,
int32_t pkgNum, char *pkgType) {
if (0 == strcmp("fqdn", pkgType)){
taosNetTestFqdn(host);
return;
}
taosNetCheckSpeed(host, port, pkgLen, pkgNum, pkgType);
return;
}
void taosNetTest(char *role, char *host, int32_t port, int32_t pkgLen,
int32_t pkgNum, char *pkgType) {
tscEmbedded = 1; tscEmbedded = 1;
if (host == NULL) host = tsLocalFqdn; if (host == NULL) host = tsLocalFqdn;
if (port == 0) port = tsServerPort; if (port == 0) port = tsServerPort;
if (0 == strcmp("speed", role)){
if (pkgLen <= MIN_SPEED_PKG_LEN) pkgLen = MIN_SPEED_PKG_LEN;
if (pkgLen > MAX_SPEED_PKG_LEN) pkgLen = MAX_SPEED_PKG_LEN;
if (pkgNum <= MIN_SPEED_PKG_NUM) pkgNum = MIN_SPEED_PKG_NUM;
if (pkgNum > MAX_SPEED_PKG_NUM) pkgNum = MAX_SPEED_PKG_NUM;
}else{
if (pkgLen <= 10) pkgLen = 1000; if (pkgLen <= 10) pkgLen = 1000;
if (pkgLen > MAX_PKG_LEN) pkgLen = MAX_PKG_LEN; if (pkgLen > MAX_PKG_LEN) pkgLen = MAX_PKG_LEN;
}
if (0 == strcmp("client", role)) { if (0 == strcmp("client", role)) {
taosNetTestClient(host, port, pkgLen); taosNetTestClient(host, port, pkgLen);
...@@ -560,7 +676,11 @@ void taosNetTest(char *role, char *host, int32_t port, int32_t pkgLen) { ...@@ -560,7 +676,11 @@ void taosNetTest(char *role, char *host, int32_t port, int32_t pkgLen) {
taosNetCheckSync(host, port); taosNetCheckSync(host, port);
} else if (0 == strcmp("startup", role)) { } else if (0 == strcmp("startup", role)) {
taosNetTestStartup(host, port); taosNetTestStartup(host, port);
} else { } else if (0 == strcmp("speed", role)) {
tscEmbedded = 0;
char type[10] = {0};
taosNetTestSpeed(host, port, pkgLen, pkgNum, strtolower(type, pkgType));
}else {
taosNetTestStartup(host, port); taosNetTestStartup(host, port);
} }
......
...@@ -35,6 +35,8 @@ class TDTestCase: ...@@ -35,6 +35,8 @@ class TDTestCase:
ret = tdSql.query('select server_status() as result') ret = tdSql.query('select server_status() as result')
tdSql.checkData(0, 0, 1) tdSql.checkData(0, 0, 1)
time.sleep(1)
ret = tdSql.query('show dnodes') ret = tdSql.query('show dnodes')
dnodeId = tdSql.getData(0, 0); dnodeId = tdSql.getData(0, 0);
...@@ -43,6 +45,7 @@ class TDTestCase: ...@@ -43,6 +45,7 @@ class TDTestCase:
ret = tdSql.execute('alter dnode "%s" debugFlag 135' % dnodeId) ret = tdSql.execute('alter dnode "%s" debugFlag 135' % dnodeId)
tdLog.info('alter dnode "%s" debugFlag 135 -> ret: %d' % (dnodeId, ret)) tdLog.info('alter dnode "%s" debugFlag 135 -> ret: %d' % (dnodeId, ret))
time.sleep(1)
ret = tdSql.query('show mnodes') ret = tdSql.query('show mnodes')
tdSql.checkRows(1) tdSql.checkRows(1)
...@@ -63,6 +66,9 @@ class TDTestCase: ...@@ -63,6 +66,9 @@ class TDTestCase:
tdSql.execute('create stable st (ts timestamp, f int) tags(t int)') tdSql.execute('create stable st (ts timestamp, f int) tags(t int)')
tdSql.execute('create table ct1 using st tags(1)'); tdSql.execute('create table ct1 using st tags(1)');
tdSql.execute('create table ct2 using st tags(2)'); tdSql.execute('create table ct2 using st tags(2)');
time.sleep(1)
ret = tdSql.query('show vnodes "{}"'.format(dnodeEndpoint)) ret = tdSql.query('show vnodes "{}"'.format(dnodeEndpoint))
tdSql.checkRows(1) tdSql.checkRows(1)
tdSql.checkData(0, 0, 2) tdSql.checkData(0, 0, 2)
......
...@@ -212,6 +212,7 @@ python3 test.py -f tools/taosdemoAllTest/taosdemoTestInsertWithJson.py ...@@ -212,6 +212,7 @@ python3 test.py -f tools/taosdemoAllTest/taosdemoTestInsertWithJson.py
python3 test.py -f tools/taosdemoAllTest/taosdemoTestQueryWithJson.py python3 test.py -f tools/taosdemoAllTest/taosdemoTestQueryWithJson.py
#query #query
python3 test.py -f query/distinctOneColTb.py
python3 ./test.py -f query/filter.py python3 ./test.py -f query/filter.py
python3 ./test.py -f query/filterCombo.py python3 ./test.py -f query/filterCombo.py
python3 ./test.py -f query/queryNormal.py python3 ./test.py -f query/queryNormal.py
...@@ -284,7 +285,7 @@ python3 ./test.py -f alter/alterTabAddTagWithNULL.py ...@@ -284,7 +285,7 @@ python3 ./test.py -f alter/alterTabAddTagWithNULL.py
python3 ./test.py -f alter/alterTimestampColDataProcess.py python3 ./test.py -f alter/alterTimestampColDataProcess.py
# client # client
#python3 ./test.py -f client/client.py python3 ./test.py -f client/client.py
python3 ./test.py -f client/version.py python3 ./test.py -f client/version.py
python3 ./test.py -f client/alterDatabase.py python3 ./test.py -f client/alterDatabase.py
python3 ./test.py -f client/noConnectionErrorTest.py python3 ./test.py -f client/noConnectionErrorTest.py
......
###################################################################
# Copyright (c) 2016 by TAOS Technologies, Inc.
# All rights reserved.
#
# This file is proprietary and confidential to TAOS Technologies.
# No part of this file may be reproduced, stored, transmitted,
# disclosed or used in any form or by any means other than as
# expressly provided by the written permission from Jianhui Tao
#
###################################################################
# -*- coding: utf-8 -*-
import sys
import taos
from util.log import *
from util.cases import *
from util.sql import *
class TDTestCase:
def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor())
def tb_all_query(self, num, sql="tb_all", where=""):
tdSql.query(
f"select distinct ts2 from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct cint from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct cbigint from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct csmallint from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct ctinyint from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct cfloat from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct cdouble from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct cbool from {sql} {where}")
if num < 2:
tdSql.checkRows(num)
else:
tdSql.checkRows(2)
tdSql.query(
f"select distinct cbinary from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct cnchar from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct ts2 as a from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct cint as a from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct cbigint as a from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct csmallint as a from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct ctinyint as a from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct cfloat as a from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct cdouble as a from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct cbool as a from {sql} {where}")
if num < 2:
tdSql.checkRows(num)
else:
tdSql.checkRows(2)
tdSql.query(
f"select distinct cbinary as a from {sql} {where}")
tdSql.checkRows(num)
tdSql.query(
f"select distinct cnchar as a from {sql} {where}")
tdSql.checkRows(num)
def tb_all_query_sub(self, num, sql="tb_all", where="",colName = "c1"):
tdSql.query(
f"select distinct {colName} from {sql} {where}")
tdSql.checkRows(num)
def errorCheck(self, sql='tb_all'):
tdSql.error(f"select distinct from {sql}")
tdSql.error(f"distinct ts2 from {sql}")
tdSql.error(f"distinct c1 from")
tdSql.error(f"select distinct ts2, avg(cint) from {sql}")
## the following line is going to core dump
#tdSql.error(f"select avg(cint), distinct ts2 from {sql}")
tdSql.error(f"select distinct ts2 from {sql} group by cint")
tdSql.error(f"select distinct ts2 from {sql} interval(1s)")
tdSql.error(f"select distinct ts2 from {sql} slimit 1 soffset 1")
tdSql.error(f"select distinct ts2 from {sql} slimit 1")
##order by is not supported but not being prohibited
#tdSql.error(f"select distinct ts2 from {sql} order by desc")
#tdSql.error(f"select distinct ts2 from {sql} order by asc")
##distinct should not use on first ts, but it can be applied
#tdSql.error(f"select distinct ts from {sql}")
##distinct should not be used in inner query, but error did not occur
# tdSql.error(f"select distinct ts2 from (select distinct ts2 from {sql})")
def query_all_tb(self, whereNum=0,inNum=0,maxNum=0,tbName="tb_all"):
self.tb_all_query(maxNum,sql=tbName)
self.tb_all_query(num=whereNum,where="where ts2 = '2021-08-06 18:01:50.550'",sql=tbName)
self.tb_all_query(num=whereNum,where="where cint = 1073741820",sql=tbName)
self.tb_all_query(num=whereNum,where="where cbigint = 1125899906842620",sql=tbName)
self.tb_all_query(num=whereNum,where="where csmallint = 150",sql=tbName)
self.tb_all_query(num=whereNum,where="where ctinyint = 10",sql=tbName)
self.tb_all_query(num=whereNum,where="where cfloat = 0.10",sql=tbName)
self.tb_all_query(num=whereNum,where="where cdouble = 0.130",sql=tbName)
self.tb_all_query(num=whereNum,where="where cbool = true",sql=tbName)
self.tb_all_query(num=whereNum,where="where cbinary = 'adc1'",sql=tbName)
self.tb_all_query(num=whereNum,where="where cnchar = '双精度浮'",sql=tbName)
self.tb_all_query(num=inNum,where="where ts2 in ( '2021-08-06 18:01:50.550' , '2021-08-06 18:01:50.551' )",sql=tbName)
self.tb_all_query(num=inNum,where="where cint in (1073741820,1073741821)",sql=tbName)
self.tb_all_query(num=inNum,where="where cbigint in (1125899906842620,1125899906842621)",sql=tbName)
self.tb_all_query(num=inNum,where="where csmallint in (150,151)",sql=tbName)
self.tb_all_query(num=inNum,where="where ctinyint in (10,11)",sql=tbName)
self.tb_all_query(num=inNum,where="where cfloat in (0.10,0.11)",sql=tbName)
self.tb_all_query(num=inNum,where="where cdouble in (0.130,0.131)",sql=tbName)
self.tb_all_query(num=inNum,where="where cbinary in ('adc0','adc1')",sql=tbName)
self.tb_all_query(num=inNum,where="where cnchar in ('双','双精度浮')",sql=tbName)
self.tb_all_query(num=inNum,where="where cbool in (0, 1)",sql=tbName)
self.tb_all_query(num=whereNum,where="where cnchar like '双__浮'",sql=tbName)
self.tb_all_query(num=maxNum,where="where cnchar like '双%'",sql=tbName)
self.tb_all_query(num=maxNum,where="where cbinary like 'adc_'",sql=tbName)
self.tb_all_query(num=maxNum,where="where cbinary like 'a%'",sql=tbName)
self.tb_all_query(num=whereNum,where="limit 1",sql=tbName)
self.tb_all_query(num=whereNum,where="limit 1 offset 1",sql=tbName)
#subquery
self.tb_all_query(num=maxNum,sql=f'(select * from {tbName})')
#subquery with where in outer query
self.tb_all_query(num=whereNum,where="where ts2 = '2021-08-06 18:01:50.550'",sql=f'(select * from {tbName})')
self.tb_all_query(num=whereNum,where="where cint = 1073741820",sql=f'(select * from {tbName})')
self.tb_all_query(num=whereNum,where="where cbigint = 1125899906842620",sql=f'(select * from {tbName})')
self.tb_all_query(num=whereNum,where="where csmallint = 150",sql=f'(select * from {tbName})')
self.tb_all_query(num=whereNum,where="where ctinyint = 10",sql=f'(select * from {tbName})')
self.tb_all_query(num=whereNum,where="where cfloat = 0.10",sql=f'(select * from {tbName})')
self.tb_all_query(num=whereNum,where="where cdouble = 0.130",sql=f'(select * from {tbName})')
self.tb_all_query(num=whereNum,where="where cbool = true",sql=f'(select * from {tbName})')
self.tb_all_query(num=whereNum,where="where cbinary = 'adc1'",sql=f'(select * from {tbName})')
self.tb_all_query(num=whereNum,where="where cnchar = '双精度浮'",sql=f'(select * from {tbName})')
self.tb_all_query(num=inNum,where="where ts2 in ( '2021-08-06 18:01:50.550' , '2021-08-06 18:01:50.551' )",sql=f'(select * from {tbName})')
self.tb_all_query(num=inNum,where="where cint in (1073741820,1073741821)",sql=f'(select * from {tbName})')
self.tb_all_query(num=inNum,where="where cbigint in (1125899906842620,1125899906842621)",sql=f'(select * from {tbName})')
self.tb_all_query(num=inNum,where="where csmallint in (150,151)",sql=f'(select * from {tbName})')
self.tb_all_query(num=inNum,where="where ctinyint in (10,11)",sql=f'(select * from {tbName})')
self.tb_all_query(num=inNum,where="where cfloat in (0.10,0.11)",sql=f'(select * from {tbName})')
self.tb_all_query(num=inNum,where="where cdouble in (0.130,0.131)",sql=f'(select * from {tbName})')
self.tb_all_query(num=inNum,where="where cbinary in ('adc0','adc1')",sql=f'(select * from {tbName})')
self.tb_all_query(num=inNum,where="where cnchar in ('双','双精度浮')",sql=f'(select * from {tbName})')
self.tb_all_query(num=inNum,where="where cbool in (0, 1)",sql=f'(select * from {tbName})')
self.tb_all_query(num=whereNum,where="where cnchar like '双__浮'",sql=f'(select * from {tbName})')
self.tb_all_query(num=maxNum,where="where cnchar like '双%'",sql=f'(select * from {tbName})')
self.tb_all_query(num=maxNum,where="where cbinary like 'adc_'",sql=f'(select * from {tbName})')
self.tb_all_query(num=maxNum,where="where cbinary like 'a%'",sql=f'(select * from {tbName})')
self.tb_all_query(num=whereNum,where="limit 1",sql=f'(select * from {tbName})')
self.tb_all_query(num=whereNum,where="limit 1 offset 1",sql=f'(select * from {tbName})')
#table query with inner query has error
tdSql.error('select distinct ts2 from (select )')
#table query with error option
self.errorCheck()
def run(self):
tdSql.prepare()
tdLog.notice(
"==============phase1 distinct col1 with no values==========")
tdSql.execute("create stable if not exists stb_all (ts timestamp, ts2 timestamp, cint int, cbigint bigint, csmallint smallint, ctinyint tinyint,cfloat float, cdouble double, cbool bool, cbinary binary(32), cnchar nchar(32)) tags(tint int)")
tdSql.execute(
"create table if not exists tb_all using stb_all tags(1)")
self.query_all_tb()
tdLog.notice(
"==============phase1 finished ==========\n\n\n")
tdLog.notice(
"==============phase2 distinct col1 all values are null==========")
tdSql.execute(
"insert into tb_all values(now,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)")
tdSql.execute(
"insert into tb_all values(now,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)")
tdSql.execute(
"insert into tb_all values(now,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)")
# normal query
self.query_all_tb()
tdLog.notice(
"==============phase2 finished ==========\n\n\n")
tdLog.notice(
"==============phase3 distinct with distinct values ==========\n\n\n")
tdSql.execute(
"insert into tb_all values(now+1s,'2021-08-06 18:01:50.550',1073741820,1125899906842620,150,10,0.10,0.130, true,'adc0','双')")
tdSql.execute(
"insert into tb_all values(now+2s,'2021-08-06 18:01:50.551',1073741821,1125899906842621,151,11,0.11,0.131,false,'adc1','双精度浮')")
tdSql.execute(
"insert into tb_all values(now+3s,'2021-08-06 18:01:50.552',1073741822,1125899906842622,152,12,0.12,0.132,NULL,'adc2','双精度')")
tdSql.execute(
"insert into tb_all values(now+4s,'2021-08-06 18:01:50.553',1073741823,1125899906842623,153,13,0.13,0.133,NULL,'adc3','双精')")
tdSql.execute(
"insert into tb_all values(now+5s,'2021-08-06 18:01:50.554',1073741824,1125899906842624,154,14,0.14,0.134,NULL,'adc4','双精度浮点型')")
# normal query
self.query_all_tb(maxNum=5,inNum=2,whereNum=1)
tdLog.notice(
"==============phase3 finishes ==========\n\n\n")
tdLog.notice(
"==============phase4 distinct with some values the same values ==========\n\n\n")
tdSql.execute(
"insert into tb_all values(now+10s,'2021-08-06 18:01:50.550',1073741820,1125899906842620,150,10,0.10,0.130, true,'adc0','双')")
tdSql.execute(
"insert into tb_all values(now+20s,'2021-08-06 18:01:50.551',1073741821,1125899906842621,151,11,0.11,0.131,false,'adc1','双精度浮')")
tdSql.execute(
"insert into tb_all values(now+30s,'2021-08-06 18:01:50.552',1073741822,1125899906842622,152,12,0.12,0.132,NULL,'adc2','双精度')")
tdSql.execute(
"insert into tb_all values(now+40s,'2021-08-06 18:01:50.553',1073741823,1125899906842623,153,13,0.13,0.133,NULL,'adc3','双精')")
tdSql.execute(
"insert into tb_all values(now+50s,'2021-08-06 18:01:50.554',1073741824,1125899906842624,154,14,0.14,0.134,NULL,'adc4','双精度浮点型')")
# normal query
self.query_all_tb(maxNum=5,inNum=2,whereNum=1)
tdLog.notice(
"==============phase4 finishes ==========\n\n\n")
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
tdCases.addWindows(__file__, TDTestCase())
tdCases.addLinux(__file__, TDTestCase())
...@@ -145,26 +145,26 @@ class taosdemoPerformace: ...@@ -145,26 +145,26 @@ class taosdemoPerformace:
binPath = buildPath + "/build/bin/" binPath = buildPath + "/build/bin/"
os.system( os.system(
"%staosdemo -f %s > taosdemoperf.txt 2>&1" % "%staosdemo -f %s > /dev/null 2>&1" %
(binPath, self.generateJson())) (binPath, self.generateJson()))
self.createTableTime = self.getCMDOutput( self.createTableTime = self.getCMDOutput(
"grep 'Spent' taosdemoperf.txt | awk 'NR==1{print $2}'") "grep 'Spent' insert_res.txt | awk 'NR==1{print $2}'")
self.insertRecordsTime = self.getCMDOutput( self.insertRecordsTime = self.getCMDOutput(
"grep 'Spent' taosdemoperf.txt | awk 'NR==2{print $2}'") "grep 'Spent' insert_res.txt | awk 'NR==2{print $2}'")
self.recordsPerSecond = self.getCMDOutput( self.recordsPerSecond = self.getCMDOutput(
"grep 'Spent' taosdemoperf.txt | awk 'NR==2{print $16}'") "grep 'Spent' insert_res.txt | awk 'NR==2{print $16}'")
self.commitID = self.getCMDOutput("git rev-parse --short HEAD") self.commitID = self.getCMDOutput("git rev-parse --short HEAD")
delay = self.getCMDOutput( delay = self.getCMDOutput(
"grep 'delay' taosdemoperf.txt | awk '{print $4}'") "grep 'delay' insert_res.txt | awk '{print $4}'")
self.avgDelay = delay[:-4] self.avgDelay = delay[:-4]
delay = self.getCMDOutput( delay = self.getCMDOutput(
"grep 'delay' taosdemoperf.txt | awk '{print $6}'") "grep 'delay' insert_res.txt | awk '{print $6}'")
self.maxDelay = delay[:-4] self.maxDelay = delay[:-4]
delay = self.getCMDOutput( delay = self.getCMDOutput(
"grep 'delay' taosdemoperf.txt | awk '{print $8}'") "grep 'delay' insert_res.txt | awk '{print $8}'")
self.minDelay = delay[:-3] self.minDelay = delay[:-3]
os.system("[ -f taosdemoperf.txt ] && rm taosdemoperf.txt") os.system("[ -f insert_res.txt ] && rm insert_res.txt")
def createTablesAndStoreData(self): def createTablesAndStoreData(self):
cursor = self.conn2.cursor() cursor = self.conn2.cursor()
...@@ -185,7 +185,7 @@ class taosdemoPerformace: ...@@ -185,7 +185,7 @@ class taosdemoPerformace:
cursor.close() cursor.close()
cursor1 = self.conn.cursor() cursor1 = self.conn.cursor()
# cursor1.execute("drop database if exists %s" % self.insertDB) cursor1.execute("drop database if exists %s" % self.insertDB)
cursor1.close() cursor1.close()
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -3,6 +3,7 @@ system sh/stop_dnodes.sh ...@@ -3,6 +3,7 @@ system sh/stop_dnodes.sh
system sh/deploy.sh -n dnode1 -i 1 system sh/deploy.sh -n dnode1 -i 1
system sh/cfg.sh -n dnode1 -c walLevel -v 1 system sh/cfg.sh -n dnode1 -c walLevel -v 1
system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4
system sh/cfg.sh -n dnode1 -c cache -v 1
system sh/exec.sh -n dnode1 -s start system sh/exec.sh -n dnode1 -s start
sleep 100 sleep 100
...@@ -93,6 +94,47 @@ sql insert into tb3_2 values ('2021-05-06 18:19:28',15,NULL,15,NULL,15,NULL,true ...@@ -93,6 +94,47 @@ sql insert into tb3_2 values ('2021-05-06 18:19:28',15,NULL,15,NULL,15,NULL,true
sql insert into tb3_2 values ('2021-06-06 18:19:28',NULL,16.0,NULL,16,NULL,16.0,NULL,'16',NULL) sql insert into tb3_2 values ('2021-06-06 18:19:28',NULL,16.0,NULL,16,NULL,16.0,NULL,'16',NULL)
sql insert into tb3_2 values ('2021-07-06 18:19:28',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL) sql insert into tb3_2 values ('2021-07-06 18:19:28',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)
sql create table stb4 (ts timestamp, c1 int, c2 float, c3 bigint, c4 smallint, c5 tinyint, c6 double, c7 bool, c8 binary(10), c9 nchar(9),c10 binary(16300)) TAGS(t1 int, t2 binary(10), t3 double)
sql create table tb4_0 using stb4 tags(0,'0',0.0)
sql create table tb4_1 using stb4 tags(1,'1',1.0)
sql create table tb4_2 using stb4 tags(2,'2',2.0)
sql create table tb4_3 using stb4 tags(3,'3',3.0)
sql create table tb4_4 using stb4 tags(4,'4',4.0)
$i = 0
$ts0 = 1625850000000
$blockNum = 5
$delta = 0
$tbname0 = tb4_
$a = 0
$b = 200
$c = 400
while $i < $blockNum
$x = 0
$rowNum = 1200
while $x < $rowNum
$ts = $ts0 + $x
$a = $a + 1
$b = $b + 1
$c = $c + 1
$d = $x / 10
$tin = $rowNum
$binary = 'binary . $c
$binary = $binary . '
$nchar = 'nchar . $c
$nchar = $nchar . '
$tbname = 'tb4_ . $i
$tbname = $tbname . '
sql insert into $tbname values ( $ts , $a , $b , $c , $d , $d , $c , true, $binary , $nchar , $binary )
$x = $x + 1
endw
$i = $i + 1
$ts0 = $ts0 + 259200000
endw
sleep 100 sleep 100
sql connect sql connect
......
...@@ -1959,6 +1959,117 @@ if $rows != 14 then ...@@ -1959,6 +1959,117 @@ if $rows != 14 then
return -1 return -1
endi endi
sql select ts,c1 from stb4 where c1 = 200;
if $rows != 1 then
return -1
endi
if $data00 != @21-07-10 01:00:00.199@ then
return -1
endi
sql select ts,c1 from stb4 where c1 != 200;
if $rows != 5999 then
return -1
endi
sql select ts,c1,c2,c3,c4 from stb4 where c1 >= 200 and c2 > 500 and c3 < 800 and c4 between 33 and 37 and c4 != 35 and c2 < 555 and c1 < 339 and c1 in (331,333,335);
if $rows != 3 then
return -1
endi
if $data00 != @21-07-10 01:00:00.330@ then
return -1
endi
if $data10 != @21-07-10 01:00:00.332@ then
return -1
endi
if $data20 != @21-07-10 01:00:00.334@ then
return -1
endi
sql select ts,c1,c2,c3,c4 from stb4 where c1 > -3 and c1 < 5;
if $rows != 4 then
return -1
endi
if $data00 != @21-07-10 01:00:00.000@ then
return -1
endi
if $data10 != @21-07-10 01:00:00.001@ then
return -1
endi
if $data20 != @21-07-10 01:00:00.002@ then
return -1
endi
if $data30 != @21-07-10 01:00:00.003@ then
return -1
endi
sql select ts,c1,c2,c3,c4 from stb4 where c1 >= 2 and c1 < 5;
if $rows != 3 then
return -1
endi
if $data00 != @21-07-10 01:00:00.001@ then
return -1
endi
if $data10 != @21-07-10 01:00:00.002@ then
return -1
endi
if $data20 != @21-07-10 01:00:00.003@ then
return -1
endi
sql select ts,c1,c2,c3,c4 from stb4 where c1 >= -3 and c1 < 1300;
if $rows != 1299 then
return -1
endi
sql select ts,c1,c2,c3,c4 from stb4 where c1 >= 1298 and c1 < 1300 or c2 > 210 and c2 < 213;
if $rows != 4 then
return -1
endi
if $data00 != @21-07-10 01:00:00.010@ then
return -1
endi
if $data10 != @21-07-10 01:00:00.011@ then
return -1
endi
if $data20 != @21-07-13 01:00:00.097@ then
return -1
endi
if $data30 != @21-07-13 01:00:00.098@ then
return -1
endi
sql select ts,c1,c2,c3,c4 from stb4 where c1 >= -3;
if $rows != 6000 then
return -1
endi
sql select ts,c1,c2,c3,c4 from stb4 where c1 < 1400;
if $rows != 1399 then
return -1
endi
sql select ts,c1,c2,c3,c4 from stb4 where c1 < 1100;
if $rows != 1099 then
return -1
endi
sql select ts,c1,c2,c3,c4 from stb4 where c1 in(10,100, 1100,3300) and c1 != 10;
if $rows != 3 then
return -1
endi
if $data00 != @21-07-10 01:00:00.099@ then
return -1
endi
if $data10 != @21-07-10 01:00:01.099@ then
return -1
endi
if $data20 != @21-07-16 01:00:00.899@ then
return -1
endi
print "ts test" print "ts test"
......
system sh/stop_dnodes.sh
system sh/deploy.sh -n dnode1 -i 1
system sh/cfg.sh -n dnode1 -c walLevel -v 1
system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 5
system sh/exec.sh -n dnode1 -s start
sleep 100
sql connect
$dbPrefix = sav_db
$tbPrefix = sav_tb
$stbPrefix = sav_stb
$tbNum = 20
$rowNum = 10
$totalNum = $tbNum * $rowNum
$ts0 = 1537146000000
$delta = 600000
print ========== alter.sim
$i = 0
$db = $dbPrefix
$stb = $stbPrefix
sql drop database if exists $db
sql create database $db
sql use $db
print ====== create tables
sql create table $stb (ts timestamp, c1 int) tags(t1 int, t2 int)
$i = 0
$ts = $ts0
while $i < $tbNum
$tb = $tbPrefix . $i
sql create table $tb using $stb tags( $i , 0 )
$i = $i + 1
sql insert into $tb values('2015-08-18 00:00:00', 1);
sql insert into $tb values('2015-08-18 00:06:00', 2);
sql insert into $tb values('2015-08-18 00:12:00', 3);
sql insert into $tb values('2015-08-18 00:18:00', 4);
sql insert into $tb values('2015-08-18 00:24:00', 5);
sql insert into $tb values('2015-08-18 00:30:00', 6);
endw
$i = 0
$tb = $tbPrefix . $i
print ====== table created
#### select distinct tag
sql select distinct t1 from $stb
if $rows != $tbNum then
return -1
endi
#### select distinct tag
sql select distinct t2 from $stb
if $rows != 1 then
print $rows
return -1
endi
#### select multi normal column
sql select distinct ts, c1 from $stb
if $rows != 6 then
return -1
endi
#### select multi column
sql select distinct ts from $stb
if $rows != 6 then
return -1
endi
### select multi normal column
### select distinct multi column on sub table
sql select distinct ts, c1 from $tb
if $rows != 6 then
return -1
endi
### select distinct
sql drop database $db
sql show databases
if $rows != 0 then
return -1
endi
system sh/exec.sh -n dnode1 -s stop -x SIGINT
...@@ -68,4 +68,16 @@ print ================== server restart completed ...@@ -68,4 +68,16 @@ print ================== server restart completed
run general/parser/interp_test.sim run general/parser/interp_test.sim
#system sh/exec.sh -n dnode1 -s stop -x SIGINT
print ================= TD-5931
sql create stable st5931(ts timestamp, f int) tags(t int)
sql create table ct5931 using st5931 tags(1)
sql create table nt5931(ts timestamp, f int)
sql select interp(*) from nt5931 where ts=now
sql select interp(*) from st5931 where ts=now
sql select interp(*) from ct5931 where ts=now
if $rows != 0 then
return -1
endi
system sh/exec.sh -n dnode1 -s stop -x SIGINT
...@@ -80,7 +80,7 @@ cd ../../../debug; make ...@@ -80,7 +80,7 @@ cd ../../../debug; make
./test.sh -f general/parser/set_tag_vals.sim ./test.sh -f general/parser/set_tag_vals.sim
./test.sh -f general/parser/tags_filter.sim ./test.sh -f general/parser/tags_filter.sim
./test.sh -f general/parser/slimit_alter_tags.sim ./test.sh -f general/parser/slimit_alter_tags.sim
#./test.sh -f general/parser/join.sim ./test.sh -f general/parser/join.sim
./test.sh -f general/parser/join_multivnode.sim ./test.sh -f general/parser/join_multivnode.sim
./test.sh -f general/parser/binary_escapeCharacter.sim ./test.sh -f general/parser/binary_escapeCharacter.sim
./test.sh -f general/parser/repeatAlter.sim ./test.sh -f general/parser/repeatAlter.sim
......
...@@ -24,9 +24,9 @@ function stopTaosd { ...@@ -24,9 +24,9 @@ function stopTaosd {
function dohavecore(){ function dohavecore(){
corefile=`find $corepath -mmin 1` corefile=`find $corepath -mmin 1`
core_file=`echo $corefile|cut -d " " -f2`
proc=`echo $corefile|cut -d "_" -f3`
if [ -n "$corefile" ];then if [ -n "$corefile" ];then
core_file=`echo $corefile|cut -d " " -f2`
proc=`file $core_file|awk -F "execfn:" '/execfn:/{print $2}'|tr -d \' |awk '{print $1}'|tr -d \,`
echo 'taosd or taos has generated core' echo 'taosd or taos has generated core'
rm case.log rm case.log
if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]] && [[ $1 == 1 ]]; then if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]] && [[ $1 == 1 ]]; then
...@@ -46,7 +46,7 @@ function dohavecore(){ ...@@ -46,7 +46,7 @@ function dohavecore(){
fi fi
fi fi
if [[ $1 == 1 ]];then if [[ $1 == 1 ]];then
echo '\n'|gdb /usr/local/taos/bin/$proc $core_file -ex "bt 10" -ex quit echo '\n'|gdb $proc $core_file -ex "bt 10" -ex quit
exit 8 exit 8
fi fi
fi fi
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册