Merge branch 'develop' into long_query

This commit is contained in:
AlexDuan 2021-08-30 19:03:09 +08:00
commit 784a0bc17a
99 changed files with 7534 additions and 4711 deletions

12
Jenkinsfile vendored
View File

@ -265,12 +265,12 @@ pipeline {
} }
} }
timeout(time: 60, unit: 'MINUTES'){ timeout(time: 60, unit: 'MINUTES'){
sh ''' // sh '''
cd ${WKC}/tests/pytest // cd ${WKC}/tests/pytest
rm -rf /var/lib/taos/* // rm -rf /var/lib/taos/*
rm -rf /var/log/taos/* // rm -rf /var/log/taos/*
./handle_crash_gen_val_log.sh // ./handle_crash_gen_val_log.sh
''' // '''
sh ''' sh '''
cd ${WKC}/tests/pytest cd ${WKC}/tests/pytest
rm -rf /var/lib/taos/* rm -rf /var/lib/taos/*

View File

@ -4,7 +4,7 @@ PROJECT(TDengine)
IF (DEFINED VERNUMBER) IF (DEFINED VERNUMBER)
SET(TD_VER_NUMBER ${VERNUMBER}) SET(TD_VER_NUMBER ${VERNUMBER})
ELSE () ELSE ()
SET(TD_VER_NUMBER "2.1.7.1") SET(TD_VER_NUMBER "2.1.7.2")
ENDIF () ENDIF ()
IF (DEFINED VERCOMPATIBLE) IF (DEFINED VERCOMPATIBLE)

2
deps/TSZ vendored

@ -1 +1 @@
Subproject commit ceda5bf9fcd7836509ac97dcc0056b3f1dd48cc5 Subproject commit 0ca5b15a8eac40327dd737be52c926fa5675712c

View File

@ -30,7 +30,7 @@ TDengine 的模块之一是时序数据库。但除此之外,为减少研发
|数据源特点和需求|不适用|可能适用|非常适用|简单说明| |数据源特点和需求|不适用|可能适用|非常适用|简单说明|
|---|---|---|---|---| |---|---|---|---|---|
|总体数据量巨大| | | √ |TDengine 在容量方面提供出色的水平扩展功能,并且具备匹配高压缩的存储结构,达到业界最优的存储效率。| |总体数据量巨大| | | √ | TDengine 在容量方面提供出色的水平扩展功能,并且具备匹配高压缩的存储结构,达到业界最优的存储效率。|
|数据输入速度偶尔或者持续巨大| | | √ | TDengine 的性能大大超过同类产品,可以在同样的硬件环境下持续处理大量的输入数据,并且提供很容易在用户环境里面运行的性能评估工具。| |数据输入速度偶尔或者持续巨大| | | √ | TDengine 的性能大大超过同类产品,可以在同样的硬件环境下持续处理大量的输入数据,并且提供很容易在用户环境里面运行的性能评估工具。|
|数据源数目巨大| | | √ | TDengine 设计中包含专门针对大量数据源的优化,包括数据的写入和查询,尤其适合高效处理海量(千万或者更多量级)的数据源。| |数据源数目巨大| | | √ | TDengine 设计中包含专门针对大量数据源的优化,包括数据的写入和查询,尤其适合高效处理海量(千万或者更多量级)的数据源。|

View File

@ -46,7 +46,7 @@ TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致
</tr> </tr>
</table> </table>
注意:与 JNI 方式不同RESTful 接口是无状态的。在使用JDBC-RESTful时需要在sql中指定表、超级表的数据库名称。例如 注意:与 JNI 方式不同RESTful 接口是无状态的。在使用JDBC-RESTful时需要在sql中指定表、超级表的数据库名称。(从 TDengine 2.1.8.0 版本开始,也可以在 RESTful url 中指定当前 SQL 语句所使用的默认数据库名。)例如:
```sql ```sql
INSERT INTO test.t1 USING test.weather (ts, temperature) TAGS('beijing') VALUES(now, 24.6); INSERT INTO test.t1 USING test.weather (ts, temperature) TAGS('beijing') VALUES(now, 24.6);
``` ```
@ -84,6 +84,7 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对
## 安装Java Connector ## 安装Java Connector
### 安装前准备 ### 安装前准备
使用Java Connector连接数据库前需要具备以下条件 使用Java Connector连接数据库前需要具备以下条件
1. Linux或Windows操作系统 1. Linux或Windows操作系统
2. Java 1.8以上运行时环境 2. Java 1.8以上运行时环境
@ -96,6 +97,7 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对
**注意**:在 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。 **注意**:在 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。
### 通过maven获取JDBC driver ### 通过maven获取JDBC driver
目前 taos-jdbcdriver 已经发布到 [Sonatype Repository](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver) 仓库,且各大仓库都已同步。 目前 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) - [sonatype](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver)
- [mvnrepository](https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver) - [mvnrepository](https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver)
@ -118,6 +120,7 @@ git clone https://github.com/taosdata/TDengine.git
cd TDengine/src/connector/jdbc cd TDengine/src/connector/jdbc
mvn clean package -Dmaven.test.skip=true mvn clean package -Dmaven.test.skip=true
``` ```
编译后在target目录下会产生taos-jdbcdriver-2.0.XX-dist.jar的jar包。 编译后在target目录下会产生taos-jdbcdriver-2.0.XX-dist.jar的jar包。
## Java连接器的使用 ## Java连接器的使用
@ -125,6 +128,7 @@ mvn clean package -Dmaven.test.skip=true
### 获取连接 ### 获取连接
#### 指定URL获取连接 #### 指定URL获取连接
通过指定URL获取连接如下所示 通过指定URL获取连接如下所示
```java ```java
@ -132,6 +136,7 @@ Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
String jdbcUrl = "jdbc:TAOS-RS://taosdemo.com:6041/test?user=root&password=taosdata"; String jdbcUrl = "jdbc:TAOS-RS://taosdemo.com:6041/test?user=root&password=taosdata";
Connection conn = DriverManager.getConnection(jdbcUrl); Connection conn = DriverManager.getConnection(jdbcUrl);
``` ```
以上示例,使用 **JDBC-RESTful** 的 driver建立了到 hostname 为 taosdemo.com端口为 6041数据库名为 test 的连接。这个 URL 中指定用户名user为 root密码password为 taosdata。 以上示例,使用 **JDBC-RESTful** 的 driver建立了到 hostname 为 taosdemo.com端口为 6041数据库名为 test 的连接。这个 URL 中指定用户名user为 root密码password为 taosdata。
使用 JDBC-RESTful 接口,不需要依赖本地函数库。与 JDBC-JNI 相比,仅需要: 使用 JDBC-RESTful 接口,不需要依赖本地函数库。与 JDBC-JNI 相比,仅需要:
@ -145,6 +150,7 @@ Class.forName("com.taosdata.jdbc.TSDBDriver");
String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata"; String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata";
Connection conn = DriverManager.getConnection(jdbcUrl); Connection conn = DriverManager.getConnection(jdbcUrl);
``` ```
以上示例,使用了 JDBC-JNI 的 driver建立了到 hostname 为 taosdemo.com端口为 6030TDengine 的默认端口),数据库名为 test 的连接。这个 URL 中指定用户名user为 root密码password为 taosdata。 以上示例,使用了 JDBC-JNI 的 driver建立了到 hostname 为 taosdemo.com端口为 6030TDengine 的默认端口),数据库名为 test 的连接。这个 URL 中指定用户名user为 root密码password为 taosdata。
**注意**:使用 JDBC-JNI 的 drivertaos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库Linux 下是 libtaos.soWindows 下是 taos.dll **注意**:使用 JDBC-JNI 的 drivertaos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库Linux 下是 libtaos.soWindows 下是 taos.dll
@ -201,6 +207,7 @@ properties 中的配置参数如下:
#### 使用客户端配置文件建立连接 #### 使用客户端配置文件建立连接
当使用 JDBC-JNI 连接 TDengine 集群时,可以使用客户端配置文件,在客户端配置文件中指定集群的 firstEp、secondEp参数。如下所示 当使用 JDBC-JNI 连接 TDengine 集群时,可以使用客户端配置文件,在客户端配置文件中指定集群的 firstEp、secondEp参数。如下所示
1. 在 Java 应用中不指定 hostname 和 port 1. 在 Java 应用中不指定 hostname 和 port
```java ```java
@ -217,6 +224,7 @@ public Connection getConn() throws Exception{
``` ```
2. 在配置文件中指定 firstEp 和 secondEp 2. 在配置文件中指定 firstEp 和 secondEp
``` ```
# first fully qualified domain name (FQDN) for TDengine system # first fully qualified domain name (FQDN) for TDengine system
firstEp cluster_node1:6030 firstEp cluster_node1:6030
@ -232,6 +240,7 @@ secondEp cluster_node2:6030
``` ```
以上示例jdbc 会使用客户端的配置文件,建立到 hostname 为 cluster_node1、端口为 6030、数据库名为 test 的连接。当集群中 firstEp 节点失效时JDBC 会尝试使用 secondEp 连接集群。 以上示例jdbc 会使用客户端的配置文件,建立到 hostname 为 cluster_node1、端口为 6030、数据库名为 test 的连接。当集群中 firstEp 节点失效时JDBC 会尝试使用 secondEp 连接集群。
TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可以正常建立到集群的连接。 TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可以正常建立到集群的连接。
> 注意:这里的配置文件指的是调用 JDBC Connector 的应用程序所在机器上的配置文件Linux OS 上默认值 /etc/taos/taos.cfg Windows OS 上默认值 C://TDengine/cfg/taos.cfg。 > 注意:这里的配置文件指的是调用 JDBC Connector 的应用程序所在机器上的配置文件Linux OS 上默认值 /etc/taos/taos.cfg Windows OS 上默认值 C://TDengine/cfg/taos.cfg。
@ -315,6 +324,7 @@ try (Statement statement = connection.createStatement()) {
``` ```
JDBC连接器可能报错的错误码包括3种JDBC driver本身的报错错误码在0x2301到0x2350之间JNI方法的报错错误码在0x2351到0x2400之间TDengine其他功能模块的报错。 JDBC连接器可能报错的错误码包括3种JDBC driver本身的报错错误码在0x2301到0x2350之间JNI方法的报错错误码在0x2351到0x2400之间TDengine其他功能模块的报错。
具体的错误码请参考: 具体的错误码请参考:
* https://github.com/taosdata/TDengine/blob/develop/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java * https://github.com/taosdata/TDengine/blob/develop/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java
* https://github.com/taosdata/TDengine/blob/develop/src/inc/taoserror.h * https://github.com/taosdata/TDengine/blob/develop/src/inc/taoserror.h
@ -395,6 +405,7 @@ public void setShort(int columnIndex, ArrayList<Short> list) throws SQLException
public void setString(int columnIndex, ArrayList<String> list, int size) throws SQLException public void setString(int columnIndex, ArrayList<String> list, int size) throws SQLException
public void setNString(int columnIndex, ArrayList<String> list, int size) throws SQLException public void setNString(int columnIndex, ArrayList<String> list, int size) throws SQLException
``` ```
其中 setString 和 setNString 都要求用户在 size 参数里声明表定义中对应列的列宽。 其中 setString 和 setNString 都要求用户在 size 参数里声明表定义中对应列的列宽。
## <a class="anchor" id="subscribe"></a>订阅 ## <a class="anchor" id="subscribe"></a>订阅
@ -452,6 +463,7 @@ conn.close();
## 与连接池使用 ## 与连接池使用
### HikariCP ### HikariCP
使用示例如下: 使用示例如下:
```java ```java
@ -485,6 +497,7 @@ conn.close();
> 更多 HikariCP 使用问题请查看[官方说明](https://github.com/brettwooldridge/HikariCP)。 > 更多 HikariCP 使用问题请查看[官方说明](https://github.com/brettwooldridge/HikariCP)。
### Druid ### Druid
使用示例如下: 使用示例如下:
```java ```java
@ -539,7 +552,7 @@ Query OK, 1 row(s) in set (0.000141s)
* Springbootdemospringboot示例源程序 * Springbootdemospringboot示例源程序
* SpringJdbcTemplateSpringJDBC模板 * SpringJdbcTemplateSpringJDBC模板
请参考:![JDBC example](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC) 请参考:[JDBC example](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC)
## 常见问题 ## 常见问题

View File

@ -654,22 +654,23 @@ conn.close()
为支持各种不同类型平台的开发TDengine 提供符合 REST 设计标准的 API即 RESTful API。为最大程度降低学习成本不同于其他数据库 RESTful API 的设计方法TDengine 直接通过 HTTP POST 请求 BODY 中包含的 SQL 语句来操作数据库,仅需要一个 URL。RESTful 连接器的使用参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1965.html)。 为支持各种不同类型平台的开发TDengine 提供符合 REST 设计标准的 API即 RESTful API。为最大程度降低学习成本不同于其他数据库 RESTful API 的设计方法TDengine 直接通过 HTTP POST 请求 BODY 中包含的 SQL 语句来操作数据库,仅需要一个 URL。RESTful 连接器的使用参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1965.html)。
注意与标准连接器的一个区别是RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,所有对表名、超级表名的引用都需要指定数据库名前缀。 注意与标准连接器的一个区别是RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,所有对表名、超级表名的引用都需要指定数据库名前缀。(从 2.1.8.0 版本开始,支持在 RESTful url 中指定 db_name这时如果 SQL 语句中没有指定数据库名前缀的话,会使用 url 中指定的这个 db_name。
### 安装 ### 安装
RESTful接口不依赖于任何TDengine的库因此客户端不需要安装任何TDengine的库只要客户端的开发语言支持HTTP协议即可。 RESTful 接口不依赖于任何 TDengine 的库,因此客户端不需要安装任何 TDengine 的库,只要客户端的开发语言支持 HTTP 协议即可。
### 验证 ### 验证
在已经安装TDengine服务器端的情况下可以按照如下方式进行验证。 在已经安装 TDengine 服务器端的情况下,可以按照如下方式进行验证。
下面以Ubuntu环境中使用curl工具确认已经安装来验证RESTful接口的正常。 下面以 Ubuntu 环境中使用 curl 工具(确认已经安装)来验证 RESTful 接口的正常。
下面示例是列出所有的数据库请把h1.taosdata.com和6041缺省值替换为实际运行的TDengine服务fqdn和端口号 下面示例是列出所有的数据库,请把 h1.taosdata.com 6041缺省值替换为实际运行的 TDengine 服务 fqdn 和端口号:
```html ```html
curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'show databases;' h1.taosdata.com:6041/rest/sql curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'show databases;' h1.taosdata.com:6041/rest/sql
``` ```
返回值结果如下表示验证通过: 返回值结果如下表示验证通过:
```json ```json
{ {
@ -682,22 +683,23 @@ curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'show databases;' h1.taos
} }
``` ```
### RESTful连接器的使用 ### RESTful 连接器的使用
#### HTTP请求格式 #### HTTP 请求格式
``` ```
http://<fqdn>:<port>/rest/sql http://<fqdn>:<port>/rest/sql/[db_name]
``` ```
参数说明: 参数说明:
- fqnd: 集群中的任一台主机FQDN或IP地址 - fqnd: 集群中的任一台主机 FQDN 或 IP 地址
- port: 配置文件中httpPort配置项缺省为6041 - port: 配置文件中 httpPort 配置项,缺省为 6041
- db_name: 可选参数,指定本次所执行的 SQL 语句的默认数据库库名。(从 2.1.8.0 版本开始支持)
例如http://h1.taos.com:6041/rest/sql 是指向地址为h1.taos.com:6041的url。 例如http://h1.taos.com:6041/rest/sql/test 是指向地址为 h1.taos.com:6041 url,并将默认使用的数据库库名设置为 test
HTTP请求的Header里需带有身份认证信息TDengine支持Basic认证与自定义认证两种机制后续版本将提供标准安全的数字签名机制来做身份验证。 HTTP 请求的 Header 里需带有身份认证信息TDengine 支持 Basic 认证与自定义认证两种机制,后续版本将提供标准安全的数字签名机制来做身份验证。
- 自定义身份认证信息如下所示(<token>稍后介绍) - 自定义身份认证信息如下所示(<token>稍后介绍)
@ -711,25 +713,25 @@ Authorization: Taosd <TOKEN>
Authorization: Basic <TOKEN> Authorization: Basic <TOKEN>
``` ```
HTTP请求的BODY里就是一个完整的SQL语句SQL语句中的数据表应提供数据库前缀例如\<db-name>.\<tb-name>。如果表名不带数据库前缀系统会返回错误。因为HTTP模块只是一个简单的转发没有当前DB的概念。 HTTP 请求的 BODY 里就是一个完整的 SQL 语句SQL 语句中的数据表应提供数据库前缀,例如 \<db_name>.\<tb_name>。如果表名不带数据库前缀,又没有在 url 中指定数据库名的话,系统会返回错误。因为 HTTP 模块只是一个简单的转发,没有当前 DB 的概念。
使用curl通过自定义身份认证方式来发起一个HTTP Request语法如下 使用 curl 通过自定义身份认证方式来发起一个 HTTP Request语法如下
```bash ```bash
curl -H 'Authorization: Basic <TOKEN>' -d '<SQL>' <ip>:<PORT>/rest/sql curl -H 'Authorization: Basic <TOKEN>' -d '<SQL>' <ip>:<PORT>/rest/sql/[db_name]
``` ```
或者 或者
```bash ```bash
curl -u username:password -d '<SQL>' <ip>:<PORT>/rest/sql curl -u username:password -d '<SQL>' <ip>:<PORT>/rest/sql/[db_name]
``` ```
其中,`TOKEN`为`{username}:{password}`经过Base64编码之后的字符串例如`root:taosdata`编码后为`cm9vdDp0YW9zZGF0YQ==` 其中,`TOKEN` `{username}:{password}` 经过 Base64 编码之后的字符串,例如 `root:taosdata` 编码后为 `cm9vdDp0YW9zZGF0YQ==`
### HTTP返回格式 ### HTTP 返回格式
返回值为JSON格式如下: 返回值为 JSON 格式,如下:
```json ```json
{ {
@ -747,9 +749,9 @@ curl -u username:password -d '<SQL>' <ip>:<PORT>/rest/sql
说明: 说明:
- status: 告知操作结果是成功还是失败。 - status: 告知操作结果是成功还是失败。
- head: 表的定义如果不返回结果集则仅有一列“affected_rows”。从 2.0.17.0 版本开始,建议不要依赖 head 返回值来判断数据列类型,而推荐使用 column_meta。在未来版本中有可能会从返回值中去掉 head 这一项。) - head: 表的定义,如果不返回结果集,则仅有一列 “affected_rows”。从 2.0.17.0 版本开始,建议不要依赖 head 返回值来判断数据列类型,而推荐使用 column_meta。在未来版本中有可能会从返回值中去掉 head 这一项。)
- column_meta: 从 2.0.17.0 版本开始,返回值中增加这一项来说明 data 里每一列的数据类型。具体每个列会用三个值来说明,分别为:列名、列类型、类型长度。例如`["current",6,4]`表示列名为“current”列类型为 6也即 float 类型;类型长度为 4也即对应 4 个字节表示的 float。如果列类型为 binary 或 nchar则类型长度表示该列最多可以保存的内容长度而不是本次返回值中的具体数据长度。当列类型是 nchar 的时候,其类型长度表示可以保存的 unicode 字符数量,而不是 bytes。 - column_meta: 从 2.0.17.0 版本开始,返回值中增加这一项来说明 data 里每一列的数据类型。具体每个列会用三个值来说明,分别为:列名、列类型、类型长度。例如`["current",6,4]`表示列名为“current”列类型为 6也即 float 类型;类型长度为 4也即对应 4 个字节表示的 float。如果列类型为 binary 或 nchar则类型长度表示该列最多可以保存的内容长度而不是本次返回值中的具体数据长度。当列类型是 nchar 的时候,其类型长度表示可以保存的 unicode 字符数量,而不是 bytes。
- data: 具体返回的数据,一行一行的呈现,如果不返回结果集,那么就仅有[[affected_rows]]。data 中每一行的数据列顺序,与 column_meta 中描述数据列的顺序完全一致。 - data: 具体返回的数据,一行一行的呈现,如果不返回结果集,那么就仅有 [[affected_rows]]。data 中每一行的数据列顺序,与 column_meta 中描述数据列的顺序完全一致。
- rows: 表明总共多少行数据。 - rows: 表明总共多少行数据。
column_meta 中的列类型说明: column_meta 中的列类型说明:
@ -766,13 +768,13 @@ column_meta 中的列类型说明:
### 自定义授权码 ### 自定义授权码
HTTP请求中需要带有授权码`<TOKEN>`,用于身份识别。授权码通常由管理员提供,可简单的通过发送`HTTP GET`请求来获取授权码,操作如下: HTTP 请求中需要带有授权码 `<TOKEN>`,用于身份识别。授权码通常由管理员提供,可简单的通过发送 `HTTP GET` 请求来获取授权码,操作如下:
```bash ```bash
curl http://<fqnd>:<port>/rest/login/<username>/<password> curl http://<fqnd>:<port>/rest/login/<username>/<password>
``` ```
其中,`fqdn`是TDengine数据库的fqdn或ip地址port是TDengine服务的端口号`username`为数据库用户名,`password`为数据库密码,返回值为`JSON`格式,各字段含义如下: 其中,`fqdn` TDengine 数据库的 fqdn ip 地址port TDengine 服务的端口号,`username` 为数据库用户名,`password` 为数据库密码,返回值为 `JSON` 格式,各字段含义如下:
- status请求结果的标志位 - status请求结果的标志位
@ -798,7 +800,7 @@ curl http://192.168.0.1:6041/rest/login/root/taosdata
### 使用示例 ### 使用示例
- 在demo库里查询表d1001的所有记录 - 在 demo 库里查询表 d1001 的所有记录:
```bash ```bash
curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001' 192.168.0.1:6041/rest/sql curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001' 192.168.0.1:6041/rest/sql
@ -818,7 +820,7 @@ curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001
} }
``` ```
- 创建库demo - 创建库 demo
```bash ```bash
curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'create database demo' 192.168.0.1:6041/rest/sql curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'create database demo' 192.168.0.1:6041/rest/sql
@ -837,9 +839,9 @@ curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'create database demo' 19
### 其他用法 ### 其他用法
#### 结果集采用Unix时间戳 #### 结果集采用 Unix 时间戳
HTTP请求URL采用`sqlt`时返回结果集的时间戳将采用Unix时间戳格式表示例如 HTTP 请求 URL 采用 `sqlt` 时,返回结果集的时间戳将采用 Unix 时间戳格式表示,例如
```bash ```bash
curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001' 192.168.0.1:6041/rest/sqlt curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001' 192.168.0.1:6041/rest/sqlt
@ -860,9 +862,9 @@ curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001
} }
``` ```
#### 结果集采用UTC时间字符串 #### 结果集采用 UTC 时间字符串
HTTP请求URL采用`sqlutc`时返回结果集的时间戳将采用UTC时间字符串表示例如 HTTP 请求 URL 采用 `sqlutc` 时,返回结果集的时间戳将采用 UTC 时间字符串表示,例如
```bash ```bash
curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.t1' 192.168.0.1:6041/rest/sqlutc curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.t1' 192.168.0.1:6041/rest/sqlutc
``` ```
@ -884,13 +886,14 @@ HTTP请求URL采用`sqlutc`时返回结果集的时间戳将采用UTC时间
### 重要配置项 ### 重要配置项
下面仅列出一些与RESTful接口有关的配置参数其他系统参数请看配置文件里的说明。注意配置修改后需要重启taosd服务才能生效 下面仅列出一些与 RESTful 接口有关的配置参数,其他系统参数请看配置文件里的说明。(注意:配置修改后,需要重启 taosd 服务才能生效)
- 对外提供RESTful服务的端口号默认绑定到 6041实际取值是 serverPort + 11因此可以通过修改 serverPort 参数的设置来修改) - 对外提供 RESTful 服务的端口号,默认绑定到 6041实际取值是 serverPort + 11因此可以通过修改 serverPort 参数的设置来修改)。
- httpMaxThreads: 启动的线程数量默认为22.0.17.0版本开始默认值改为CPU核数的一半向下取整 - httpMaxThreads: 启动的线程数量,默认为 22.0.17.0 版本开始,默认值改为 CPU 核数的一半向下取整)。
- restfulRowLimit: 返回结果集JSON格式的最大条数默认值为10240 - restfulRowLimit: 返回结果集JSON 格式)的最大条数,默认值为 10240。
- httpEnableCompress: 是否支持压缩默认不支持目前TDengine仅支持gzip压缩格式 - httpEnableCompress: 是否支持压缩,默认不支持,目前 TDengine 仅支持 gzip 压缩格式。
- httpDebugFlag: 日志开关默认131。131仅错误和报警信息135调试信息143非常详细的调试信息默认131 - httpDebugFlag: 日志开关,默认 131。131仅错误和报警信息135调试信息143非常详细的调试信息默认 131。
- httpDbNameMandatory: 是否必须在 RESTful url 中指定默认的数据库名。默认为 0即关闭此检查。如果设置为 1那么每个 RESTful url 中都必须设置一个默认数据库名,否则无论此时执行的 SQL 语句是否需要指定数据库,都会返回一个执行错误,拒绝执行此 SQL 语句。
## <a class="anchor" id="csharp"></a>CSharp Connector ## <a class="anchor" id="csharp"></a>CSharp Connector

View File

@ -14,7 +14,7 @@ TDengine的集群管理极其简单除添加和删除节点需要人工干预
**第一步**如果搭建集群的物理节点中存有之前的测试数据、装过1.X的版本或者装过其他版本的TDengine请先将其删除并清空所有数据如果需要保留原有数据请联系涛思交付团队进行旧版本升级、数据迁移具体步骤请参考博客[《TDengine多种安装包的安装和卸载》](https://www.taosdata.com/blog/2019/08/09/566.html)。 **第一步**如果搭建集群的物理节点中存有之前的测试数据、装过1.X的版本或者装过其他版本的TDengine请先将其删除并清空所有数据如果需要保留原有数据请联系涛思交付团队进行旧版本升级、数据迁移具体步骤请参考博客[《TDengine多种安装包的安装和卸载》](https://www.taosdata.com/blog/2019/08/09/566.html)。
**注意1**因为FQDN的信息会写进文件如果之前没有配置或者更改FQDN且启动了TDengine。请一定在确保数据无用或者备份的前提下清理一下之前的数据`rm -rf /var/lib/taos/*` **注意1**因为FQDN的信息会写进文件如果之前没有配置或者更改FQDN且启动了TDengine。请一定在确保数据无用或者备份的前提下清理一下之前的数据`rm -rf /var/lib/taos/*`
**注意2**客户端也需要配置确保它可以正确解析每个节点的FQDN配置不管是通过DNS服务还是 Host 文件。 **注意2**客户端也需要配置确保它可以正确解析每个节点的FQDN配置不管是通过DNS服务还是修改 hosts 文件。
**第二步**建议关闭所有物理节点的防火墙至少保证端口6030 - 6042的TCP和UDP端口都是开放的。**强烈建议**先关闭防火墙,集群搭建完毕之后,再来配置端口; **第二步**建议关闭所有物理节点的防火墙至少保证端口6030 - 6042的TCP和UDP端口都是开放的。**强烈建议**先关闭防火墙,集群搭建完毕之后,再来配置端口;

View File

@ -35,7 +35,7 @@ taos> DESCRIBE meters;
- 内部函数 now 是客户端的当前时间 - 内部函数 now 是客户端的当前时间
- 插入记录时,如果时间戳为 now插入数据时使用提交这条记录的客户端的当前时间 - 插入记录时,如果时间戳为 now插入数据时使用提交这条记录的客户端的当前时间
- Epoch Time时间戳也可以是一个长整数表示从格林威治时间 1970-01-01 00:00:00.000 (UTC/GMT) 开始的毫秒数(相应地,如果所在 Database 的时间精度设置为“微秒”,则长整型格式的时间戳含义也就对应于从格林威治时间 1970-01-01 00:00:00.000 (UTC/GMT) 开始的微秒数;纳秒精度的逻辑也是类似的。) - Epoch Time时间戳也可以是一个长整数表示从格林威治时间 1970-01-01 00:00:00.000 (UTC/GMT) 开始的毫秒数(相应地,如果所在 Database 的时间精度设置为“微秒”,则长整型格式的时间戳含义也就对应于从格林威治时间 1970-01-01 00:00:00.000 (UTC/GMT) 开始的微秒数;纳秒精度的逻辑也是类似的。)
- 时间可以加减,比如 now-2h表明查询时刻向前推 2 个小时(最近 2 小时)。数字后面的时间单位可以是 b(纳秒)、u(微秒)、a(毫秒)、s(秒)、m(分)、h(小时)、d(天)、w(周)。 比如 `select * from t1 where ts > now-2w and ts <= now-1w`,表示查询两周前整整一周的数据。在指定降操作down sampling的时间窗口interval时间单位还可以使用 n(自然月) 和 y(自然年)。 - 时间可以加减,比如 now-2h表明查询时刻向前推 2 个小时(最近 2 小时)。数字后面的时间单位可以是 b(纳秒)、u(微秒)、a(毫秒)、s(秒)、m(分)、h(小时)、d(天)、w(周)。 比如 `select * from t1 where ts > now-2w and ts <= now-1w`,表示查询两周前整整一周的数据。在指定降采样操作down sampling的时间窗口interval时间单位还可以使用 n(自然月) 和 y(自然年)。
TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传递的 PRECISION 参数就可以支持微秒和纳秒。(从 2.1.5.0 版本开始支持纳秒精度) TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传递的 PRECISION 参数就可以支持微秒和纳秒。(从 2.1.5.0 版本开始支持纳秒精度)
@ -722,6 +722,7 @@ Query OK, 1 row(s) in set (0.001091s)
1. <> 算子也可以写为 != ,请注意,这个算子不能用于数据表第一列的 timestamp 字段。 1. <> 算子也可以写为 != ,请注意,这个算子不能用于数据表第一列的 timestamp 字段。
2. like 算子使用通配符字符串进行匹配检查。 2. like 算子使用通配符字符串进行匹配检查。
* 在通配符字符串中:'%'(百分号)匹配 0 到任意个字符;'\_'(下划线)匹配单个任意字符。 * 在通配符字符串中:'%'(百分号)匹配 0 到任意个字符;'\_'(下划线)匹配单个任意字符。
* 如果希望匹配字符串中原本就带有的 \_下划线字符那么可以在通配符字符串中写作 `\_`,也即加一个反斜线来进行转义。(从 2.1.8.0 版本开始支持)
* 通配符字符串最长不能超过 20 字节。(从 2.1.6.1 版本开始,通配符字符串的长度放宽到了 100 字节,并可以通过 taos.cfg 中的 maxWildCardsLength 参数来配置这一长度限制。但不建议使用太长的通配符字符串,将有可能严重影响 LIKE 操作的执行性能。) * 通配符字符串最长不能超过 20 字节。(从 2.1.6.1 版本开始,通配符字符串的长度放宽到了 100 字节,并可以通过 taos.cfg 中的 maxWildCardsLength 参数来配置这一长度限制。但不建议使用太长的通配符字符串,将有可能严重影响 LIKE 操作的执行性能。)
3. 同时进行多个字段的范围过滤,需要使用关键词 AND 来连接不同的查询条件,暂不支持 OR 连接的不同列之间的查询过滤条件。 3. 同时进行多个字段的范围过滤,需要使用关键词 AND 来连接不同的查询条件,暂不支持 OR 连接的不同列之间的查询过滤条件。
4. 针对单一字段的过滤,如果是时间过滤条件,则一条语句中只支持设定一个;但针对其他的(普通)列或标签列,则可以使用 `OR` 关键字进行组合条件的查询过滤。例如: `((value > 20 AND value < 30) OR (value < 12))` 4. 针对单一字段的过滤,如果是时间过滤条件,则一条语句中只支持设定一个;但针对其他的(普通)列或标签列,则可以使用 `OR` 关键字进行组合条件的查询过滤。例如: `((value > 20 AND value < 30) OR (value < 12))`
@ -1220,27 +1221,36 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
``` ```
功能说明:返回表/超级表的指定时间截面、指定字段的记录。 功能说明:返回表/超级表的指定时间截面、指定字段的记录。
返回结果数据类型:同应用的字段。 返回结果数据类型:同字段类型
应用字段:所有字段。 应用字段:数值型字段。
适用于:**表、超级表**。 适用于:**表、超级表**。
说明:(从 2.0.15.0 版本开始新增此函数INTERP 必须指定时间断面,如果该时间断面不存在直接对应的数据,那么会根据 FILL 参数的设定进行插值。其中条件语句里面可以附带更多的筛选条件例如标签、tbname。 说明:(从 2.0.15.0 版本开始新增此函数INTERP 必须指定时间断面,如果该时间断面不存在直接对应的数据,那么会根据 FILL 参数的设定进行插值。此外条件语句里面可附带筛选条件例如标签、tbname。
INTERP 查询要求查询的时间区间必须位于数据集合(表)的所有记录的时间范围之内。如果给定的时间戳位于时间范围之外,即使有插值指令,仍然不返回结果。
示例: 示例:
```mysql ```sql
taos> select interp(*) from meters where ts='2017-7-14 10:42:00.005' fill(prev); taos> SELECT INTERP(*) FROM meters WHERE ts='2017-7-14 18:40:00.004';
interp(ts) | interp(f1) | interp(f2) | interp(f3) | interp(ts) | interp(current) | interp(voltage) | interp(phase) |
==================================================================== ==========================================================================================
2017-07-14 10:42:00.005 | 5 | 9 | 6 | 2017-07-14 18:40:00.004 | 9.84020 | 216 | 0.32222 |
Query OK, 1 row(s) in set (0.002912s) Query OK, 1 row(s) in set (0.002652s)
```
taos> select interp(*) from meters where tbname in ('t1') and ts='2017-7-14 10:42:00.005' fill(prev); 如果给定的时间戳无对应的数据,在不指定插值生成策略的情况下,不会返回结果,如果指定了插值策略,会根据插值策略返回结果。
interp(ts) | interp(f1) | interp(f2) | interp(f3) |
==================================================================== ```sql
2017-07-14 10:42:00.005 | 5 | 6 | 7 | taos> SELECT INTERP(*) FROM meters WHERE tbname IN ('d636') AND ts='2017-7-14 18:40:00.005';
Query OK, 1 row(s) in set (0.002005s) Query OK, 0 row(s) in set (0.004022s)
taos> SELECT INTERP(*) FROM meters WHERE tbname IN ('d636') AND ts='2017-7-14 18:40:00.005' FILL(PREV);;
interp(ts) | interp(current) | interp(voltage) | interp(phase) |
==========================================================================================
2017-07-14 18:40:00.005 | 9.88150 | 217 | 0.32500 |
Query OK, 1 row(s) in set (0.003056s)
``` ```
### 计算函数 ### 计算函数

View File

@ -6,7 +6,7 @@ TDengine is a highly efficient platform to store, query, and analyze time-series
* [TDengine Introduction and Features](/evaluation#intro) * [TDengine Introduction and Features](/evaluation#intro)
* [TDengine Use Scenes](/evaluation#scenes) * [TDengine Use Scenes](/evaluation#scenes)
* [TDengine Performance Metrics and Verification]((/evaluation#)) * [TDengine Performance Metrics and Verification](/evaluation#)
## [Getting Started](/getting-started) ## [Getting Started](/getting-started)

View File

@ -0,0 +1,243 @@
# Quickly experience TDengine through Docker
While it is not recommended to deploy TDengine services via Docker in a production environment, Docker tools do a good job of shielding the environmental differences in the underlying operating system and are well suited for use in development testing or first-time experience with the toolset for installing and running TDengine. In particular, Docker makes it relatively easy to try TDengine on Mac OSX and Windows systems without having to install a virtual machine or rent an additional Linux server. In addition, starting from version 2.0.14.0, TDengine provides images that support both X86-64, X86, arm64, and arm32 platforms, so non-mainstream computers that can run docker, such as NAS, Raspberry Pi, and embedded development boards, can also easily experience TDengine based on this document.
The following article explains how to quickly build a single-node TDengine runtime environment via Docker to support development and testing through a Step by Step style introduction.
## Docker download
The Docker tools themselves can be downloaded from [Docker official site](https://docs.docker.com/get-docker/).
After installation, you can check the Docker version in the command line terminal. If the version number is output properly, the Docker environment has been installed successfully.
```bash
$ docker -v
Docker version 20.10.3, build 48d30b5
```
## Running TDengine in a Docker container
1, Use the command to pull the TDengine image and make it run in the background.
```bash
$ docker run -d --name tdengine tdengine/tdengine
7760c955f225d72e9c1ec5a4cef66149a7b94dae7598b11eb392138877e7d292
```
- **docker run**: Running a container via Docker
- **--name tdengine**: Set the container name, we can see the corresponding container by the container name
- **-d**: Keeping containers running in the background
- **tdengine/tdengine**: Pulled from the official TDengine published application image
- **7760c955f225d72e9c1ec5a4cef66149a7b94dae7598b11eb392138877e7d292**: The long character returned is the container ID, and we can also view the corresponding container by its container ID
2, Verify that the container is running correctly.
```bash
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS ···
c452519b0f9b tdengine/tdengine "taosd" 14 minutes ago Up 14 minutes ···
```
- **docker ps**: Lists information about all containers that are in running state.
- **CONTAINER ID**: Container ID.
- **IMAGE**: The mirror used.
- **COMMAND**: The command to run when starting the container.
- **CREATED**: The time when the container was created.
- **STATUS**: The container status. Up means running.
3, Go inside the Docker container and use TDengine.
```bash
$ docker exec -it tdengine /bin/bash
root@c452519b0f9b:~/TDengine-server-2.0.20.13#
```
- **docker exec**: Enter the container via the docker exec command; if you exit, the container will not stop.
- **-i**: Enter the interactive mode.
- **-t**: Specify a terminal.
- **c452519b0f9b**: The container ID, which needs to be modified according to the value returned by the docker ps command.
- **/bin/bash**: Load the container and run bash to interact with it.
4, After entering the container, execute the taos shell client program.
```bash
$ root@c452519b0f9b:~/TDengine-server-2.0.20.13# taos
Welcome to the TDengine shell from Linux, Client Version:2.0.20.13
Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.
taos>
```
The TDengine terminal successfully connects to the server and prints out a welcome message and version information. If it fails, an error message is printed.
In the TDengine terminal, you can create/delete databases, tables, super tables, etc., and perform insert and query operations via SQL commands. For details, you can refer to [TAOS SQL guide](https://www.taosdata.com/en/documentation/taos-sql).
## Learn more about TDengine with taosdemo
1, Following the above steps, exit the TDengine terminal program first.
```bash
$ taos> q
root@c452519b0f9b:~/TDengine-server-2.0.20.13#
```
2, Execute taosdemo from the command line interface.
```bash
root@c452519b0f9b:~/TDengine-server-2.0.20.13# taosdemo
taosdemo is simulating data generated by power equipments monitoring...
host: 127.0.0.1:6030
user: root
password: taosdata
configDir:
resultFile: ./output.txt
thread num of insert data: 10
thread num of create table: 10
top insert interval: 0
number of records per req: 30000
max sql length: 1048576
database count: 1
database[0]:
database[0] name: test
drop: yes
replica: 1
precision: ms
super table count: 1
super table[0]:
stbName: meters
autoCreateTable: no
childTblExists: no
childTblCount: 10000
childTblPrefix: d
dataSource: rand
iface: taosc
insertRows: 10000
interlaceRows: 0
disorderRange: 1000
disorderRatio: 0
maxSqlLen: 1048576
timeStampStep: 1
startTimestamp: 2017-07-14 10:40:00.000
sampleFormat:
sampleFile:
tagsFile:
columnCount: 3
column[0]:FLOAT column[1]:INT column[2]:FLOAT
tagCount: 2
tag[0]:INT tag[1]:BINARY(16)
Press enter key to continue or Ctrl-C to stop
```
After enter, this command will automatically create a super table meters under the database test, there are 10,000 tables under this super table, the table name is "d0" to "d9999", each table has 10,000 records, each record has four fields (ts, current, voltage, phase), the time stamp is from "2017-07-14 10:40:00 000" to "2017-07-14 10:40:09 999", each table has a tag location and groupId, groupId is set from 1 to 10 and location is set to "beijing" or "shanghai".
It takes about a few minutes to execute this command and ends up inserting a total of 100 million records.
3, Go to the TDengine terminal and view the data generated by taosdemo.
- **Go to the terminal interface.**
```bash
$ root@c452519b0f9b:~/TDengine-server-2.0.20.13# taos
Welcome to the TDengine shell from Linux, Client Version:2.0.20.13
Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.
taos>
```
- **View the database.**
```bash
$ taos> show databases;
name | created_time | ntables | vgroups | ···
test | 2021-08-18 06:01:11.021 | 10000 | 6 | ···
log | 2021-08-18 05:51:51.065 | 4 | 1 | ···
```
- **View Super Tables.**
```bash
$ taos> use test;
Database changed.
$ taos> show stables;
name | created_time | columns | tags | tables |
============================================================================================
meters | 2021-08-18 06:01:11.116 | 4 | 2 | 10000 |
Query OK, 1 row(s) in set (0.003259s)
```
- **View the table and limit the output to 10 entries.**
```bash
$ taos> select * from test.t0 limit 10;
DB error: Table does not exist (0.002857s)
taos> select * from test.d0 limit 10;
ts | current | voltage | phase |
======================================================================================
2017-07-14 10:40:00.000 | 10.12072 | 223 | 0.34167 |
2017-07-14 10:40:00.001 | 10.16103 | 224 | 0.34445 |
2017-07-14 10:40:00.002 | 10.00204 | 220 | 0.33334 |
2017-07-14 10:40:00.003 | 10.00030 | 220 | 0.33333 |
2017-07-14 10:40:00.004 | 9.84029 | 216 | 0.32222 |
2017-07-14 10:40:00.005 | 9.88028 | 217 | 0.32500 |
2017-07-14 10:40:00.006 | 9.88110 | 217 | 0.32500 |
2017-07-14 10:40:00.007 | 10.08137 | 222 | 0.33889 |
2017-07-14 10:40:00.008 | 10.12063 | 223 | 0.34167 |
2017-07-14 10:40:00.009 | 10.16086 | 224 | 0.34445 |
Query OK, 10 row(s) in set (0.016791s)
```
- **View the tag values for the d0 table.**
```bash
$ taos> select groupid, location from test.d0;
groupid | location |
=================================
0 | shanghai |
Query OK, 1 row(s) in set (0.003490s)
```
## Stop the TDengine service that is running in Docker
```bash
$ docker stop tdengine
tdengine
```
- **docker stop**: Stop the specified running docker image with docker stop.
- **tdengine**: The name of the container.
## TDengine connected in Docker during programming development
There are two ideas for connecting from outside of Docker to use TDengine services running inside a Docker container:
1, By port mapping (-p), the open network port inside the container is mapped to the specified port of the host. By mounting the local directory (-v), you can synchronize the data inside the host and the container to prevent data loss after the container is deleted.
```bash
$ docker run -d -v /etc/taos:/etc/taos -P 6041:6041 tdengine/tdengine
526aa188da767ae94b244226a2b2eec2b5f17dd8eff592893d9ec0cd0f3a1ccd
$ curl -u root:taosdata -d 'show databases' 127.0.0.1:6041/rest/sql
{"status":"succ","head":["name","created_time","ntables","vgroups","replica","quorum","days","keep0,keep1,keep(D)","cache(MB)","blocks","minrows","maxrows","wallevel","fsync","comp","cachelast","precision","update","status"],"column_meta":[["name",8,32],["created_time",9,8],["ntables",4,4],["vgroups",4,4],["replica",3,2],["quorum",3,2],["days",3,2],["keep0,keep1,keep(D)",8,24],["cache(MB)",4,4],["blocks",4,4],["minrows",4,4],["maxrows",4,4],["wallevel",2,1],["fsync",4,4],["comp",2,1],["cachelast",2,1],["precision",8,3],["update",2,1],["status",8,10]],"data":[["test","2021-08-18 06:01:11.021",10000,4,1,1,10,"3650,3650,3650",16,6,100,4096,1,3000,2,0,"ms",0,"ready"],["log","2021-08-18 05:51:51.065",4,1,1,1,10,"30,30,30",1,3,100,4096,1,3000,2,0,"us",0,"ready"]],"rows":2}
```
- The first command starts a docker container with TDengine running and maps the 6041 port of the container to port 6041 of the host.
- The second command, accessing TDengine through the RESTful interface, connects to port 6041 on the local machine, so the connection is successful.
Note: In this example, for convenience reasons, only port 6041 is mapped, which is required for RESTful. If you wish to connect to the TDengine service in a non-RESTful manner, you will need to map a total of 11 ports starting at 6030. In the example, mounting the local directory also only deals with the /etc/taos directory where the configuration files are located, but not the data storage directory.
2, Go directly to the docker container to do development via the exec command. That is, put the program code in the same Docker container where the TDengine server is located and connect to the TDengine service local to the container.
```bash
$ docker exec -it tdengine /bin/bash
```

View File

@ -2,7 +2,7 @@
## <a class="anchor" id="install"></a>Quick Install ## <a class="anchor" id="install"></a>Quick Install
TDengine software consists of 3 parts: server, client, and alarm module. At the moment, TDengine server only runs on Linux (Windows, mac OS and more OS supports will come soon), but client can run on either Windows or Linux. TDengine client can be installed and run on Windows or Linux. Applications based-on any OSes can all connect to server taosd via a RESTful interface. About CPU, TDengine supports X64/ARM64/MIPS64/Alpha64, and ARM32、RISC-V, other more CPU architectures will be supported soon. You can set up and install TDengine server either from the [source code](https://www.taosdata.com/en/getting-started/#Install-from-Source) or the [packages](https://www.taosdata.com/en/getting-started/#Install-from-Package). TDengine software consists of 3 components: server, client, and alarm module. At the moment, TDengine server only runs on Linux (Windows, mac OS and more OS supports will come soon), but client can run on either Windows or Linux. TDengine client can be installed and run on Windows or Linux. Applications based-on any OSes can all connect to server taosd via a RESTful interface. About CPU, TDengine supports X64/ARM64/MIPS64/Alpha64, and ARM32、RISC-V, other more CPU architectures will be supported soon. You can set up and install TDengine server either from the [source code](https://www.taosdata.com/en/getting-started/#Install-from-Source) or the [packages](https://www.taosdata.com/en/getting-started/#Install-from-Package).
### <a class="anchor" id="source-install"></a>Install from Source ### <a class="anchor" id="source-install"></a>Install from Source
@ -10,7 +10,9 @@ Please visit our [TDengine github page](https://github.com/taosdata/TDengine) fo
### Install from Docker Container ### Install from Docker Container
Please visit our [TDengine Official Docker Image: Distribution, Downloading, and Usage](https://www.taosdata.com/blog/2020/05/13/1509.html). For the time being, it is not recommended to use Docker to deploy the client or server side of TDengine in production environments, but it is convenient to use Docker to deploy in development environments or when trying it for the first time. In particular, with Docker, it is easy to try TDengine in Mac OS X and Windows environments.
Please refer to the detailed operation in [Quickly experience TDengine through Docker](https://www.taosdata.com/en/documentation/getting-started/docker).
### <a class="anchor" id="package-install"></a>Install from Package ### <a class="anchor" id="package-install"></a>Install from Package

View File

@ -119,7 +119,7 @@ As the data points are a series of data points over time, the data points genera
9. in addition to storage and query operations, various statistical and real-time calculation operations are also required; 9. in addition to storage and query operations, various statistical and real-time calculation operations are also required;
10. data volume is huge, a system may generate over 10 billion data points in a day. 10. data volume is huge, a system may generate over 10 billion data points in a day.
By utilizing the above characteristics, TDengine designs the storage and computing engine in a special and optimized way for time-series data, resulting in massive improvements in system efficiency. In light of the characteristics mentioned above, TDengine designs the storage and computing engine in a special and optimized way for time-series data, resulting in massive improvements in system efficiency.
### Relational Database Model ### Relational Database Model
@ -139,7 +139,7 @@ TDengine suggests using collection point ID as the table name (like D1001 in the
### STable: A Collection of Data Points in the Same Type ### STable: A Collection of Data Points in the Same Type
The method of one table for each point will bring a greatly increasing number of tables, which is difficult to manage. Moreover, applications often need to take aggregation operations between collection points, thus aggregation operations will become complicated. To support aggregation over multiple tables efficiently, the [STable(Super Table)](https://www.taosdata.com/en/documentation/super-table) concept is introduced by TDengine. The method of one table for each point will bring a greatly increasing number of tables, which is difficult to manage. Moreover, applications often need to take aggregation operations between collection points, thus aggregation operations will become complicated. To support aggregation over multiple tables efficiently, the STable (Super Table) concept is introduced by TDengine.
STable is an abstract collection for a type of data point. A STable contains a set of points (tables) that have the same schema or data structure, but with different static attributes (tags). To describe a STable (a combination of data collection points of a specific type), in addition to defining the table structure of the collected metrics, it is also necessary to define the schema of its tag. The data type of tags can be int, float, string, and there can be multiple tags, which can be added, deleted, or modified afterward. If the whole system has N different types of data collection points, N STables need to be established. STable is an abstract collection for a type of data point. A STable contains a set of points (tables) that have the same schema or data structure, but with different static attributes (tags). To describe a STable (a combination of data collection points of a specific type), in addition to defining the table structure of the collected metrics, it is also necessary to define the schema of its tag. The data type of tags can be int, float, string, and there can be multiple tags, which can be added, deleted, or modified afterward. If the whole system has N different types of data collection points, N STables need to be established.

View File

@ -26,6 +26,7 @@ Replace the database operating in the current connection with “power”, other
- Any table or STable belongs to a database. Before creating a table, a database must be created first. - Any table or STable belongs to a database. Before creating a table, a database must be created first.
- Tables in two different databases cannot be JOIN. - Tables in two different databases cannot be JOIN.
- You need to specify a timestamp when creating and inserting records, or querying history records.
## <a class="anchor" id="create-stable"></a> Create a STable ## <a class="anchor" id="create-stable"></a> Create a STable

View File

@ -504,8 +504,8 @@ Query OK, 1 row(s) in set (0.000141s)
- Please refer to [springbootdemo](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/springbootdemo) if using taos-jdbcdriver in Spring JdbcTemplate. - Please refer to [springbootdemo](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/springbootdemo) if using taos-jdbcdriver in Spring JdbcTemplate.
## Example Codes ## Example Codes
you see sample code here: ![JDBC example](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC)
you see sample code here: [JDBC example](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC)
## FAQ ## FAQ

View File

@ -16,7 +16,7 @@ Please refer to the [video tutorial](https://www.taosdata.com/blog/2020/11/11/19
**Note 1:** Because the information of FQDN will be written into a file, if FQDN has not been configured or changed before, and TDengine has been started, be sure to clean up the previous data `rm -rf /var/lib/taos/*`on the premise of ensuring that the data is useless or backed up; **Note 1:** Because the information of FQDN will be written into a file, if FQDN has not been configured or changed before, and TDengine has been started, be sure to clean up the previous data `rm -rf /var/lib/taos/*`on the premise of ensuring that the data is useless or backed up;
**Note 2:** The client also needs to be configured to ensure that it can correctly parse the FQDN configuration of each node, whether through DNS service or Host file. **Note 2:** The client also needs to be configured to ensure that it can correctly parse the FQDN configuration of each node, whether through DNS service or modify hosts file.
**Step 2:** It is recommended to close the firewall of all physical nodes, and at least ensure that the TCP and UDP ports of ports 6030-6042 are open. It is **strongly recommended** to close the firewall first and configure the ports after the cluster is built; **Step 2:** It is recommended to close the firewall of all physical nodes, and at least ensure that the TCP and UDP ports of ports 6030-6042 are open. It is **strongly recommended** to close the firewall first and configure the ports after the cluster is built;

View File

@ -194,6 +194,9 @@ keepColumnName 1
# maximum number of rows returned by the restful interface # maximum number of rows returned by the restful interface
# restfulRowLimit 10240 # restfulRowLimit 10240
# database name must be specified in restful interface if the following parameter is set, off by default
# httpDbNameMandatory 1
# The following parameter is used to limit the maximum number of lines in log files. # The following parameter is used to limit the maximum number of lines in log files.
# max number of lines per log filters # max number of lines per log filters
# numOfLogLines 10000000 # numOfLogLines 10000000

View File

@ -19,18 +19,21 @@ else
fi fi
# Dynamic directory # Dynamic directory
data_dir="/var/lib/taos"
if [ "$osType" != "Darwin" ]; then if [ "$osType" != "Darwin" ]; then
data_dir="/var/lib/taos"
log_dir="/var/log/taos" log_dir="/var/log/taos"
else else
log_dir=~/TDengine/log data_dir="/usr/local/var/lib/taos"
log_dir="/usr/local/var/log/taos"
fi fi
data_link_dir="/usr/local/taos/data" if [ "$osType" != "Darwin" ]; then
log_link_dir="/usr/local/taos/log" cfg_install_dir="/etc/taos"
else
cfg_install_dir="/etc/taos" cfg_install_dir="/usr/local/etc/taos"
fi
if [ "$osType" != "Darwin" ]; then if [ "$osType" != "Darwin" ]; then
bin_link_dir="/usr/bin" bin_link_dir="/usr/bin"
@ -44,10 +47,18 @@ else
fi fi
#install main path #install main path
install_main_dir="/usr/local/taos" if [ "$osType" != "Darwin" ]; then
install_main_dir="/usr/local/taos"
else
install_main_dir="/usr/local/Cellar/tdengine/${verNumber}"
fi
# old bin dir # old bin dir
bin_dir="/usr/local/taos/bin" if [ "$osType" != "Darwin" ]; then
bin_dir="/usr/local/taos/bin"
else
bin_dir="/usr/local/Cellar/tdengine/${verNumber}/bin"
fi
service_config_dir="/etc/systemd/system" service_config_dir="/etc/systemd/system"
@ -59,12 +70,11 @@ GREEN_UNDERLINE='\033[4;32m'
NC='\033[0m' NC='\033[0m'
csudo="" csudo=""
if command -v sudo > /dev/null; then
csudo="sudo"
fi
if [ "$osType" != "Darwin" ]; then if [ "$osType" != "Darwin" ]; then
if command -v sudo > /dev/null; then
csudo="sudo"
fi
initd_mod=0 initd_mod=0
service_mod=2 service_mod=2
if pidof systemd &> /dev/null; then if pidof systemd &> /dev/null; then
@ -138,16 +148,15 @@ function install_main_path() {
function install_bin() { function install_bin() {
# Remove links # Remove links
${csudo} rm -f ${bin_link_dir}/taos || : ${csudo} rm -f ${bin_link_dir}/taos || :
if [ "$osType" != "Darwin" ]; then
${csudo} rm -f ${bin_link_dir}/taosd || : ${csudo} rm -f ${bin_link_dir}/taosd || :
${csudo} rm -f ${bin_link_dir}/taosdemo || : ${csudo} rm -f ${bin_link_dir}/taosdemo || :
${csudo} rm -f ${bin_link_dir}/perfMonitor || :
${csudo} rm -f ${bin_link_dir}/taosdump || : ${csudo} rm -f ${bin_link_dir}/taosdump || :
${csudo} rm -f ${bin_link_dir}/set_core || :
fi
if [ "$osType" != "Darwin" ]; then
${csudo} rm -f ${bin_link_dir}/perfMonitor || :
${csudo} rm -f ${bin_link_dir}/set_core || :
${csudo} rm -f ${bin_link_dir}/rmtaos || : ${csudo} rm -f ${bin_link_dir}/rmtaos || :
fi
${csudo} cp -r ${binary_dir}/build/bin/* ${install_main_dir}/bin ${csudo} cp -r ${binary_dir}/build/bin/* ${install_main_dir}/bin
${csudo} cp -r ${script_dir}/taosd-dump-cfg.gdb ${install_main_dir}/bin ${csudo} cp -r ${script_dir}/taosd-dump-cfg.gdb ${install_main_dir}/bin
@ -163,19 +172,17 @@ function install_bin() {
#Make link #Make link
[ -x ${install_main_dir}/bin/taos ] && ${csudo} ln -s ${install_main_dir}/bin/taos ${bin_link_dir}/taos || : [ -x ${install_main_dir}/bin/taos ] && ${csudo} ln -s ${install_main_dir}/bin/taos ${bin_link_dir}/taos || :
if [ "$osType" != "Darwin" ]; then
[ -x ${install_main_dir}/bin/taosd ] && ${csudo} ln -s ${install_main_dir}/bin/taosd ${bin_link_dir}/taosd || : [ -x ${install_main_dir}/bin/taosd ] && ${csudo} ln -s ${install_main_dir}/bin/taosd ${bin_link_dir}/taosd || :
[ -x ${install_main_dir}/bin/taosdump ] && ${csudo} ln -s ${install_main_dir}/bin/taosdump ${bin_link_dir}/taosdump || : [ -x ${install_main_dir}/bin/taosdump ] && ${csudo} ln -s ${install_main_dir}/bin/taosdump ${bin_link_dir}/taosdump || :
[ -x ${install_main_dir}/bin/taosdemo ] && ${csudo} ln -s ${install_main_dir}/bin/taosdemo ${bin_link_dir}/taosdemo || : [ -x ${install_main_dir}/bin/taosdemo ] && ${csudo} ln -s ${install_main_dir}/bin/taosdemo ${bin_link_dir}/taosdemo || :
if [ "$osType" != "Darwin" ]; then
[ -x ${install_main_dir}/bin/perfMonitor ] && ${csudo} ln -s ${install_main_dir}/bin/perfMonitor ${bin_link_dir}/perfMonitor || : [ -x ${install_main_dir}/bin/perfMonitor ] && ${csudo} ln -s ${install_main_dir}/bin/perfMonitor ${bin_link_dir}/perfMonitor || :
[ -x ${install_main_dir}/set_core.sh ] && ${csudo} ln -s ${install_main_dir}/bin/set_core.sh ${bin_link_dir}/set_core || : [ -x ${install_main_dir}/set_core.sh ] && ${csudo} ln -s ${install_main_dir}/bin/set_core.sh ${bin_link_dir}/set_core || :
fi fi
if [ "$osType" != "Darwin" ]; then if [ "$osType" != "Darwin" ]; then
[ -x ${install_main_dir}/bin/remove.sh ] && ${csudo} ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/rmtaos || : [ -x ${install_main_dir}/bin/remove.sh ] && ${csudo} ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/rmtaos || :
else
[ -x ${install_main_dir}/bin/remove_client.sh ] && ${csudo} ln -s ${install_main_dir}/bin/remove_client.sh ${bin_link_dir}/rmtaos || :
fi fi
} }
@ -222,7 +229,7 @@ function install_jemalloc() {
fi fi
if [ -d /etc/ld.so.conf.d ]; then if [ -d /etc/ld.so.conf.d ]; then
${csudo} echo "/usr/local/lib" > /etc/ld.so.conf.d/jemalloc.conf echo "/usr/local/lib" | ${csudo} tee /etc/ld.so.conf.d/jemalloc.conf
${csudo} ldconfig ${csudo} ldconfig
else else
echo "/etc/ld.so.conf.d not found!" echo "/etc/ld.so.conf.d not found!"
@ -248,8 +255,6 @@ function install_lib() {
fi fi
else else
${csudo} cp -Rf ${binary_dir}/build/lib/libtaos.* ${install_main_dir}/driver && ${csudo} chmod 777 ${install_main_dir}/driver/* ${csudo} cp -Rf ${binary_dir}/build/lib/libtaos.* ${install_main_dir}/driver && ${csudo} chmod 777 ${install_main_dir}/driver/*
${csudo} ln -sf ${install_main_dir}/driver/libtaos.1.dylib ${lib_link_dir}/libtaos.1.dylib
${csudo} ln -sf ${lib_link_dir}/libtaos.1.dylib ${lib_link_dir}/libtaos.dylib
fi fi
install_jemalloc install_jemalloc
@ -261,10 +266,14 @@ function install_lib() {
function install_header() { function install_header() {
if [ "$osType" != "Darwin" ]; then
${csudo} rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taoserror.h || : ${csudo} rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taoserror.h || :
fi
${csudo} cp -f ${source_dir}/src/inc/taos.h ${source_dir}/src/inc/taoserror.h ${install_main_dir}/include && ${csudo} chmod 644 ${install_main_dir}/include/* ${csudo} cp -f ${source_dir}/src/inc/taos.h ${source_dir}/src/inc/taoserror.h ${install_main_dir}/include && ${csudo} chmod 644 ${install_main_dir}/include/*
if [ "$osType" != "Darwin" ]; then
${csudo} ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h ${csudo} ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h
${csudo} ln -s ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h ${csudo} ln -s ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h
fi
} }
function install_config() { function install_config() {
@ -272,23 +281,20 @@ function install_config() {
if [ ! -f ${cfg_install_dir}/taos.cfg ]; then if [ ! -f ${cfg_install_dir}/taos.cfg ]; then
${csudo} mkdir -p ${cfg_install_dir} ${csudo} mkdir -p ${cfg_install_dir}
[ -f ${script_dir}/../cfg/taos.cfg ] && ${csudo} cp ${script_dir}/../cfg/taos.cfg ${cfg_install_dir} [ -f ${script_dir}/../cfg/taos.cfg ] &&
${csudo} cp ${script_dir}/../cfg/taos.cfg ${cfg_install_dir}
${csudo} chmod 644 ${cfg_install_dir}/* ${csudo} chmod 644 ${cfg_install_dir}/*
fi fi
${csudo} cp -f ${script_dir}/../cfg/taos.cfg ${install_main_dir}/cfg/taos.cfg.org ${csudo} cp -f ${script_dir}/../cfg/taos.cfg ${install_main_dir}/cfg/taos.cfg.org
${csudo} ln -s ${cfg_install_dir}/taos.cfg ${install_main_dir}/cfg
if [ "$osType" != "Darwin" ]; then ${csudo} ln -s ${cfg_install_dir}/taos.cfg ${install_main_dir}/cfg
fi
} }
function install_log() { function install_log() {
${csudo} rm -rf ${log_dir} || : ${csudo} rm -rf ${log_dir} || :
if [ "$osType" != "Darwin" ]; then
${csudo} mkdir -p ${log_dir} && ${csudo} chmod 777 ${log_dir} ${csudo} mkdir -p ${log_dir} && ${csudo} chmod 777 ${log_dir}
else
mkdir -p ${log_dir} && chmod 777 ${log_dir}
fi
${csudo} ln -s ${log_dir} ${install_main_dir}/log ${csudo} ln -s ${log_dir} ${install_main_dir}/log
} }
@ -309,7 +315,6 @@ function install_connector() {
echo "WARNING: go connector not found, please check if want to use it!" echo "WARNING: go connector not found, please check if want to use it!"
fi fi
${csudo} cp -rf ${source_dir}/src/connector/python ${install_main_dir}/connector ${csudo} cp -rf ${source_dir}/src/connector/python ${install_main_dir}/connector
${csudo} cp ${binary_dir}/build/lib/*.jar ${install_main_dir}/connector &> /dev/null && ${csudo} chmod 777 ${install_main_dir}/connector/*.jar || echo &> /dev/null ${csudo} cp ${binary_dir}/build/lib/*.jar ${install_main_dir}/connector &> /dev/null && ${csudo} chmod 777 ${install_main_dir}/connector/*.jar || echo &> /dev/null
} }
@ -492,15 +497,12 @@ function install_TDengine() {
install_main_path install_main_path
if [ "$osType" != "Darwin" ]; then
install_data install_data
fi
install_log install_log
install_header install_header
install_lib install_lib
install_connector install_connector
install_examples install_examples
install_bin install_bin
if [ "$osType" != "Darwin" ]; then if [ "$osType" != "Darwin" ]; then

View File

@ -1,6 +1,6 @@
name: tdengine name: tdengine
base: core18 base: core18
version: '2.1.7.1' version: '2.1.7.2'
icon: snap/gui/t-dengine.svg icon: snap/gui/t-dengine.svg
summary: an open-source big data platform designed and optimized for IoT. summary: an open-source big data platform designed and optimized for IoT.
description: | description: |
@ -72,7 +72,7 @@ parts:
- usr/bin/taosd - usr/bin/taosd
- usr/bin/taos - usr/bin/taos
- usr/bin/taosdemo - usr/bin/taosdemo
- usr/lib/libtaos.so.2.1.7.1 - usr/lib/libtaos.so.2.1.7.2
- usr/lib/libtaos.so.1 - usr/lib/libtaos.so.1
- usr/lib/libtaos.so - usr/lib/libtaos.so

View File

@ -36,7 +36,7 @@ extern "C" {
(((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_CHILD_TABLE)) (((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_CHILD_TABLE))
#define UTIL_TABLE_IS_NORMAL_TABLE(metaInfo) \ #define UTIL_TABLE_IS_NORMAL_TABLE(metaInfo) \
(!(UTIL_TABLE_IS_SUPER_TABLE(metaInfo) || UTIL_TABLE_IS_CHILD_TABLE(metaInfo) || UTIL_TABLE_IS_TMP_TABLE(metaInfo))) (!(UTIL_TABLE_IS_SUPER_TABLE(metaInfo) || UTIL_TABLE_IS_CHILD_TABLE(metaInfo)))
#define UTIL_TABLE_IS_TMP_TABLE(metaInfo) \ #define UTIL_TABLE_IS_TMP_TABLE(metaInfo) \
(((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_TEMP_TABLE)) (((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_TEMP_TABLE))
@ -191,6 +191,7 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo);
void tscFieldInfoCopy(SFieldInfo* pFieldInfo, const SFieldInfo* pSrc, const SArray* pExprList); void tscFieldInfoCopy(SFieldInfo* pFieldInfo, const SFieldInfo* pSrc, const SArray* pExprList);
static FORCE_INLINE int32_t tscNumOfFields(SQueryInfo* pQueryInfo) { return pQueryInfo->fieldsInfo.numOfOutput; } static FORCE_INLINE int32_t tscNumOfFields(SQueryInfo* pQueryInfo) { return pQueryInfo->fieldsInfo.numOfOutput; }
int32_t tscGetFirstInvisibleFieldPos(SQueryInfo* pQueryInfo);
int32_t tscFieldInfoCompare(const SFieldInfo* pFieldInfo1, const SFieldInfo* pFieldInfo2, int32_t *diffSize); int32_t tscFieldInfoCompare(const SFieldInfo* pFieldInfo1, const SFieldInfo* pFieldInfo2, int32_t *diffSize);
void tscInsertPrimaryTsSourceColumn(SQueryInfo* pQueryInfo, uint64_t uid); void tscInsertPrimaryTsSourceColumn(SQueryInfo* pQueryInfo, uint64_t uid);
@ -364,6 +365,8 @@ STblCond* tsGetTableFilter(SArray* filters, uint64_t uid, int16_t idx);
void tscRemoveCachedTableMeta(STableMetaInfo* pTableMetaInfo, uint64_t id); void tscRemoveCachedTableMeta(STableMetaInfo* pTableMetaInfo, uint64_t id);
char* cloneCurrentDBName(SSqlObj* pSql);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -492,6 +492,7 @@ bool tscHasReachLimitation(SQueryInfo *pQueryInfo, SSqlRes *pRes);
void tscSetBoundColumnInfo(SParsedDataColInfo *pColInfo, SSchema *pSchema, int32_t numOfCols); void tscSetBoundColumnInfo(SParsedDataColInfo *pColInfo, SSchema *pSchema, int32_t numOfCols);
char *tscGetErrorMsgPayload(SSqlCmd *pCmd); char *tscGetErrorMsgPayload(SSqlCmd *pCmd);
int32_t tscErrorMsgWithCode(int32_t code, char* dstBuffer, const char* errMsg, const char* sql);
int32_t tscInvalidOperationMsg(char *msg, const char *additionalInfo, const char *sql); int32_t tscInvalidOperationMsg(char *msg, const char *additionalInfo, const char *sql);
int32_t tscSQLSyntaxErrMsg(char* msg, const char* additionalInfo, const char* sql); int32_t tscSQLSyntaxErrMsg(char* msg, const char* additionalInfo, const char* sql);

View File

@ -363,15 +363,6 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
} }
if (TSDB_QUERY_HAS_TYPE(pCmd->insertParam.insertType, TSDB_QUERY_TYPE_STMT_INSERT)) { // stmt insert if (TSDB_QUERY_HAS_TYPE(pCmd->insertParam.insertType, TSDB_QUERY_TYPE_STMT_INSERT)) { // stmt insert
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
code = tscGetTableMeta(pSql, pTableMetaInfo);
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
taosReleaseRef(tscObjRef, pSql->self);
return;
} else {
assert(code == TSDB_CODE_SUCCESS);
}
(*pSql->fp)(pSql->param, pSql, code); (*pSql->fp)(pSql->param, pSql, code);
} else if (TSDB_QUERY_HAS_TYPE(pCmd->insertParam.insertType, TSDB_QUERY_TYPE_FILE_INSERT)) { // file insert } else if (TSDB_QUERY_HAS_TYPE(pCmd->insertParam.insertType, TSDB_QUERY_TYPE_FILE_INSERT)) { // file insert
tscImportDataFromFile(pSql); tscImportDataFromFile(pSql);

View File

@ -35,6 +35,7 @@ typedef struct SCompareParam {
static bool needToMerge(SSDataBlock* pBlock, SArray* columnIndexList, int32_t index, char **buf) { static bool needToMerge(SSDataBlock* pBlock, SArray* columnIndexList, int32_t index, char **buf) {
int32_t ret = 0; int32_t ret = 0;
size_t size = taosArrayGetSize(columnIndexList); size_t size = taosArrayGetSize(columnIndexList);
if (size > 0) { if (size > 0) {
ret = compare_aRv(pBlock, columnIndexList, (int32_t) size, index, buf, TSDB_ORDER_ASC); ret = compare_aRv(pBlock, columnIndexList, (int32_t) size, index, buf, TSDB_ORDER_ASC);
@ -564,9 +565,11 @@ static void savePrevOrderColumns(char** prevRow, SArray* pColumnList, SSDataBloc
(*hasPrev) = true; (*hasPrev) = true;
} }
// tsdb_func_tag function only produce one row of result. Therefore, we need to copy the
// output value to multiple rows
static void setTagValueForMultipleRows(SQLFunctionCtx* pCtx, int32_t numOfOutput, int32_t numOfRows) { static void setTagValueForMultipleRows(SQLFunctionCtx* pCtx, int32_t numOfOutput, int32_t numOfRows) {
if (numOfRows <= 1) { if (numOfRows <= 1) {
return ; return;
} }
for (int32_t k = 0; k < numOfOutput; ++k) { for (int32_t k = 0; k < numOfOutput; ++k) {
@ -574,12 +577,49 @@ static void setTagValueForMultipleRows(SQLFunctionCtx* pCtx, int32_t numOfOutput
continue; continue;
} }
int32_t inc = numOfRows - 1; // tsdb_func_tag function only produce one row of result
char* src = pCtx[k].pOutput; char* src = pCtx[k].pOutput;
char* dst = pCtx[k].pOutput + pCtx[k].outputBytes;
for (int32_t i = 0; i < inc; ++i) { // Let's start from the second row, as the first row has result value already.
pCtx[k].pOutput += pCtx[k].outputBytes; for (int32_t i = 1; i < numOfRows; ++i) {
memcpy(pCtx[k].pOutput, src, (size_t)pCtx[k].outputBytes); memcpy(dst, src, (size_t)pCtx[k].outputBytes);
dst += pCtx[k].outputBytes;
}
}
}
static void doMergeResultImpl(SMultiwayMergeInfo* pInfo, SQLFunctionCtx *pCtx, int32_t numOfExpr, int32_t rowIndex, char** pDataPtr) {
for (int32_t j = 0; j < numOfExpr; ++j) {
pCtx[j].pInput = pDataPtr[j] + pCtx[j].inputBytes * rowIndex;
}
for (int32_t j = 0; j < numOfExpr; ++j) {
int32_t functionId = pCtx[j].functionId;
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
continue;
}
if (functionId < 0) {
SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1);
doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE);
} else {
aAggs[functionId].mergeFunc(&pCtx[j]);
}
}
}
static void doFinalizeResultImpl(SMultiwayMergeInfo* pInfo, SQLFunctionCtx *pCtx, int32_t numOfExpr) {
for(int32_t j = 0; j < numOfExpr; ++j) {
int32_t functionId = pCtx[j].functionId;
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
continue;
}
if (functionId < 0) {
SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1);
doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE);
} else {
aAggs[functionId].xFinalize(&pCtx[j]);
} }
} }
} }
@ -588,52 +628,18 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD
SMultiwayMergeInfo* pInfo = pOperator->info; SMultiwayMergeInfo* pInfo = pOperator->info;
SQLFunctionCtx* pCtx = pInfo->binfo.pCtx; SQLFunctionCtx* pCtx = pInfo->binfo.pCtx;
char** add = calloc(pBlock->info.numOfCols, POINTER_BYTES); char** addrPtr = calloc(pBlock->info.numOfCols, POINTER_BYTES);
for(int32_t i = 0; i < pBlock->info.numOfCols; ++i) { for(int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
add[i] = pCtx[i].pInput; addrPtr[i] = pCtx[i].pInput;
pCtx[i].size = 1; pCtx[i].size = 1;
} }
for(int32_t i = 0; i < pBlock->info.rows; ++i) { for(int32_t i = 0; i < pBlock->info.rows; ++i) {
if (pInfo->hasPrev) { if (pInfo->hasPrev) {
if (needToMerge(pBlock, pInfo->orderColumnList, i, pInfo->prevRow)) { if (needToMerge(pBlock, pInfo->orderColumnList, i, pInfo->prevRow)) {
for (int32_t j = 0; j < numOfExpr; ++j) { doMergeResultImpl(pInfo, pCtx, numOfExpr, i, addrPtr);
pCtx[j].pInput = add[j] + pCtx[j].inputBytes * i;
}
for (int32_t j = 0; j < numOfExpr; ++j) {
int32_t functionId = pCtx[j].functionId;
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
continue;
}
if (functionId < 0) {
SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1);
doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE);
continue;
}
aAggs[functionId].mergeFunc(&pCtx[j]);
}
} else { } else {
for(int32_t j = 0; j < numOfExpr; ++j) { // TODO refactor doFinalizeResultImpl(pInfo, pCtx, numOfExpr);
int32_t functionId = pCtx[j].functionId;
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
continue;
}
if (functionId < 0) {
SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1);
doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE);
continue;
}
aAggs[functionId].xFinalize(&pCtx[j]);
}
int32_t numOfRows = getNumOfResult(pOperator->pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput); int32_t numOfRows = getNumOfResult(pOperator->pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput);
setTagValueForMultipleRows(pCtx, pOperator->numOfOutput, numOfRows); setTagValueForMultipleRows(pCtx, pOperator->numOfOutput, numOfRows);
@ -643,7 +649,7 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD
for(int32_t j = 0; j < numOfExpr; ++j) { for(int32_t j = 0; j < numOfExpr; ++j) {
pCtx[j].pOutput += (pCtx[j].outputBytes * numOfRows); pCtx[j].pOutput += (pCtx[j].outputBytes * numOfRows);
if (pCtx[j].functionId == TSDB_FUNC_TOP || pCtx[j].functionId == TSDB_FUNC_BOTTOM) { if (pCtx[j].functionId == TSDB_FUNC_TOP || pCtx[j].functionId == TSDB_FUNC_BOTTOM) {
if(j > 0)pCtx[j].ptsOutputBuf = pCtx[j - 1].pOutput; if(j > 0) pCtx[j].ptsOutputBuf = pCtx[j - 1].pOutput;
} }
} }
@ -655,48 +661,10 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD
aAggs[pCtx[j].functionId].init(&pCtx[j], pCtx[j].resultInfo); aAggs[pCtx[j].functionId].init(&pCtx[j], pCtx[j].resultInfo);
} }
for (int32_t j = 0; j < numOfExpr; ++j) { doMergeResultImpl(pInfo, pCtx, numOfExpr, i, addrPtr);
pCtx[j].pInput = add[j] + pCtx[j].inputBytes * i;
}
for (int32_t j = 0; j < numOfExpr; ++j) {
int32_t functionId = pCtx[j].functionId;
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
continue;
}
if (functionId < 0) {
SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1);
doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE);
continue;
}
aAggs[functionId].mergeFunc(&pCtx[j]);
}
} }
} else { } else {
for (int32_t j = 0; j < numOfExpr; ++j) { doMergeResultImpl(pInfo, pCtx, numOfExpr, i, addrPtr);
pCtx[j].pInput = add[j] + pCtx[j].inputBytes * i;
}
for (int32_t j = 0; j < numOfExpr; ++j) {
int32_t functionId = pCtx[j].functionId;
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
continue;
}
if (functionId < 0) {
SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1);
doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE);
continue;
}
aAggs[functionId].mergeFunc(&pCtx[j]);
}
} }
savePrevOrderColumns(pInfo->prevRow, pInfo->orderColumnList, pBlock, i, &pInfo->hasPrev); savePrevOrderColumns(pInfo->prevRow, pInfo->orderColumnList, pBlock, i, &pInfo->hasPrev);
@ -704,11 +672,11 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD
{ {
for(int32_t i = 0; i < pBlock->info.numOfCols; ++i) { for(int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
pCtx[i].pInput = add[i]; pCtx[i].pInput = addrPtr[i];
} }
} }
tfree(add); tfree(addrPtr);
} }
static bool isAllSourcesCompleted(SGlobalMerger *pMerger) { static bool isAllSourcesCompleted(SGlobalMerger *pMerger) {
@ -816,6 +784,8 @@ SSDataBlock* doMultiwayMergeSort(void* param, bool* newgroup) {
SLocalDataSource *pOneDataSrc = pMerger->pLocalDataSrc[pTree->pNode[0].index]; SLocalDataSource *pOneDataSrc = pMerger->pLocalDataSrc[pTree->pNode[0].index];
bool sameGroup = true; bool sameGroup = true;
if (pInfo->hasPrev) { if (pInfo->hasPrev) {
// todo refactor extract method
int32_t numOfCols = (int32_t)taosArrayGetSize(pInfo->orderColumnList); int32_t numOfCols = (int32_t)taosArrayGetSize(pInfo->orderColumnList);
// if this row belongs to current result set group // if this row belongs to current result set group
@ -955,9 +925,10 @@ SSDataBlock* doGlobalAggregate(void* param, bool* newgroup) {
break; break;
} }
bool sameGroup = true;
if (pAggInfo->hasGroupColData) { if (pAggInfo->hasGroupColData) {
bool sameGroup = isSameGroup(pAggInfo->groupColumnList, pBlock, pAggInfo->currentGroupColData); sameGroup = isSameGroup(pAggInfo->groupColumnList, pBlock, pAggInfo->currentGroupColData);
if (!sameGroup) { if (!sameGroup && !pAggInfo->multiGroupResults) {
*newgroup = true; *newgroup = true;
pAggInfo->hasDataBlockForNewGroup = true; pAggInfo->hasDataBlockForNewGroup = true;
pAggInfo->pExistBlock = pBlock; pAggInfo->pExistBlock = pBlock;
@ -976,26 +947,10 @@ SSDataBlock* doGlobalAggregate(void* param, bool* newgroup) {
} }
if (handleData) { // data in current group is all handled if (handleData) { // data in current group is all handled
for(int32_t j = 0; j < pOperator->numOfOutput; ++j) { doFinalizeResultImpl(pAggInfo, pAggInfo->binfo.pCtx, pOperator->numOfOutput);
int32_t functionId = pAggInfo->binfo.pCtx[j].functionId;
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
continue;
}
if (functionId < 0) {
SUdfInfo* pUdfInfo = taosArrayGet(pAggInfo->udfInfo, -1 * functionId - 1);
doInvokeUdf(pUdfInfo, &pAggInfo->binfo.pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE);
continue;
}
aAggs[functionId].xFinalize(&pAggInfo->binfo.pCtx[j]);
}
int32_t numOfRows = getNumOfResult(pOperator->pRuntimeEnv, pAggInfo->binfo.pCtx, pOperator->numOfOutput); int32_t numOfRows = getNumOfResult(pOperator->pRuntimeEnv, pAggInfo->binfo.pCtx, pOperator->numOfOutput);
pAggInfo->binfo.pRes->info.rows += numOfRows;
pAggInfo->binfo.pRes->info.rows += numOfRows;
setTagValueForMultipleRows(pAggInfo->binfo.pCtx, pOperator->numOfOutput, numOfRows); setTagValueForMultipleRows(pAggInfo->binfo.pCtx, pOperator->numOfOutput, numOfRows);
} }
@ -1019,71 +974,127 @@ SSDataBlock* doGlobalAggregate(void* param, bool* newgroup) {
return (pRes->info.rows != 0)? pRes:NULL; return (pRes->info.rows != 0)? pRes:NULL;
} }
static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) { static void doHandleDataInCurrentGroup(SSLimitOperatorInfo* pInfo, SSDataBlock* pBlock, int32_t rowIndex) {
SSLimitOperatorInfo *pInfo = pOperator->info; if (pInfo->currentOffset > 0) {
assert(pInfo->currentGroupOffset >= 0); pInfo->currentOffset -= 1;
} else {
// discard the data rows in current group
if (pInfo->limit.limit < 0 || (pInfo->limit.limit >= 0 && pInfo->rowsTotal < pInfo->limit.limit)) {
size_t num1 = taosArrayGetSize(pInfo->pRes->pDataBlock);
for (int32_t i = 0; i < num1; ++i) {
SColumnInfoData *pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
SColumnInfoData *pDstInfoData = taosArrayGet(pInfo->pRes->pDataBlock, i);
SSDataBlock* pBlock = NULL; SColumnInfo *pColInfo = &pColInfoData->info;
if (pInfo->currentGroupOffset == 0) {
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); char *pSrc = rowIndex * pColInfo->bytes + (char *)pColInfoData->pData;
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); char *pDst = (char *)pDstInfoData->pData + (pInfo->pRes->info.rows * pColInfo->bytes);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { memcpy(pDst, pSrc, pColInfo->bytes);
}
pInfo->rowsTotal += 1;
pInfo->pRes->info.rows += 1;
}
}
}
static void ensureOutputBuf(SSLimitOperatorInfo * pInfo, SSDataBlock *pResultBlock, int32_t numOfRows) {
if (pInfo->capacity < pResultBlock->info.rows + numOfRows) {
int32_t total = pResultBlock->info.rows + numOfRows;
size_t num = taosArrayGetSize(pResultBlock->pDataBlock);
for (int32_t i = 0; i < num; ++i) {
SColumnInfoData *pInfoData = taosArrayGet(pResultBlock->pDataBlock, i);
char *tmp = realloc(pInfoData->pData, total * pInfoData->info.bytes);
if (tmp != NULL) {
pInfoData->pData = tmp;
} else {
// todo handle the malloc failure
}
pInfo->capacity = total;
pInfo->threshold = (int64_t)(total * 0.8);
}
}
}
enum {
BLOCK_NEW_GROUP = 1,
BLOCK_NO_GROUP = 2,
BLOCK_SAME_GROUP = 3,
};
static int32_t doSlimitImpl(SOperatorInfo* pOperator, SSLimitOperatorInfo* pInfo, SSDataBlock* pBlock) {
int32_t rowIndex = 0;
while (rowIndex < pBlock->info.rows) {
int32_t numOfCols = (int32_t)taosArrayGetSize(pInfo->orderColumnList);
bool samegroup = true;
if (pInfo->hasPrev) {
for (int32_t i = 0; i < numOfCols; ++i) {
SColIndex *pIndex = taosArrayGet(pInfo->orderColumnList, i);
SColumnInfoData *pColInfoData = taosArrayGet(pBlock->pDataBlock, pIndex->colIndex);
SColumnInfo *pColInfo = &pColInfoData->info;
char *d = rowIndex * pColInfo->bytes + (char *)pColInfoData->pData;
int32_t ret = columnValueAscendingComparator(pInfo->prevRow[i], d, pColInfo->type, pColInfo->bytes);
if (ret != 0) { // it is a new group
samegroup = false;
break;
}
}
}
if (!samegroup || !pInfo->hasPrev) {
pInfo->ignoreCurrentGroup = false;
savePrevOrderColumns(pInfo->prevRow, pInfo->orderColumnList, pBlock, rowIndex, &pInfo->hasPrev);
pInfo->currentOffset = pInfo->limit.offset; // reset the offset value for a new group
pInfo->rowsTotal = 0;
if (pInfo->currentGroupOffset > 0) {
pInfo->ignoreCurrentGroup = true;
pInfo->currentGroupOffset -= 1; // now we are in the next group data
rowIndex += 1;
continue;
}
// A new group has arrived according to the result rows, and the group limitation has already reached.
// Let's jump out of current loop and return immediately.
if (pInfo->slimit.limit >= 0 && pInfo->groupTotal >= pInfo->slimit.limit) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
pOperator->status = OP_EXEC_DONE; pOperator->status = OP_EXEC_DONE;
return BLOCK_NO_GROUP;
} }
if (*newgroup == false && pInfo->limit.limit > 0 && pInfo->rowsTotal >= pInfo->limit.limit) { pInfo->groupTotal += 1;
while ((*newgroup) == false) { // ignore the remain blocks
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); // data in current group not allowed, return if current result does not belong to the previous group.And there
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); // are results exists in current SSDataBlock
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); if (!pInfo->multigroupResult && !samegroup && pInfo->pRes->info.rows > 0) {
if (pBlock == NULL) { return BLOCK_NEW_GROUP;
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
pOperator->status = OP_EXEC_DONE;
return NULL;
}
}
} }
return pBlock; doHandleDataInCurrentGroup(pInfo, pBlock, rowIndex);
} else { // handle the offset in the same group
// All the data in current group needs to be discarded, due to the limit parameter in the SQL statement
if (pInfo->ignoreCurrentGroup) {
rowIndex += 1;
continue;
} }
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); doHandleDataInCurrentGroup(pInfo, pBlock, rowIndex);
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
pOperator->status = OP_EXEC_DONE;
return NULL;
} }
while(1) { rowIndex += 1;
if (*newgroup) {
pInfo->currentGroupOffset -= 1;
*newgroup = false;
} }
while ((*newgroup) == false) { return BLOCK_SAME_GROUP;
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
pOperator->status = OP_EXEC_DONE;
return NULL;
}
}
// now we have got the first data block of the next group.
if (pInfo->currentGroupOffset == 0) {
return pBlock;
}
}
return NULL;
} }
SSDataBlock* doSLimit(void* param, bool* newgroup) { SSDataBlock* doSLimit(void* param, bool* newgroup) {
@ -1093,63 +1104,41 @@ SSDataBlock* doSLimit(void* param, bool* newgroup) {
} }
SSLimitOperatorInfo *pInfo = pOperator->info; SSLimitOperatorInfo *pInfo = pOperator->info;
pInfo->pRes->info.rows = 0;
if (pInfo->pPrevBlock != NULL) {
ensureOutputBuf(pInfo, pInfo->pRes, pInfo->pPrevBlock->info.rows);
int32_t ret = doSlimitImpl(pOperator, pInfo, pInfo->pPrevBlock);
assert(ret != BLOCK_NEW_GROUP);
pInfo->pPrevBlock = NULL;
}
assert(pInfo->currentGroupOffset >= 0);
while(1) {
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
SSDataBlock *pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
SSDataBlock *pBlock = NULL;
while (1) {
pBlock = skipGroupBlock(pOperator, newgroup);
if (pBlock == NULL) { if (pBlock == NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); return pInfo->pRes->info.rows == 0 ? NULL : pInfo->pRes;
pOperator->status = OP_EXEC_DONE;
return NULL;
} }
if (*newgroup) { // a new group arrives ensureOutputBuf(pInfo, pInfo->pRes, pBlock->info.rows);
pInfo->groupTotal += 1; int32_t ret = doSlimitImpl(pOperator, pInfo, pBlock);
pInfo->rowsTotal = 0; if (ret == BLOCK_NEW_GROUP) {
pInfo->currentOffset = pInfo->limit.offset; pInfo->pPrevBlock = pBlock;
return pInfo->pRes;
} }
assert(pInfo->currentGroupOffset == 0); if (pOperator->status == OP_EXEC_DONE) {
return pInfo->pRes->info.rows == 0 ? NULL : pInfo->pRes;
if (pInfo->currentOffset >= pBlock->info.rows) {
pInfo->currentOffset -= pBlock->info.rows;
} else {
if (pInfo->currentOffset == 0) {
break;
} }
int32_t remain = (int32_t)(pBlock->info.rows - pInfo->currentOffset); // now the number of rows in current group is enough, let's return to the invoke function
pBlock->info.rows = remain; if (pInfo->pRes->info.rows > pInfo->threshold) {
return pInfo->pRes;
// move the remain rows of this data block to the front.
for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
SColumnInfoData *pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
int16_t bytes = pColInfoData->info.bytes;
memmove(pColInfoData->pData, pColInfoData->pData + bytes * pInfo->currentOffset, remain * bytes);
}
pInfo->currentOffset = 0;
break;
} }
} }
if (pInfo->slimit.limit > 0 && pInfo->groupTotal > pInfo->slimit.limit) { // reach the group limit, abort
return NULL;
}
if (pInfo->limit.limit > 0 && (pInfo->rowsTotal + pBlock->info.rows >= pInfo->limit.limit)) {
pBlock->info.rows = (int32_t)(pInfo->limit.limit - pInfo->rowsTotal);
pInfo->rowsTotal = pInfo->limit.limit;
if (pInfo->slimit.limit > 0 && pInfo->groupTotal >= pInfo->slimit.limit) {
pOperator->status = OP_EXEC_DONE;
}
// setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
} else {
pInfo->rowsTotal += pBlock->info.rows;
}
return pBlock;
} }

View File

@ -1777,6 +1777,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int32_t numOfRow
} }
_error: _error:
pParentSql->res.code = code;
tfree(tokenBuf); tfree(tokenBuf);
tfree(line); tfree(line);
taos_free_result(pSql); taos_free_result(pSql);

View File

@ -32,9 +32,6 @@ typedef struct {
uint8_t type; uint8_t type;
int16_t length; int16_t length;
char* value; char* value;
//===================================
uint32_t fieldSchemaIdx;
} TAOS_SML_KV; } TAOS_SML_KV;
typedef struct { typedef struct {
@ -47,9 +44,6 @@ typedef struct {
// first kv must be timestamp // first kv must be timestamp
TAOS_SML_KV* fields; TAOS_SML_KV* fields;
int32_t fieldNum; int32_t fieldNum;
//================================
uint32_t schemaIdx;
} TAOS_SML_DATA_POINT; } TAOS_SML_DATA_POINT;
typedef enum { typedef enum {
@ -62,10 +56,23 @@ typedef enum {
typedef struct { typedef struct {
uint64_t id; uint64_t id;
SHashObj* smlDataToSchema;
} SSmlLinesInfo; } SSmlLinesInfo;
//================================================================================================= //=================================================================================================
static uint64_t linesSmlHandleId = 0;
uint64_t genLinesSmlId() {
uint64_t id;
do {
id = atomic_add_fetch_64(&linesSmlHandleId, 1);
} while (id == 0);
return id;
}
int compareSmlColKv(const void* p1, const void* p2) { int compareSmlColKv(const void* p1, const void* p2) {
TAOS_SML_KV* kv1 = (TAOS_SML_KV*)p1; TAOS_SML_KV* kv1 = (TAOS_SML_KV*)p1;
TAOS_SML_KV* kv2 = (TAOS_SML_KV*)p2; TAOS_SML_KV* kv2 = (TAOS_SML_KV*)p2;
@ -168,11 +175,46 @@ static int32_t buildSmlKvSchema(TAOS_SML_KV* smlKv, SHashObj* hash, SArray* arra
taosHashPut(hash, field.name, tagKeyLen, &fieldIdx, sizeof(fieldIdx)); taosHashPut(hash, field.name, tagKeyLen, &fieldIdx, sizeof(fieldIdx));
} }
smlKv->fieldSchemaIdx = (uint32_t)fieldIdx; uintptr_t valPointer = (uintptr_t)smlKv;
taosHashPut(info->smlDataToSchema, &valPointer, sizeof(uintptr_t), &fieldIdx, sizeof(fieldIdx));
return 0; return 0;
} }
static int32_t getSmlMd5ChildTableName(TAOS_SML_DATA_POINT* point, char* tableName, int* tableNameLen,
SSmlLinesInfo* info) {
tscDebug("SML:0x%"PRIx64" taos_sml_insert get child table name through md5", info->id);
qsort(point->tags, point->tagNum, sizeof(TAOS_SML_KV), compareSmlColKv);
SStringBuilder sb; memset(&sb, 0, sizeof(sb));
char sTableName[TSDB_TABLE_NAME_LEN] = {0};
strtolower(sTableName, point->stableName);
taosStringBuilderAppendString(&sb, sTableName);
for (int j = 0; j < point->tagNum; ++j) {
taosStringBuilderAppendChar(&sb, ',');
TAOS_SML_KV* tagKv = point->tags + j;
char tagName[TSDB_COL_NAME_LEN] = {0};
strtolower(tagName, tagKv->key);
taosStringBuilderAppendString(&sb, tagName);
taosStringBuilderAppendChar(&sb, '=');
taosStringBuilderAppend(&sb, tagKv->value, tagKv->length);
}
size_t len = 0;
char* keyJoined = taosStringBuilderGetResult(&sb, &len);
MD5_CTX context;
MD5Init(&context);
MD5Update(&context, (uint8_t *)keyJoined, (uint32_t)len);
MD5Final(&context);
*tableNameLen = snprintf(tableName, *tableNameLen,
"t_%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", context.digest[0],
context.digest[1], context.digest[2], context.digest[3], context.digest[4], context.digest[5], context.digest[6],
context.digest[7], context.digest[8], context.digest[9], context.digest[10], context.digest[11],
context.digest[12], context.digest[13], context.digest[14], context.digest[15]);
taosStringBuilderDestroy(&sb);
tscDebug("SML:0x%"PRIx64" child table name: %s", info->id, tableName);
return 0;
}
static int32_t buildDataPointSchemas(TAOS_SML_DATA_POINT* points, int numPoint, SArray* stableSchemas, SSmlLinesInfo* info) { static int32_t buildDataPointSchemas(TAOS_SML_DATA_POINT* points, int numPoint, SArray* stableSchemas, SSmlLinesInfo* info) {
int32_t code = 0; int32_t code = 0;
SHashObj* sname2shema = taosHashInit(32, SHashObj* sname2shema = taosHashInit(32,
@ -203,6 +245,15 @@ static int32_t buildDataPointSchemas(TAOS_SML_DATA_POINT* points, int numPoint,
for (int j = 0; j < point->tagNum; ++j) { for (int j = 0; j < point->tagNum; ++j) {
TAOS_SML_KV* tagKv = point->tags + j; TAOS_SML_KV* tagKv = point->tags + j;
if (!point->childTableName) {
char childTableName[TSDB_TABLE_NAME_LEN];
int32_t tableNameLen = TSDB_TABLE_NAME_LEN;
getSmlMd5ChildTableName(point, childTableName, &tableNameLen, info);
point->childTableName = calloc(1, tableNameLen+1);
strncpy(point->childTableName, childTableName, tableNameLen);
point->childTableName[tableNameLen] = '\0';
}
code = buildSmlKvSchema(tagKv, pStableSchema->tagHash, pStableSchema->tags, info); code = buildSmlKvSchema(tagKv, pStableSchema->tagHash, pStableSchema->tags, info);
if (code != 0) { if (code != 0) {
tscError("SML:0x%"PRIx64" build data point schema failed. point no.: %d, tag key: %s", info->id, i, tagKv->key); tscError("SML:0x%"PRIx64" build data point schema failed. point no.: %d, tag key: %s", info->id, i, tagKv->key);
@ -219,7 +270,8 @@ static int32_t buildDataPointSchemas(TAOS_SML_DATA_POINT* points, int numPoint,
} }
} }
point->schemaIdx = (uint32_t)stableIdx; uintptr_t valPointer = (uintptr_t)point;
taosHashPut(info->smlDataToSchema, &valPointer, sizeof(uintptr_t), &stableIdx, sizeof(stableIdx));
} }
size_t numStables = taosArrayGetSize(stableSchemas); size_t numStables = taosArrayGetSize(stableSchemas);
@ -319,7 +371,22 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf
buildColumnDescription(action->alterSTable.field, result+n, capacity-n, &outBytes); buildColumnDescription(action->alterSTable.field, result+n, capacity-n, &outBytes);
TAOS_RES* res = taos_query(taos, result); //TODO async doAsyncQuery TAOS_RES* res = taos_query(taos, result); //TODO async doAsyncQuery
code = taos_errno(res); code = taos_errno(res);
char* errStr = taos_errstr(res);
char* begin = strstr(errStr, "duplicated column names");
bool tscDupColNames = (begin != NULL);
if (code != TSDB_CODE_SUCCESS) {
tscError("SML:0x%"PRIx64" apply schema action. error: %s", info->id, errStr);
}
taos_free_result(res); taos_free_result(res);
if (code == TSDB_CODE_MND_FIELD_ALREAY_EXIST || code == TSDB_CODE_MND_TAG_ALREAY_EXIST || tscDupColNames) {
TAOS_RES* res2 = taos_query(taos, "RESET QUERY CACHE");
code = taos_errno(res2);
if (code != TSDB_CODE_SUCCESS) {
tscError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2));
}
taos_free_result(res2);
}
break; break;
} }
case SCHEMA_ACTION_ADD_TAG: { case SCHEMA_ACTION_ADD_TAG: {
@ -328,7 +395,22 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf
result+n, capacity-n, &outBytes); result+n, capacity-n, &outBytes);
TAOS_RES* res = taos_query(taos, result); //TODO async doAsyncQuery TAOS_RES* res = taos_query(taos, result); //TODO async doAsyncQuery
code = taos_errno(res); code = taos_errno(res);
char* errStr = taos_errstr(res);
char* begin = strstr(errStr, "duplicated column names");
bool tscDupColNames = (begin != NULL);
if (code != TSDB_CODE_SUCCESS) {
tscError("SML:0x%"PRIx64" apply schema action. error : %s", info->id, taos_errstr(res));
}
taos_free_result(res); taos_free_result(res);
if (code == TSDB_CODE_MND_TAG_ALREAY_EXIST || code == TSDB_CODE_MND_FIELD_ALREAY_EXIST || tscDupColNames) {
TAOS_RES* res2 = taos_query(taos, "RESET QUERY CACHE");
code = taos_errno(res2);
if (code != TSDB_CODE_SUCCESS) {
tscError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2));
}
taos_free_result(res2);
}
break; break;
} }
case SCHEMA_ACTION_CHANGE_COLUMN_SIZE: { case SCHEMA_ACTION_CHANGE_COLUMN_SIZE: {
@ -337,7 +419,19 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf
capacity-n, &outBytes); capacity-n, &outBytes);
TAOS_RES* res = taos_query(taos, result); //TODO async doAsyncQuery TAOS_RES* res = taos_query(taos, result); //TODO async doAsyncQuery
code = taos_errno(res); code = taos_errno(res);
if (code != TSDB_CODE_SUCCESS) {
tscError("SML:0x%"PRIx64" apply schema action. error : %s", info->id, taos_errstr(res));
}
taos_free_result(res); taos_free_result(res);
if (code == TSDB_CODE_MND_INVALID_COLUMN_LENGTH || code == TSDB_CODE_TSC_INVALID_COLUMN_LENGTH) {
TAOS_RES* res2 = taos_query(taos, "RESET QUERY CACHE");
code = taos_errno(res2);
if (code != TSDB_CODE_SUCCESS) {
tscError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2));
}
taos_free_result(res2);
}
break; break;
} }
case SCHEMA_ACTION_CHANGE_TAG_SIZE: { case SCHEMA_ACTION_CHANGE_TAG_SIZE: {
@ -346,7 +440,19 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf
capacity-n, &outBytes); capacity-n, &outBytes);
TAOS_RES* res = taos_query(taos, result); //TODO async doAsyncQuery TAOS_RES* res = taos_query(taos, result); //TODO async doAsyncQuery
code = taos_errno(res); code = taos_errno(res);
if (code != TSDB_CODE_SUCCESS) {
tscError("SML:0x%"PRIx64" apply schema action. error : %s", info->id, taos_errstr(res));
}
taos_free_result(res); taos_free_result(res);
if (code == TSDB_CODE_MND_INVALID_TAG_LENGTH || code == TSDB_CODE_TSC_INVALID_TAG_LENGTH) {
TAOS_RES* res2 = taos_query(taos, "RESET QUERY CACHE");
code = taos_errno(res2);
if (code != TSDB_CODE_SUCCESS) {
tscError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2));
}
taos_free_result(res2);
}
break; break;
} }
case SCHEMA_ACTION_CREATE_STABLE: { case SCHEMA_ACTION_CREATE_STABLE: {
@ -375,7 +481,19 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf
outBytes = snprintf(pos, freeBytes, ")"); outBytes = snprintf(pos, freeBytes, ")");
TAOS_RES* res = taos_query(taos, result); TAOS_RES* res = taos_query(taos, result);
code = taos_errno(res); code = taos_errno(res);
if (code != TSDB_CODE_SUCCESS) {
tscError("SML:0x%"PRIx64" apply schema action. error : %s", info->id, taos_errstr(res));
}
taos_free_result(res); taos_free_result(res);
if (code == TSDB_CODE_MND_TABLE_ALREADY_EXIST) {
TAOS_RES* res2 = taos_query(taos, "RESET QUERY CACHE");
code = taos_errno(res2);
if (code != TSDB_CODE_SUCCESS) {
tscError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2));
}
taos_free_result(res2);
}
break; break;
} }
@ -385,7 +503,7 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf
free(result); free(result);
if (code != 0) { if (code != 0) {
tscError("SML:0x%"PRIx64 "apply schema action failure. %s", info->id, tstrerror(code)); tscError("SML:0x%"PRIx64 " apply schema action failure. %s", info->id, tstrerror(code));
} }
return code; return code;
} }
@ -398,70 +516,12 @@ static int32_t destroySmlSTableSchema(SSmlSTableSchema* schema) {
return 0; return 0;
} }
int32_t loadTableMeta(TAOS* taos, char* tableName, SSmlSTableSchema* schema, SSmlLinesInfo* info) { static int32_t fillDbSchema(STableMeta* tableMeta, char* tableName, SSmlSTableSchema* schema, SSmlLinesInfo* info) {
int32_t code = 0;
STscObj *pObj = (STscObj *)taos;
if (pObj == NULL || pObj->signature != pObj) {
terrno = TSDB_CODE_TSC_DISCONNECTED;
return TSDB_CODE_TSC_DISCONNECTED;
}
tscDebug("SML:0x%"PRIx64" load table schema. super table name: %s", info->id, tableName);
char tableNameLowerCase[TSDB_TABLE_NAME_LEN];
strtolower(tableNameLowerCase, tableName);
char sql[256];
snprintf(sql, 256, "describe %s", tableNameLowerCase);
TAOS_RES* res = taos_query(taos, sql);
code = taos_errno(res);
if (code != 0) {
tscError("SML:0x%"PRIx64" describe table failure. %s", info->id, taos_errstr(res));
taos_free_result(res);
return code;
}
taos_free_result(res);
SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
if (pSql == NULL){
tscError("failed to allocate memory, reason:%s", strerror(errno));
code = TSDB_CODE_TSC_OUT_OF_MEMORY;
return code;
}
pSql->pTscObj = taos;
pSql->signature = pSql;
pSql->fp = NULL;
SStrToken tableToken = {.z=tableNameLowerCase, .n=(uint32_t)strlen(tableNameLowerCase), .type=TK_ID};
tGetToken(tableNameLowerCase, &tableToken.type);
// Check if the table name available or not
if (tscValidateName(&tableToken) != TSDB_CODE_SUCCESS) {
code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
sprintf(pSql->cmd.payload, "table name is invalid");
tscFreeSqlObj(pSql);
return code;
}
SName sname = {0};
if ((code = tscSetTableFullName(&sname, &tableToken, pSql)) != TSDB_CODE_SUCCESS) {
tscFreeSqlObj(pSql);
return code;
}
char fullTableName[TSDB_TABLE_FNAME_LEN] = {0};
memset(fullTableName, 0, tListLen(fullTableName));
tNameExtractFullName(&sname, fullTableName);
tscFreeSqlObj(pSql);
schema->tags = taosArrayInit(8, sizeof(SSchema)); schema->tags = taosArrayInit(8, sizeof(SSchema));
schema->fields = taosArrayInit(64, sizeof(SSchema)); schema->fields = taosArrayInit(64, sizeof(SSchema));
schema->tagHash = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false); schema->tagHash = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false);
schema->fieldHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false); schema->fieldHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false);
size_t size = 0;
STableMeta* tableMeta = NULL;
taosHashGetCloneExt(tscTableMetaMap, fullTableName, strlen(fullTableName), NULL, (void **)&tableMeta, &size);
tstrncpy(schema->sTableName, tableName, strlen(tableName)+1); tstrncpy(schema->sTableName, tableName, strlen(tableName)+1);
schema->precision = tableMeta->tableInfo.precision; schema->precision = tableMeta->tableInfo.precision;
for (int i=0; i<tableMeta->tableInfo.numOfColumns; ++i) { for (int i=0; i<tableMeta->tableInfo.numOfColumns; ++i) {
@ -484,9 +544,93 @@ int32_t loadTableMeta(TAOS* taos, char* tableName, SSmlSTableSchema* schema, SSm
size_t tagIndex = taosArrayGetSize(schema->tags) - 1; size_t tagIndex = taosArrayGetSize(schema->tags) - 1;
taosHashPut(schema->tagHash, field.name, strlen(field.name), &tagIndex, sizeof(tagIndex)); taosHashPut(schema->tagHash, field.name, strlen(field.name), &tagIndex, sizeof(tagIndex));
} }
tscDebug("SML:0x%"PRIx64 " load table meta succeed. table name: %s, columns number: %d, tag number: %d, precision: %d", tscDebug("SML:0x%"PRIx64 " load table schema succeed. table name: %s, columns number: %d, tag number: %d, precision: %d",
info->id, tableName, tableMeta->tableInfo.numOfColumns, tableMeta->tableInfo.numOfTags, schema->precision); info->id, tableName, tableMeta->tableInfo.numOfColumns, tableMeta->tableInfo.numOfTags, schema->precision);
free(tableMeta); tableMeta = NULL; return TSDB_CODE_SUCCESS;
}
static int32_t retrieveTableMeta(TAOS* taos, char* tableName, STableMeta** pTableMeta, SSmlLinesInfo* info) {
int32_t code = 0;
int32_t retries = 0;
STableMeta* tableMeta = NULL;
while (retries++ < TSDB_MAX_REPLICA && tableMeta == NULL) {
STscObj* pObj = (STscObj*)taos;
if (pObj == NULL || pObj->signature != pObj) {
terrno = TSDB_CODE_TSC_DISCONNECTED;
return TSDB_CODE_TSC_DISCONNECTED;
}
tscDebug("SML:0x%" PRIx64 " retrieve table meta. super table name: %s", info->id, tableName);
char tableNameLowerCase[TSDB_TABLE_NAME_LEN];
strtolower(tableNameLowerCase, tableName);
char sql[256];
snprintf(sql, 256, "describe %s", tableNameLowerCase);
TAOS_RES* res = taos_query(taos, sql);
code = taos_errno(res);
if (code != 0) {
tscError("SML:0x%" PRIx64 " describe table failure. %s", info->id, taos_errstr(res));
taos_free_result(res);
return code;
}
taos_free_result(res);
SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
if (pSql == NULL) {
tscError("SML:0x%" PRIx64 " failed to allocate memory, reason:%s", info->id, strerror(errno));
code = TSDB_CODE_TSC_OUT_OF_MEMORY;
return code;
}
pSql->pTscObj = taos;
pSql->signature = pSql;
pSql->fp = NULL;
registerSqlObj(pSql);
SStrToken tableToken = {.z = tableNameLowerCase, .n = (uint32_t)strlen(tableNameLowerCase), .type = TK_ID};
tGetToken(tableNameLowerCase, &tableToken.type);
// Check if the table name available or not
if (tscValidateName(&tableToken) != TSDB_CODE_SUCCESS) {
code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
sprintf(pSql->cmd.payload, "table name is invalid");
tscFreeRegisteredSqlObj(pSql);
return code;
}
SName sname = {0};
if ((code = tscSetTableFullName(&sname, &tableToken, pSql)) != TSDB_CODE_SUCCESS) {
tscFreeRegisteredSqlObj(pSql);
return code;
}
char fullTableName[TSDB_TABLE_FNAME_LEN] = {0};
memset(fullTableName, 0, tListLen(fullTableName));
tNameExtractFullName(&sname, fullTableName);
tscFreeRegisteredSqlObj(pSql);
size_t size = 0;
taosHashGetCloneExt(tscTableMetaMap, fullTableName, strlen(fullTableName), NULL, (void**)&tableMeta, &size);
}
if (tableMeta != NULL) {
*pTableMeta = tableMeta;
return TSDB_CODE_SUCCESS;
} else {
tscError("SML:0x%" PRIx64 " failed to retrieve table meta. super table name: %s", info->id, tableName);
return TSDB_CODE_TSC_NO_META_CACHED;
}
}
static int32_t loadTableSchemaFromDB(TAOS* taos, char* tableName, SSmlSTableSchema* schema, SSmlLinesInfo* info) {
int32_t code = 0;
STableMeta* tableMeta = NULL;
code = retrieveTableMeta(taos, tableName, &tableMeta, info);
if (code == TSDB_CODE_SUCCESS) {
assert(tableMeta != NULL);
fillDbSchema(tableMeta, tableName, schema, info);
free(tableMeta);
tableMeta = NULL;
}
return code; return code;
} }
@ -498,7 +642,7 @@ static int32_t modifyDBSchemas(TAOS* taos, SArray* stableSchemas, SSmlLinesInfo*
SSmlSTableSchema dbSchema; SSmlSTableSchema dbSchema;
memset(&dbSchema, 0, sizeof(SSmlSTableSchema)); memset(&dbSchema, 0, sizeof(SSmlSTableSchema));
code = loadTableMeta(taos, pointSchema->sTableName, &dbSchema, info); code = loadTableSchemaFromDB(taos, pointSchema->sTableName, &dbSchema, info);
if (code == TSDB_CODE_MND_INVALID_TABLE_NAME) { if (code == TSDB_CODE_MND_INVALID_TABLE_NAME) {
SSchemaAction schemaAction = {0}; SSchemaAction schemaAction = {0};
schemaAction.action = SCHEMA_ACTION_CREATE_STABLE; schemaAction.action = SCHEMA_ACTION_CREATE_STABLE;
@ -507,7 +651,7 @@ static int32_t modifyDBSchemas(TAOS* taos, SArray* stableSchemas, SSmlLinesInfo*
schemaAction.createSTable.tags = pointSchema->tags; schemaAction.createSTable.tags = pointSchema->tags;
schemaAction.createSTable.fields = pointSchema->fields; schemaAction.createSTable.fields = pointSchema->fields;
applySchemaAction(taos, &schemaAction, info); applySchemaAction(taos, &schemaAction, info);
code = loadTableMeta(taos, pointSchema->sTableName, &dbSchema, info); code = loadTableSchemaFromDB(taos, pointSchema->sTableName, &dbSchema, info);
if (code != 0) { if (code != 0) {
tscError("SML:0x%"PRIx64" reconcile point schema failed. can not create %s", info->id, pointSchema->sTableName); tscError("SML:0x%"PRIx64" reconcile point schema failed. can not create %s", info->id, pointSchema->sTableName);
return code; return code;
@ -567,74 +711,6 @@ static int32_t modifyDBSchemas(TAOS* taos, SArray* stableSchemas, SSmlLinesInfo*
return 0; return 0;
} }
static int32_t getSmlMd5ChildTableName(TAOS_SML_DATA_POINT* point, char* tableName, int* tableNameLen,
SSmlLinesInfo* info) {
tscDebug("SML:0x%"PRIx64" taos_sml_insert get child table name through md5", info->id);
qsort(point->tags, point->tagNum, sizeof(TAOS_SML_KV), compareSmlColKv);
SStringBuilder sb; memset(&sb, 0, sizeof(sb));
char sTableName[TSDB_TABLE_NAME_LEN] = {0};
strtolower(sTableName, point->stableName);
taosStringBuilderAppendString(&sb, sTableName);
for (int j = 0; j < point->tagNum; ++j) {
taosStringBuilderAppendChar(&sb, ',');
TAOS_SML_KV* tagKv = point->tags + j;
char tagName[TSDB_COL_NAME_LEN] = {0};
strtolower(tagName, tagKv->key);
taosStringBuilderAppendString(&sb, tagName);
taosStringBuilderAppendChar(&sb, '=');
taosStringBuilderAppend(&sb, tagKv->value, tagKv->length);
}
size_t len = 0;
char* keyJoined = taosStringBuilderGetResult(&sb, &len);
MD5_CTX context;
MD5Init(&context);
MD5Update(&context, (uint8_t *)keyJoined, (uint32_t)len);
MD5Final(&context);
*tableNameLen = snprintf(tableName, *tableNameLen,
"t_%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", context.digest[0],
context.digest[1], context.digest[2], context.digest[3], context.digest[4], context.digest[5], context.digest[6],
context.digest[7], context.digest[8], context.digest[9], context.digest[10], context.digest[11],
context.digest[12], context.digest[13], context.digest[14], context.digest[15]);
taosStringBuilderDestroy(&sb);
tscDebug("SML:0x%"PRIx64" child table name: %s", info->id, tableName);
return 0;
}
static int32_t changeChildTableTagValue(TAOS* taos, const char* cTableName, const char* tagName, TAOS_BIND* bind, SSmlLinesInfo* info) {
char sql[512];
sprintf(sql, "alter table %s set tag %s=?", cTableName, tagName);
int32_t code;
TAOS_STMT* stmt = taos_stmt_init(taos);
code = taos_stmt_prepare(stmt, sql, (unsigned long)strlen(sql));
if (code != 0) {
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt));
return code;
}
code = taos_stmt_bind_param(stmt, bind);
if (code != 0) {
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt));
return code;
}
code = taos_stmt_execute(stmt);
if (code != 0) {
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt));
return code;
}
code = taos_stmt_close(stmt);
if (code != 0) {
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt));
return code;
}
return code;
}
static int32_t creatChildTableIfNotExists(TAOS* taos, const char* cTableName, const char* sTableName, static int32_t creatChildTableIfNotExists(TAOS* taos, const char* cTableName, const char* sTableName,
SArray* tagsSchema, SArray* tagsBind, SSmlLinesInfo* info) { SArray* tagsSchema, SArray* tagsBind, SSmlLinesInfo* info) {
size_t numTags = taosArrayGetSize(tagsSchema); size_t numTags = taosArrayGetSize(tagsSchema);
@ -673,28 +749,28 @@ static int32_t creatChildTableIfNotExists(TAOS* taos, const char* cTableName, co
free(sql); free(sql);
if (code != 0) { if (code != 0) {
tfree(stmt); tscError("SML:0x%"PRIx64" taos_stmt_prepare returns %d:%s", info->id, code, tstrerror(code));
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); taos_stmt_close(stmt);
return code; return code;
} }
code = taos_stmt_bind_param(stmt, TARRAY_GET_START(tagsBind)); code = taos_stmt_bind_param(stmt, TARRAY_GET_START(tagsBind));
if (code != 0) { if (code != 0) {
tfree(stmt); tscError("SML:0x%"PRIx64" taos_stmt_bind_param returns %d:%s", info->id, code, tstrerror(code));
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); taos_stmt_close(stmt);
return code; return code;
} }
code = taos_stmt_execute(stmt); code = taos_stmt_execute(stmt);
if (code != 0) { if (code != 0) {
tfree(stmt); tscError("SML:0x%"PRIx64" taos_stmt_execute returns %d:%s", info->id, code, tstrerror(code));
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); taos_stmt_close(stmt);
return code; return code;
} }
code = taos_stmt_close(stmt); code = taos_stmt_close(stmt);
if (code != 0) { if (code != 0) {
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); tscError("SML:0x%"PRIx64" taos_stmt_close return %d:%s", info->id, code, tstrerror(code));
return code; return code;
} }
return code; return code;
@ -726,27 +802,29 @@ static int32_t insertChildTableBatch(TAOS* taos, char* cTableName, SArray* cols
tscDebug("SML:0x%"PRIx64" insert rows into child table %s. num of rows: %zu", info->id, cTableName, taosArrayGetSize(rowsBind)); tscDebug("SML:0x%"PRIx64" insert rows into child table %s. num of rows: %zu", info->id, cTableName, taosArrayGetSize(rowsBind));
int32_t code = 0; int32_t code = 0;
int32_t try = 0;
TAOS_STMT* stmt = taos_stmt_init(taos); TAOS_STMT* stmt = taos_stmt_init(taos);
if (stmt == NULL) { if (stmt == NULL) {
tfree(sql); tfree(sql);
return TSDB_CODE_TSC_OUT_OF_MEMORY; return TSDB_CODE_TSC_OUT_OF_MEMORY;
} }
code = taos_stmt_prepare(stmt, sql, (unsigned long)strlen(sql)); code = taos_stmt_prepare(stmt, sql, (unsigned long)strlen(sql));
tfree(sql); tfree(sql);
if (code != 0) { if (code != 0) {
tfree(stmt); tscError("SML:0x%"PRIx64" taos_stmt_prepare return %d:%s", info->id, code, tstrerror(code));
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); taos_stmt_close(stmt);
return code; return code;
} }
bool tryAgain = false;
int32_t try = 0;
do { do {
code = taos_stmt_set_tbname(stmt, cTableName); code = taos_stmt_set_tbname(stmt, cTableName);
if (code != 0) { if (code != 0) {
tfree(stmt); tscError("SML:0x%"PRIx64" taos_stmt_set_tbname return %d:%s", info->id, code, tstrerror(code));
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); taos_stmt_close(stmt);
return code; return code;
} }
@ -755,31 +833,52 @@ static int32_t insertChildTableBatch(TAOS* taos, char* cTableName, SArray* cols
TAOS_BIND* colsBinds = taosArrayGetP(rowsBind, i); TAOS_BIND* colsBinds = taosArrayGetP(rowsBind, i);
code = taos_stmt_bind_param(stmt, colsBinds); code = taos_stmt_bind_param(stmt, colsBinds);
if (code != 0) { if (code != 0) {
tfree(stmt); tscError("SML:0x%"PRIx64" taos_stmt_bind_param return %d:%s", info->id, code, tstrerror(code));
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); taos_stmt_close(stmt);
return code; return code;
} }
code = taos_stmt_add_batch(stmt); code = taos_stmt_add_batch(stmt);
if (code != 0) { if (code != 0) {
tfree(stmt); tscError("SML:0x%"PRIx64" taos_stmt_add_batch return %d:%s", info->id, code, tstrerror(code));
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); taos_stmt_close(stmt);
return code; return code;
} }
} }
code = taos_stmt_execute(stmt); code = taos_stmt_execute(stmt);
if (code != 0) { if (code != 0) {
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); tscError("SML:0x%"PRIx64" taos_stmt_execute return %d:%s, try:%d", info->id, code, tstrerror(code), try);
}
} while (code == TSDB_CODE_TDB_TABLE_RECONFIGURE && try++ < TSDB_MAX_REPLICA);
if (code != 0) {
tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
} else {
taos_stmt_close(stmt);
} }
tryAgain = false;
if ((code == TSDB_CODE_TDB_INVALID_TABLE_ID
|| code == TSDB_CODE_VND_INVALID_VGROUP_ID
|| code == TSDB_CODE_TDB_TABLE_RECONFIGURE
|| code == TSDB_CODE_APP_NOT_READY
|| code == TSDB_CODE_RPC_NETWORK_UNAVAIL) && try++ < TSDB_MAX_REPLICA) {
tryAgain = true;
}
if (code == TSDB_CODE_TDB_INVALID_TABLE_ID || code == TSDB_CODE_VND_INVALID_VGROUP_ID) {
TAOS_RES* res2 = taos_query(taos, "RESET QUERY CACHE");
int32_t code2 = taos_errno(res2);
if (code2 != TSDB_CODE_SUCCESS) {
tscError("SML:0x%" PRIx64 " insert child table. reset query cache. error: %s", info->id, taos_errstr(res2));
}
taos_free_result(res2);
if (tryAgain) {
taosMsleep(50 * (2 << try));
}
}
if (code == TSDB_CODE_APP_NOT_READY || code == TSDB_CODE_RPC_NETWORK_UNAVAIL) {
if (tryAgain) {
taosMsleep( 50 * (2 << try));
}
}
} while (tryAgain);
taos_stmt_close(stmt);
return code; return code;
} }
@ -787,16 +886,10 @@ static int32_t arrangePointsByChildTableName(TAOS_SML_DATA_POINT* points, int nu
SHashObj* cname2points, SArray* stableSchemas, SSmlLinesInfo* info) { SHashObj* cname2points, SArray* stableSchemas, SSmlLinesInfo* info) {
for (int32_t i = 0; i < numPoints; ++i) { for (int32_t i = 0; i < numPoints; ++i) {
TAOS_SML_DATA_POINT * point = points + i; TAOS_SML_DATA_POINT * point = points + i;
if (!point->childTableName) { uintptr_t valPointer = (uintptr_t)point;
char childTableName[TSDB_TABLE_NAME_LEN]; size_t* pSchemaIndex = taosHashGet(info->smlDataToSchema, &valPointer, sizeof(uintptr_t));
int32_t tableNameLen = TSDB_TABLE_NAME_LEN; assert(pSchemaIndex != NULL);
getSmlMd5ChildTableName(point, childTableName, &tableNameLen, info); SSmlSTableSchema* stableSchema = taosArrayGet(stableSchemas, *pSchemaIndex);
point->childTableName = calloc(1, tableNameLen+1);
strncpy(point->childTableName, childTableName, tableNameLen);
point->childTableName[tableNameLen] = '\0';
}
SSmlSTableSchema* stableSchema = taosArrayGet(stableSchemas, point->schemaIdx);
for (int j = 0; j < point->tagNum; ++j) { for (int j = 0; j < point->tagNum; ++j) {
TAOS_SML_KV* kv = point->tags + j; TAOS_SML_KV* kv = point->tags + j;
@ -840,16 +933,10 @@ static int32_t applyChildTableTags(TAOS* taos, char* cTableName, char* sTableNam
TAOS_SML_DATA_POINT * pDataPoint = taosArrayGetP(cTablePoints, i); TAOS_SML_DATA_POINT * pDataPoint = taosArrayGetP(cTablePoints, i);
for (int j = 0; j < pDataPoint->tagNum; ++j) { for (int j = 0; j < pDataPoint->tagNum; ++j) {
TAOS_SML_KV* kv = pDataPoint->tags + j; TAOS_SML_KV* kv = pDataPoint->tags + j;
tagKVs[kv->fieldSchemaIdx] = kv; uintptr_t valPointer = (uintptr_t)kv;
} size_t* pFieldSchemaIdx = taosHashGet(info->smlDataToSchema, &valPointer, sizeof(uintptr_t));
} assert(pFieldSchemaIdx != NULL);
tagKVs[*pFieldSchemaIdx] = kv;
int32_t notNullTagsIndices[TSDB_MAX_TAGS] = {0};
int32_t numNotNullTags = 0;
for (int32_t i = 0; i < numTags; ++i) {
if (tagKVs[i] != NULL) {
notNullTagsIndices[numNotNullTags] = i;
++numNotNullTags;
} }
} }
@ -863,7 +950,10 @@ static int32_t applyChildTableTags(TAOS* taos, char* cTableName, char* sTableNam
for (int j = 0; j < numTags; ++j) { for (int j = 0; j < numTags; ++j) {
if (tagKVs[j] == NULL) continue; if (tagKVs[j] == NULL) continue;
TAOS_SML_KV* kv = tagKVs[j]; TAOS_SML_KV* kv = tagKVs[j];
TAOS_BIND* bind = taosArrayGet(tagBinds, kv->fieldSchemaIdx); uintptr_t valPointer = (uintptr_t)kv;
size_t* pFieldSchemaIdx = taosHashGet(info->smlDataToSchema, &valPointer, sizeof(uintptr_t));
assert(pFieldSchemaIdx != NULL);
TAOS_BIND* bind = taosArrayGet(tagBinds, *pFieldSchemaIdx);
bind->buffer_type = kv->type; bind->buffer_type = kv->type;
bind->length = malloc(sizeof(uintptr_t*)); bind->length = malloc(sizeof(uintptr_t*));
*bind->length = kv->length; *bind->length = kv->length;
@ -871,65 +961,8 @@ static int32_t applyChildTableTags(TAOS* taos, char* cTableName, char* sTableNam
bind->is_null = NULL; bind->is_null = NULL;
} }
// select tag1,tag2,... from stable where tbname in (ctable) int32_t code = creatChildTableIfNotExists(taos, cTableName, sTableName, sTableSchema->tags, tagBinds, info);
char* sql = malloc(tsMaxSQLStringLen+1);
int freeBytes = tsMaxSQLStringLen + 1;
snprintf(sql, freeBytes, "select tbname, ");
for (int i = 0; i < numNotNullTags ; ++i) {
snprintf(sql + strlen(sql), freeBytes-strlen(sql), "%s,", tagKVs[notNullTagsIndices[i]]->key);
}
snprintf(sql + strlen(sql) - 1, freeBytes - strlen(sql) + 1,
" from %s where tbname in (\'%s\')", sTableName, cTableName);
sql[strlen(sql)] = '\0';
TAOS_RES* result = taos_query(taos, sql);
free(sql);
int32_t code = taos_errno(result);
if (code != 0) {
tscError("SML:0x%"PRIx64" get child table %s tags failed. error string %s", info->id, cTableName, taos_errstr(result));
goto cleanup;
}
// check tag value and set tag values if different
TAOS_ROW row = taos_fetch_row(result);
if (row != NULL) {
int numFields = taos_field_count(result);
TAOS_FIELD* fields = taos_fetch_fields(result);
int* lengths = taos_fetch_lengths(result);
for (int i = 1; i < numFields; ++i) {
uint8_t dbType = fields[i].type;
int32_t length = lengths[i];
char* val = row[i];
TAOS_SML_KV* tagKV = tagKVs[notNullTagsIndices[i-1]];
if (tagKV->type != dbType) {
tscError("SML:0x%"PRIx64" child table %s tag %s type mismatch. point type : %d, db type : %d",
info->id, cTableName, tagKV->key, tagKV->type, dbType);
return TSDB_CODE_TSC_INVALID_VALUE;
}
assert(tagKV->value);
if (val == NULL || length != tagKV->length || memcmp(tagKV->value, val, length) != 0) {
TAOS_BIND* bind = taosArrayGet(tagBinds, tagKV->fieldSchemaIdx);
code = changeChildTableTagValue(taos, cTableName, tagKV->key, bind, info);
if (code != 0) {
tscError("SML:0x%"PRIx64" change child table tag failed. table name %s, tag %s", info->id, cTableName, tagKV->key);
goto cleanup;
}
}
}
tscDebug("SML:0x%"PRIx64" successfully applied point tags. child table: %s", info->id, cTableName);
} else {
code = creatChildTableIfNotExists(taos, cTableName, sTableName, sTableSchema->tags, tagBinds, info);
if (code != 0) {
goto cleanup;
}
}
cleanup:
taos_free_result(result);
for (int i = 0; i < taosArrayGetSize(tagBinds); ++i) { for (int i = 0; i < taosArrayGetSize(tagBinds); ++i) {
TAOS_BIND* bind = taosArrayGet(tagBinds, i); TAOS_BIND* bind = taosArrayGet(tagBinds, i);
free(bind->length); free(bind->length);
@ -963,7 +996,10 @@ static int32_t applyChildTableFields(TAOS* taos, SSmlSTableSchema* sTableSchema,
} }
for (int j = 0; j < point->fieldNum; ++j) { for (int j = 0; j < point->fieldNum; ++j) {
TAOS_SML_KV* kv = point->fields + j; TAOS_SML_KV* kv = point->fields + j;
TAOS_BIND* bind = colBinds + kv->fieldSchemaIdx; uintptr_t valPointer = (uintptr_t)kv;
size_t* pFieldSchemaIdx = taosHashGet(info->smlDataToSchema, &valPointer, sizeof(uintptr_t));
assert(pFieldSchemaIdx != NULL);
TAOS_BIND* bind = colBinds + *pFieldSchemaIdx;
bind->buffer_type = kv->type; bind->buffer_type = kv->type;
bind->length = malloc(sizeof(uintptr_t*)); bind->length = malloc(sizeof(uintptr_t*));
*bind->length = kv->length; *bind->length = kv->length;
@ -1000,9 +1036,11 @@ static int32_t applyDataPoints(TAOS* taos, TAOS_SML_DATA_POINT* points, int32_t
while (pCTablePoints) { while (pCTablePoints) {
SArray* cTablePoints = *pCTablePoints; SArray* cTablePoints = *pCTablePoints;
TAOS_SML_DATA_POINT* point = taosArrayGetP(cTablePoints, 0); TAOS_SML_DATA_POINT* point = taosArrayGetP(cTablePoints, 0);
SSmlSTableSchema* sTableSchema = taosArrayGet(stableSchemas, point->schemaIdx); uintptr_t valPointer = (uintptr_t)point;
size_t* pSchemaIndex = taosHashGet(info->smlDataToSchema, &valPointer, sizeof(uintptr_t));
assert(pSchemaIndex != NULL);
SSmlSTableSchema* sTableSchema = taosArrayGet(stableSchemas, *pSchemaIndex);
tscDebug("SML:0x%"PRIx64" apply child table tags. child table: %s", info->id, point->childTableName); tscDebug("SML:0x%"PRIx64" apply child table tags. child table: %s", info->id, point->childTableName);
code = applyChildTableTags(taos, point->childTableName, point->stableName, sTableSchema, cTablePoints, info); code = applyChildTableTags(taos, point->childTableName, point->stableName, sTableSchema, cTablePoints, info);
@ -1014,7 +1052,7 @@ static int32_t applyDataPoints(TAOS* taos, TAOS_SML_DATA_POINT* points, int32_t
tscDebug("SML:0x%"PRIx64" apply child table points. child table: %s", info->id, point->childTableName); tscDebug("SML:0x%"PRIx64" apply child table points. child table: %s", info->id, point->childTableName);
code = applyChildTableFields(taos, sTableSchema, point->childTableName, cTablePoints, info); code = applyChildTableFields(taos, sTableSchema, point->childTableName, cTablePoints, info);
if (code != 0) { if (code != 0) {
tscError("Apply child table fields failed. child table %s, error %s", point->childTableName, tstrerror(code)); tscError("SML:0x%"PRIx64" Apply child table fields failed. child table %s, error %s", info->id, point->childTableName, tstrerror(code));
goto cleanup; goto cleanup;
} }
@ -1034,10 +1072,11 @@ cleanup:
return code; return code;
} }
int taos_sml_insert(TAOS* taos, TAOS_SML_DATA_POINT* points, int numPoint, SSmlLinesInfo* info) { int tscSmlInsert(TAOS* taos, TAOS_SML_DATA_POINT* points, int numPoint, SSmlLinesInfo* info) {
tscDebug("SML:0x%"PRIx64" taos_sml_insert. number of points: %d", info->id, numPoint); tscDebug("SML:0x%"PRIx64" taos_sml_insert. number of points: %d", info->id, numPoint);
int32_t code = TSDB_CODE_SUCCESS; int32_t code = TSDB_CODE_SUCCESS;
info->smlDataToSchema = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), true, false);
tscDebug("SML:0x%"PRIx64" build data point schemas", info->id); tscDebug("SML:0x%"PRIx64" build data point schemas", info->id);
SArray* stableSchemas = taosArrayInit(32, sizeof(SSmlSTableSchema)); // SArray<STableColumnsSchema> SArray* stableSchemas = taosArrayInit(32, sizeof(SSmlSTableSchema)); // SArray<STableColumnsSchema>
@ -1067,6 +1106,15 @@ clean_up:
taosArrayDestroy(schema->tags); taosArrayDestroy(schema->tags);
} }
taosArrayDestroy(stableSchemas); taosArrayDestroy(stableSchemas);
taosHashCleanup(info->smlDataToSchema);
return code;
}
int taos_sml_insert(TAOS* taos, TAOS_SML_DATA_POINT* points, int numPoint) {
SSmlLinesInfo* info = calloc(1, sizeof(SSmlLinesInfo));
info->id = genLinesSmlId();
int code = tscSmlInsert(taos, points, numPoint, info);
free(info);
return code; return code;
} }
@ -2076,18 +2124,6 @@ int32_t tscParseLine(const char* sql, TAOS_SML_DATA_POINT* smlData, SSmlLinesInf
//========================================================================= //=========================================================================
static uint64_t linesSmlHandleId = 0;
uint64_t genLinesSmlId() {
uint64_t id;
do {
id = atomic_add_fetch_64(&linesSmlHandleId, 1);
} while (id == 0);
return id;
}
void destroySmlDataPoint(TAOS_SML_DATA_POINT* point) { void destroySmlDataPoint(TAOS_SML_DATA_POINT* point) {
for (int i=0; i<point->tagNum; ++i) { for (int i=0; i<point->tagNum; ++i) {
free((point->tags+i)->key); free((point->tags+i)->key);
@ -2157,7 +2193,7 @@ int taos_insert_lines(TAOS* taos, char* lines[], int numLines) {
} }
TAOS_SML_DATA_POINT* points = TARRAY_GET_START(lpPoints); TAOS_SML_DATA_POINT* points = TARRAY_GET_START(lpPoints);
code = taos_sml_insert(taos, points, (int)numPoints, info); code = tscSmlInsert(taos, points, (int)numPoints, info);
if (code != 0) { if (code != 0) {
tscError("SML:0x%"PRIx64" taos_sml_insert error: %s", info->id, tstrerror((code))); tscError("SML:0x%"PRIx64" taos_sml_insert error: %s", info->id, tstrerror((code)));
} }

View File

@ -206,6 +206,8 @@ static int normalStmtPrepare(STscStmt* stmt) {
return code; return code;
} }
start = i + token.n; start = i + token.n;
} else if (token.type == TK_ILLEGAL) {
return invalidOperationMsg(tscGetErrorMsgPayload(&stmt->pSql->cmd), "invalid sql");
} }
i += token.n; i += token.n;
@ -1538,6 +1540,8 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
pRes->qId = 0; pRes->qId = 0;
pRes->numOfRows = 1; pRes->numOfRows = 1;
registerSqlObj(pSql);
strtolower(pSql->sqlstr, sql); strtolower(pSql->sqlstr, sql);
tscDebugL("0x%"PRIx64" SQL: %s", pSql->self, pSql->sqlstr); tscDebugL("0x%"PRIx64" SQL: %s", pSql->self, pSql->sqlstr);
@ -1547,8 +1551,6 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
pSql->cmd.insertParam.numOfParams = 0; pSql->cmd.insertParam.numOfParams = 0;
pSql->cmd.batchSize = 0; pSql->cmd.batchSize = 0;
registerSqlObj(pSql);
int32_t ret = stmtParseInsertTbTags(pSql, pStmt); int32_t ret = stmtParseInsertTbTags(pSql, pStmt);
if (ret != TSDB_CODE_SUCCESS) { if (ret != TSDB_CODE_SUCCESS) {
STMT_RET(ret); STMT_RET(ret);

View File

@ -40,7 +40,6 @@
#include "qScript.h" #include "qScript.h"
#include "ttype.h" #include "ttype.h"
#include "qFilter.h" #include "qFilter.h"
#include "httpInt.h"
#define DEFAULT_PRIMARY_TIMESTAMP_COL_NAME "_c0" #define DEFAULT_PRIMARY_TIMESTAMP_COL_NAME "_c0"
@ -72,7 +71,6 @@ static int convertTimestampStrToInt64(tVariant *pVar, int32_t precision);
static bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType, uint8_t precision); static bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType, uint8_t precision);
static bool has(SArray* pFieldList, int32_t startIdx, const char* name); static bool has(SArray* pFieldList, int32_t startIdx, const char* name);
static char* cloneCurrentDBName(SSqlObj* pSql);
static int32_t getDelimiterIndex(SStrToken* pTableName); static int32_t getDelimiterIndex(SStrToken* pTableName);
static bool validateTableColumnInfo(SArray* pFieldList, SSqlCmd* pCmd); static bool validateTableColumnInfo(SArray* pFieldList, SSqlCmd* pCmd);
static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pCmd); static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pCmd);
@ -117,7 +115,7 @@ static int32_t validateColumnName(char* name);
static int32_t setKillInfo(SSqlObj* pSql, struct SSqlInfo* pInfo, int32_t killType); static int32_t setKillInfo(SSqlObj* pSql, struct SSqlInfo* pInfo, int32_t killType);
static int32_t setCompactVnodeInfo(SSqlObj* pSql, struct SSqlInfo* pInfo); static int32_t setCompactVnodeInfo(SSqlObj* pSql, struct SSqlInfo* pInfo);
static bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField); static int32_t validateOneTag(SSqlCmd* pCmd, TAOS_FIELD* pTagField);
static bool hasTimestampForPointInterpQuery(SQueryInfo* pQueryInfo); static bool hasTimestampForPointInterpQuery(SQueryInfo* pQueryInfo);
static bool hasNormalColumnFilter(SQueryInfo* pQueryInfo); static bool hasNormalColumnFilter(SQueryInfo* pQueryInfo);
@ -427,13 +425,12 @@ int32_t readFromFile(char *name, uint32_t *len, void **buf) {
return TSDB_CODE_TSC_APP_ERROR; return TSDB_CODE_TSC_APP_ERROR;
} }
close(fd); close(fd);
tfree(*buf);
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
int32_t handleUserDefinedFunc(SSqlObj* pSql, struct SSqlInfo* pInfo) { int32_t handleUserDefinedFunc(SSqlObj* pSql, struct SSqlInfo* pInfo) {
const char *msg1 = "function name is too long"; const char *msg1 = "invalidate function name";
const char *msg2 = "path is too long"; const char *msg2 = "path is too long";
const char *msg3 = "invalid outputtype"; const char *msg3 = "invalid outputtype";
const char *msg4 = "invalid script"; const char *msg4 = "invalid script";
@ -450,7 +447,10 @@ int32_t handleUserDefinedFunc(SSqlObj* pSql, struct SSqlInfo* pInfo) {
} }
createInfo->name.z[createInfo->name.n] = 0; createInfo->name.z[createInfo->name.n] = 0;
// funcname's naming rule is same to column
if (validateColumnName(createInfo->name.z) != TSDB_CODE_SUCCESS) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
strdequote(createInfo->name.z); strdequote(createInfo->name.z);
if (strlen(createInfo->name.z) >= TSDB_FUNC_NAME_LEN) { if (strlen(createInfo->name.z) >= TSDB_FUNC_NAME_LEN) {
@ -893,6 +893,7 @@ int32_t tscValidateSqlInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
} }
case TSDB_SQL_SELECT: { case TSDB_SQL_SELECT: {
const char * msg1 = "no nested query supported in union clause";
code = loadAllTableMeta(pSql, pInfo); code = loadAllTableMeta(pSql, pInfo);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
return code; return code;
@ -906,6 +907,10 @@ int32_t tscValidateSqlInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
tscTrace("0x%"PRIx64" start to parse the %dth subclause, total:%"PRIzu, pSql->self, i, size); tscTrace("0x%"PRIx64" start to parse the %dth subclause, total:%"PRIzu, pSql->self, i, size);
if (size > 1 && pSqlNode->from && pSqlNode->from->type == SQL_NODE_FROM_SUBQUERY) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
// normalizeSqlNode(pSqlNode); // normalize the column name in each function // normalizeSqlNode(pSqlNode); // normalize the column name in each function
if ((code = validateSqlNode(pSql, pSqlNode, pQueryInfo)) != TSDB_CODE_SUCCESS) { if ((code = validateSqlNode(pSql, pSqlNode, pQueryInfo)) != TSDB_CODE_SUCCESS) {
return code; return code;
@ -926,7 +931,6 @@ int32_t tscValidateSqlInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
pQueryInfo = pCmd->active; pQueryInfo = pCmd->active;
pQueryInfo->pUdfInfo = pUdfInfo; pQueryInfo->pUdfInfo = pUdfInfo;
pQueryInfo->udfCopy = true; pQueryInfo->udfCopy = true;
} }
} }
@ -1080,6 +1084,7 @@ int32_t validateIntervalNode(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNode* pS
const char* msg1 = "sliding cannot be used without interval"; const char* msg1 = "sliding cannot be used without interval";
const char* msg2 = "interval cannot be less than 1 us"; const char* msg2 = "interval cannot be less than 1 us";
const char* msg3 = "interval value is too small"; const char* msg3 = "interval value is too small";
const char* msg4 = "only point interpolation query requires keyword EVERY";
SSqlCmd* pCmd = &pSql->cmd; SSqlCmd* pCmd = &pSql->cmd;
@ -1111,7 +1116,6 @@ int32_t validateIntervalNode(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNode* pS
} }
if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit != 'y') { if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit != 'y') {
// interval cannot be less than 10 milliseconds // interval cannot be less than 10 milliseconds
if (convertTimePrecision(pQueryInfo->interval.interval, tinfo.precision, TSDB_TIME_PRECISION_MICRO) < tsMinIntervalTime) { if (convertTimePrecision(pQueryInfo->interval.interval, tinfo.precision, TSDB_TIME_PRECISION_MICRO) < tsMinIntervalTime) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
@ -1126,9 +1130,15 @@ int32_t validateIntervalNode(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNode* pS
return TSDB_CODE_TSC_INVALID_OPERATION; return TSDB_CODE_TSC_INVALID_OPERATION;
} }
bool interpQuery = tscIsPointInterpQuery(pQueryInfo);
if ((pSqlNode->interval.token == TK_EVERY && (!interpQuery)) || (pSqlNode->interval.token == TK_INTERVAL && interpQuery)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4);
}
// The following part is used to check for the invalid query expression. // The following part is used to check for the invalid query expression.
return checkInvalidExprForTimeWindow(pCmd, pQueryInfo); return checkInvalidExprForTimeWindow(pCmd, pQueryInfo);
} }
static int32_t validateStateWindowNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode, bool isStable) { static int32_t validateStateWindowNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode, bool isStable) {
const char* msg1 = "invalid column name"; const char* msg1 = "invalid column name";
@ -1535,9 +1545,7 @@ static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pC
/* /*
* tags name /column name is truncated in sql.y * tags name /column name is truncated in sql.y
*/ */
bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) { int32_t validateOneTag(SSqlCmd* pCmd, TAOS_FIELD* pTagField) {
//const char* msg1 = "timestamp not allowed in tags";
const char* msg2 = "duplicated column names";
const char* msg3 = "tag length too long"; const char* msg3 = "tag length too long";
const char* msg4 = "invalid tag name"; const char* msg4 = "invalid tag name";
const char* msg5 = "invalid binary/nchar tag length"; const char* msg5 = "invalid binary/nchar tag length";
@ -1552,8 +1560,7 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) {
// no more max columns // no more max columns
if (numOfTags + numOfCols >= TSDB_MAX_COLUMNS) { if (numOfTags + numOfCols >= TSDB_MAX_COLUMNS) {
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
return false;
} }
// no more than 6 tags // no more than 6 tags
@ -1561,8 +1568,7 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) {
char msg[128] = {0}; char msg[128] = {0};
sprintf(msg, "tags no more than %d", TSDB_MAX_TAGS); sprintf(msg, "tags no more than %d", TSDB_MAX_TAGS);
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg);
return false;
} }
// no timestamp allowable // no timestamp allowable
@ -1572,8 +1578,7 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) {
//} //}
if ((pTagField->type < TSDB_DATA_TYPE_BOOL) || (pTagField->type > TSDB_DATA_TYPE_UBIGINT)) { if ((pTagField->type < TSDB_DATA_TYPE_BOOL) || (pTagField->type > TSDB_DATA_TYPE_UBIGINT)) {
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
return false;
} }
SSchema* pTagSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta); SSchema* pTagSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);
@ -1585,20 +1590,17 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) {
// length less than TSDB_MAX_TASG_LEN // length less than TSDB_MAX_TASG_LEN
if (nLen + pTagField->bytes > TSDB_MAX_TAGS_LEN) { if (nLen + pTagField->bytes > TSDB_MAX_TAGS_LEN) {
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
return false;
} }
// tags name can not be a keyword // tags name can not be a keyword
if (validateColumnName(pTagField->name) != TSDB_CODE_SUCCESS) { if (validateColumnName(pTagField->name) != TSDB_CODE_SUCCESS) {
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4);
return false;
} }
// binary(val), val can not be equalled to or less than 0 // binary(val), val can not be equalled to or less than 0
if ((pTagField->type == TSDB_DATA_TYPE_BINARY || pTagField->type == TSDB_DATA_TYPE_NCHAR) && pTagField->bytes <= 0) { if ((pTagField->type == TSDB_DATA_TYPE_BINARY || pTagField->type == TSDB_DATA_TYPE_NCHAR) && pTagField->bytes <= 0) {
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
return false;
} }
// field name must be unique // field name must be unique
@ -1606,17 +1608,16 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) {
for (int32_t i = 0; i < numOfTags + numOfCols; ++i) { for (int32_t i = 0; i < numOfTags + numOfCols; ++i) {
if (strncasecmp(pTagField->name, pSchema[i].name, sizeof(pTagField->name) - 1) == 0) { if (strncasecmp(pTagField->name, pSchema[i].name, sizeof(pTagField->name) - 1) == 0) {
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); //return tscErrorMsgWithCode(TSDB_CODE_TSC_DUP_COL_NAMES, tscGetErrorMsgPayload(pCmd), pTagField->name, NULL);
return false; return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "duplicated column names");
} }
} }
return true; return TSDB_CODE_SUCCESS;
} }
bool validateOneColumn(SSqlCmd* pCmd, TAOS_FIELD* pColField) { int32_t validateOneColumn(SSqlCmd* pCmd, TAOS_FIELD* pColField) {
const char* msg1 = "too many columns"; const char* msg1 = "too many columns";
const char* msg2 = "duplicated column names";
const char* msg3 = "column length too long"; const char* msg3 = "column length too long";
const char* msg4 = "invalid data type"; const char* msg4 = "invalid data type";
const char* msg5 = "invalid column name"; const char* msg5 = "invalid column name";
@ -1631,18 +1632,15 @@ bool validateOneColumn(SSqlCmd* pCmd, TAOS_FIELD* pColField) {
// no more max columns // no more max columns
if (numOfCols >= TSDB_MAX_COLUMNS || numOfTags + numOfCols >= TSDB_MAX_COLUMNS) { if (numOfCols >= TSDB_MAX_COLUMNS || numOfTags + numOfCols >= TSDB_MAX_COLUMNS) {
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
return false;
} }
if (pColField->type < TSDB_DATA_TYPE_BOOL || pColField->type > TSDB_DATA_TYPE_UBIGINT) { if (pColField->type < TSDB_DATA_TYPE_BOOL || pColField->type > TSDB_DATA_TYPE_UBIGINT) {
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4);
return false;
} }
if (validateColumnName(pColField->name) != TSDB_CODE_SUCCESS) { if (validateColumnName(pColField->name) != TSDB_CODE_SUCCESS) {
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
return false;
} }
SSchema* pSchema = tscGetTableSchema(pTableMeta); SSchema* pSchema = tscGetTableSchema(pTableMeta);
@ -1653,25 +1651,23 @@ bool validateOneColumn(SSqlCmd* pCmd, TAOS_FIELD* pColField) {
} }
if (pColField->bytes <= 0) { if (pColField->bytes <= 0) {
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
return false;
} }
// length less than TSDB_MAX_BYTES_PER_ROW // length less than TSDB_MAX_BYTES_PER_ROW
if (nLen + pColField->bytes > TSDB_MAX_BYTES_PER_ROW) { if (nLen + pColField->bytes > TSDB_MAX_BYTES_PER_ROW) {
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
return false;
} }
// field name must be unique // field name must be unique
for (int32_t i = 0; i < numOfTags + numOfCols; ++i) { for (int32_t i = 0; i < numOfTags + numOfCols; ++i) {
if (strncasecmp(pColField->name, pSchema[i].name, sizeof(pColField->name) - 1) == 0) { if (strncasecmp(pColField->name, pSchema[i].name, sizeof(pColField->name) - 1) == 0) {
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); //return tscErrorMsgWithCode(TSDB_CODE_TSC_DUP_COL_NAMES, tscGetErrorMsgPayload(pCmd), pColField->name, NULL);
return false; return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "duplicated column names");
} }
} }
return true; return TSDB_CODE_SUCCESS;
} }
/* is contained in pFieldList or not */ /* is contained in pFieldList or not */
@ -1687,34 +1683,6 @@ static bool has(SArray* pFieldList, int32_t startIdx, const char* name) {
static char* getAccountId(SSqlObj* pSql) { return pSql->pTscObj->acctId; } static char* getAccountId(SSqlObj* pSql) { return pSql->pTscObj->acctId; }
static char* cloneCurrentDBName(SSqlObj* pSql) {
char *p = NULL;
HttpContext *pCtx = NULL;
pthread_mutex_lock(&pSql->pTscObj->mutex);
STscObj *pTscObj = pSql->pTscObj;
switch (pTscObj->from) {
case TAOS_REQ_FROM_HTTP:
pCtx = pSql->param;
if (pCtx && pCtx->db[0] != '\0') {
char db[TSDB_ACCT_ID_LEN + TSDB_DB_NAME_LEN] = {0};
int32_t len = sprintf(db, "%s%s%s", pTscObj->acctId, TS_PATH_DELIMITER, pCtx->db);
assert(len <= sizeof(db));
p = strdup(db);
}
break;
default:
break;
}
if (p == NULL) {
p = strdup(pSql->pTscObj->db);
}
pthread_mutex_unlock(&pSql->pTscObj->mutex);
return p;
}
/* length limitation, strstr cannot be applied */ /* length limitation, strstr cannot be applied */
static int32_t getDelimiterIndex(SStrToken* pTableName) { static int32_t getDelimiterIndex(SStrToken* pTableName) {
for (uint32_t i = 0; i < pTableName->n; ++i) { for (uint32_t i = 0; i < pTableName->n; ++i) {
@ -5103,10 +5071,6 @@ static void cleanQueryExpr(SCondExpr* pCondExpr) {
tSqlExprDestroy(pCondExpr->pTableCond); tSqlExprDestroy(pCondExpr->pTableCond);
} }
if (pCondExpr->pTagCond) {
tSqlExprDestroy(pCondExpr->pTagCond);
}
if (pCondExpr->pColumnCond) { if (pCondExpr->pColumnCond) {
tSqlExprDestroy(pCondExpr->pColumnCond); tSqlExprDestroy(pCondExpr->pColumnCond);
} }
@ -6069,7 +6033,6 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
const char* msg19 = "invalid new tag name"; const char* msg19 = "invalid new tag name";
const char* msg20 = "table is not super table"; const char* msg20 = "table is not super table";
const char* msg21 = "only binary/nchar column length could be modified"; const char* msg21 = "only binary/nchar column length could be modified";
const char* msg22 = "new column length should be bigger than old one";
const char* msg23 = "only column length coulbe be modified"; const char* msg23 = "only column length coulbe be modified";
const char* msg24 = "invalid binary/nchar column length"; const char* msg24 = "invalid binary/nchar column length";
@ -6121,8 +6084,9 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
} }
TAOS_FIELD* p = taosArrayGet(pFieldList, 0); TAOS_FIELD* p = taosArrayGet(pFieldList, 0);
if (!validateOneTags(pCmd, p)) { int32_t ret = validateOneTag(pCmd, p);
return TSDB_CODE_TSC_INVALID_OPERATION; if (ret != TSDB_CODE_SUCCESS) {
return ret;
} }
tscFieldInfoAppend(&pQueryInfo->fieldsInfo, p); tscFieldInfoAppend(&pQueryInfo->fieldsInfo, p);
@ -6299,8 +6263,9 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
} }
TAOS_FIELD* p = taosArrayGet(pFieldList, 0); TAOS_FIELD* p = taosArrayGet(pFieldList, 0);
if (!validateOneColumn(pCmd, p)) { int32_t ret = validateOneColumn(pCmd, p);
return TSDB_CODE_TSC_INVALID_OPERATION; if (ret != TSDB_CODE_SUCCESS) {
return ret;
} }
tscFieldInfoAppend(&pQueryInfo->fieldsInfo, p); tscFieldInfoAppend(&pQueryInfo->fieldsInfo, p);
@ -6363,7 +6328,7 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
} }
if (pItem->bytes <= pColSchema->bytes) { if (pItem->bytes <= pColSchema->bytes) {
return invalidOperationMsg(pMsg, msg22); return tscErrorMsgWithCode(TSDB_CODE_TSC_INVALID_COLUMN_LENGTH, pMsg, pItem->name, NULL);
} }
SSchema* pSchema = (SSchema*) pTableMetaInfo->pTableMeta->schema; SSchema* pSchema = (SSchema*) pTableMetaInfo->pTableMeta->schema;
@ -6414,7 +6379,7 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
} }
if (pItem->bytes <= pColSchema->bytes) { if (pItem->bytes <= pColSchema->bytes) {
return invalidOperationMsg(pMsg, msg22); return tscErrorMsgWithCode(TSDB_CODE_TSC_INVALID_TAG_LENGTH, pMsg, pItem->name, NULL);
} }
SSchema* pSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta); SSchema* pSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);
@ -7204,7 +7169,6 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo
const char* msg1 = "interval not allowed in group by normal column"; const char* msg1 = "interval not allowed in group by normal column";
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
SSchema* pSchema = tscGetTableSchema(pTableMetaInfo->pTableMeta); SSchema* pSchema = tscGetTableSchema(pTableMetaInfo->pTableMeta);
SSchema* tagSchema = NULL; SSchema* tagSchema = NULL;
@ -7231,8 +7195,6 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo
} }
} }
size_t size = tscNumOfExprs(pQueryInfo);
if (TSDB_COL_IS_TAG(pColIndex->flag)) { if (TSDB_COL_IS_TAG(pColIndex->flag)) {
int32_t f = TSDB_FUNC_TAG; int32_t f = TSDB_FUNC_TAG;
@ -7240,8 +7202,10 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo
f = TSDB_FUNC_TAGPRJ; f = TSDB_FUNC_TAGPRJ;
} }
int32_t pos = tscGetFirstInvisibleFieldPos(pQueryInfo);
SColumnIndex index = {.tableIndex = pQueryInfo->groupbyExpr.tableIndex, .columnIndex = colIndex}; SColumnIndex index = {.tableIndex = pQueryInfo->groupbyExpr.tableIndex, .columnIndex = colIndex};
SExprInfo* pExpr = tscExprAppend(pQueryInfo, f, &index, s->type, s->bytes, getNewResColId(pCmd), s->bytes, true); SExprInfo* pExpr = tscExprInsert(pQueryInfo, pos, f, &index, s->type, s->bytes, getNewResColId(pCmd), s->bytes, true);
memset(pExpr->base.aliasName, 0, sizeof(pExpr->base.aliasName)); memset(pExpr->base.aliasName, 0, sizeof(pExpr->base.aliasName));
tstrncpy(pExpr->base.aliasName, s->name, sizeof(pExpr->base.aliasName)); tstrncpy(pExpr->base.aliasName, s->name, sizeof(pExpr->base.aliasName));
@ -7251,13 +7215,15 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo
// NOTE: tag column does not add to source column list // NOTE: tag column does not add to source column list
SColumnList ids = createColumnList(1, 0, pColIndex->colIndex); SColumnList ids = createColumnList(1, 0, pColIndex->colIndex);
insertResultField(pQueryInfo, (int32_t)size, &ids, s->bytes, (int8_t)s->type, s->name, pExpr); insertResultField(pQueryInfo, pos, &ids, s->bytes, (int8_t)s->type, s->name, pExpr);
} else { } else {
// if this query is "group by" normal column, time window query is not allowed // if this query is "group by" normal column, time window query is not allowed
if (isTimeWindowQuery(pQueryInfo)) { if (isTimeWindowQuery(pQueryInfo)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
} }
size_t size = tscNumOfExprs(pQueryInfo);
bool hasGroupColumn = false; bool hasGroupColumn = false;
for (int32_t j = 0; j < size; ++j) { for (int32_t j = 0; j < size; ++j) {
SExprInfo* pExpr = tscExprGet(pQueryInfo, j); SExprInfo* pExpr = tscExprGet(pQueryInfo, j);
@ -8485,7 +8451,10 @@ int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) {
size_t len = strlen(name); size_t len = strlen(name);
taosHashGetCloneExt(tscTableMetaMap, name, len, NULL, (void **)&pTableMeta, &tableMetaCapacity); if (NULL == taosHashGetCloneExt(tscTableMetaMap, name, len, NULL, (void **)&pTableMeta, &tableMetaCapacity)) {
// not found
tfree(pTableMeta);
}
if (pTableMeta && pTableMeta->id.uid > 0) { if (pTableMeta && pTableMeta->id.uid > 0) {
tscDebug("0x%"PRIx64" retrieve table meta %s from local buf", pSql->self, name); tscDebug("0x%"PRIx64" retrieve table meta %s from local buf", pSql->self, name);
@ -8729,6 +8698,7 @@ static int32_t doValidateSubquery(SSqlNode* pSqlNode, int32_t index, SSqlObj* pS
if (taosArrayGetSize(subInfo->pSubquery) >= 2) { if (taosArrayGetSize(subInfo->pSubquery) >= 2) {
return invalidOperationMsg(msgBuf, "not support union in subquery"); return invalidOperationMsg(msgBuf, "not support union in subquery");
} }
SQueryInfo* pSub = calloc(1, sizeof(SQueryInfo)); SQueryInfo* pSub = calloc(1, sizeof(SQueryInfo));
tscInitQueryInfo(pSub); tscInitQueryInfo(pSub);
@ -8751,6 +8721,7 @@ static int32_t doValidateSubquery(SSqlNode* pSqlNode, int32_t index, SSqlObj* pS
if (pTableMetaInfo1 == NULL) { if (pTableMetaInfo1 == NULL) {
return TSDB_CODE_TSC_OUT_OF_MEMORY; return TSDB_CODE_TSC_OUT_OF_MEMORY;
} }
pTableMetaInfo1->pTableMeta = extractTempTableMetaFromSubquery(pSub); pTableMetaInfo1->pTableMeta = extractTempTableMetaFromSubquery(pSub);
pTableMetaInfo1->tableMetaCapacity = tscGetTableMetaSize(pTableMetaInfo1->pTableMeta); pTableMetaInfo1->tableMetaCapacity = tscGetTableMetaSize(pTableMetaInfo1->pTableMeta);
@ -8816,7 +8787,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
* select server_status(); * select server_status();
* select server_version(); * select server_version();
* select client_version(); * select client_version();
* select current_database(); * select database();
*/ */
if (pSqlNode->from == NULL) { if (pSqlNode->from == NULL) {
assert(pSqlNode->fillType == NULL && pSqlNode->pGroupby == NULL && pSqlNode->pWhere == NULL && assert(pSqlNode->fillType == NULL && pSqlNode->pGroupby == NULL && pSqlNode->pWhere == NULL &&
@ -8834,7 +8805,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
// check if there is 3 level select // check if there is 3 level select
SRelElementPair* subInfo = taosArrayGet(pSqlNode->from->list, i); SRelElementPair* subInfo = taosArrayGet(pSqlNode->from->list, i);
SSqlNode* p = taosArrayGetP(subInfo->pSubquery, 0); SSqlNode* p = taosArrayGetP(subInfo->pSubquery, 0);
if (p->from->type == SQL_NODE_FROM_SUBQUERY){ if (p->from->type == SQL_NODE_FROM_SUBQUERY) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg9); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg9);
} }
@ -8927,6 +8898,15 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
} }
} }
// disable group result mixed up if interval/session window query exists.
if (isTimeWindowQuery(pQueryInfo)) {
size_t num = taosArrayGetSize(pQueryInfo->pUpstream);
for(int32_t i = 0; i < num; ++i) {
SQueryInfo* pUp = taosArrayGetP(pQueryInfo->pUpstream, i);
pUp->multigroupResult = false;
}
}
// parse the having clause in the first place // parse the having clause in the first place
int32_t joinQuery = (pSqlNode->from != NULL && taosArrayGetSize(pSqlNode->from->list) > 1); int32_t joinQuery = (pSqlNode->from != NULL && taosArrayGetSize(pSqlNode->from->list) > 1);
if (validateHavingClause(pQueryInfo, pSqlNode->pHaving, pCmd, pSqlNode->pSelNodeList, joinQuery, timeWindowQuery) != if (validateHavingClause(pQueryInfo, pSqlNode->pHaving, pCmd, pSqlNode->pSelNodeList, joinQuery, timeWindowQuery) !=

View File

@ -332,21 +332,41 @@ int tscSendMsgToServer(SSqlObj *pSql) {
.code = 0 .code = 0
}; };
rpcSendRequest(pObj->pRpcObj->pDnodeConn, &pSql->epSet, &rpcMsg, &pSql->rpcRid); rpcSendRequest(pObj->pRpcObj->pDnodeConn, &pSql->epSet, &rpcMsg, &pSql->rpcRid);
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) { // handle three situation
SRpcMsg* rpcMsg = pSchedMsg->ahandle; // 1. epset retry, only return last failure ep
SRpcEpSet* pEpSet = pSchedMsg->thandle; // 2. no epset retry, like 'taos -h invalidFqdn', return invalidFqdn
// 3. other situation, no expected
void tscSetFqdnErrorMsg(SSqlObj* pSql, SRpcEpSet* pEpSet) {
SSqlCmd* pCmd = &pSql->cmd;
SSqlRes* pRes = &pSql->res;
char* msgBuf = tscGetErrorMsgPayload(pCmd);
if (pEpSet) {
sprintf(msgBuf, "%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(msgBuf, "%s\"%s\"", tstrerror(pRes->code),tEpset.fqdn[(tEpset.inUse)%(tEpset.numOfEps)]);
} else {
sprintf(msgBuf, "%s", tstrerror(pRes->code));
}
}
void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
TSDB_CACHE_PTR_TYPE handle = (TSDB_CACHE_PTR_TYPE) rpcMsg->ahandle; TSDB_CACHE_PTR_TYPE handle = (TSDB_CACHE_PTR_TYPE) rpcMsg->ahandle;
SSqlObj* pSql = (SSqlObj*)taosAcquireRef(tscObjRef, handle); SSqlObj* pSql = (SSqlObj*)taosAcquireRef(tscObjRef, handle);
if (pSql == NULL) { if (pSql == NULL) {
rpcFreeCont(rpcMsg->pCont); rpcFreeCont(rpcMsg->pCont);
free(rpcMsg);
free(pEpSet);
return; return;
} }
@ -357,15 +377,12 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) {
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
pSql->rpcRid = -1; pSql->rpcRid = -1;
if (pObj->signature != pObj) { if (pObj->signature != pObj) {
tscDebug("0x%"PRIx64" DB connection is closed, cmd:%d pObj:%p signature:%p", pSql->self, pCmd->command, pObj, pObj->signature); tscDebug("0x%"PRIx64" DB connection is closed, cmd:%d pObj:%p signature:%p", pSql->self, pCmd->command, pObj, pObj->signature);
taosRemoveRef(tscObjRef, handle); taosRemoveRef(tscObjRef, handle);
taosReleaseRef(tscObjRef, handle); taosReleaseRef(tscObjRef, handle);
rpcFreeCont(rpcMsg->pCont); rpcFreeCont(rpcMsg->pCont);
free(rpcMsg);
free(pEpSet);
return; return;
} }
@ -377,8 +394,6 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) {
taosRemoveRef(tscObjRef, handle); taosRemoveRef(tscObjRef, handle);
taosReleaseRef(tscObjRef, handle); taosReleaseRef(tscObjRef, handle);
rpcFreeCont(rpcMsg->pCont); rpcFreeCont(rpcMsg->pCont);
free(rpcMsg);
free(pEpSet);
return; return;
} }
@ -432,8 +447,6 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) {
if (rpcMsg->code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) { if (rpcMsg->code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
taosReleaseRef(tscObjRef, handle); taosReleaseRef(tscObjRef, handle);
rpcFreeCont(rpcMsg->pCont); rpcFreeCont(rpcMsg->pCont);
free(rpcMsg);
free(pEpSet);
return; return;
} }
} }
@ -500,28 +513,13 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) {
if (rpcMsg->code != TSDB_CODE_SUCCESS) { if (rpcMsg->code != TSDB_CODE_SUCCESS) {
pRes->code = rpcMsg->code; pRes->code = rpcMsg->code;
} }
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 (rpcMsg->code == TSDB_CODE_RPC_FQDN_ERROR) {
tscAllocPayload(pCmd, TSDB_FQDN_LEN + 64); tscAllocPayload(pCmd, TSDB_FQDN_LEN + 64);
// handle three situation tscSetFqdnErrorMsg(pSql, pEpSet);
// 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) {
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 {
sprintf(tscGetErrorMsgPayload(pCmd), "%s", tstrerror(pRes->code));
}
} }
(*pSql->fp)(pSql->param, pSql, rpcMsg->code); (*pSql->fp)(pSql->param, pSql, rpcMsg->code);
} }
@ -532,35 +530,6 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) {
taosReleaseRef(tscObjRef, handle); taosReleaseRef(tscObjRef, handle);
rpcFreeCont(rpcMsg->pCont); rpcFreeCont(rpcMsg->pCont);
free(rpcMsg);
free(pEpSet);
}
void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
int64_t st = taosGetTimestampUs();
SSchedMsg schedMsg = {0};
schedMsg.fp = doProcessMsgFromServer;
SRpcMsg* rpcMsgCopy = calloc(1, sizeof(SRpcMsg));
memcpy(rpcMsgCopy, rpcMsg, sizeof(struct SRpcMsg));
schedMsg.ahandle = (void*)rpcMsgCopy;
SRpcEpSet* pEpSetCopy = NULL;
if (pEpSet != NULL) {
pEpSetCopy = calloc(1, sizeof(SRpcEpSet));
memcpy(pEpSetCopy, pEpSet, sizeof(SRpcEpSet));
}
schedMsg.thandle = (void*)pEpSetCopy;
schedMsg.msg = NULL;
taosScheduleTask(tscQhandle, &schedMsg);
int64_t et = taosGetTimestampUs();
if (et - st > 100) {
tscDebug("add message to task queue, elapsed time:%"PRId64, et - st);
}
} }
int doBuildAndSendMsg(SSqlObj *pSql) { int doBuildAndSendMsg(SSqlObj *pSql) {
@ -733,8 +702,13 @@ static int32_t tscEstimateQueryMsgSize(SSqlObj *pSql) {
} }
} }
return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + srcColFilterSize + srcTagFilterSize + exprSize + tsBufSize + SCond* pCond = &pQueryInfo->tagCond.tbnameCond;
tableSerialize + sqlLen + 4096 + pQueryInfo->bufLen; if (pCond->len > 0) {
srcColListSize += pCond->len;
}
return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + srcColFilterSize + srcTagFilterSize +
exprSize + tsBufSize + tableSerialize + sqlLen + 4096 + pQueryInfo->bufLen;
} }
static char *doSerializeTableInfo(SQueryTableMsg *pQueryMsg, SSqlObj *pSql, STableMetaInfo *pTableMetaInfo, char *pMsg, static char *doSerializeTableInfo(SQueryTableMsg *pQueryMsg, SSqlObj *pSql, STableMetaInfo *pTableMetaInfo, char *pMsg,
@ -1429,7 +1403,6 @@ int32_t tscBuildSyncDbReplicaMsg(SSqlObj* pSql, SSqlInfo *pInfo) {
} }
int32_t tscBuildShowMsg(SSqlObj *pSql, SSqlInfo *pInfo) { int32_t tscBuildShowMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
STscObj *pObj = pSql->pTscObj;
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
pCmd->msgType = TSDB_MSG_TYPE_CM_SHOW; pCmd->msgType = TSDB_MSG_TYPE_CM_SHOW;
pCmd->payloadLen = sizeof(SShowMsg) + 100; pCmd->payloadLen = sizeof(SShowMsg) + 100;
@ -1452,9 +1425,9 @@ int32_t tscBuildShowMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
} }
if (tNameIsEmpty(&pTableMetaInfo->name)) { if (tNameIsEmpty(&pTableMetaInfo->name)) {
pthread_mutex_lock(&pObj->mutex); char *p = cloneCurrentDBName(pSql);
tstrncpy(pShowMsg->db, pObj->db, sizeof(pShowMsg->db)); tstrncpy(pShowMsg->db, p, sizeof(pShowMsg->db));
pthread_mutex_unlock(&pObj->mutex); tfree(p);
} else { } else {
tNameGetFullDbName(&pTableMetaInfo->name, pShowMsg->db); tNameGetFullDbName(&pTableMetaInfo->name, pShowMsg->db);
} }
@ -2951,10 +2924,14 @@ int32_t tscGetTableMetaImpl(SSqlObj* pSql, STableMetaInfo *pTableMetaInfo, bool
if (pTableMetaInfo->tableMetaCapacity != 0 && pTableMetaInfo->pTableMeta != NULL) { if (pTableMetaInfo->tableMetaCapacity != 0 && pTableMetaInfo->pTableMeta != NULL) {
memset(pTableMetaInfo->pTableMeta, 0, pTableMetaInfo->tableMetaCapacity); memset(pTableMetaInfo->pTableMeta, 0, pTableMetaInfo->tableMetaCapacity);
} }
taosHashGetCloneExt(tscTableMetaMap, name, len, NULL, (void **)&(pTableMetaInfo->pTableMeta), &pTableMetaInfo->tableMetaCapacity);
if (NULL == taosHashGetCloneExt(tscTableMetaMap, name, len, NULL, (void **)&(pTableMetaInfo->pTableMeta), &pTableMetaInfo->tableMetaCapacity)) {
tfree(pTableMetaInfo->pTableMeta);
}
STableMeta* pMeta = pTableMetaInfo->pTableMeta; STableMeta* pMeta = pTableMetaInfo->pTableMeta;
STableMeta* pSTMeta = (STableMeta *)(pSql->pBuf); STableMeta* pSTMeta = (STableMeta *)(pSql->pBuf);
if (pMeta && pMeta->id.uid > 0) { if (pMeta && pMeta->id.uid > 0) {
// in case of child table, here only get the // in case of child table, here only get the
if (pMeta->tableType == TSDB_CHILD_TABLE) { if (pMeta->tableType == TSDB_CHILD_TABLE) {
@ -2964,6 +2941,8 @@ int32_t tscGetTableMetaImpl(SSqlObj* pSql, STableMetaInfo *pTableMetaInfo, bool
return getTableMetaFromMnode(pSql, pTableMetaInfo, autocreate); return getTableMetaFromMnode(pSql, pTableMetaInfo, autocreate);
} }
} }
tscDebug("0x%"PRIx64 " %s retrieve tableMeta from cache, numOfCols:%d, numOfTags:%d", pSql->self, name, pMeta->tableInfo.numOfColumns, pMeta->tableInfo.numOfTags);
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }

View File

@ -15,8 +15,9 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include "os.h" #include "os.h"
#include "texpr.h" #include "texpr.h"
#include "tsched.h"
#include "qTsbuf.h" #include "qTsbuf.h"
#include "tcompare.h" #include "tcompare.h"
#include "tscLog.h" #include "tscLog.h"
@ -2443,7 +2444,11 @@ static void doSendQueryReqs(SSchedMsg* pSchedMsg) {
SSqlObj* pSql = pSchedMsg->ahandle; SSqlObj* pSql = pSchedMsg->ahandle;
SPair* p = pSchedMsg->msg; SPair* p = pSchedMsg->msg;
for(int32_t i = p->first; i < p->second; ++i) { for (int32_t i = p->first; i < p->second; ++i) {
if (i >= pSql->subState.numOfSub) {
tfree(p);
return;
}
SSqlObj* pSub = pSql->pSubs[i]; SSqlObj* pSub = pSql->pSubs[i];
SRetrieveSupport* pSupport = pSub->param; SRetrieveSupport* pSupport = pSub->param;
@ -2583,7 +2588,12 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
int32_t numOfTasks = (pState->numOfSub + MAX_REQUEST_PER_TASK - 1)/MAX_REQUEST_PER_TASK; int32_t numOfTasks = (pState->numOfSub + MAX_REQUEST_PER_TASK - 1)/MAX_REQUEST_PER_TASK;
assert(numOfTasks >= 1); assert(numOfTasks >= 1);
int32_t num = (pState->numOfSub/numOfTasks) + 1; int32_t num;
if (pState->numOfSub / numOfTasks == MAX_REQUEST_PER_TASK) {
num = MAX_REQUEST_PER_TASK;
} else {
num = pState->numOfSub / numOfTasks + 1;
}
tscDebug("0x%"PRIx64 " query will be sent by %d threads", pSql->self, numOfTasks); tscDebug("0x%"PRIx64 " query will be sent by %d threads", pSql->self, numOfTasks);
for(int32_t j = 0; j < numOfTasks; ++j) { for(int32_t j = 0; j < numOfTasks; ++j) {
@ -2739,7 +2749,7 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO
} }
} else { // reach the maximum retry count, abort } else { // reach the maximum retry count, abort
atomic_val_compare_exchange_32(&pParentSql->res.code, TSDB_CODE_SUCCESS, numOfRows); atomic_val_compare_exchange_32(&pParentSql->res.code, TSDB_CODE_SUCCESS, numOfRows);
tscError("0x%"PRIx64" sub:0x%"PRIx64" retrieve failed,code:%s,orderOfSub:%d failed.no more retry,set global code:%s", pParentSql->self, pSql->self, tscError("0x%"PRIx64" sub:0x%"PRIx64" retrieve failed, code:%s, orderOfSub:%d FAILED. no more retry, set global code:%s", pParentSql->self, pSql->self,
tstrerror(numOfRows), subqueryIndex, tstrerror(pParentSql->res.code)); tstrerror(numOfRows), subqueryIndex, tstrerror(pParentSql->res.code));
} }
} }
@ -2986,7 +2996,7 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR
tscDebug("0x%"PRIx64" sub:0x%"PRIx64" retrieve numOfRows:%d totalNumOfRows:%" PRIu64 " from ep:%s, orderOfSub:%d", tscDebug("0x%"PRIx64" sub:0x%"PRIx64" retrieve numOfRows:%d totalNumOfRows:%" PRIu64 " from ep:%s, orderOfSub:%d",
pParentSql->self, pSql->self, pRes->numOfRows, pState->numOfRetrievedRows, pSql->epSet.fqdn[pSql->epSet.inUse], idx); pParentSql->self, pSql->self, pRes->numOfRows, pState->numOfRetrievedRows, pSql->epSet.fqdn[pSql->epSet.inUse], idx);
if (num > tsMaxNumOfOrderedResults && /*tscIsProjectionQueryOnSTable(pQueryInfo, 0) &&*/ !(tscGetQueryInfo(&pParentSql->cmd)->distinct)) { if (num > tsMaxNumOfOrderedResults && tscIsProjectionQueryOnSTable(pQueryInfo, 0) && !(tscGetQueryInfo(&pParentSql->cmd)->distinct)) {
tscError("0x%"PRIx64" sub:0x%"PRIx64" num of OrderedRes is too many, max allowed:%" PRId32 " , current:%" PRId64, tscError("0x%"PRIx64" sub:0x%"PRIx64" num of OrderedRes is too many, max allowed:%" PRId32 " , current:%" PRId64,
pParentSql->self, pSql->self, tsMaxNumOfOrderedResults, num); pParentSql->self, pSql->self, tsMaxNumOfOrderedResults, num);
tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_SORTED_RES_TOO_MANY); tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_SORTED_RES_TOO_MANY);

View File

@ -29,6 +29,7 @@
#include "tsclient.h" #include "tsclient.h"
#include "ttimer.h" #include "ttimer.h"
#include "ttokendef.h" #include "ttokendef.h"
#include "httpInt.h"
static void freeQueryInfoImpl(SQueryInfo* pQueryInfo); static void freeQueryInfoImpl(SQueryInfo* pQueryInfo);
@ -2120,6 +2121,22 @@ TAOS_FIELD tscCreateField(int8_t type, const char* name, int16_t bytes) {
return f; return f;
} }
int32_t tscGetFirstInvisibleFieldPos(SQueryInfo* pQueryInfo) {
if (pQueryInfo->fieldsInfo.numOfOutput <= 0 || pQueryInfo->fieldsInfo.internalField == NULL) {
return 0;
}
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
SInternalField* pField = taosArrayGet(pQueryInfo->fieldsInfo.internalField, i);
if (!pField->visible) {
return i;
}
}
return pQueryInfo->fieldsInfo.numOfOutput;
}
SInternalField* tscFieldInfoAppend(SFieldInfo* pFieldInfo, TAOS_FIELD* pField) { SInternalField* tscFieldInfoAppend(SFieldInfo* pFieldInfo, TAOS_FIELD* pField) {
assert(pFieldInfo != NULL); assert(pFieldInfo != NULL);
pFieldInfo->numOfOutput++; pFieldInfo->numOfOutput++;
@ -3165,6 +3182,7 @@ void tscInitQueryInfo(SQueryInfo* pQueryInfo) {
pQueryInfo->slimit.offset = 0; pQueryInfo->slimit.offset = 0;
pQueryInfo->pUpstream = taosArrayInit(4, POINTER_BYTES); pQueryInfo->pUpstream = taosArrayInit(4, POINTER_BYTES);
pQueryInfo->window = TSWINDOW_INITIALIZER; pQueryInfo->window = TSWINDOW_INITIALIZER;
pQueryInfo->multigroupResult = true;
} }
int32_t tscAddQueryInfo(SSqlCmd* pCmd) { int32_t tscAddQueryInfo(SSqlCmd* pCmd) {
@ -3176,7 +3194,6 @@ int32_t tscAddQueryInfo(SSqlCmd* pCmd) {
} }
tscInitQueryInfo(pQueryInfo); tscInitQueryInfo(pQueryInfo);
pQueryInfo->msg = pCmd->payload; // pointer to the parent error message buffer pQueryInfo->msg = pCmd->payload; // pointer to the parent error message buffer
if (pCmd->pQueryInfo == NULL) { if (pCmd->pQueryInfo == NULL) {
@ -3225,6 +3242,7 @@ static void freeQueryInfoImpl(SQueryInfo* pQueryInfo) {
taosArrayDestroy(pQueryInfo->pUpstream); taosArrayDestroy(pQueryInfo->pUpstream);
pQueryInfo->pUpstream = NULL; pQueryInfo->pUpstream = NULL;
pQueryInfo->bufLen = 0;
} }
void tscClearSubqueryInfo(SSqlCmd* pCmd) { void tscClearSubqueryInfo(SSqlCmd* pCmd) {
@ -3259,6 +3277,7 @@ int32_t tscQueryInfoCopy(SQueryInfo* pQueryInfo, const SQueryInfo* pSrc) {
pQueryInfo->window = pSrc->window; pQueryInfo->window = pSrc->window;
pQueryInfo->sessionWindow = pSrc->sessionWindow; pQueryInfo->sessionWindow = pSrc->sessionWindow;
pQueryInfo->pTableMetaInfo = NULL; pQueryInfo->pTableMetaInfo = NULL;
pQueryInfo->multigroupResult = pSrc->multigroupResult;
pQueryInfo->bufLen = pSrc->bufLen; pQueryInfo->bufLen = pSrc->bufLen;
pQueryInfo->orderProjectQuery = pSrc->orderProjectQuery; pQueryInfo->orderProjectQuery = pSrc->orderProjectQuery;
@ -3649,19 +3668,20 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, __async_cb_func_t
pNewQueryInfo->limit = pQueryInfo->limit; pNewQueryInfo->limit = pQueryInfo->limit;
pNewQueryInfo->slimit = pQueryInfo->slimit; pNewQueryInfo->slimit = pQueryInfo->slimit;
pNewQueryInfo->order = pQueryInfo->order; pNewQueryInfo->order = pQueryInfo->order;
pNewQueryInfo->vgroupLimit = pQueryInfo->vgroupLimit;
pNewQueryInfo->tsBuf = NULL; pNewQueryInfo->tsBuf = NULL;
pNewQueryInfo->fillType = pQueryInfo->fillType; pNewQueryInfo->fillType = pQueryInfo->fillType;
pNewQueryInfo->fillVal = NULL; pNewQueryInfo->fillVal = NULL;
pNewQueryInfo->numOfFillVal = 0;
pNewQueryInfo->clauseLimit = pQueryInfo->clauseLimit; pNewQueryInfo->clauseLimit = pQueryInfo->clauseLimit;
pNewQueryInfo->prjOffset = pQueryInfo->prjOffset; pNewQueryInfo->prjOffset = pQueryInfo->prjOffset;
pNewQueryInfo->numOfFillVal = 0;
pNewQueryInfo->numOfTables = 0; pNewQueryInfo->numOfTables = 0;
pNewQueryInfo->pTableMetaInfo = NULL; pNewQueryInfo->pTableMetaInfo = NULL;
pNewQueryInfo->bufLen = pQueryInfo->bufLen; pNewQueryInfo->bufLen = pQueryInfo->bufLen;
pNewQueryInfo->buf = malloc(pQueryInfo->bufLen); pNewQueryInfo->vgroupLimit = pQueryInfo->vgroupLimit;
pNewQueryInfo->distinct = pQueryInfo->distinct; pNewQueryInfo->distinct = pQueryInfo->distinct;
pNewQueryInfo->multigroupResult = pQueryInfo->multigroupResult;
pNewQueryInfo->buf = malloc(pQueryInfo->bufLen);
if (pNewQueryInfo->buf == NULL) { if (pNewQueryInfo->buf == NULL) {
terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
goto _error; goto _error;
@ -3887,6 +3907,8 @@ static void tscSubqueryCompleteCallback(void* param, TAOS_RES* tres, int code) {
// todo refactor // todo refactor
tscDebug("0x%"PRIx64" all subquery response received, retry", pParentSql->self); tscDebug("0x%"PRIx64" all subquery response received, retry", pParentSql->self);
if (code && !((code == TSDB_CODE_TDB_INVALID_TABLE_ID || code == TSDB_CODE_VND_INVALID_VGROUP_ID) && pParentSql->retry < pParentSql->maxRetry)) { if (code && !((code == TSDB_CODE_TDB_INVALID_TABLE_ID || code == TSDB_CODE_VND_INVALID_VGROUP_ID) && pParentSql->retry < pParentSql->maxRetry)) {
pParentSql->res.code = code;
tscAsyncResultOnError(pParentSql); tscAsyncResultOnError(pParentSql);
return; return;
} }
@ -3966,6 +3988,7 @@ void executeQuery(SSqlObj* pSql, SQueryInfo* pQueryInfo) {
pNew->signature = pNew; pNew->signature = pNew;
pNew->sqlstr = strdup(pSql->sqlstr); pNew->sqlstr = strdup(pSql->sqlstr);
pNew->fp = tscSubqueryCompleteCallback; pNew->fp = tscSubqueryCompleteCallback;
pNew->fetchFp = tscSubqueryCompleteCallback;
pNew->maxRetry = pSql->maxRetry; pNew->maxRetry = pSql->maxRetry;
pNew->cmd.resColumnId = TSDB_RES_COL_ID; pNew->cmd.resColumnId = TSDB_RES_COL_ID;
@ -4146,6 +4169,31 @@ int32_t tscInvalidOperationMsg(char* msg, const char* additionalInfo, const char
return TSDB_CODE_TSC_INVALID_OPERATION; return TSDB_CODE_TSC_INVALID_OPERATION;
} }
int32_t tscErrorMsgWithCode(int32_t code, char* dstBuffer, const char* errMsg, const char* sql) {
const char* msgFormat1 = "%s:%s";
const char* msgFormat2 = "%s:\'%s\' (%s)";
const char* msgFormat3 = "%s:\'%s\'";
const int32_t BACKWARD_CHAR_STEP = 0;
if (sql == NULL) {
assert(errMsg != NULL);
sprintf(dstBuffer, msgFormat1, tstrerror(code), errMsg);
return code;
}
char buf[64] = {0}; // only extract part of sql string
strncpy(buf, (sql - BACKWARD_CHAR_STEP), tListLen(buf) - 1);
if (errMsg != NULL) {
sprintf(dstBuffer, msgFormat2, tstrerror(code), buf, errMsg);
} else {
sprintf(dstBuffer, msgFormat3, tstrerror(code), buf); // no additional information for invalid sql error
}
return code;
}
bool tscHasReachLimitation(SQueryInfo* pQueryInfo, SSqlRes* pRes) { bool tscHasReachLimitation(SQueryInfo* pQueryInfo, SSqlRes* pRes) {
assert(pQueryInfo != NULL && pQueryInfo->clauseLimit != 0); assert(pQueryInfo != NULL && pQueryInfo->clauseLimit != 0);
return (pQueryInfo->clauseLimit > 0 && pRes->numOfClauseTotal >= pQueryInfo->clauseLimit); return (pQueryInfo->clauseLimit > 0 && pRes->numOfClauseTotal >= pQueryInfo->clauseLimit);
@ -4508,21 +4556,20 @@ int32_t tscCreateTableMetaFromSTableMeta(STableMeta** ppChild, const char* name,
memset((char *)p, 0, sz); memset((char *)p, 0, sz);
} }
STableMeta* pChild1; if (NULL == taosHashGetCloneExt(tscTableMetaMap, pChild->sTableName, strnlen(pChild->sTableName, TSDB_TABLE_FNAME_LEN), NULL, (void **)&p, &sz)) {
tfree(p);
taosHashGetCloneExt(tscTableMetaMap, pChild->sTableName, strnlen(pChild->sTableName, TSDB_TABLE_FNAME_LEN), NULL, (void **)&p, &sz); } else {
*ppSTable = p; *ppSTable = p;
}
// tableMeta exists, build child table meta according to the super table meta // tableMeta exists, build child table meta according to the super table meta
// the uid need to be checked in addition to the general name of the super table. // the uid need to be checked in addition to the general name of the super table.
if (p && p->id.uid > 0 && pChild->suid == p->id.uid) { if (p && p->id.uid > 0 && pChild->suid == p->id.uid) {
int32_t totalBytes = (p->tableInfo.numOfColumns + p->tableInfo.numOfTags) * sizeof(SSchema); int32_t totalBytes = (p->tableInfo.numOfColumns + p->tableInfo.numOfTags) * sizeof(SSchema);
int32_t tableMetaSize = sizeof(STableMeta) + totalBytes; int32_t tableMetaSize = sizeof(STableMeta) + totalBytes;
if (*tableMetaCapacity < tableMetaSize) { if (*tableMetaCapacity < tableMetaSize) {
pChild1 = realloc(pChild, tableMetaSize); STableMeta* pChild1 = realloc(pChild, tableMetaSize);
if(pChild1 == NULL) if(pChild1 == NULL) return -1;
return -1;
pChild = pChild1; pChild = pChild1;
*tableMetaCapacity = (size_t)tableMetaSize; *tableMetaCapacity = (size_t)tableMetaSize;
} }
@ -4793,6 +4840,7 @@ int32_t tscCreateQueryFromQueryInfo(SQueryInfo* pQueryInfo, SQueryAttr* pQueryAt
pQueryAttr->distinct = pQueryInfo->distinct; pQueryAttr->distinct = pQueryInfo->distinct;
pQueryAttr->sw = pQueryInfo->sessionWindow; pQueryAttr->sw = pQueryInfo->sessionWindow;
pQueryAttr->stateWindow = pQueryInfo->stateWindow; pQueryAttr->stateWindow = pQueryInfo->stateWindow;
pQueryAttr->multigroupResult = pQueryInfo->multigroupResult;
pQueryAttr->numOfCols = numOfCols; pQueryAttr->numOfCols = numOfCols;
pQueryAttr->numOfOutput = numOfOutput; pQueryAttr->numOfOutput = numOfOutput;
@ -5065,3 +5113,31 @@ void tscRemoveCachedTableMeta(STableMetaInfo* pTableMetaInfo, uint64_t id) {
taosHashRemove(tscTableMetaMap, fname, len); taosHashRemove(tscTableMetaMap, fname, len);
tscDebug("0x%"PRIx64" remove table meta %s, numOfRemain:%d", id, fname, (int32_t) taosHashGetSize(tscTableMetaMap)); tscDebug("0x%"PRIx64" remove table meta %s, numOfRemain:%d", id, fname, (int32_t) taosHashGetSize(tscTableMetaMap));
} }
char* cloneCurrentDBName(SSqlObj* pSql) {
char *p = NULL;
HttpContext *pCtx = NULL;
pthread_mutex_lock(&pSql->pTscObj->mutex);
STscObj *pTscObj = pSql->pTscObj;
switch (pTscObj->from) {
case TAOS_REQ_FROM_HTTP:
pCtx = pSql->param;
if (pCtx && pCtx->db[0] != '\0') {
char db[TSDB_ACCT_ID_LEN + TSDB_DB_NAME_LEN] = {0};
int32_t len = sprintf(db, "%s%s%s", pTscObj->acctId, TS_PATH_DELIMITER, pCtx->db);
assert(len <= sizeof(db));
p = strdup(db);
}
break;
default:
break;
}
if (p == NULL) {
p = strdup(pSql->pTscObj->db);
}
pthread_mutex_unlock(&pSql->pTscObj->mutex);
return p;
}

View File

@ -130,6 +130,7 @@ extern int32_t tsHttpMaxThreads;
extern int8_t tsHttpEnableCompress; extern int8_t tsHttpEnableCompress;
extern int8_t tsHttpEnableRecordSql; extern int8_t tsHttpEnableRecordSql;
extern int8_t tsTelegrafUseFieldNum; extern int8_t tsTelegrafUseFieldNum;
extern int8_t tsHttpDbNameMandatory;
// mqtt // mqtt
extern int8_t tsEnableMqttModule; extern int8_t tsEnableMqttModule;

View File

@ -175,6 +175,7 @@ int32_t tsHttpMaxThreads = 2;
int8_t tsHttpEnableCompress = 1; int8_t tsHttpEnableCompress = 1;
int8_t tsHttpEnableRecordSql = 0; int8_t tsHttpEnableRecordSql = 0;
int8_t tsTelegrafUseFieldNum = 0; int8_t tsTelegrafUseFieldNum = 0;
int8_t tsHttpDbNameMandatory = 0;
// mqtt // mqtt
int8_t tsEnableMqttModule = 0; // not finished yet, not started it by default int8_t tsEnableMqttModule = 0; // not finished yet, not started it by default
@ -1290,6 +1291,16 @@ static void doInitGlobalConfig(void) {
cfg.unitType = TAOS_CFG_UTYPE_NONE; cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg); taosInitConfigOption(cfg);
cfg.option = "httpDbNameMandatory";
cfg.ptr = &tsHttpDbNameMandatory;
cfg.valType = TAOS_CFG_VTYPE_INT8;
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG;
cfg.minValue = 0;
cfg.maxValue = 1;
cfg.ptrLength = 0;
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
// debug flag // debug flag
cfg.option = "numOfLogLines"; cfg.option = "numOfLogLines";
cfg.ptr = &tsNumOfLogLines; cfg.ptr = &tsNumOfLogLines;

@ -1 +1 @@
Subproject commit 050667e5b4d0eafa5387e4283e713559b421203f Subproject commit b8f76da4a708d158ec3cc4b844571dc4414e36b4

@ -1 +1 @@
Subproject commit b62a26ecc164a310104df57691691b237e091c89 Subproject commit ce5201014136503d34fecbd56494b67b4961056c

View File

@ -117,7 +117,6 @@
<exclude>**/DatetimeBefore1970Test.java</exclude> <exclude>**/DatetimeBefore1970Test.java</exclude>
<exclude>**/FailOverTest.java</exclude> <exclude>**/FailOverTest.java</exclude>
<exclude>**/InvalidResultSetPointerTest.java</exclude> <exclude>**/InvalidResultSetPointerTest.java</exclude>
<exclude>**/RestfulConnectionTest.java</exclude>
<exclude>**/TSDBJNIConnectorTest.java</exclude> <exclude>**/TSDBJNIConnectorTest.java</exclude>
<exclude>**/TaosInfoMonitorTest.java</exclude> <exclude>**/TaosInfoMonitorTest.java</exclude>
<exclude>**/UnsignedNumberJniTest.java</exclude> <exclude>**/UnsignedNumberJniTest.java</exclude>

View File

@ -40,13 +40,13 @@ public class TSDBError {
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_SUBSCRIBE_FAILED, "failed to create subscription"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_SUBSCRIBE_FAILED, "failed to create subscription");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNSUPPORTED_ENCODING, "Unsupported encoding"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNSUPPORTED_ENCODING, "Unsupported encoding");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_TDENGINE_ERROR, "internal error of database"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_TDENGINE_ERROR, "internal error of database, please see taoslog for more details");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL, "JNI connection is NULL"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL, "JNI connection is NULL");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL, "JNI result set is NULL"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL, "JNI result set is NULL");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0, "invalid num of fields"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0, "invalid num of fields");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_SQL_NULL, "empty sql string"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_SQL_NULL, "empty sql string");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_FETCH_END, "fetch to the end of resultSet"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_FETCH_END, "fetch to the end of resultSet");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_OUT_OF_MEMORY, "JNI alloc memory failed"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_OUT_OF_MEMORY, "JNI alloc memory failed, please see taoslog for more details");
} }
public static SQLException createSQLException(int errorCode) { public static SQLException createSQLException(int errorCode) {

View File

@ -278,25 +278,20 @@ public class TSDBJNIConnector {
private native int validateCreateTableSqlImp(long connection, byte[] sqlBytes); private native int validateCreateTableSqlImp(long connection, byte[] sqlBytes);
public long prepareStmt(String sql) throws SQLException { public long prepareStmt(String sql) throws SQLException {
long stmt; long stmt = prepareStmtImp(sql.getBytes(), this.taos);
try {
stmt = prepareStmtImp(sql.getBytes(), this.taos);
} catch (Exception e) {
e.printStackTrace();
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_ENCODING);
}
if (stmt == TSDBConstants.JNI_CONNECTION_NULL) { if (stmt == TSDBConstants.JNI_CONNECTION_NULL) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL, "connection already closed");
} }
if (stmt == TSDBConstants.JNI_SQL_NULL) { if (stmt == TSDBConstants.JNI_SQL_NULL) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_SQL_NULL); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_SQL_NULL);
} }
if (stmt == TSDBConstants.JNI_OUT_OF_MEMORY) { if (stmt == TSDBConstants.JNI_OUT_OF_MEMORY) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_OUT_OF_MEMORY); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_OUT_OF_MEMORY);
} }
if (stmt == TSDBConstants.JNI_TDENGINE_ERROR) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_TDENGINE_ERROR);
}
return stmt; return stmt;
} }
@ -313,8 +308,7 @@ public class TSDBJNIConnector {
private native int setBindTableNameImp(long stmt, String name, long conn); private native int setBindTableNameImp(long stmt, String name, long conn);
public void setBindTableNameAndTags(long stmt, String tableName, int numOfTags, ByteBuffer tags, ByteBuffer typeList, ByteBuffer lengthList, ByteBuffer nullList) throws SQLException { public void setBindTableNameAndTags(long stmt, String tableName, int numOfTags, ByteBuffer tags, ByteBuffer typeList, ByteBuffer lengthList, ByteBuffer nullList) throws SQLException {
int code = setTableNameTagsImp(stmt, tableName, numOfTags, tags.array(), typeList.array(), lengthList.array(), int code = setTableNameTagsImp(stmt, tableName, numOfTags, tags.array(), typeList.array(), lengthList.array(), nullList.array(), this.taos);
nullList.array(), this.taos);
if (code != TSDBConstants.JNI_SUCCESS) { if (code != TSDBConstants.JNI_SUCCESS) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "failed to bind table name and corresponding tags"); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "failed to bind table name and corresponding tags");
} }

View File

@ -18,7 +18,7 @@ public class RestfulConnection extends AbstractConnection {
private final String url; private final String url;
private final String database; private final String database;
private final String token; private final String token;
/******************************************************/
private boolean isClosed; private boolean isClosed;
private final DatabaseMetaData metadata; private final DatabaseMetaData metadata;

View File

@ -88,17 +88,24 @@ public class RestfulStatement extends AbstractStatement {
} }
private String getUrl() throws SQLException { private String getUrl() throws SQLException {
String dbname = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_DBNAME);
if (dbname == null || dbname.trim().isEmpty()) {
dbname = "";
} else {
dbname = "/" + dbname.toLowerCase();
}
TimestampFormat timestampFormat = TimestampFormat.valueOf(conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).trim().toUpperCase()); TimestampFormat timestampFormat = TimestampFormat.valueOf(conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).trim().toUpperCase());
String url; String url;
switch (timestampFormat) { switch (timestampFormat) {
case TIMESTAMP: case TIMESTAMP:
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt"; url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt" + dbname;
break; break;
case UTC: case UTC:
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc"; url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc" + dbname;
break; break;
default: default:
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql" + dbname;
} }
return url; return url;
} }

View File

@ -0,0 +1,101 @@
package com.taosdata.jdbc.cases;
import org.junit.Before;
import org.junit.Test;
import java.sql.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class MultiConnectionWithDifferentDbTest {
private static String host = "127.0.0.1";
private static String db1 = "db1";
private static String db2 = "db2";
private long ts;
@Test
public void test() {
List<Thread> threads = IntStream.range(1, 3).mapToObj(i -> new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 10; j++) {
queryDb();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void queryDb() {
String url = "jdbc:TAOS-RS://" + host + ":6041/db" + i + "?user=root&password=taosdata";
try (Connection connection = DriverManager.getConnection(url)) {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("select * from weather");
assertNotNull(rs);
rs.next();
long actual = rs.getTimestamp("ts").getTime();
assertEquals(ts, actual);
int f1 = rs.getInt("f1");
assertEquals(i, f1);
String loc = i == 1 ? "beijing" : "shanghai";
String loc_actual = rs.getString("loc");
assertEquals(loc, loc_actual);
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}, "thread-" + i)).collect(Collectors.toList());
threads.forEach(Thread::start);
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Before
public void before() {
ts = System.currentTimeMillis();
try {
Connection conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata");
Statement stmt = conn.createStatement();
stmt.execute("drop database if exists " + db1);
stmt.execute("create database if not exists " + db1);
stmt.execute("use " + db1);
stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))");
stmt.execute("insert into t1 using weather tags('beijing') values(" + ts + ", 1)");
stmt.execute("drop database if exists " + db2);
stmt.execute("create database if not exists " + db2);
stmt.execute("use " + db2);
stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))");
stmt.execute("insert into t1 using weather tags('shanghai') values(" + ts + ", 2)");
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,84 @@
package com.taosdata.jdbc.cases;
import org.junit.Before;
import org.junit.Test;
import java.sql.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class UseNowInsertTimestampTest {
String url = "jdbc:TAOS://127.0.0.1:6030/?user=root&password=taosdata";
@Test
public void millisec() {
try (Connection conn = DriverManager.getConnection(url)) {
Statement stmt = conn.createStatement();
stmt.execute("drop database if exists test");
stmt.execute("create database if not exists test precision 'ms'");
stmt.execute("use test");
stmt.execute("create table weather(ts timestamp, f1 int)");
stmt.execute("insert into weather values(now, 1)");
ResultSet rs = stmt.executeQuery("select * from weather");
rs.next();
Timestamp ts = rs.getTimestamp("ts");
assertEquals(13, Long.toString(ts.getTime()).length());
int nanos = ts.getNanos();
assertEquals(0, nanos % 1000_000);
stmt.execute("drop database if exists test");
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void microsec() {
try (Connection conn = DriverManager.getConnection(url)) {
Statement stmt = conn.createStatement();
stmt.execute("drop database if exists test");
stmt.execute("create database if not exists test precision 'us'");
stmt.execute("use test");
stmt.execute("create table weather(ts timestamp, f1 int)");
stmt.execute("insert into weather values(now, 1)");
ResultSet rs = stmt.executeQuery("select * from weather");
rs.next();
Timestamp ts = rs.getTimestamp("ts");
int nanos = ts.getNanos();
assertEquals(0, nanos % 1000);
stmt.execute("drop database if exists test");
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void nanosec() {
try (Connection conn = DriverManager.getConnection(url)) {
Statement stmt = conn.createStatement();
stmt.execute("drop database if exists test");
stmt.execute("create database if not exists test precision 'ns'");
stmt.execute("use test");
stmt.execute("create table weather(ts timestamp, f1 int)");
stmt.execute("insert into weather values(now, 1)");
ResultSet rs = stmt.executeQuery("select * from weather");
rs.next();
Timestamp ts = rs.getTimestamp("ts");
int nanos = ts.getNanos();
assertTrue(nanos % 1000 != 0);
stmt.execute("drop database if exists test");
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,69 @@
package com.taosdata.jdbc.rs;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.sql.*;
import static org.junit.Assert.*;
public class DatabaseSpecifiedTest {
private static String host = "127.0.0.1";
private static String dbname = "test_db_spec";
private Connection connection;
private long ts;
@Test
public void test() throws SQLException {
// when
connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/" + dbname + "?user=root&password=taosdata");
try (Statement stmt = connection.createStatement();) {
ResultSet rs = stmt.executeQuery("select * from weather");
//then
assertNotNull(rs);
rs.next();
long now = rs.getTimestamp("ts").getTime();
assertEquals(ts, now);
int f1 = rs.getInt(2);
assertEquals(1, f1);
String loc = rs.getString("loc");
assertEquals("beijing", loc);
}
connection.close();
}
@Before
public void before() {
ts = System.currentTimeMillis();
try {
Connection connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata");
Statement stmt = connection.createStatement();
stmt.execute("drop database if exists " + dbname);
stmt.execute("create database if not exists " + dbname);
stmt.execute("use " + dbname);
stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))");
stmt.execute("insert into t1 using weather tags('beijing') values( " + ts + ", 1)");
stmt.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@After
public void after() {
try {
if (connection != null)
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -9,6 +9,8 @@ import org.junit.Test;
import java.sql.*; import java.sql.*;
import java.util.Properties; import java.util.Properties;
import static org.junit.Assert.assertEquals;
public class RestfulConnectionTest { public class RestfulConnectionTest {
private static final String host = "127.0.0.1"; private static final String host = "127.0.0.1";
@ -26,7 +28,7 @@ public class RestfulConnectionTest {
ResultSet rs = stmt.executeQuery("select server_status()"); ResultSet rs = stmt.executeQuery("select server_status()");
rs.next(); rs.next();
int status = rs.getInt("server_status()"); int status = rs.getInt("server_status()");
Assert.assertEquals(1, status); assertEquals(1, status);
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -38,7 +40,7 @@ public class RestfulConnectionTest {
ResultSet rs = pstmt.executeQuery(); ResultSet rs = pstmt.executeQuery();
rs.next(); rs.next();
int status = rs.getInt("server_status()"); int status = rs.getInt("server_status()");
Assert.assertEquals(1, status); assertEquals(1, status);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
@ -49,7 +51,7 @@ public class RestfulConnectionTest {
@Test @Test
public void nativeSQL() throws SQLException { public void nativeSQL() throws SQLException {
String nativeSQL = conn.nativeSQL("select * from log.log"); String nativeSQL = conn.nativeSQL("select * from log.log");
Assert.assertEquals("select * from log.log", nativeSQL); assertEquals("select * from log.log", nativeSQL);
} }
@Test @Test
@ -87,7 +89,7 @@ public class RestfulConnectionTest {
public void getMetaData() throws SQLException { public void getMetaData() throws SQLException {
DatabaseMetaData meta = conn.getMetaData(); DatabaseMetaData meta = conn.getMetaData();
Assert.assertNotNull(meta); Assert.assertNotNull(meta);
Assert.assertEquals("com.taosdata.jdbc.rs.RestfulDriver", meta.getDriverName()); assertEquals("com.taosdata.jdbc.rs.RestfulDriver", meta.getDriverName());
} }
@Test @Test
@ -103,25 +105,25 @@ public class RestfulConnectionTest {
@Test @Test
public void setCatalog() throws SQLException { public void setCatalog() throws SQLException {
conn.setCatalog("test"); conn.setCatalog("test");
Assert.assertEquals("test", conn.getCatalog()); assertEquals("test", conn.getCatalog());
} }
@Test @Test
public void getCatalog() throws SQLException { public void getCatalog() throws SQLException {
conn.setCatalog("log"); conn.setCatalog("log");
Assert.assertEquals("log", conn.getCatalog()); assertEquals("log", conn.getCatalog());
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
public void setTransactionIsolation() throws SQLException { public void setTransactionIsolation() throws SQLException {
conn.setTransactionIsolation(Connection.TRANSACTION_NONE); conn.setTransactionIsolation(Connection.TRANSACTION_NONE);
Assert.assertEquals(Connection.TRANSACTION_NONE, conn.getTransactionIsolation()); assertEquals(Connection.TRANSACTION_NONE, conn.getTransactionIsolation());
conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
} }
@Test @Test
public void getTransactionIsolation() throws SQLException { public void getTransactionIsolation() throws SQLException {
Assert.assertEquals(Connection.TRANSACTION_NONE, conn.getTransactionIsolation()); assertEquals(Connection.TRANSACTION_NONE, conn.getTransactionIsolation());
} }
@Test @Test
@ -140,7 +142,7 @@ public class RestfulConnectionTest {
ResultSet rs = stmt.executeQuery("select server_status()"); ResultSet rs = stmt.executeQuery("select server_status()");
rs.next(); rs.next();
int status = rs.getInt("server_status()"); int status = rs.getInt("server_status()");
Assert.assertEquals(1, status); assertEquals(1, status);
conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
} }
@ -152,7 +154,7 @@ public class RestfulConnectionTest {
ResultSet rs = pstmt.executeQuery(); ResultSet rs = pstmt.executeQuery();
rs.next(); rs.next();
int status = rs.getInt("server_status()"); int status = rs.getInt("server_status()");
Assert.assertEquals(1, status); assertEquals(1, status);
conn.prepareStatement("select server_status", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); conn.prepareStatement("select server_status", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
} }
@ -175,13 +177,13 @@ public class RestfulConnectionTest {
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
public void setHoldability() throws SQLException { public void setHoldability() throws SQLException {
conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
Assert.assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, conn.getHoldability()); assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, conn.getHoldability());
conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT);
} }
@Test @Test
public void getHoldability() throws SQLException { public void getHoldability() throws SQLException {
Assert.assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, conn.getHoldability()); assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, conn.getHoldability());
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
@ -210,7 +212,7 @@ public class RestfulConnectionTest {
ResultSet rs = stmt.executeQuery("select server_status()"); ResultSet rs = stmt.executeQuery("select server_status()");
rs.next(); rs.next();
int status = rs.getInt("server_status()"); int status = rs.getInt("server_status()");
Assert.assertEquals(1, status); assertEquals(1, status);
conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
} }
@ -222,7 +224,7 @@ public class RestfulConnectionTest {
ResultSet rs = pstmt.executeQuery(); ResultSet rs = pstmt.executeQuery();
rs.next(); rs.next();
int status = rs.getInt("server_status()"); int status = rs.getInt("server_status()");
Assert.assertEquals(1, status); assertEquals(1, status);
conn.prepareStatement("select server_status", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); conn.prepareStatement("select server_status", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
} }
@ -299,11 +301,11 @@ public class RestfulConnectionTest {
Properties info = conn.getClientInfo(); Properties info = conn.getClientInfo();
String charset = info.getProperty(TSDBDriver.PROPERTY_KEY_CHARSET); String charset = info.getProperty(TSDBDriver.PROPERTY_KEY_CHARSET);
Assert.assertEquals("UTF-8", charset); assertEquals("UTF-8", charset);
String locale = info.getProperty(TSDBDriver.PROPERTY_KEY_LOCALE); String locale = info.getProperty(TSDBDriver.PROPERTY_KEY_LOCALE);
Assert.assertEquals("en_US.UTF-8", locale); assertEquals("en_US.UTF-8", locale);
String timezone = info.getProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE); String timezone = info.getProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE);
Assert.assertEquals("UTC-8", timezone); assertEquals("UTC-8", timezone);
} }
@Test @Test
@ -313,11 +315,11 @@ public class RestfulConnectionTest {
conn.setClientInfo(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); conn.setClientInfo(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
String charset = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_CHARSET); String charset = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_CHARSET);
Assert.assertEquals("UTF-8", charset); assertEquals("UTF-8", charset);
String locale = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_LOCALE); String locale = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_LOCALE);
Assert.assertEquals("en_US.UTF-8", locale); assertEquals("en_US.UTF-8", locale);
String timezone = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIME_ZONE); String timezone = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIME_ZONE);
Assert.assertEquals("UTC-8", timezone); assertEquals("UTC-8", timezone);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test(expected = SQLFeatureNotSupportedException.class)
@ -345,14 +347,15 @@ public class RestfulConnectionTest {
conn.abort(null); conn.abort(null);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test
public void setNetworkTimeout() throws SQLException { public void setNetworkTimeout() throws SQLException {
conn.setNetworkTimeout(null, 1000); conn.setNetworkTimeout(null, 1000);
} }
@Test(expected = SQLFeatureNotSupportedException.class) @Test
public void getNetworkTimeout() throws SQLException { public void getNetworkTimeout() throws SQLException {
conn.getNetworkTimeout(); int timeout = conn.getNetworkTimeout();
assertEquals(0, timeout);
} }
@Test @Test

View File

@ -2,7 +2,7 @@ import taos
conn = taos.connect(host='127.0.0.1', conn = taos.connect(host='127.0.0.1',
user='root', user='root',
passworkd='taodata', password='taosdata',
database='log') database='log')
cursor = conn.cursor() cursor = conn.cursor()

View File

@ -104,6 +104,9 @@ int32_t* taosGetErrno();
#define TSDB_CODE_TSC_FILE_EMPTY TAOS_DEF_ERROR_CODE(0, 0x021A) //"File is empty") #define TSDB_CODE_TSC_FILE_EMPTY TAOS_DEF_ERROR_CODE(0, 0x021A) //"File is empty")
#define TSDB_CODE_TSC_LINE_SYNTAX_ERROR TAOS_DEF_ERROR_CODE(0, 0x021B) //"Syntax error in Line") #define TSDB_CODE_TSC_LINE_SYNTAX_ERROR TAOS_DEF_ERROR_CODE(0, 0x021B) //"Syntax error in Line")
#define TSDB_CODE_TSC_NO_META_CACHED TAOS_DEF_ERROR_CODE(0, 0x021C) //"No table meta cached") #define TSDB_CODE_TSC_NO_META_CACHED TAOS_DEF_ERROR_CODE(0, 0x021C) //"No table meta cached")
#define TSDB_CODE_TSC_DUP_COL_NAMES TAOS_DEF_ERROR_CODE(0, 0x021D) //"duplicated column names")
#define TSDB_CODE_TSC_INVALID_TAG_LENGTH TAOS_DEF_ERROR_CODE(0, 0x021E) //"Invalid tag length")
#define TSDB_CODE_TSC_INVALID_COLUMN_LENGTH TAOS_DEF_ERROR_CODE(0, 0x021F) //"Invalid column length")
// mnode // mnode
#define TSDB_CODE_MND_MSG_NOT_PROCESSED TAOS_DEF_ERROR_CODE(0, 0x0300) //"Message not processed") #define TSDB_CODE_MND_MSG_NOT_PROCESSED TAOS_DEF_ERROR_CODE(0, 0x0300) //"Message not processed")
@ -186,6 +189,9 @@ int32_t* taosGetErrno();
#define TSDB_CODE_MND_INVALID_FUNC TAOS_DEF_ERROR_CODE(0, 0x0374) //"Invalid func") #define TSDB_CODE_MND_INVALID_FUNC TAOS_DEF_ERROR_CODE(0, 0x0374) //"Invalid func")
#define TSDB_CODE_MND_INVALID_FUNC_BUFSIZE TAOS_DEF_ERROR_CODE(0, 0x0375) //"Invalid func bufSize") #define TSDB_CODE_MND_INVALID_FUNC_BUFSIZE TAOS_DEF_ERROR_CODE(0, 0x0375) //"Invalid func bufSize")
#define TSDB_CODE_MND_INVALID_TAG_LENGTH TAOS_DEF_ERROR_CODE(0, 0x0376) //"invalid tag length")
#define TSDB_CODE_MND_INVALID_COLUMN_LENGTH TAOS_DEF_ERROR_CODE(0, 0x0377) //"invalid column length")
#define TSDB_CODE_MND_DB_NOT_SELECTED TAOS_DEF_ERROR_CODE(0, 0x0380) //"Database not specified or available") #define TSDB_CODE_MND_DB_NOT_SELECTED TAOS_DEF_ERROR_CODE(0, 0x0380) //"Database not specified or available")
#define TSDB_CODE_MND_DB_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0381) //"Database already exists") #define TSDB_CODE_MND_DB_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0381) //"Database already exists")
#define TSDB_CODE_MND_INVALID_DB_OPTION TAOS_DEF_ERROR_CODE(0, 0x0382) //"Invalid database options") #define TSDB_CODE_MND_INVALID_DB_OPTION TAOS_DEF_ERROR_CODE(0, 0x0382) //"Invalid database options")

View File

@ -91,125 +91,126 @@
#define TK_ACCOUNT 73 #define TK_ACCOUNT 73
#define TK_USE 74 #define TK_USE 74
#define TK_DESCRIBE 75 #define TK_DESCRIBE 75
#define TK_ALTER 76 #define TK_DESC 76
#define TK_PASS 77 #define TK_ALTER 77
#define TK_PRIVILEGE 78 #define TK_PASS 78
#define TK_LOCAL 79 #define TK_PRIVILEGE 79
#define TK_COMPACT 80 #define TK_LOCAL 80
#define TK_LP 81 #define TK_COMPACT 81
#define TK_RP 82 #define TK_LP 82
#define TK_IF 83 #define TK_RP 83
#define TK_EXISTS 84 #define TK_IF 84
#define TK_AS 85 #define TK_EXISTS 85
#define TK_OUTPUTTYPE 86 #define TK_AS 86
#define TK_AGGREGATE 87 #define TK_OUTPUTTYPE 87
#define TK_BUFSIZE 88 #define TK_AGGREGATE 88
#define TK_PPS 89 #define TK_BUFSIZE 89
#define TK_TSERIES 90 #define TK_PPS 90
#define TK_DBS 91 #define TK_TSERIES 91
#define TK_STORAGE 92 #define TK_DBS 92
#define TK_QTIME 93 #define TK_STORAGE 93
#define TK_CONNS 94 #define TK_QTIME 94
#define TK_STATE 95 #define TK_CONNS 95
#define TK_COMMA 96 #define TK_STATE 96
#define TK_KEEP 97 #define TK_COMMA 97
#define TK_CACHE 98 #define TK_KEEP 98
#define TK_REPLICA 99 #define TK_CACHE 99
#define TK_QUORUM 100 #define TK_REPLICA 100
#define TK_DAYS 101 #define TK_QUORUM 101
#define TK_MINROWS 102 #define TK_DAYS 102
#define TK_MAXROWS 103 #define TK_MINROWS 103
#define TK_BLOCKS 104 #define TK_MAXROWS 104
#define TK_CTIME 105 #define TK_BLOCKS 105
#define TK_WAL 106 #define TK_CTIME 106
#define TK_FSYNC 107 #define TK_WAL 107
#define TK_COMP 108 #define TK_FSYNC 108
#define TK_PRECISION 109 #define TK_COMP 109
#define TK_UPDATE 110 #define TK_PRECISION 110
#define TK_CACHELAST 111 #define TK_UPDATE 111
#define TK_PARTITIONS 112 #define TK_CACHELAST 112
#define TK_UNSIGNED 113 #define TK_PARTITIONS 113
#define TK_TAGS 114 #define TK_UNSIGNED 114
#define TK_USING 115 #define TK_TAGS 115
#define TK_NULL 116 #define TK_USING 116
#define TK_NOW 117 #define TK_NULL 117
#define TK_SELECT 118 #define TK_NOW 118
#define TK_UNION 119 #define TK_SELECT 119
#define TK_ALL 120 #define TK_UNION 120
#define TK_DISTINCT 121 #define TK_ALL 121
#define TK_FROM 122 #define TK_DISTINCT 122
#define TK_VARIABLE 123 #define TK_FROM 123
#define TK_INTERVAL 124 #define TK_VARIABLE 124
#define TK_SESSION 125 #define TK_INTERVAL 125
#define TK_STATE_WINDOW 126 #define TK_EVERY 126
#define TK_FILL 127 #define TK_SESSION 127
#define TK_SLIDING 128 #define TK_STATE_WINDOW 128
#define TK_ORDER 129 #define TK_FILL 129
#define TK_BY 130 #define TK_SLIDING 130
#define TK_ASC 131 #define TK_ORDER 131
#define TK_DESC 132 #define TK_BY 132
#define TK_GROUP 133 #define TK_ASC 133
#define TK_HAVING 134 #define TK_GROUP 134
#define TK_LIMIT 135 #define TK_HAVING 135
#define TK_OFFSET 136 #define TK_LIMIT 136
#define TK_SLIMIT 137 #define TK_OFFSET 137
#define TK_SOFFSET 138 #define TK_SLIMIT 138
#define TK_WHERE 139 #define TK_SOFFSET 139
#define TK_RESET 140 #define TK_WHERE 140
#define TK_QUERY 141 #define TK_RESET 141
#define TK_SYNCDB 142 #define TK_QUERY 142
#define TK_ADD 143 #define TK_SYNCDB 143
#define TK_COLUMN 144 #define TK_ADD 144
#define TK_MODIFY 145 #define TK_COLUMN 145
#define TK_TAG 146 #define TK_MODIFY 146
#define TK_CHANGE 147 #define TK_TAG 147
#define TK_SET 148 #define TK_CHANGE 148
#define TK_KILL 149 #define TK_SET 149
#define TK_CONNECTION 150 #define TK_KILL 150
#define TK_STREAM 151 #define TK_CONNECTION 151
#define TK_COLON 152 #define TK_STREAM 152
#define TK_ABORT 153 #define TK_COLON 153
#define TK_AFTER 154 #define TK_ABORT 154
#define TK_ATTACH 155 #define TK_AFTER 155
#define TK_BEFORE 156 #define TK_ATTACH 156
#define TK_BEGIN 157 #define TK_BEFORE 157
#define TK_CASCADE 158 #define TK_BEGIN 158
#define TK_CLUSTER 159 #define TK_CASCADE 159
#define TK_CONFLICT 160 #define TK_CLUSTER 160
#define TK_COPY 161 #define TK_CONFLICT 161
#define TK_DEFERRED 162 #define TK_COPY 162
#define TK_DELIMITERS 163 #define TK_DEFERRED 163
#define TK_DETACH 164 #define TK_DELIMITERS 164
#define TK_EACH 165 #define TK_DETACH 165
#define TK_END 166 #define TK_EACH 166
#define TK_EXPLAIN 167 #define TK_END 167
#define TK_FAIL 168 #define TK_EXPLAIN 168
#define TK_FOR 169 #define TK_FAIL 169
#define TK_IGNORE 170 #define TK_FOR 170
#define TK_IMMEDIATE 171 #define TK_IGNORE 171
#define TK_INITIALLY 172 #define TK_IMMEDIATE 172
#define TK_INSTEAD 173 #define TK_INITIALLY 173
#define TK_MATCH 174 #define TK_INSTEAD 174
#define TK_KEY 175 #define TK_MATCH 175
#define TK_OF 176 #define TK_KEY 176
#define TK_RAISE 177 #define TK_OF 177
#define TK_REPLACE 178 #define TK_RAISE 178
#define TK_RESTRICT 179 #define TK_REPLACE 179
#define TK_ROW 180 #define TK_RESTRICT 180
#define TK_STATEMENT 181 #define TK_ROW 181
#define TK_TRIGGER 182 #define TK_STATEMENT 182
#define TK_VIEW 183 #define TK_TRIGGER 183
#define TK_IPTOKEN 184 #define TK_VIEW 184
#define TK_SEMI 185 #define TK_IPTOKEN 185
#define TK_NONE 186 #define TK_SEMI 186
#define TK_PREV 187 #define TK_NONE 187
#define TK_LINEAR 188 #define TK_PREV 188
#define TK_IMPORT 189 #define TK_LINEAR 189
#define TK_TBNAME 190 #define TK_IMPORT 190
#define TK_JOIN 191 #define TK_TBNAME 191
#define TK_INSERT 192 #define TK_JOIN 192
#define TK_INTO 193 #define TK_INSERT 193
#define TK_VALUES 194 #define TK_INTO 194
#define TK_VALUES 195
#define TK_SPACE 300 #define TK_SPACE 300

View File

@ -108,7 +108,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
arguments->is_raw_time = true; arguments->is_raw_time = true;
break; break;
case 'f': case 'f':
if (wordexp(arg, &full_path, 0) != 0) { if ((0 == strlen(arg)) || (wordexp(arg, &full_path, 0) != 0)) {
fprintf(stderr, "Invalid path %s\n", arg); fprintf(stderr, "Invalid path %s\n", arg);
return -1; return -1;
} }

File diff suppressed because it is too large Load Diff

View File

@ -225,16 +225,15 @@ static struct argp_option options[] = {
{"password", 'p', 0, 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},
{"mysqlFlag", 'q', "MYSQLFLAG", 0, "mysqlFlag, Default is 0", 0}, {"mysqlFlag", 'q', "MYSQLFLAG", 0, "mysqlFlag, Default is 0", 0},
// input/output file // input/output file
{"outpath", 'o', "OUTPATH", 0, "Output file path.", 1}, {"outpath", 'o', "OUTPATH", 0, "Output file path.", 1},
{"inpath", 'i', "INPATH", 0, "Input file path.", 1}, {"inpath", 'i', "INPATH", 0, "Input file path.", 1},
{"resultFile", 'r', "RESULTFILE", 0, "DumpOut/In Result file path and name.", 1}, {"resultFile", 'r', "RESULTFILE", 0, "DumpOut/In Result file path and name.", 1},
#ifdef _TD_POWER_ #ifdef _TD_POWER_
{"config", 'c', "CONFIG_DIR", 0, "Configure directory. Default is /etc/power/taos.cfg.", 1}, {"config-dir", 'c', "CONFIG_DIR", 0, "Configure directory. Default is /etc/power/taos.cfg.", 1},
#else #else
{"config", 'c', "CONFIG_DIR", 0, "Configure directory. Default is /etc/taos/taos.cfg.", 1}, {"config-dir", 'c', "CONFIG_DIR", 0, "Configure directory. Default is /etc/taos/taos.cfg.", 1},
#endif #endif
{"encode", 'e', "ENCODE", 0, "Input file encoding.", 1}, {"encode", 'e', "ENCODE", 0, "Input file encoding.", 1},
// dump unit options // dump unit options
@ -244,7 +243,7 @@ static struct argp_option options[] = {
// dump format options // dump format options
{"schemaonly", 's', 0, 0, "Only dump schema.", 2}, {"schemaonly", 's', 0, 0, "Only dump schema.", 2},
{"without-property", 'N', 0, 0, "Dump schema without properties.", 2}, {"without-property", 'N', 0, 0, "Dump schema without properties.", 2},
{"avro", 'V', 0, 0, "Dump apache avro format data file. By default, dump sql command sequence.", 2}, {"avro", 'v', 0, 0, "Dump apache avro format data file. By default, dump sql command sequence.", 2},
{"start-time", 'S', "START_TIME", 0, "Start time to dump. Either epoch or ISO8601/RFC3339 format is acceptable. ISO8601 format example: 2017-10-01T00:00:00.000+0800 or 2017-10-0100:00:00:000+0800 or '2017-10-01 00:00:00.000+0800'", 4}, {"start-time", 'S', "START_TIME", 0, "Start time to dump. Either epoch or ISO8601/RFC3339 format is acceptable. ISO8601 format example: 2017-10-01T00:00:00.000+0800 or 2017-10-0100:00:00:000+0800 or '2017-10-01 00:00:00.000+0800'", 4},
{"end-time", 'E', "END_TIME", 0, "End time to dump. Either epoch or ISO8601/RFC3339 format is acceptable. ISO8601 format example: 2017-10-01T00:00:00.000+0800 or 2017-10-0100:00:00.000+0800 or '2017-10-01 00:00:00.000+0800'", 5}, {"end-time", 'E', "END_TIME", 0, "End time to dump. Either epoch or ISO8601/RFC3339 format is acceptable. ISO8601 format example: 2017-10-01T00:00:00.000+0800 or 2017-10-0100:00:00.000+0800 or '2017-10-01 00:00:00.000+0800'", 5},
#if TSDB_SUPPORT_NANOSECOND == 1 #if TSDB_SUPPORT_NANOSECOND == 1
@ -267,7 +266,6 @@ typedef struct arguments {
char *user; char *user;
char password[SHELL_MAX_PASSWORD_LEN]; char password[SHELL_MAX_PASSWORD_LEN];
uint16_t port; uint16_t port;
char cversion[12];
uint16_t mysqlFlag; uint16_t mysqlFlag;
// output file // output file
char outpath[MAX_FILE_NAME_LEN]; char outpath[MAX_FILE_NAME_LEN];
@ -338,7 +336,6 @@ struct arguments g_args = {
"taosdata", "taosdata",
#endif #endif
0, 0,
"",
0, 0,
// outpath and inpath // outpath and inpath
"", "",
@ -370,6 +367,24 @@ struct arguments g_args = {
false // performance_print false // performance_print
}; };
static void errorPrintReqArg2(char *program, char *wrong_arg)
{
fprintf(stderr,
"%s: option requires a number argument '-%s'\n",
program, wrong_arg);
fprintf(stderr,
"Try `taosdump --help' or `taosdump --usage' for more information.\n");
}
static void errorPrintReqArg3(char *program, char *wrong_arg)
{
fprintf(stderr,
"%s: option '%s' requires an argument\n",
program, wrong_arg);
fprintf(stderr,
"Try `taosdump --help' or `taosdump --usage' for more information.\n");
}
/* Parse a single option. */ /* Parse a single option. */
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) {
/* Get the input argument from argp_parse, which we /* Get the input argument from argp_parse, which we
@ -390,20 +405,15 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
case 'p': case 'p':
break; break;
case 'P': case 'P':
if (!isStringNumber(arg)) {
errorPrintReqArg2("taosdump", "P");
exit(EXIT_FAILURE);
}
g_args.port = atoi(arg); g_args.port = atoi(arg);
break; break;
case 'q': case 'q':
g_args.mysqlFlag = atoi(arg); g_args.mysqlFlag = atoi(arg);
break; break;
case 'v':
if (wordexp(arg, &full_path, 0) != 0) {
errorPrint("Invalid client vesion %s\n", arg);
return -1;
}
tstrncpy(g_args.cversion, full_path.we_wordv[0], 11);
wordfree(&full_path);
break;
// output file path
case 'o': case 'o':
if (wordexp(arg, &full_path, 0) != 0) { if (wordexp(arg, &full_path, 0) != 0) {
errorPrint("Invalid path %s\n", arg); errorPrint("Invalid path %s\n", arg);
@ -430,9 +440,13 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
g_args.resultFile = arg; g_args.resultFile = arg;
break; break;
case 'c': case 'c':
if (0 == strlen(arg)) {
errorPrintReqArg3("taosdump", "-c or --config-dir");
exit(EXIT_FAILURE);
}
if (wordexp(arg, &full_path, 0) != 0) { if (wordexp(arg, &full_path, 0) != 0) {
errorPrint("Invalid path %s\n", arg); errorPrint("Invalid path %s\n", arg);
return -1; exit(EXIT_FAILURE);
} }
tstrncpy(configDir, full_path.we_wordv[0], MAX_FILE_NAME_LEN); tstrncpy(configDir, full_path.we_wordv[0], MAX_FILE_NAME_LEN);
wordfree(&full_path); wordfree(&full_path);
@ -453,7 +467,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
case 'N': case 'N':
g_args.with_property = false; g_args.with_property = false;
break; break;
case 'V': case 'v':
g_args.avro = true; g_args.avro = true;
break; break;
case 'S': case 'S':
@ -660,6 +674,9 @@ static void parse_timestamp(
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
static char verType[32] = {0};
sprintf(verType, "version: %s\n", version);
argp_program_version = verType;
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
@ -686,7 +703,6 @@ int main(int argc, char *argv[]) {
printf("user: %s\n", g_args.user); printf("user: %s\n", g_args.user);
printf("password: %s\n", g_args.password); printf("password: %s\n", g_args.password);
printf("port: %u\n", g_args.port); printf("port: %u\n", g_args.port);
printf("cversion: %s\n", g_args.cversion);
printf("mysqlFlag: %d\n", g_args.mysqlFlag); printf("mysqlFlag: %d\n", g_args.mysqlFlag);
printf("outpath: %s\n", g_args.outpath); printf("outpath: %s\n", g_args.outpath);
printf("inpath: %s\n", g_args.inpath); printf("inpath: %s\n", g_args.inpath);
@ -715,11 +731,6 @@ int main(int argc, char *argv[]) {
} }
} }
printf("==============================\n"); printf("==============================\n");
if (g_args.cversion[0] != 0){
tstrncpy(version, g_args.cversion, 11);
}
if (taosCheckParam(&g_args) < 0) { if (taosCheckParam(&g_args) < 0) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -737,7 +748,6 @@ int main(int argc, char *argv[]) {
fprintf(g_fpOfResult, "user: %s\n", g_args.user); fprintf(g_fpOfResult, "user: %s\n", g_args.user);
fprintf(g_fpOfResult, "password: %s\n", g_args.password); fprintf(g_fpOfResult, "password: %s\n", g_args.password);
fprintf(g_fpOfResult, "port: %u\n", g_args.port); fprintf(g_fpOfResult, "port: %u\n", g_args.port);
fprintf(g_fpOfResult, "cversion: %s\n", g_args.cversion);
fprintf(g_fpOfResult, "mysqlFlag: %d\n", g_args.mysqlFlag); fprintf(g_fpOfResult, "mysqlFlag: %d\n", g_args.mysqlFlag);
fprintf(g_fpOfResult, "outpath: %s\n", g_args.outpath); fprintf(g_fpOfResult, "outpath: %s\n", g_args.outpath);
fprintf(g_fpOfResult, "inpath: %s\n", g_args.inpath); fprintf(g_fpOfResult, "inpath: %s\n", g_args.inpath);

View File

@ -1518,6 +1518,13 @@ static int32_t mnodeChangeSuperTableColumn(SMnodeMsg *pMsg) {
// update // update
SSchema *schema = (SSchema *) (pStable->schema + col); SSchema *schema = (SSchema *) (pStable->schema + col);
ASSERT(schema->type == TSDB_DATA_TYPE_BINARY || schema->type == TSDB_DATA_TYPE_NCHAR); ASSERT(schema->type == TSDB_DATA_TYPE_BINARY || schema->type == TSDB_DATA_TYPE_NCHAR);
if (pAlter->schema[0].bytes <= schema->bytes) {
mError("msg:%p, app:%p stable:%s, modify column len. column:%s, len from %d to %d", pMsg, pMsg->rpcMsg.ahandle,
pStable->info.tableId, name, schema->bytes, pAlter->schema[0].bytes);
return TSDB_CODE_MND_INVALID_COLUMN_LENGTH;
}
schema->bytes = pAlter->schema[0].bytes; schema->bytes = pAlter->schema[0].bytes;
pStable->sversion++; pStable->sversion++;
mInfo("msg:%p, app:%p stable %s, start to modify column %s len to %d", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, mInfo("msg:%p, app:%p stable %s, start to modify column %s len to %d", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId,
@ -1548,6 +1555,12 @@ static int32_t mnodeChangeSuperTableTag(SMnodeMsg *pMsg) {
// update // update
SSchema *schema = (SSchema *) (pStable->schema + col + pStable->numOfColumns); SSchema *schema = (SSchema *) (pStable->schema + col + pStable->numOfColumns);
ASSERT(schema->type == TSDB_DATA_TYPE_BINARY || schema->type == TSDB_DATA_TYPE_NCHAR); ASSERT(schema->type == TSDB_DATA_TYPE_BINARY || schema->type == TSDB_DATA_TYPE_NCHAR);
if (pAlter->schema[0].bytes <= schema->bytes) {
mError("msg:%p, app:%p stable:%s, modify tag len. tag:%s, len from %d to %d", pMsg, pMsg->rpcMsg.ahandle,
pStable->info.tableId, name, schema->bytes, pAlter->schema[0].bytes);
return TSDB_CODE_MND_INVALID_TAG_LENGTH;
}
schema->bytes = pAlter->schema[0].bytes; schema->bytes = pAlter->schema[0].bytes;
pStable->tversion++; pStable->tversion++;
mInfo("msg:%p, app:%p stable %s, start to modify tag len %s to %d", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, mInfo("msg:%p, app:%p stable %s, start to modify tag len %s to %d", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId,

View File

@ -50,14 +50,20 @@ void osInit() {
char* taosGetCmdlineByPID(int pid) { char* taosGetCmdlineByPID(int pid) {
static char cmdline[1024]; static char cmdline[1024];
sprintf(cmdline, "/proc/%d/cmdline", pid); sprintf(cmdline, "/proc/%d/cmdline", pid);
FILE* f = fopen(cmdline, "r");
if (f) { int fd = open(cmdline, O_RDONLY);
size_t size; if (fd >= 0) {
size = fread(cmdline, sizeof(char), 1024, f); int n = read(fd, cmdline, sizeof(cmdline) - 1);
if (size > 0) { if (n < 0) n = 0;
if ('\n' == cmdline[size - 1]) cmdline[size - 1] = '\0';
} if (n > 0 && cmdline[n - 1] == '\n') --n;
fclose(f);
cmdline[n] = 0;
close(fd);
} else {
cmdline[0] = 0;
} }
return cmdline; return cmdline;
} }

View File

@ -6,6 +6,7 @@ INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc)
INCLUDE_DIRECTORIES(inc) INCLUDE_DIRECTORIES(inc)
AUX_SOURCE_DIRECTORY(src SRC) AUX_SOURCE_DIRECTORY(src SRC)

View File

@ -19,6 +19,7 @@
#include "httpLog.h" #include "httpLog.h"
#include "httpRestHandle.h" #include "httpRestHandle.h"
#include "httpRestJson.h" #include "httpRestJson.h"
#include "tglobal.h"
static HttpDecodeMethod restDecodeMethod = {"rest", restProcessRequest}; static HttpDecodeMethod restDecodeMethod = {"rest", restProcessRequest};
static HttpDecodeMethod restDecodeMethod2 = {"restful", restProcessRequest}; static HttpDecodeMethod restDecodeMethod2 = {"restful", restProcessRequest};
@ -111,6 +112,14 @@ bool restProcessSqlRequest(HttpContext* pContext, int32_t timestampFmt) {
pContext->db[0] = '\0'; pContext->db[0] = '\0';
HttpString *path = &pContext->parser->path[REST_USER_USEDB_URL_POS]; HttpString *path = &pContext->parser->path[REST_USER_USEDB_URL_POS];
if (tsHttpDbNameMandatory) {
if (path->pos == 0) {
httpError("context:%p, fd:%d, user:%s, database name is mandatory", pContext, pContext->fd, pContext->user);
httpSendErrorResp(pContext, TSDB_CODE_HTTP_INVALID_URL);
return false;
}
}
if (path->pos > 0 && !(strlen(sql) > 4 && (sql[0] == 'u' || sql[0] == 'U') && if (path->pos > 0 && !(strlen(sql) > 4 && (sql[0] == 'u' || sql[0] == 'U') &&
(sql[1] == 's' || sql[1] == 'S') && (sql[2] == 'e' || sql[2] == 'E') && sql[3] == ' ')) (sql[1] == 's' || sql[1] == 'S') && (sql[2] == 'e' || sql[2] == 'E') && sql[3] == ' '))
{ {

View File

@ -34,7 +34,7 @@
#define monTrace(...) { if (monDebugFlag & DEBUG_TRACE) { taosPrintLog("MON ", monDebugFlag, __VA_ARGS__); }} #define monTrace(...) { if (monDebugFlag & DEBUG_TRACE) { taosPrintLog("MON ", monDebugFlag, __VA_ARGS__); }}
#define SQL_LENGTH 1030 #define SQL_LENGTH 1030
#define LOG_LEN_STR 100 #define LOG_LEN_STR 512
#define IP_LEN_STR TSDB_EP_LEN #define IP_LEN_STR TSDB_EP_LEN
#define CHECK_INTERVAL 1000 #define CHECK_INTERVAL 1000

View File

@ -221,6 +221,7 @@ typedef struct SQueryAttr {
bool distinct; // distinct query or not bool distinct; // distinct query or not
bool stateWindow; // window State on sub/normal table bool stateWindow; // window State on sub/normal table
bool createFilterOperator; // if filter operator is needed bool createFilterOperator; // if filter operator is needed
bool multigroupResult; // multigroup result can exist in one SSDataBlock
int32_t interBufSize; // intermediate buffer sizse int32_t interBufSize; // intermediate buffer sizse
int32_t havingNum; // having expr number int32_t havingNum; // having expr number
@ -477,6 +478,13 @@ typedef struct SSLimitOperatorInfo {
char **prevRow; char **prevRow;
SArray *orderColumnList; SArray *orderColumnList;
bool hasPrev;
bool ignoreCurrentGroup;
bool multigroupResult;
SSDataBlock *pRes; // result buffer
SSDataBlock *pPrevBlock;
int64_t capacity;
int64_t threshold;
} SSLimitOperatorInfo; } SSLimitOperatorInfo;
typedef struct SFilterOperatorInfo { typedef struct SFilterOperatorInfo {
@ -488,8 +496,9 @@ typedef struct SFillOperatorInfo {
SFillInfo *pFillInfo; SFillInfo *pFillInfo;
SSDataBlock *pRes; SSDataBlock *pRes;
int64_t totalInputRows; int64_t totalInputRows;
void **p;
SSDataBlock *existNewGroupBlock; SSDataBlock *existNewGroupBlock;
bool multigroupResult;
} SFillOperatorInfo; } SFillOperatorInfo;
typedef struct SGroupbyOperatorInfo { typedef struct SGroupbyOperatorInfo {
@ -551,9 +560,9 @@ typedef struct SMultiwayMergeInfo {
bool hasDataBlockForNewGroup; bool hasDataBlockForNewGroup;
SSDataBlock *pExistBlock; SSDataBlock *pExistBlock;
bool hasPrev;
bool groupMix;
SArray *udfInfo; SArray *udfInfo;
bool hasPrev;
bool multiGroupResults;
} SMultiwayMergeInfo; } SMultiwayMergeInfo;
// todo support the disk-based sort // todo support the disk-based sort
@ -575,7 +584,7 @@ SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorI
SOperatorInfo* createTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
SOperatorInfo* createAllTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createAllTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
SOperatorInfo* createSWindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createSWindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, bool multigroupResult);
SOperatorInfo* createGroupbyOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createGroupbyOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
SOperatorInfo* createMultiTableAggOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createMultiTableAggOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
@ -584,10 +593,10 @@ SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInf
SOperatorInfo* createDistinctOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createDistinctOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv); SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv);
SOperatorInfo* createMultiwaySortOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput, SOperatorInfo* createMultiwaySortOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput,
int32_t numOfRows, void* merger, bool groupMix); int32_t numOfRows, void* merger);
SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* param, SArray* pUdfInfo); SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* param, SArray* pUdfInfo, bool groupResultMixedUp);
SOperatorInfo* createStatewindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createStatewindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* merger); SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* merger, bool multigroupResult);
SOperatorInfo* createFilterOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, SOperatorInfo* createFilterOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
int32_t numOfOutput, SColumnInfo* pCols, int32_t numOfFilter); int32_t numOfOutput, SColumnInfo* pCols, int32_t numOfFilter);
@ -604,6 +613,7 @@ bool doFilterDataBlock(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilter
void doCompactSDataBlock(SSDataBlock* pBlock, int32_t numOfRows, int8_t* p); void doCompactSDataBlock(SSDataBlock* pBlock, int32_t numOfRows, int8_t* p);
SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numOfRows); SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numOfRows);
void* destroyOutputBuf(SSDataBlock* pBlock); void* destroyOutputBuf(SSDataBlock* pBlock);
void* doDestroyFilterInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols); void* doDestroyFilterInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols);

View File

@ -80,6 +80,7 @@ typedef struct tVariantListItem {
} tVariantListItem; } tVariantListItem;
typedef struct SIntervalVal { typedef struct SIntervalVal {
int32_t token;
SStrToken interval; SStrToken interval;
SStrToken offset; SStrToken offset;
} SIntervalVal; } SIntervalVal;

View File

@ -165,6 +165,7 @@ typedef struct SQueryInfo {
bool orderProjectQuery; bool orderProjectQuery;
bool stateWindow; bool stateWindow;
bool globalMerge; bool globalMerge;
bool multigroupResult;
} SQueryInfo; } SQueryInfo;
/** /**

View File

@ -162,7 +162,10 @@ cmd ::= DESCRIBE ids(X) cpxName(Y). {
X.n += Y.n; X.n += Y.n;
setDCLSqlElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &X); setDCLSqlElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &X);
} }
cmd ::= DESC ids(X) cpxName(Y). {
X.n += Y.n;
setDCLSqlElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &X);
}
/////////////////////////////////THE ALTER STATEMENT//////////////////////////////////////// /////////////////////////////////THE ALTER STATEMENT////////////////////////////////////////
cmd ::= ALTER USER ids(X) PASS ids(Y). { setAlterUserSql(pInfo, TSDB_ALTER_USER_PASSWD, &X, &Y, NULL); } cmd ::= ALTER USER ids(X) PASS ids(Y). { setAlterUserSql(pInfo, TSDB_ALTER_USER_PASSWD, &X, &Y, NULL); }
cmd ::= ALTER USER ids(X) PRIVILEGE ids(Y). { setAlterUserSql(pInfo, TSDB_ALTER_USER_PRIVILEGES, &X, NULL, &Y);} cmd ::= ALTER USER ids(X) PRIVILEGE ids(Y). { setAlterUserSql(pInfo, TSDB_ALTER_USER_PRIVILEGES, &X, NULL, &Y);}
@ -479,7 +482,7 @@ tagitem(A) ::= PLUS(X) FLOAT(Y). {
//////////////////////// The SELECT statement ///////////////////////////////// //////////////////////// The SELECT statement /////////////////////////////////
%type select {SSqlNode*} %type select {SSqlNode*}
%destructor select {destroySqlNode($$);} %destructor select {destroySqlNode($$);}
select(A) ::= SELECT(T) selcollist(W) from(X) where_opt(Y) interval_opt(K) sliding_opt(S) session_option(H) windowstate_option(D) fill_opt(F)groupby_opt(P) having_opt(N) orderby_opt(Z) slimit_opt(G) limit_opt(L). { select(A) ::= SELECT(T) selcollist(W) from(X) where_opt(Y) interval_option(K) sliding_opt(S) session_option(H) windowstate_option(D) fill_opt(F)groupby_opt(P) having_opt(N) orderby_opt(Z) slimit_opt(G) limit_opt(L). {
A = tSetQuerySqlNode(&T, W, X, Y, P, Z, &K, &H, &D, &S, F, &L, &G, N); A = tSetQuerySqlNode(&T, W, X, Y, P, Z, &K, &H, &D, &S, F, &L, &G, N);
} }
@ -493,7 +496,7 @@ union(Y) ::= union(Z) UNION ALL select(X). { Y = appendSelectClause(Z, X); }
cmd ::= union(X). { setSqlInfo(pInfo, X, NULL, TSDB_SQL_SELECT); } cmd ::= union(X). { setSqlInfo(pInfo, X, NULL, TSDB_SQL_SELECT); }
// Support for the SQL exprssion without from & where subclauses, e.g., // Support for the SQL exprssion without from & where subclauses, e.g.,
// select current_database() // select database()
// select server_version() // select server_version()
// select client_version() // select client_version()
// select server_state() // select server_state()
@ -569,10 +572,14 @@ tablelist(A) ::= tablelist(Y) COMMA ids(X) cpxName(Z) ids(F). {
%type tmvar {SStrToken} %type tmvar {SStrToken}
tmvar(A) ::= VARIABLE(X). {A = X;} tmvar(A) ::= VARIABLE(X). {A = X;}
%type interval_opt {SIntervalVal} %type interval_option {SIntervalVal}
interval_opt(N) ::= INTERVAL LP tmvar(E) RP. {N.interval = E; N.offset.n = 0;} interval_option(N) ::= intervalKey(A) LP tmvar(E) RP. {N.interval = E; N.offset.n = 0; N.token = A;}
interval_opt(N) ::= INTERVAL LP tmvar(E) COMMA tmvar(X) RP. {N.interval = E; N.offset = X;} interval_option(N) ::= intervalKey(A) LP tmvar(E) COMMA tmvar(X) RP. {N.interval = E; N.offset = X; N.token = A;}
interval_opt(N) ::= . {memset(&N, 0, sizeof(N));} interval_option(N) ::= . {memset(&N, 0, sizeof(N));}
%type intervalKey {int32_t}
intervalKey(A) ::= INTERVAL. {A = TK_INTERVAL;}
intervalKey(A) ::= EVERY. {A = TK_EVERY; }
%type session_option {SSessionWindowVal} %type session_option {SSessionWindowVal}
session_option(X) ::= . {X.col.n = 0; X.gap.n = 0;} session_option(X) ::= . {X.col.n = 0; X.gap.n = 0;}
@ -581,6 +588,7 @@ session_option(X) ::= SESSION LP ids(V) cpxName(Z) COMMA tmvar(Y) RP. {
X.col = V; X.col = V;
X.gap = Y; X.gap = Y;
} }
%type windowstate_option {SWindowStateVal} %type windowstate_option {SWindowStateVal}
windowstate_option(X) ::= . { X.col.n = 0; X.col.z = NULL;} windowstate_option(X) ::= . { X.col.n = 0; X.col.z = NULL;}
windowstate_option(X) ::= STATE_WINDOW LP ids(V) RP. { X.col = V; } windowstate_option(X) ::= STATE_WINDOW LP ids(V) RP. { X.col = V; }

View File

@ -1214,6 +1214,31 @@ static int32_t minmax_merge_impl(SQLFunctionCtx *pCtx, int32_t bytes, char *outp
DUPATE_DATA_WITHOUT_TS(pCtx, *(int64_t *)output, v, notNullElems, isMin); DUPATE_DATA_WITHOUT_TS(pCtx, *(int64_t *)output, v, notNullElems, isMin);
break; break;
} }
case TSDB_DATA_TYPE_UTINYINT: {
uint8_t v = GET_UINT8_VAL(input);
DUPATE_DATA_WITHOUT_TS(pCtx, *(uint8_t *)output, v, notNullElems, isMin);
break;
}
case TSDB_DATA_TYPE_USMALLINT: {
uint16_t v = GET_UINT16_VAL(input);
DUPATE_DATA_WITHOUT_TS(pCtx, *(uint16_t *)output, v, notNullElems, isMin);
break;
}
case TSDB_DATA_TYPE_UINT: {
uint32_t v = GET_UINT32_VAL(input);
DUPATE_DATA_WITHOUT_TS(pCtx, *(uint32_t *)output, v, notNullElems, isMin);
break;
}
case TSDB_DATA_TYPE_UBIGINT: {
uint64_t v = GET_UINT64_VAL(input);
DUPATE_DATA_WITHOUT_TS(pCtx, *(uint64_t *)output, v, notNullElems, isMin);
break;
}
default: default:
break; break;
} }

View File

@ -38,15 +38,12 @@
#define SET_REVERSE_SCAN_FLAG(runtime) ((runtime)->scanFlag = REVERSE_SCAN) #define SET_REVERSE_SCAN_FLAG(runtime) ((runtime)->scanFlag = REVERSE_SCAN)
#define TSWINDOW_IS_EQUAL(t1, t2) (((t1).skey == (t2).skey) && ((t1).ekey == (t2).ekey)) #define TSWINDOW_IS_EQUAL(t1, t2) (((t1).skey == (t2).skey) && ((t1).ekey == (t2).ekey))
#define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC)) #define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC))
#define SDATA_BLOCK_INITIALIZER (SDataBlockInfo) {{0}, 0} #define SDATA_BLOCK_INITIALIZER (SDataBlockInfo) {{0}, 0}
#define MULTI_KEY_DELIM "-" #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;\
@ -233,6 +230,12 @@ static void destroyStateWindowOperatorInfo(void* param, int32_t numOfOutput);
static void destroyAggOperatorInfo(void* param, int32_t numOfOutput); static void destroyAggOperatorInfo(void* param, int32_t numOfOutput);
static void destroyOperatorInfo(SOperatorInfo* pOperator); static void destroyOperatorInfo(SOperatorInfo* pOperator);
static void doSetOperatorCompleted(SOperatorInfo* pOperator) {
pOperator->status = OP_EXEC_DONE;
if (pOperator->pRuntimeEnv != NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
}
}
static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock); static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock);
@ -2262,30 +2265,30 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf
case OP_Fill: { case OP_Fill: {
SOperatorInfo* pInfo = pRuntimeEnv->proot; SOperatorInfo* pInfo = pRuntimeEnv->proot;
pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput); pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput, pQueryAttr->multigroupResult);
break; break;
} }
case OP_MultiwayMergeSort: { case OP_MultiwayMergeSort: {
bool groupMix = true; pRuntimeEnv->proot = createMultiwaySortOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput, 4096, merger);
if (pQueryAttr->slimit.offset != 0 || pQueryAttr->slimit.limit != -1) {
groupMix = false;
}
pRuntimeEnv->proot = createMultiwaySortOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput,
4096, merger, groupMix); // TODO hack it
break; break;
} }
case OP_GlobalAggregate: { case OP_GlobalAggregate: { // If fill operator exists, the result rows of different group can not be in the same SSDataBlock.
bool multigroupResult = pQueryAttr->multigroupResult;
if (pQueryAttr->multigroupResult) {
multigroupResult = (pQueryAttr->fillType == TSDB_FILL_NONE);
}
pRuntimeEnv->proot = createGlobalAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3, pRuntimeEnv->proot = createGlobalAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3,
pQueryAttr->numOfExpr3, merger, pQueryAttr->pUdfInfo); pQueryAttr->numOfExpr3, merger, pQueryAttr->pUdfInfo, multigroupResult);
break; break;
} }
case OP_SLimit: { case OP_SLimit: {
pRuntimeEnv->proot = createSLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3, int32_t num = pRuntimeEnv->proot->numOfOutput;
pQueryAttr->numOfExpr3, merger); SExprInfo* pExpr = pRuntimeEnv->proot->pExpr;
pRuntimeEnv->proot = createSLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pExpr, num, merger, pQueryAttr->multigroupResult);
break; break;
} }
@ -3636,27 +3639,15 @@ void updateOutputBuf(SOptrBasicInfo* pBInfo, int32_t *bufCapacity, int32_t numOf
SColumnInfoData *pColInfo = taosArrayGet(pDataBlock->pDataBlock, i); SColumnInfoData *pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
pBInfo->pCtx[i].pOutput = pColInfo->pData + pColInfo->info.bytes * pDataBlock->info.rows; pBInfo->pCtx[i].pOutput = pColInfo->pData + pColInfo->info.bytes * pDataBlock->info.rows;
// re-estabilish output buffer pointer. // set the correct pointer after the memory buffer reallocated.
int32_t functionId = pBInfo->pCtx[i].functionId; int32_t functionId = pBInfo->pCtx[i].functionId;
if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF || functionId == TSDB_FUNC_DERIVATIVE){
if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF || functionId == TSDB_FUNC_DERIVATIVE) {
if (i > 0) pBInfo->pCtx[i].ptsOutputBuf = pBInfo->pCtx[i-1].pOutput; if (i > 0) pBInfo->pCtx[i].ptsOutputBuf = pBInfo->pCtx[i-1].pOutput;
} }
} }
} }
void clearOutputBuf(SOptrBasicInfo* pBInfo, int32_t *bufCapacity) {
SSDataBlock* pDataBlock = pBInfo->pRes;
for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
SColumnInfoData *pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
int32_t functionId = pBInfo->pCtx[i].functionId;
if (functionId < 0) {
memset(pBInfo->pCtx[i].pOutput, 0, pColInfo->info.bytes * (*bufCapacity));
}
}
}
void copyTsColoum(SSDataBlock* pRes, SQLFunctionCtx* pCtx, int32_t numOfOutput) { void copyTsColoum(SSDataBlock* pRes, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
bool needCopyTs = false; bool needCopyTs = false;
int32_t tsNum = 0; int32_t tsNum = 0;
@ -3687,6 +3678,19 @@ void copyTsColoum(SSDataBlock* pRes, SQLFunctionCtx* pCtx, int32_t numOfOutput)
} }
} }
void clearOutputBuf(SOptrBasicInfo* pBInfo, int32_t *bufCapacity) {
SSDataBlock* pDataBlock = pBInfo->pRes;
for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
SColumnInfoData *pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
int32_t functionId = pBInfo->pCtx[i].functionId;
if (functionId < 0) {
memset(pBInfo->pCtx[i].pOutput, 0, pColInfo->info.bytes * (*bufCapacity));
}
}
}
void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size) { void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size) {
for (int32_t j = 0; j < size; ++j) { for (int32_t j = 0; j < size; ++j) {
SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]); SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
@ -4199,6 +4203,7 @@ static void toSSDataBlock(SGroupResInfo *pGroupResInfo, SQueryRuntimeEnv* pRunti
// refactor : extract method // refactor : extract method
SColumnInfoData* pInfoData = taosArrayGet(pBlock->pDataBlock, 0); SColumnInfoData* pInfoData = taosArrayGet(pBlock->pDataBlock, 0);
//add condition (pBlock->info.rows >= 1) just to runtime happy //add condition (pBlock->info.rows >= 1) just to runtime happy
if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP && pBlock->info.rows >= 1) { if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP && pBlock->info.rows >= 1) {
STimeWindow* w = &pBlock->info.window; STimeWindow* w = &pBlock->info.window;
@ -4313,15 +4318,15 @@ static void doCopyQueryResultToMsg(SQInfo *pQInfo, int32_t numOfRows, char *data
} }
} }
int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity) { int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity, void** p) {
void** p = calloc(pFillInfo->numOfCols, POINTER_BYTES);
for(int32_t i = 0; i < pFillInfo->numOfCols; ++i) { for(int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
SColumnInfoData* pColInfoData = taosArrayGet(pOutput->pDataBlock, i); SColumnInfoData* pColInfoData = taosArrayGet(pOutput->pDataBlock, i);
p[i] = pColInfoData->pData; p[i] = pColInfoData->pData + (pColInfoData->info.bytes * pOutput->info.rows);
} }
pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity); int32_t numOfRows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity - pOutput->info.rows);
tfree(p); pOutput->info.rows += numOfRows;
return pOutput->info.rows; return pOutput->info.rows;
} }
@ -5365,11 +5370,12 @@ static void destroyGlobalAggOperatorInfo(void* param, int32_t numOfOutput) {
static void destroySlimitOperatorInfo(void* param, int32_t numOfOutput) { static void destroySlimitOperatorInfo(void* param, int32_t numOfOutput) {
SSLimitOperatorInfo *pInfo = (SSLimitOperatorInfo*) param; SSLimitOperatorInfo *pInfo = (SSLimitOperatorInfo*) param;
taosArrayDestroy(pInfo->orderColumnList); taosArrayDestroy(pInfo->orderColumnList);
pInfo->pRes = destroyOutputBuf(pInfo->pRes);
tfree(pInfo->prevRow); tfree(pInfo->prevRow);
} }
SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream,
SExprInfo* pExpr, int32_t numOfOutput, void* param, SArray* pUdfInfo) { SExprInfo* pExpr, int32_t numOfOutput, void* param, SArray* pUdfInfo, bool groupResultMixedUp) {
SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo)); SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo));
pInfo->resultRowFactor = pInfo->resultRowFactor =
@ -5377,13 +5383,12 @@ SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv,
pRuntimeEnv->scanFlag = MERGE_STAGE; // TODO init when creating pCtx pRuntimeEnv->scanFlag = MERGE_STAGE; // TODO init when creating pCtx
pInfo->multiGroupResults = groupResultMixedUp;
pInfo->pMerge = param; pInfo->pMerge = param;
pInfo->bufCapacity = 4096; pInfo->bufCapacity = 4096;
pInfo->udfInfo = pUdfInfo; pInfo->udfInfo = pUdfInfo;
pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity * pInfo->resultRowFactor); pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity * pInfo->resultRowFactor);
pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset); pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
pInfo->orderColumnList = getOrderCheckColumns(pRuntimeEnv->pQueryAttr); pInfo->orderColumnList = getOrderCheckColumns(pRuntimeEnv->pQueryAttr);
pInfo->groupColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr); pInfo->groupColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr);
@ -5438,17 +5443,15 @@ SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv,
} }
SOperatorInfo *createMultiwaySortOperatorInfo(SQueryRuntimeEnv *pRuntimeEnv, SExprInfo *pExpr, int32_t numOfOutput, SOperatorInfo *createMultiwaySortOperatorInfo(SQueryRuntimeEnv *pRuntimeEnv, SExprInfo *pExpr, int32_t numOfOutput,
int32_t numOfRows, void *merger, bool groupMix) { int32_t numOfRows, void *merger) {
SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo)); SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo));
pInfo->pMerge = merger; pInfo->pMerge = merger;
pInfo->groupMix = groupMix;
pInfo->bufCapacity = numOfRows; pInfo->bufCapacity = numOfRows;
pInfo->orderColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr); pInfo->orderColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr);
pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows); pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows);
{ { // todo extract method to create prev compare buffer
int32_t len = 0; int32_t len = 0;
for(int32_t i = 0; i < numOfOutput; ++i) { for(int32_t i = 0; i < numOfOutput; ++i) {
len += pExpr[i].base.colBytes; len += pExpr[i].base.colBytes;
@ -5456,8 +5459,8 @@ SOperatorInfo *createMultiwaySortOperatorInfo(SQueryRuntimeEnv *pRuntimeEnv, SEx
int32_t numOfCols = (pInfo->orderColumnList != NULL)? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0; int32_t numOfCols = (pInfo->orderColumnList != NULL)? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0;
pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len)); pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
int32_t offset = POINTER_BYTES * numOfCols;
int32_t offset = POINTER_BYTES * numOfCols;
for(int32_t i = 0; i < numOfCols; ++i) { for(int32_t i = 0; i < numOfCols; ++i) {
pInfo->prevRow[i] = (char*)pInfo->prevRow + offset; pInfo->prevRow[i] = (char*)pInfo->prevRow + offset;
@ -5473,7 +5476,8 @@ SOperatorInfo *createMultiwaySortOperatorInfo(SQueryRuntimeEnv *pRuntimeEnv, SEx
pOperator->status = OP_IN_EXECUTING; pOperator->status = OP_IN_EXECUTING;
pOperator->info = pInfo; pOperator->info = pInfo;
pOperator->pRuntimeEnv = pRuntimeEnv; pOperator->pRuntimeEnv = pRuntimeEnv;
pOperator->numOfOutput = pRuntimeEnv->pQueryAttr->numOfCols; pOperator->numOfOutput = numOfOutput;
pOperator->pExpr = pExpr;
pOperator->exec = doMultiwayMergeSort; pOperator->exec = doMultiwayMergeSort;
pOperator->cleanup = destroyGlobalAggOperatorInfo; pOperator->cleanup = destroyGlobalAggOperatorInfo;
return pOperator; return pOperator;
@ -5519,8 +5523,7 @@ static SSDataBlock* doSort(void* param, bool* newgroup) {
// start to flush data into disk and try do multiway merge sort // start to flush data into disk and try do multiway merge sort
if (pBlock == NULL) { if (pBlock == NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); doSetOperatorCompleted(pOperator);
pOperator->status = OP_EXEC_DONE;
break; break;
} }
@ -5631,8 +5634,7 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) {
doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock); doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock);
} }
pOperator->status = OP_EXEC_DONE; doSetOperatorCompleted(pOperator);
setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
finalizeQueryResult(pOperator, pInfo->pCtx, &pInfo->resultRowInfo, pInfo->rowCellInfoOffset); finalizeQueryResult(pOperator, pInfo->pCtx, &pInfo->resultRowInfo, pInfo->rowCellInfoOffset);
pInfo->pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput); pInfo->pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
@ -5708,7 +5710,7 @@ static SSDataBlock* doSTableAggregate(void* param, bool* newgroup) {
toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes); toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes);
if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
pOperator->status = OP_EXEC_DONE; doSetOperatorCompleted(pOperator);
} }
return pInfo->pRes; return pInfo->pRes;
@ -5826,8 +5828,7 @@ static SSDataBlock* doLimit(void* param, bool* newgroup) {
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); doSetOperatorCompleted(pOperator);
pOperator->status = OP_EXEC_DONE;
return NULL; return NULL;
} }
@ -5855,8 +5856,7 @@ static SSDataBlock* doLimit(void* param, bool* newgroup) {
pBlock->info.rows = (int32_t)(pInfo->limit - pInfo->total); pBlock->info.rows = (int32_t)(pInfo->limit - pInfo->total);
pInfo->total = pInfo->limit; pInfo->total = pInfo->limit;
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); doSetOperatorCompleted(pOperator);
pOperator->status = OP_EXEC_DONE;
} else { } else {
pInfo->total += pBlock->info.rows; pInfo->total += pBlock->info.rows;
} }
@ -5891,8 +5891,7 @@ static SSDataBlock* doFilter(void* param, bool* newgroup) {
} }
} }
setQueryStatus(pRuntimeEnv, QUERY_COMPLETED); doSetOperatorCompleted(pOperator);
pOperator->status = OP_EXEC_DONE;
return NULL; return NULL;
} }
@ -5907,9 +5906,8 @@ static SSDataBlock* doIntervalAgg(void* param, bool* newgroup) {
SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
if (pOperator->status == OP_RES_TO_RETURN) { if (pOperator->status == OP_RES_TO_RETURN) {
toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes); toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
pOperator->status = OP_EXEC_DONE; doSetOperatorCompleted(pOperator);
} }
return pIntervalInfo->pRes; return pIntervalInfo->pRes;
@ -5950,7 +5948,7 @@ static SSDataBlock* doIntervalAgg(void* param, bool* newgroup) {
toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes); toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
pOperator->status = OP_EXEC_DONE; doSetOperatorCompleted(pOperator);
} }
return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes; return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes;
@ -5969,7 +5967,7 @@ static SSDataBlock* doAllIntervalAgg(void* param, bool* newgroup) {
toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes); toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
pOperator->status = OP_EXEC_DONE; doSetOperatorCompleted(pOperator);
} }
return pIntervalInfo->pRes; return pIntervalInfo->pRes;
@ -6027,9 +6025,10 @@ static SSDataBlock* doSTableIntervalAgg(void* param, bool* newgroup) {
if (pOperator->status == OP_RES_TO_RETURN) { if (pOperator->status == OP_RES_TO_RETURN) {
int64_t st = taosGetTimestampUs(); int64_t st = taosGetTimestampUs();
copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset); copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) { if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
pOperator->status = OP_EXEC_DONE; doSetOperatorCompleted(pOperator);
} }
SQInfo* pQInfo = pRuntimeEnv->qinfo; SQInfo* pQInfo = pRuntimeEnv->qinfo;
@ -6389,19 +6388,13 @@ static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) {
return pInfo->binfo.pRes; return pInfo->binfo.pRes;
} }
static SSDataBlock* doFill(void* param, bool* newgroup) { static void doHandleRemainBlockFromNewGroup(SFillOperatorInfo *pInfo, SQueryRuntimeEnv *pRuntimeEnv, bool *newgroup) {
SOperatorInfo* pOperator = (SOperatorInfo*) param;
if (pOperator->status == OP_EXEC_DONE) {
return NULL;
}
SFillOperatorInfo *pInfo = pOperator->info;
SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
if (taosFillHasMoreResults(pInfo->pFillInfo)) { if (taosFillHasMoreResults(pInfo->pFillInfo)) {
*newgroup = false; *newgroup = false;
doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity); doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity, pInfo->p);
return pInfo->pRes; if (pInfo->pRes->info.rows > pRuntimeEnv->resultInfo.threshold || (!pInfo->multigroupResult)) {
return;
}
} }
// handle the cached new group data block // handle the cached new group data block
@ -6413,11 +6406,47 @@ static SSDataBlock* doFill(void* param, bool* newgroup) {
taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey); taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey);
taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock); taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock);
doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity); doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity, pInfo->p);
pInfo->existNewGroupBlock = NULL; pInfo->existNewGroupBlock = NULL;
*newgroup = true; *newgroup = true;
return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
} }
}
static SSDataBlock* doFill(void* param, bool* newgroup) {
SOperatorInfo* pOperator = (SOperatorInfo*) param;
SFillOperatorInfo *pInfo = pOperator->info;
pInfo->pRes->info.rows = 0;
if (pOperator->status == OP_EXEC_DONE) {
return NULL;
}
SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
doHandleRemainBlockFromNewGroup(pInfo, pRuntimeEnv, newgroup);
if (pInfo->pRes->info.rows > pRuntimeEnv->resultInfo.threshold || (!pInfo->multigroupResult && pInfo->pRes->info.rows > 0)) {
return pInfo->pRes;
}
// if (taosFillHasMoreResults(pInfo->pFillInfo)) {
// *newgroup = false;
// doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity);
// return pInfo->pRes;
// }
//
// // handle the cached new group data block
// if (pInfo->existNewGroupBlock) {
// pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows;
// int64_t ekey = Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)?pRuntimeEnv->pQueryAttr->window.ekey:pInfo->existNewGroupBlock->info.window.ekey;
// taosResetFillInfo(pInfo->pFillInfo, pInfo->pFillInfo->start);
//
// taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey);
// taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock);
//
// doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
// pInfo->existNewGroupBlock = NULL;
// *newgroup = true;
// return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
// }
while(1) { while(1) {
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
@ -6432,8 +6461,8 @@ static SSDataBlock* doFill(void* param, bool* newgroup) {
pInfo->existNewGroupBlock = pBlock; pInfo->existNewGroupBlock = pBlock;
*newgroup = false; *newgroup = false;
// fill the previous group data block // Fill the previous group data block, before handle the data block of new group.
// before handle a new data block, close the fill operation for previous group data block // Close the fill operation for previous group data block
taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQueryAttr->window.ekey); taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQueryAttr->window.ekey);
} else { } else {
if (pBlock == NULL) { if (pBlock == NULL) {
@ -6445,28 +6474,61 @@ static SSDataBlock* doFill(void* param, bool* newgroup) {
taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQueryAttr->window.ekey); taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQueryAttr->window.ekey);
} else { } else {
pInfo->totalInputRows += pBlock->info.rows; pInfo->totalInputRows += pBlock->info.rows;
taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, pBlock->info.window.ekey);
int64_t ekey = /*Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) ? pRuntimeEnv->pQueryAttr->window.ekey
: */pBlock->info.window.ekey;
taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, ekey);
taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock); taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock);
} }
} }
doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity); doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity, pInfo->p);
if (pInfo->pRes->info.rows > 0) { // current group has no more result to return
// current group has no more result to return
if (pInfo->pRes->info.rows > 0) {
// 1. The result in current group not reach the threshold of output result, continue
// 2. If multiple group results existing in one SSDataBlock is not allowed, return immediately
if (pInfo->pRes->info.rows > pRuntimeEnv->resultInfo.threshold || pBlock == NULL || (!pInfo->multigroupResult)) {
return pInfo->pRes; return pInfo->pRes;
}
doHandleRemainBlockFromNewGroup(pInfo, pRuntimeEnv, newgroup);
if (pInfo->pRes->info.rows > pRuntimeEnv->resultInfo.threshold || pBlock == NULL) {
return pInfo->pRes;
}
// if (taosFillHasMoreResults(pInfo->pFillInfo)) {
// *newgroup = false;
// doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity);
// return pInfo->pRes;
// }
//
// // handle the cached new group data block
// if (pInfo->existNewGroupBlock) {
// pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows;
// int64_t ekey = Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)?pRuntimeEnv->pQueryAttr->window.ekey:pInfo->existNewGroupBlock->info.window.ekey;
// taosResetFillInfo(pInfo->pFillInfo, pInfo->pFillInfo->start);
//
// taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey);
// taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock);
//
// doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
// pInfo->existNewGroupBlock = NULL;
// *newgroup = true;
//
// if (pInfo->pRes->info.rows > pRuntimeEnv->resultInfo.threshold) {
// return pInfo->pRes;
// }
//
//// return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
// }
} else if (pInfo->existNewGroupBlock) { // try next group } else if (pInfo->existNewGroupBlock) { // try next group
pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows; pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows;
int64_t ekey = /*Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) ? pRuntimeEnv->pQueryAttr->window.ekey int64_t ekey = pInfo->existNewGroupBlock->info.window.ekey;
:*/ pInfo->existNewGroupBlock->info.window.ekey;
taosResetFillInfo(pInfo->pFillInfo, pInfo->pFillInfo->start); taosResetFillInfo(pInfo->pFillInfo, pInfo->pFillInfo->start);
taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey); taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey);
taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock); taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock);
doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity); doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity, pInfo->p);
pInfo->existNewGroupBlock = NULL; pInfo->existNewGroupBlock = NULL;
*newgroup = true; *newgroup = true;
@ -6474,7 +6536,6 @@ static SSDataBlock* doFill(void* param, bool* newgroup) {
} else { } else {
return NULL; return NULL;
} }
// return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
} }
} }
@ -6575,6 +6636,7 @@ static void destroySFillOperatorInfo(void* param, int32_t numOfOutput) {
SFillOperatorInfo* pInfo = (SFillOperatorInfo*) param; SFillOperatorInfo* pInfo = (SFillOperatorInfo*) param;
pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo); pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
pInfo->pRes = destroyOutputBuf(pInfo->pRes); pInfo->pRes = destroyOutputBuf(pInfo->pRes);
tfree(pInfo->p);
} }
static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) { static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) {
@ -6918,10 +6980,10 @@ SOperatorInfo* createGroupbyOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperato
return pOperator; return pOperator;
} }
SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, bool multigroupResult) {
int32_t numOfOutput) {
SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo)); SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo));
pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity); pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
pInfo->multigroupResult = multigroupResult;
{ {
SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr; SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
@ -6936,6 +6998,8 @@ SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorIn
taosCreateFillInfo(pQueryAttr->order.order, w.skey, 0, (int32_t)pRuntimeEnv->resultInfo.capacity, numOfOutput, taosCreateFillInfo(pQueryAttr->order.order, w.skey, 0, (int32_t)pRuntimeEnv->resultInfo.capacity, numOfOutput,
pQueryAttr->interval.sliding, pQueryAttr->interval.slidingUnit, pQueryAttr->interval.sliding, pQueryAttr->interval.slidingUnit,
(int8_t)pQueryAttr->precision, pQueryAttr->fillType, pColInfo, pRuntimeEnv->qinfo); (int8_t)pQueryAttr->precision, pQueryAttr->fillType, pColInfo, pRuntimeEnv->qinfo);
pInfo->p = calloc(pInfo->pFillInfo->numOfCols, POINTER_BYTES);
} }
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
@ -6955,7 +7019,7 @@ SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorIn
return pOperator; return pOperator;
} }
SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* pMerger) { SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* pMerger, bool multigroupResult) {
SSLimitOperatorInfo* pInfo = calloc(1, sizeof(SSLimitOperatorInfo)); SSLimitOperatorInfo* pInfo = calloc(1, sizeof(SSLimitOperatorInfo));
SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr; SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
@ -6963,9 +7027,11 @@ SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperator
pInfo->orderColumnList = getResultGroupCheckColumns(pQueryAttr); pInfo->orderColumnList = getResultGroupCheckColumns(pQueryAttr);
pInfo->slimit = pQueryAttr->slimit; pInfo->slimit = pQueryAttr->slimit;
pInfo->limit = pQueryAttr->limit; pInfo->limit = pQueryAttr->limit;
pInfo->capacity = pRuntimeEnv->resultInfo.capacity;
pInfo->currentGroupOffset = pQueryAttr->slimit.offset; pInfo->threshold = (int64_t)(pInfo->capacity * 0.8);
pInfo->currentOffset = pQueryAttr->limit.offset; pInfo->currentOffset = pQueryAttr->limit.offset;
pInfo->currentGroupOffset = pQueryAttr->slimit.offset;
pInfo->multigroupResult= multigroupResult;
// TODO refactor // TODO refactor
int32_t len = 0; int32_t len = 0;
@ -6973,10 +7039,10 @@ SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperator
len += pExpr[i].base.resBytes; len += pExpr[i].base.resBytes;
} }
int32_t numOfCols = pInfo->orderColumnList != NULL? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0; int32_t numOfCols = (pInfo->orderColumnList != NULL)? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0;
pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len)); pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
int32_t offset = POINTER_BYTES * numOfCols;
int32_t offset = POINTER_BYTES * numOfCols;
for(int32_t i = 0; i < numOfCols; ++i) { for(int32_t i = 0; i < numOfCols; ++i) {
pInfo->prevRow[i] = (char*)pInfo->prevRow + offset; pInfo->prevRow[i] = (char*)pInfo->prevRow + offset;
@ -6984,6 +7050,8 @@ SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperator
offset += pExpr[index->colIndex].base.resBytes; offset += pExpr[index->colIndex].base.resBytes;
} }
pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
pOperator->name = "SLimitOperator"; pOperator->name = "SLimitOperator";
@ -7219,13 +7287,11 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
if (pBlock == NULL) { if (pBlock == NULL) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); doSetOperatorCompleted(pOperator);
pOperator->status = OP_EXEC_DONE;
break; break;
} }
if (!initMultiDistinctInfo(pInfo, pOperator, pBlock)) { if (!initMultiDistinctInfo(pInfo, pOperator, pBlock)) {
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); doSetOperatorCompleted(pOperator);
pOperator->status = OP_EXEC_DONE;
break; break;
} }
// ensure result output buf // ensure result output buf
@ -7482,12 +7548,15 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols); pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols);
pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput); pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput);
pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols); pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols);
pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen); pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen);
pQueryMsg->colCondLen = htons(pQueryMsg->colCondLen); pQueryMsg->colCondLen = htons(pQueryMsg->colCondLen);
pQueryMsg->tsBuf.tsOffset = htonl(pQueryMsg->tsBuf.tsOffset); pQueryMsg->tsBuf.tsOffset = htonl(pQueryMsg->tsBuf.tsOffset);
pQueryMsg->tsBuf.tsLen = htonl(pQueryMsg->tsBuf.tsLen); pQueryMsg->tsBuf.tsLen = htonl(pQueryMsg->tsBuf.tsLen);
pQueryMsg->tsBuf.tsNumOfBlocks = htonl(pQueryMsg->tsBuf.tsNumOfBlocks); pQueryMsg->tsBuf.tsNumOfBlocks = htonl(pQueryMsg->tsBuf.tsNumOfBlocks);
pQueryMsg->tsBuf.tsOrder = htonl(pQueryMsg->tsBuf.tsOrder); pQueryMsg->tsBuf.tsOrder = htonl(pQueryMsg->tsBuf.tsOrder);
pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags); pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags);
pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen); pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen);
pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput); pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput);

View File

@ -430,7 +430,7 @@ void taosFillSetInputDataBlock(SFillInfo* pFillInfo, const SSDataBlock* pInput)
SColumnInfoData* pColData = taosArrayGet(pInput->pDataBlock, i); SColumnInfoData* pColData = taosArrayGet(pInput->pDataBlock, i);
pFillInfo->pData[i] = pColData->pData; pFillInfo->pData[i] = pColData->pData;
if (TSDB_COL_IS_TAG(pCol->flag)/* || IS_VAR_DATA_TYPE(pCol->col.type)*/) { // copy the tag value to tag value buffer if (TSDB_COL_IS_TAG(pCol->flag)) { // copy the tag value to tag value buffer
SFillTagColInfo* pTag = &pFillInfo->pTags[pCol->tagIndex]; SFillTagColInfo* pTag = &pFillInfo->pTags[pCol->tagIndex];
assert (pTag->col.colId == pCol->col.colId); assert (pTag->col.colId == pCol->col.colId);
memcpy(pTag->tagVal, pColData->pData, pCol->col.bytes); // TODO not memcpy?? memcpy(pTag->tagVal, pColData->pData, pCol->col.bytes); // TODO not memcpy??

File diff suppressed because it is too large Load Diff

View File

@ -3480,8 +3480,8 @@ void filterPrepare(void* expr, void* param) {
SArray *arr = (SArray *)(pCond->arr); SArray *arr = (SArray *)(pCond->arr);
for (size_t i = 0; i < taosArrayGetSize(arr); i++) { for (size_t i = 0; i < taosArrayGetSize(arr); i++) {
char* p = taosArrayGetP(arr, i); char* p = taosArrayGetP(arr, i);
strtolower(varDataVal(p), varDataVal(p)); strntolower_s(varDataVal(p), varDataVal(p), varDataLen(p));
taosHashPut(pObj, varDataVal(p),varDataLen(p), &dummy, sizeof(dummy)); taosHashPut(pObj, varDataVal(p), varDataLen(p), &dummy, sizeof(dummy));
} }
} else { } else {
buildFilterSetFromBinary((void **)&pObj, pCond->pz, pCond->nLen); buildFilterSetFromBinary((void **)&pObj, pCond->pz, pCond->nLen);

View File

@ -32,6 +32,7 @@ char * strnchr(char *haystack, char needle, int32_t len, bool skipquote);
char ** strsplit(char *src, const char *delim, int32_t *num); char ** strsplit(char *src, const char *delim, int32_t *num);
char * strtolower(char *dst, const char *src); char * strtolower(char *dst, const char *src);
char * strntolower(char *dst, const char *src, int32_t n); char * strntolower(char *dst, const char *src, int32_t n);
char * strntolower_s(char *dst, const char *src, int32_t n);
int64_t strnatoi(char *num, int32_t len); int64_t strnatoi(char *num, int32_t len);
char * strbetween(char *string, char *begin, char *end); char * strbetween(char *string, char *begin, char *end);
char * paGetToken(char *src, char **token, int32_t *tokenLen); char * paGetToken(char *src, char **token, int32_t *tokenLen);

View File

@ -538,7 +538,8 @@ void taosCacheCleanup(SCacheObj *pCacheObj) {
pCacheObj->deleting = 1; pCacheObj->deleting = 1;
// wait for the refresh thread quit before destroying the cache object. // wait for the refresh thread quit before destroying the cache object.
while(atomic_load_8(&pCacheObj->deleting) != 0) { // But in the dll, the child thread will be killed before atexit takes effect.So here we only wait for 2 seconds.
for (int i = 0; i < 40&&atomic_load_8(&pCacheObj->deleting) != 0; i++) {
taosMsleep(50); taosMsleep(50);
} }

View File

@ -112,6 +112,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TSC_EXCEED_SQL_LIMIT, "SQL statement too lon
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_FILE_EMPTY, "File is empty") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_FILE_EMPTY, "File is empty")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_LINE_SYNTAX_ERROR, "Syntax error in Line") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_LINE_SYNTAX_ERROR, "Syntax error in Line")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_NO_META_CACHED, "No table meta cached") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_NO_META_CACHED, "No table meta cached")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_DUP_COL_NAMES, "duplicated column names")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_TAG_LENGTH, "Invalid tag length")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_COLUMN_LENGTH, "Invalid column length")
// mnode // mnode
TAOS_DEFINE_ERROR(TSDB_CODE_MND_MSG_NOT_PROCESSED, "Message not processed") TAOS_DEFINE_ERROR(TSDB_CODE_MND_MSG_NOT_PROCESSED, "Message not processed")
@ -194,6 +197,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_FUNC_ALREADY_EXIST, "Func already exists")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_FUNC, "Invalid func") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_FUNC, "Invalid func")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_FUNC_BUFSIZE, "Invalid func bufSize") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_FUNC_BUFSIZE, "Invalid func bufSize")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_TAG_LENGTH, "invalid tag length")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_COLUMN_LENGTH, "invalid column length")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_DB_NOT_SELECTED, "Database not specified or available") TAOS_DEFINE_ERROR(TSDB_CODE_MND_DB_NOT_SELECTED, "Database not specified or available")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_DB_ALREADY_EXIST, "Database already exists") TAOS_DEFINE_ERROR(TSDB_CODE_MND_DB_ALREADY_EXIST, "Database already exists")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_DB_OPTION, "Invalid database options") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_DB_OPTION, "Invalid database options")

View File

@ -671,7 +671,7 @@ void taosNetTest(char *role, char *host, int32_t port, int32_t pkgLen,
taosNetCheckSpeed(host, port, pkgLen, pkgNum, strtolower(type, pkgType)); taosNetCheckSpeed(host, port, pkgLen, pkgNum, strtolower(type, pkgType));
}else if (0 == strcmp("fqdn", role)) { }else if (0 == strcmp("fqdn", role)) {
taosNetTestFqdn(host); taosNetTestFqdn(host);
}else { } else {
taosNetTestStartup(host, port); taosNetTestStartup(host, port);
} }

View File

@ -137,6 +137,7 @@ static SKeyword keywordTable[] = {
{"COMMA", TK_COMMA}, {"COMMA", TK_COMMA},
{"NULL", TK_NULL}, {"NULL", TK_NULL},
{"SELECT", TK_SELECT}, {"SELECT", TK_SELECT},
{"EVERY", TK_EVERY},
{"FROM", TK_FROM}, {"FROM", TK_FROM},
{"VARIABLE", TK_VARIABLE}, {"VARIABLE", TK_VARIABLE},
{"INTERVAL", TK_INTERVAL}, {"INTERVAL", TK_INTERVAL},

View File

@ -64,13 +64,16 @@ int32_t strRmquote(char *z, int32_t len){
int32_t j = 0; int32_t j = 0;
for (uint32_t k = 1; k < len - 1; ++k) { for (uint32_t k = 1; k < len - 1; ++k) {
if (z[k] == '\\' || (z[k] == delim && z[k + 1] == delim)) { if (z[k] == '\\' || (z[k] == delim && z[k + 1] == delim)) {
if (z[k] == '\\' && z[k + 1] == '_') {
//match '_' self
} else {
z[j] = z[k + 1]; z[j] = z[k + 1];
cnt++; cnt++;
j++; j++;
k++; k++;
continue; continue;
} }
}
z[j] = z[k]; z[j] = z[k];
j++; j++;
@ -162,6 +165,8 @@ char *strnchr(char *haystack, char needle, int32_t len, bool skipquote) {
return NULL; return NULL;
} }
char* strtolower(char *dst, const char *src) { char* strtolower(char *dst, const char *src) {
int esc = 0; int esc = 0;
char quote = 0, *p = dst, c; char quote = 0, *p = dst, c;
@ -219,6 +224,26 @@ char* strntolower(char *dst, const char *src, int32_t n) {
return dst; return dst;
} }
char* strntolower_s(char *dst, const char *src, int32_t n) {
char *p = dst, c;
assert(dst != NULL);
if (n == 0) {
return NULL;
}
while (n-- > 0) {
c = *src;
if (c >= 'A' && c <= 'Z') {
c -= 'A' - 'a';
}
*p++ = c;
src++;
}
return dst;
}
char *paGetToken(char *string, char **token, int32_t *tokenLen) { char *paGetToken(char *string, char **token, int32_t *tokenLen) {
char quote = 0; char quote = 0;

View File

@ -61,7 +61,7 @@ int main(int argc, char* argv[]) {
time_t ct = time(0); time_t ct = time(0);
int64_t ts = ct * 1000; int64_t ts = ct * 1000;
char* lineFormat = "sta%d,t0=true,t1=127i8,t2=32767i16,t3=%di32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=255u8,c6=32770u16,c7=2147483699u32,c8=9223372036854775899u64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" %lldms"; char* lineFormat = "sta%d,t0=true,t1=127i8,t2=32767i16,t3=%di32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=254u8,c6=32770u16,c7=2147483699u32,c8=9223372036854775899u64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" %lldms";
char** lines = calloc(numSuperTables * numChildTables * numRowsPerChildTable, sizeof(char*)); char** lines = calloc(numSuperTables * numChildTables * numRowsPerChildTable, sizeof(char*));
int l = 0; int l = 0;
@ -75,7 +75,7 @@ int main(int argc, char* argv[]) {
} }
} }
} }
shuffle(lines, numSuperTables * numChildTables * numRowsPerChildTable); //shuffle(lines, numSuperTables * numChildTables * numRowsPerChildTable);
printf("%s\n", "begin taos_insert_lines"); printf("%s\n", "begin taos_insert_lines");
int64_t begin = getTimeInUs(); int64_t begin = getTimeInUs();
@ -83,119 +83,5 @@ int main(int argc, char* argv[]) {
int64_t end = getTimeInUs(); int64_t end = getTimeInUs();
printf("code: %d, %s. time used: %"PRId64"\n", code, tstrerror(code), end-begin); printf("code: %d, %s. time used: %"PRId64"\n", code, tstrerror(code), end-begin);
char* lines_000_0[] = {
"sta1,id=sta1_1,t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=255u8,t6=32770u16,t7=2147483699u32,t8=9223372036854775899u64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=255u8,c6=32770u16,c7=2147483699u32,c8=9223372036854775899u64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833639000us"
};
code = taos_insert_lines(taos, lines_000_0 , sizeof(lines_000_0)/sizeof(char*));
if (0 == code) {
printf("taos_insert_lines() lines_000_0 should return error\n");
return -1;
}
char* lines_000_1[] = {
"sta2,id=\"sta2_1\",t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=255u8,t6=32770u16,t7=2147483699u32,t8=9223372036854775899u64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=255u8,c6=32770u16,c7=2147483699u32,c8=9223372036854775899u64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833639001"
};
code = taos_insert_lines(taos, lines_000_1 , sizeof(lines_000_1)/sizeof(char*));
if (0 == code) {
printf("taos_insert_lines() lines_000_1 should return error\n");
return -1;
}
char* lines_000_2[] = {
"sta3,id=\"sta3_1\",t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=255u8,c6=32770u16,c7=2147483699u32,c8=9223372036854775899u64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" 0"
};
code = taos_insert_lines(taos, lines_000_2 , sizeof(lines_000_2)/sizeof(char*));
if (0 != code) {
printf("taos_insert_lines() lines_000_2 return code:%d (%s)\n", code, (char*)tstrerror(code));
return -1;
}
char* lines_001_0[] = {
"sta4,t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833639000us",
};
code = taos_insert_lines(taos, lines_001_0 , sizeof(lines_001_0)/sizeof(char*));
if (0 != code) {
printf("taos_insert_lines() lines_001_0 return code:%d (%s)\n", code, (char*)tstrerror(code));
return -1;
}
char* lines_001_1[] = {
"sta5,id=\"sta5_1\",t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833639001"
};
code = taos_insert_lines(taos, lines_001_1 , sizeof(lines_001_1)/sizeof(char*));
if (0 != code) {
printf("taos_insert_lines() lines_001_1 return code:%d (%s)\n", code, (char*)tstrerror(code));
return -1;
}
char* lines_001_2[] = {
"sta6,id=\"sta6_1\",t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" 0"
};
code = taos_insert_lines(taos, lines_001_2 , sizeof(lines_001_2)/sizeof(char*));
if (0 != code) {
printf("taos_insert_lines() lines_001_2 return code:%d (%s)\n", code, (char*)tstrerror(code));
return -1;
}
char* lines_002[] = {
"stb,id=\"stb_1\",t20=t,t21=T,t22=true,t23=True,t24=TRUE,t25=f,t26=F,t27=false,t28=False,t29=FALSE,t10=33.12345,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c20=t,c21=T,c22=true,c23=True,c24=TRUE,c25=f,c26=F,c27=false,c28=False,c29=FALSE,c10=33.12345,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833639000000ns",
"stc,id=\"stc_1\",t20=t,t21=T,t22=true,t23=True,t24=TRUE,t25=f,t26=F,t27=false,t28=False,t29=FALSE,t10=33.12345,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c20=t,c21=T,c22=true,c23=True,c24=TRUE,c25=f,c26=F,c27=false,c28=False,c29=FALSE,c10=33.12345,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833639019us",
"stc,id=\"stc_1\",t20=t,t21=T,t22=true,t23=True,t24=TRUE,t25=f,t26=F,t27=false,t28=False,t29=FALSE,t10=33.12345,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c20=t,c21=T,c22=true,c23=True,c24=TRUE,c25=f,c26=F,c27=false,c28=False,c29=FALSE,c10=33.12345,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833640ms",
"stc,id=\"stc_1\",t20=t,t21=T,t22=true,t23=True,t24=TRUE,t25=f,t26=F,t27=false,t28=False,t29=FALSE,t10=33.12345,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c20=t,c21=T,c22=true,c23=True,c24=TRUE,c25=f,c26=F,c27=false,c28=False,c29=FALSE,c10=33.12345,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006834s"
};
code = taos_insert_lines(taos, lines_002 , sizeof(lines_002)/sizeof(char*));
if (0 != code) {
printf("taos_insert_lines() lines_002 return code:%d (%s)\n", code, (char*)tstrerror(code));
return -1;
}
//Duplicate key check;
char* lines_003_1[] = {
"std,id=\"std_3_1\",t1=4i64,Id=\"std\",t2=true c1=true 1626006834s"
};
code = taos_insert_lines(taos, lines_003_1 , sizeof(lines_003_1)/sizeof(char*));
if (0 == code) {
printf("taos_insert_lines() lines_003_1 return code:%d (%s)\n", code, (char*)tstrerror(code));
return -1;
}
char* lines_003_2[] = {
"std,id=\"std_3_2\",tag1=4i64,Tag2=true,tAg3=2,TaG2=\"dup!\" c1=true 1626006834s"
};
code = taos_insert_lines(taos, lines_003_2 , sizeof(lines_003_2)/sizeof(char*));
if (0 == code) {
printf("taos_insert_lines() lines_003_2 return code:%d (%s)\n", code, (char*)tstrerror(code));
return -1;
}
char* lines_003_3[] = {
"std,id=\"std_3_3\",tag1=4i64 field1=true,Field2=2,FIElD1=\"dup!\",fIeLd4=true 1626006834s"
};
code = taos_insert_lines(taos, lines_003_3 , sizeof(lines_003_3)/sizeof(char*));
if (0 == code) {
printf("taos_insert_lines() lines_003_3 return code:%d (%s)\n", code, (char*)tstrerror(code));
return -1;
}
char* lines_003_4[] = {
"std,id=\"std_3_4\",tag1=4i64,dupkey=4i16,tag2=T field1=true,dUpkEy=1e3f32,field2=\"1234\" 1626006834s"
};
code = taos_insert_lines(taos, lines_003_4 , sizeof(lines_003_4)/sizeof(char*));
if (0 == code) {
printf("taos_insert_lines() lines_003_4 return code:%d (%s)\n", code, (char*)tstrerror(code));
return -1;
}
return 0; return 0;
} }

3
tests/nettest/FQDNnettest.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
taos -n fqdn

12
tests/nettest/TCPUDP.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
for N in -1 0 1 10000 10001
do
for l in 1023 1024 1073741824 1073741825
do
for S in udp tcp
do
taos -n speed -h BCC-2 -P 6030 -N $N -l $l -S $S 2>&1 | tee -a result.txt
done
done
done

View File

@ -1,6 +1,5 @@
#!/bin/bash #!/bin/bash
for N in -1 0 1 10000 10001 for N in -1 0 1 10000 10001
do do
for l in 1023 1024 1073741824 1073741825 for l in 1023 1024 1073741824 1073741825

View File

@ -172,6 +172,10 @@ python3 test.py -f tools/taosdemoTestSampleData.py
python3 test.py -f tools/taosdemoTestInterlace.py python3 test.py -f tools/taosdemoTestInterlace.py
python3 test.py -f tools/taosdemoTestQuery.py python3 test.py -f tools/taosdemoTestQuery.py
# restful test for python
python3 test.py -f restful/restful_bind_db1.py
python3 test.py -f restful/restful_bind_db2.py
# nano support # nano support
python3 test.py -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoInsert.py python3 test.py -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoInsert.py
python3 test.py -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuery.py python3 test.py -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuery.py
@ -260,7 +264,7 @@ python3 ./test.py -f query/queryTsisNull.py
python3 ./test.py -f query/subqueryFilter.py python3 ./test.py -f query/subqueryFilter.py
python3 ./test.py -f query/nestedQuery/queryInterval.py python3 ./test.py -f query/nestedQuery/queryInterval.py
python3 ./test.py -f query/queryStateWindow.py python3 ./test.py -f query/queryStateWindow.py
python3 ./test.py -f query/nestedQuery/queryWithOrderLimit.py # python3 ./test.py -f query/nestedQuery/queryWithOrderLimit.py
python3 ./test.py -f query/nestquery_last_row.py python3 ./test.py -f query/nestquery_last_row.py
python3 ./test.py -f query/queryCnameDisplay.py python3 ./test.py -f query/queryCnameDisplay.py
python3 ./test.py -f query/operator_cost.py python3 ./test.py -f query/operator_cost.py
@ -385,6 +389,7 @@ python3 ./test.py -f insert/schemalessInsert.py
python3 ./test.py -f alter/alterColMultiTimes.py python3 ./test.py -f alter/alterColMultiTimes.py
python3 ./test.py -f query/queryWildcardLength.py python3 ./test.py -f query/queryWildcardLength.py
python3 ./test.py -f query/queryTbnameUpperLower.py python3 ./test.py -f query/queryTbnameUpperLower.py
python3 ./test.py -f query/query.py
#======================p4-end=============== #======================p4-end===============

View File

@ -72,7 +72,6 @@ class TDTestCase:
tdSql.checkData(1, 1, "2018-09-17 09:00:20.009") tdSql.checkData(1, 1, "2018-09-17 09:00:20.009")
tdSql.checkData(1, 3, "2018-09-17 09:00:20.009") tdSql.checkData(1, 3, "2018-09-17 09:00:20.009")
tdSql.query("select ts from(select ts,derivative(col, 10s, 0) from stb group by tbname)") tdSql.query("select ts from(select ts,derivative(col, 10s, 0) from stb group by tbname)")
tdSql.checkData(0, 0, "2018-09-17 09:00:10.000") tdSql.checkData(0, 0, "2018-09-17 09:00:10.000")

View File

@ -94,6 +94,23 @@ class TDTestCase:
tdSql.error("select diff(col13) from test") tdSql.error("select diff(col13) from test")
tdSql.error("select diff(col14) from test") tdSql.error("select diff(col14) from test")
tdSql.query("select ts,diff(col1),ts from test1")
tdSql.checkRows(10)
tdSql.checkData(0, 0, "2018-09-17 09:00:00.000")
tdSql.checkData(0, 1, "2018-09-17 09:00:00.000")
tdSql.checkData(0, 3, "2018-09-17 09:00:00.000")
tdSql.checkData(9, 0, "2018-09-17 09:00:00.009")
tdSql.checkData(9, 1, "2018-09-17 09:00:00.009")
tdSql.checkData(9, 3, "2018-09-17 09:00:00.009")
tdSql.query("select ts,diff(col1),ts from test group by tbname")
tdSql.checkRows(10)
tdSql.checkData(0, 0, "2018-09-17 09:00:00.000")
tdSql.checkData(0, 1, "2018-09-17 09:00:00.000")
tdSql.checkData(0, 3, "2018-09-17 09:00:00.000")
tdSql.checkData(9, 0, "2018-09-17 09:00:00.009")
tdSql.checkData(9, 1, "2018-09-17 09:00:00.009")
tdSql.checkData(9, 3, "2018-09-17 09:00:00.009")
tdSql.query("select ts,diff(col1),ts from test1") tdSql.query("select ts,diff(col1),ts from test1")
tdSql.checkRows(10) tdSql.checkRows(10)

View File

@ -57,15 +57,15 @@ class TDTestCase:
tdSql.checkRows(0) tdSql.checkRows(0)
tdSql.query("select interp(pav) from ap1 where ts = '2021-07-25 02:19:54' FILL (LINEAR)") tdSql.query("select interp(pav) from ap1 where ts = '2021-07-25 02:19:54' FILL (LINEAR)")
tdSql.checkRows(0) tdSql.checkRows(0)
tdSql.query("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' INTERVAL(1000a) FILL (LINEAR)") tdSql.query("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (LINEAR)")
tdSql.checkRows(6) tdSql.checkRows(6)
tdSql.query("select interp(pav) from ap1 where ts>= '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' INTERVAL(1000a) FILL (NEXT)") tdSql.query("select interp(pav) from ap1 where ts>= '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (NEXT)")
tdSql.checkRows(6) tdSql.checkRows(6)
tdSql.checkData(0,1,2.90799) tdSql.checkData(0,1,2.90799)
tdSql.query("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts <= '2021-07-25 02:20:00' INTERVAL(1000a) FILL (PREV)") tdSql.query("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts <= '2021-07-25 02:20:00' every(1000a) FILL (PREV)")
tdSql.checkRows(7) tdSql.checkRows(7)
tdSql.checkData(1,1,1.47885) tdSql.checkData(1,1,1.47885)
tdSql.query("select interp(pav) from ap1 where ts>= '2021-07-25 02:19:54' and ts <= '2021-07-25 02:20:00' INTERVAL(1000a) FILL (LINEAR)") tdSql.query("select interp(pav) from ap1 where ts>= '2021-07-25 02:19:54' and ts <= '2021-07-25 02:20:00' every(1000a) FILL (LINEAR)")
tdSql.checkRows(7) tdSql.checkRows(7)
# check desc order # check desc order
@ -74,13 +74,13 @@ class TDTestCase:
tdSql.checkRows(0) tdSql.checkRows(0)
tdSql.query("select interp(pav) from ap1 where ts = '2021-07-25 02:19:54' FILL (LINEAR) order by ts desc") tdSql.query("select interp(pav) from ap1 where ts = '2021-07-25 02:19:54' FILL (LINEAR) order by ts desc")
tdSql.checkRows(0) tdSql.checkRows(0)
tdSql.query("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' INTERVAL(1000a) FILL (LINEAR) order by ts desc") tdSql.query("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (LINEAR) order by ts desc")
tdSql.checkRows(6) tdSql.checkRows(6)
tdSql.query("select interp(pav) from ap1 where ts>= '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' INTERVAL(1000a) FILL (NEXT) order by ts desc") tdSql.query("select interp(pav) from ap1 where ts>= '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (NEXT) order by ts desc")
tdSql.checkRows(6) tdSql.checkRows(6)
tdSql.checkData(0,1,4.60900) tdSql.checkData(0,1,4.60900)
tdSql.error("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts <= '2021-07-25 02:20:00' INTERVAL(1000a) FILL (PREV) order by ts desc") tdSql.error("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts <= '2021-07-25 02:20:00' every(1000a) FILL (PREV) order by ts desc")
tdSql.query("select interp(pav) from ap1 where ts>= '2021-07-25 02:19:54' and ts <= '2021-07-25 02:20:00' INTERVAL(1000a) FILL (LINEAR) order by ts desc") tdSql.query("select interp(pav) from ap1 where ts>= '2021-07-25 02:19:54' and ts <= '2021-07-25 02:20:00' every(1000a) FILL (LINEAR) order by ts desc")
tdSql.checkRows(7) tdSql.checkRows(7)
# check exception # check exception
@ -88,7 +88,7 @@ class TDTestCase:
tdSql.error("select interp(*) from ap1 FILL(NEXT)") tdSql.error("select interp(*) from ap1 FILL(NEXT)")
tdSql.error("select interp(*) from ap1 ts >= '2021-07-25 02:19:54' FILL(NEXT)") tdSql.error("select interp(*) from ap1 ts >= '2021-07-25 02:19:54' FILL(NEXT)")
tdSql.error("select interp(*) from ap1 ts <= '2021-07-25 02:19:54' FILL(NEXT)") tdSql.error("select interp(*) from ap1 ts <= '2021-07-25 02:19:54' FILL(NEXT)")
tdSql.error("select interp(*) from ap1 where ts >'2021-07-25 02:19:59.938' and ts < now interval(1s) fill(next)") tdSql.error("select interp(*) from ap1 where ts >'2021-07-25 02:19:59.938' and ts < now every(1s) fill(next)")
def stop(self): def stop(self):
tdSql.close() tdSql.close()

View File

@ -697,10 +697,10 @@ class TDTestCase:
tdSql.checkRows(tbnum*3) tdSql.checkRows(tbnum*3)
tdSql.query(f"select distinct c1 c2, c2 c3 from t1 where c1 <{tbnum}") tdSql.query(f"select distinct c1 c2, c2 c3 from t1 where c1 <{tbnum}")
tdSql.checkRows(3) tdSql.checkRows(3)
tdSql.query("select distinct c1, c2 from stb1 order by ts") tdSql.error("select distinct c1, c2 from stb1 order by ts")
tdSql.checkRows(tbnum*3+1) #tdSql.checkRows(tbnum*3+1)
tdSql.query("select distinct c1, c2 from t1 order by ts") tdSql.error("select distinct c1, c2 from t1 order by ts")
tdSql.checkRows(4) #tdSql.checkRows(4)
tdSql.error("select distinct c1, ts from stb1 group by c2") tdSql.error("select distinct c1, ts from stb1 group by c2")
tdSql.error("select distinct c1, ts from t1 group by c2") tdSql.error("select distinct c1, ts from t1 group by c2")
tdSql.error("select distinct c1, max(c2) from stb1 ") tdSql.error("select distinct c1, max(c2) from stb1 ")
@ -884,6 +884,126 @@ class TDTestCase:
pass pass
def td6068(self):
tdLog.printNoPrefix("==========TD-6068==========")
tdSql.execute("drop database if exists db")
tdSql.execute("create database if not exists db keep 3650")
tdSql.execute("use db")
tdSql.execute("create stable db.stb1 (ts timestamp, c1 int, c2 float, c3 timestamp, c4 binary(16), c5 double, c6 bool) tags(t1 int)")
for i in range(100):
sql = f"create table db.t{i} using db.stb1 tags({i})"
tdSql.execute(sql)
tdSql.execute(f"insert into db.t{i} values (now-10h, {i}, {i+random.random()}, now-10h, 'a_{i}', '{i-random.random()}', True)")
tdSql.execute(f"insert into db.t{i} values (now-9h, {i+random.randint(1,10)}, {i+random.random()}, now-9h, 'a_{i}', '{i-random.random()}', FALSE )")
tdSql.execute(f"insert into db.t{i} values (now-8h, {i+random.randint(1,10)}, {i+random.random()}, now-8h, 'b_{i}', '{i-random.random()}', True)")
tdSql.execute(f"insert into db.t{i} values (now-7h, {i+random.randint(1,10)}, {i+random.random()}, now-7h, 'b_{i}', '{i-random.random()}', FALSE )")
tdSql.execute(f"insert into db.t{i} values (now-6h, {i+random.randint(1,10)}, {i+random.random()}, now-6h, 'c_{i}', '{i-random.random()}', True)")
tdSql.execute(f"insert into db.t{i} values (now-5h, {i+random.randint(1,10)}, {i+random.random()}, now-5h, 'c_{i}', '{i-random.random()}', FALSE )")
tdSql.execute(f"insert into db.t{i} (ts)values (now-4h)")
tdSql.execute(f"insert into db.t{i} (ts)values (now-11h)")
tdSql.execute(f"insert into db.t{i} (ts)values (now-450m)")
tdSql.query("select ts as t,derivative(c1, 10m, 0) from t1")
tdSql.checkRows(5)
tdSql.checkCols(3)
for i in range(5):
data=tdSql.getData(i, 0)
tdSql.checkData(i, 1, data)
tdSql.query("select ts as t, derivative(c1, 1h, 0) from stb1 group by tbname")
tdSql.checkRows(500)
tdSql.checkCols(4)
tdSql.query("select ts as t, derivative(c1, 1s, 0) from t1")
tdSql.query("select ts as t, derivative(c1, 1d, 0) from t1")
tdSql.error("select ts as t, derivative(c1, 1h, 0) from stb1")
tdSql.query("select ts as t, derivative(c2, 1h, 0) from t1")
tdSql.checkRows(5)
tdSql.error("select ts as t, derivative(c3, 1h, 0) from t1")
tdSql.error("select ts as t, derivative(c4, 1h, 0) from t1")
tdSql.query("select ts as t, derivative(c5, 1h, 0) from t1")
tdSql.checkRows(5)
tdSql.error("select ts as t, derivative(c6, 1h, 0) from t1")
tdSql.error("select ts as t, derivative(t1, 1h, 0) from t1")
tdSql.query("select ts as t, diff(c1) from t1")
tdSql.checkRows(5)
tdSql.checkCols(3)
for i in range(5):
data=tdSql.getData(i, 0)
tdSql.checkData(i, 1, data)
tdSql.query("select ts as t, diff(c1) from stb1 group by tbname")
tdSql.checkRows(500)
tdSql.checkCols(4)
tdSql.query("select ts as t, diff(c1) from t1")
tdSql.query("select ts as t, diff(c1) from t1")
tdSql.error("select ts as t, diff(c1) from stb1")
tdSql.query("select ts as t, diff(c2) from t1")
tdSql.checkRows(5)
tdSql.error("select ts as t, diff(c3) from t1")
tdSql.error("select ts as t, diff(c4) from t1")
tdSql.query("select ts as t, diff(c5) from t1")
tdSql.checkRows(5)
tdSql.error("select ts as t, diff(c6) from t1")
tdSql.error("select ts as t, diff(t1) from t1")
tdSql.error("select ts as t, diff(c1, c2) from t1")
tdSql.error("select ts as t, bottom(c1, 0) from t1")
tdSql.query("select ts as t, bottom(c1, 5) from t1")
tdSql.checkRows(5)
tdSql.checkCols(3)
for i in range(5):
data=tdSql.getData(i, 0)
tdSql.checkData(i, 1, data)
tdSql.query("select ts as t, bottom(c1, 5) from stb1")
tdSql.checkRows(5)
tdSql.query("select ts as t, bottom(c1, 5) from stb1 group by tbname")
tdSql.checkRows(500)
tdSql.query("select ts as t, bottom(c1, 8) from t1")
tdSql.checkRows(6)
tdSql.query("select ts as t, bottom(c2, 8) from t1")
tdSql.checkRows(6)
tdSql.error("select ts as t, bottom(c3, 5) from t1")
tdSql.error("select ts as t, bottom(c4, 5) from t1")
tdSql.query("select ts as t, bottom(c5, 8) from t1")
tdSql.checkRows(6)
tdSql.error("select ts as t, bottom(c6, 5) from t1")
tdSql.error("select ts as t, bottom(c5, 8) as b from t1 order by b")
tdSql.error("select ts as t, bottom(t1, 1) from t1")
tdSql.error("select ts as t, bottom(t1, 1) from stb1")
tdSql.error("select ts as t, bottom(t1, 3) from stb1 order by c3")
tdSql.error("select ts as t, bottom(t1, 3) from t1 order by c3")
tdSql.error("select ts as t, top(c1, 0) from t1")
tdSql.query("select ts as t, top(c1, 5) from t1")
tdSql.checkRows(5)
tdSql.checkCols(3)
for i in range(5):
data=tdSql.getData(i, 0)
tdSql.checkData(i, 1, data)
tdSql.query("select ts as t, top(c1, 5) from stb1")
tdSql.checkRows(5)
tdSql.query("select ts as t, top(c1, 5) from stb1 group by tbname")
tdSql.checkRows(500)
tdSql.query("select ts as t, top(c1, 8) from t1")
tdSql.checkRows(6)
tdSql.query("select ts as t, top(c2, 8) from t1")
tdSql.checkRows(6)
tdSql.error("select ts as t, top(c3, 5) from t1")
tdSql.error("select ts as t, top(c4, 5) from t1")
tdSql.query("select ts as t, top(c5, 8) from t1")
tdSql.checkRows(6)
tdSql.error("select ts as t, top(c6, 5) from t1")
tdSql.error("select ts as t, top(c5, 8) as b from t1 order by b")
tdSql.error("select ts as t, top(t1, 1) from t1")
tdSql.error("select ts as t, top(t1, 1) from stb1")
tdSql.error("select ts as t, top(t1, 3) from stb1 order by c3")
tdSql.error("select ts as t, top(t1, 3) from t1 order by c3")
pass
def run(self): def run(self):
# master branch # master branch
@ -891,8 +1011,9 @@ class TDTestCase:
# self.td4082() # self.td4082()
# self.td4288() # self.td4288()
# self.td4724() # self.td4724()
self.td5798() # self.td5798()
# self.td5935() # self.td5935()
self.td6068()
# develop branch # develop branch
# self.td4097() # self.td4097()

View File

@ -25,7 +25,7 @@ class TDTestCase:
self.tables = 10 self.tables = 10
self.rows = 20 self.rows = 20
self.columns = 5 self.columns = 100
self.perfix = 't' self.perfix = 't'
self.ts = 1601481600000 self.ts = 1601481600000
@ -33,8 +33,8 @@ class TDTestCase:
print("==============step1") print("==============step1")
sql = "create table st(ts timestamp, " sql = "create table st(ts timestamp, "
for i in range(self.columns - 1): for i in range(self.columns - 1):
sql += "c%d int, " % (i + 1) sql += "c%d bigint, " % (i + 1)
sql += "c5 int) tags(t1 int)" sql += "c100 bigint) tags(t1 int)"
tdSql.execute(sql) tdSql.execute(sql)
for i in range(self.tables): for i in range(self.tables):

View File

@ -25,6 +25,18 @@ class TDTestCase:
self.ts = 1538548685000 self.ts = 1538548685000
def bug_6387(self):
tdSql.execute("create database bug6387 ")
tdSql.execute("use bug6387 ")
tdSql.execute("create table test(ts timestamp, c1 int) tags(t1 int)")
for i in range(5000):
sql = "insert into t%d using test tags(1) values " % i
for j in range(21):
sql = sql + "(now+%ds,%d)" % (j ,j )
tdSql.execute(sql)
tdSql.query("select count(*) from test interval(1s) group by tbname")
tdSql.checkData(0,1,1)
def run(self): def run(self):
tdSql.prepare() tdSql.prepare()
@ -122,6 +134,9 @@ class TDTestCase:
tdSql.query("select * from tb0") tdSql.query("select * from tb0")
tdSql.checkRows(1) tdSql.checkRows(1)
#For jira: https://jira.taosdata.com:18080/browse/TD-6387
self.bug_6387()
def stop(self): def stop(self):
tdSql.close() tdSql.close()

View File

@ -0,0 +1,545 @@
###################################################################
# 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 -*-
from copy import deepcopy
from util.log import tdLog
from util.cases import tdCases
from util.sql import tdSql
from util.common import tdCom
class TDTestCase:
def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor(), logSql)
def insertData(self, tb_name):
insert_sql_list = [f'insert into {tb_name} values ("2021-01-01 12:00:00", 1, 1, 1, 3, 1.1, 1.1, "binary", "nchar", true, 1)',
f'insert into {tb_name} values ("2021-01-05 12:00:00", 2, 2, 1, 3, 1.1, 1.1, "binary", "nchar", true, 2)',
f'insert into {tb_name} values ("2021-01-07 12:00:00", 1, 3, 1, 2, 1.1, 1.1, "binary", "nchar", true, 3)',
f'insert into {tb_name} values ("2021-01-09 12:00:00", 1, 2, 4, 3, 1.1, 1.1, "binary", "nchar", true, 4)',
f'insert into {tb_name} values ("2021-01-11 12:00:00", 1, 2, 5, 5, 1.1, 1.1, "binary", "nchar", true, 5)',
f'insert into {tb_name} values ("2021-01-13 12:00:00", 1, 2, 1, 3, 6.6, 1.1, "binary", "nchar", true, 6)',
f'insert into {tb_name} values ("2021-01-15 12:00:00", 1, 2, 1, 3, 1.1, 7.7, "binary", "nchar", true, 7)',
f'insert into {tb_name} values ("2021-01-17 12:00:00", 1, 2, 1, 3, 1.1, 1.1, "binary8", "nchar", true, 8)',
f'insert into {tb_name} values ("2021-01-19 12:00:00", 1, 2, 1, 3, 1.1, 1.1, "binary", "nchar9", true, 9)',
f'insert into {tb_name} values ("2021-01-21 12:00:00", 1, 2, 1, 3, 1.1, 1.1, "binary", "nchar", false, 10)',
f'insert into {tb_name} values ("2021-01-23 12:00:00", 1, 3, 1, 3, 1.1, 1.1, Null, Null, false, 11)'
]
for sql in insert_sql_list:
tdSql.execute(sql)
def initTb(self):
tdCom.cleanTb()
tb_name = tdCom.getLongName(8, "letters")
tdSql.execute(
f"CREATE TABLE {tb_name} (ts timestamp, c1 tinyint, c2 smallint, c3 int, c4 bigint, c5 float, c6 double, c7 binary(100), c8 nchar(200), c9 bool, c10 int)")
self.insertData(tb_name)
return tb_name
def initStb(self):
tdCom.cleanTb()
tb_name = tdCom.getLongName(8, "letters")
tdSql.execute(
f"CREATE TABLE {tb_name} (ts timestamp, c1 tinyint, c2 smallint, c3 int, c4 bigint, c5 float, c6 double, c7 binary(100), c8 nchar(200), c9 bool, c10 int) tags (t1 tinyint, t2 smallint, t3 int, t4 bigint, t5 float, t6 double, t7 binary(100), t8 nchar(200), t9 bool, t10 int)")
tdSql.execute(
f'CREATE TABLE {tb_name}_sub using {tb_name} tags (1, 1, 1, 3, 1.1, 1.1, "binary", "nchar", true, 1)')
self.insertData(f'{tb_name}_sub')
return tb_name
def queryLastC10(self, query_sql, multi=False):
if multi:
res = tdSql.query(query_sql.replace('c10', 'last(*)'), True)
else:
res = tdSql.query(query_sql.replace('*', 'last(*)'), True)
return int(res[0][-1])
def queryFullColType(self, tb_name):
## ts
query_sql = f'select * from {tb_name} where ts > "2021-01-11 12:00:00" or ts < "2021-01-13 12:00:00"'
tdSql.query(query_sql)
tdSql.checkRows(11)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## != or
query_sql = f'select * from {tb_name} where c1 != 1 or c2 = 3'
tdSql.query(query_sql)
tdSql.checkRows(3)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## <> or
query_sql = f'select * from {tb_name} where c1 <> 1 or c3 = 3'
tdSql.query(query_sql)
tdSql.checkRows(1)
tdSql.checkEqual(self.queryLastC10(query_sql), 2)
## >= or
query_sql = f'select * from {tb_name} where c1 >= 2 or c3 = 4'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 4)
## <= or
query_sql = f'select * from {tb_name} where c1 <= 1 or c3 = 4'
tdSql.query(query_sql)
tdSql.checkRows(10)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## <> or is Null
query_sql = f'select * from {tb_name} where c1 <> 1 or c7 is Null'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## > or is not Null
query_sql = f'select * from {tb_name} where c2 > 2 or c8 is not Null'
tdSql.query(query_sql)
tdSql.checkRows(11)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## > or < or >= or <= or != or <> or = Null
query_sql = f'select * from {tb_name} where c1 > 1 or c2 < 2 or c3 >= 4 or c4 <= 2 or c5 != 1.1 or c6 <> 1.1 or c7 is Null'
tdSql.query(query_sql)
tdSql.checkRows(8)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## tiny small int big or
query_sql = f'select * from {tb_name} where c1 = 2 or c2 = 3 or c3 = 4 or c4 = 5'
tdSql.query(query_sql)
tdSql.checkRows(5)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## float double binary nchar bool or
query_sql = f'select * from {tb_name} where c5=6.6 or c6=7.7 or c7="binary8" or c8="nchar9" or c9=false'
tdSql.query(query_sql)
tdSql.checkRows(6)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## all types or
query_sql = f'select * from {tb_name} where c1=2 or c2=3 or c3=4 or c4=5 or c5=6.6 or c6=7.7 or c7="binary8" or c8="nchar9" or c9=false'
tdSql.query(query_sql)
tdSql.checkRows(10)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
def queryMultiExpression(self, tb_name):
## condition_A and condition_B or condition_C (> < >=)
query_sql = f'select * from {tb_name} where c1 > 2 and c2 < 4 or c3 >= 4'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 5)
## (condition_A and condition_B) or condition_C (<= != <>)
query_sql = f'select * from {tb_name} where (c1 <= 1 and c2 != 2) or c4 <> 3'
tdSql.query(query_sql)
tdSql.checkRows(4)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## condition_A and (condition_B or condition_C) (Null not Null)
query_sql = f'select * from {tb_name} where c1 is not Null and (c6 = 7.7 or c8 is Null)'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## condition_A or condition_B and condition_C (> < >=)
query_sql = f'select * from {tb_name} where c1 > 2 or c2 < 4 and c3 >= 4'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 5)
## (condition_A or condition_B) and condition_C (<= != <>)
query_sql = f'select * from {tb_name} where (c1 <= 1 or c2 != 2) and c4 <> 3'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 5)
## condition_A or (condition_B and condition_C) (Null not Null)
query_sql = f'select * from {tb_name} where c6 >= 7.7 or (c1 is not Null and c3 =5)'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 7)
## condition_A or (condition_B and condition_C) or condition_D (> != < Null)
query_sql = f'select * from {tb_name} where c1 != 1 or (c2 >2 and c3 < 1) or c7 is Null'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## condition_A and (condition_B or condition_C) and condition_D (>= = <= not Null)
query_sql = f'select * from {tb_name} where c4 >= 4 and (c1 = 2 or c5 <= 1.1) and c7 is not Null'
tdSql.query(query_sql)
tdSql.checkRows(1)
tdSql.checkEqual(self.queryLastC10(query_sql), 5)
## (condition_A and condition_B) or (condition_C or condition_D) (Null >= > =)
query_sql = f'select * from {tb_name} where (c8 is Null and c1 >= 1) or (c3 > 3 or c4 =2)'
tdSql.query(query_sql)
tdSql.checkRows(4)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## (condition_A or condition_B) or condition_C or (condition_D and condition_E) (>= <= = not Null <>)
query_sql = f'select * from {tb_name} where (c1 >= 2 or c2 <= 1) or c3 = 4 or (c7 is not Null and c6 <> 1.1)'
tdSql.query(query_sql)
tdSql.checkRows(4)
tdSql.checkEqual(self.queryLastC10(query_sql), 7)
## condition_A or (condition_B and condition_C) or (condition_D and condition_E) and condition_F
query_sql = f'select * from {tb_name} where c1 != 1 or (c2 <= 1 and c3 <4) or (c3 >= 4 or c7 is not Null) and c9 <> true'
tdSql.query(query_sql)
tdSql.checkRows(3)
tdSql.checkEqual(self.queryLastC10(query_sql), 10)
## (condition_A or (condition_B and condition_C) or (condition_D and condition_E)) and condition_F
query_sql = f'select * from {tb_name} where (c1 != 1 or (c2 <= 2 and c3 >= 4) or (c3 >= 4 or c7 is not Null)) and c9 != false'
tdSql.query(query_sql)
tdSql.checkRows(9)
tdSql.checkEqual(self.queryLastC10(query_sql), 9)
## (condition_A or condition_B) or (condition_C or condition_D) and (condition_E or condition_F or condition_G)
query_sql = f'select * from {tb_name} where c1 != 1 or (c2 <= 3 and c3 > 4) and c3 <= 5 and (c7 is not Null and c9 != false)'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 5)
def queryMultiIn(self, tb_name):
## in and in
query_sql = f'select * from {tb_name} where c7 in ("binary") and c8 in ("nchar")'
tdSql.query(query_sql)
tdSql.checkRows(8)
tdSql.checkEqual(self.queryLastC10(query_sql), 10)
## in or in
query_sql = f'select * from {tb_name} where c1 in (2, 4) or c2 in (1, 4)'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 2)
## in and in or condition_A
query_sql = f'select * from {tb_name} where c7 in ("binary") and c8 in ("nchar") or c10 != 10'
tdSql.query(query_sql)
tdSql.checkRows(11)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## in or in and condition_A
query_sql = f'select * from {tb_name} where c7 in ("binary") or c8 in ("nchar") and c10 != 10'
tdSql.query(query_sql)
tdSql.checkRows(10)
tdSql.checkEqual(self.queryLastC10(query_sql), 10)
## in or in or condition_A
query_sql = f'select * from {tb_name} where c1 in (2, 4) or c2 in (3, 4) or c9 != true'
tdSql.query(query_sql)
tdSql.checkRows(4)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## in or in or in or in
query_sql = f'select * from {tb_name} where c1 in (2, 4) or c2 in (3, 4) or c9 in (false) or c10 in (5, 6 ,22)'
tdSql.query(query_sql)
tdSql.checkRows(6)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## in or in and in or in
query_sql = f'select * from {tb_name} where c1 in (2, 4) or c2 in (3, 4) and c9 in (false) or c10 in (5, 6 ,22)'
tdSql.query(query_sql)
tdSql.checkRows(4)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## condition_A or in or condition_B and in
query_sql = f'select * from {tb_name} where c1 = 2 or c2 in (2, 4) and c9 = false or c10 in (6 ,22)'
tdSql.query(query_sql)
tdSql.checkRows(3)
tdSql.checkEqual(self.queryLastC10(query_sql), 10)
## in and condition_A or in and in and condition_B
query_sql = f'select * from {tb_name} where c1 in (2, 3) and c2 <> 3 or c10 <= 4 and c10 in (4 ,22) and c9 != false'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 4)
## (in and condition_A or in) and in and condition_B
query_sql = f'select * from {tb_name} where (c1 in (2, 3) and c2 <> 3 or c10 <= 4) and c10 in (4 ,22) and c9 != false'
tdSql.query(query_sql)
tdSql.checkRows(1)
tdSql.checkEqual(self.queryLastC10(query_sql), 4)
def queryMultiLike(self, tb_name):
## like and like
query_sql = f'select * from {tb_name} where c7 like "bi%" and c8 like ("ncha_")'
tdSql.query(query_sql)
tdSql.checkRows(9)
tdSql.checkEqual(self.queryLastC10(query_sql), 10)
## like or like
query_sql = f'select * from {tb_name} where c7 like "binar12345" or c8 like "nchar_"'
tdSql.query(query_sql)
tdSql.checkRows(1)
tdSql.checkEqual(self.queryLastC10(query_sql), 9)
## like and like or condition_A
query_sql = f'select * from {tb_name} where c7 like "binary_" and c8 like "ncha_" or c1 != 1'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 8)
## like or like and condition_A
query_sql = f'select * from {tb_name} where c7 like ("binar_") or c8 like ("nchar_") and c10 != 8'
tdSql.query(query_sql)
tdSql.checkRows(9)
tdSql.checkEqual(self.queryLastC10(query_sql), 10)
## like or like or condition_A
query_sql = f'select * from {tb_name} where c7 like ("binary_") or c8 like ("nchar_") or c10 = 6'
tdSql.query(query_sql)
tdSql.checkRows(3)
tdSql.checkEqual(self.queryLastC10(query_sql), 9)
## like or like or like or like
query_sql = f'select * from {tb_name} where c7 like ("binary_") or c8 like ("nchar_") or c10 = 6 or c7 is Null'
tdSql.query(query_sql)
tdSql.checkRows(4)
tdSql.checkEqual(self.queryLastC10(query_sql), 11)
## like or like and like or like
query_sql = f'select * from {tb_name} where c7 like ("binary_") or c8 like ("ncha_") and c10 = 6 or c10 = 9'
tdSql.query(query_sql)
tdSql.checkRows(3)
tdSql.checkEqual(self.queryLastC10(query_sql), 9)
## condition_A or like or condition_B and like
query_sql = f'select * from {tb_name} where c1 = 2 or c7 like "binary_" or c10 = 3 and c8 like "ncha%"'
tdSql.query(query_sql)
tdSql.checkRows(3)
tdSql.checkEqual(self.queryLastC10(query_sql), 8)
## like and condition_A or like and like and condition_B
query_sql = f'select * from {tb_name} where c7 like "bin%" and c2 = 3 or c10 <= 4 and c7 like "binar_" and c8 like "ncha_"'
tdSql.query(query_sql)
tdSql.checkRows(4)
tdSql.checkEqual(self.queryLastC10(query_sql), 4)
## (like and condition_A or like) and like and condition_B
query_sql = f'select * from {tb_name} where (c7 like "bin%" and c2 = 3 or c8 like "nchar_") and c7 like "binar_" and c9 != false'
tdSql.query(query_sql)
tdSql.checkRows(2)
tdSql.checkEqual(self.queryLastC10(query_sql), 9)
def queryPreCal(self, tb_name):
## avg sum condition_A or condition_B
query_sql = f'select avg(c3), sum(c3) from {tb_name} where c10 = 5 or c8 is Null'
res = tdSql.query(query_sql, True)[0]
tdSql.checkEqual(int(res[0]), 3)
tdSql.checkEqual(int(res[1]), 6)
## avg sum condition_A or condition_B or condition_C
query_sql = f'select avg(c3), sum(c3) from {tb_name} where c10 = 4 or c8 is Null or c9 = false '
res = tdSql.query(query_sql, True)[0]
tdSql.checkEqual(int(res[0]), 2)
tdSql.checkEqual(int(res[1]), 6)
## count avg sum condition_A or condition_B or condition_C interval
query_sql = f'select count(*), avg(c3), sum(c3) from {tb_name} where c10 = 4 or c8 is Null or c9 = false interval(16d)'
res = tdSql.query(query_sql, True)
tdSql.checkRows(2)
tdSql.checkEqual(int(res[0][1]), 1)
tdSql.checkEqual(int(res[0][2]), 4)
tdSql.checkEqual(int(res[0][3]), 4)
tdSql.checkEqual(int(res[1][1]), 2)
tdSql.checkEqual(int(res[1][2]), 1)
tdSql.checkEqual(int(res[1][3]), 2)
## count avg sum condition_A or condition_B or in and like or condition_C interval
query_sql = f'select count(*), sum(c3) from {tb_name} where c10 = 4 or c8 is Null or c2 in (1, 2) and c7 like "binary_" or c1 <> 1 interval(16d)'
res = tdSql.query(query_sql, True)
tdSql.checkRows(2)
tdSql.checkEqual(int(res[0][1]), 2)
tdSql.checkEqual(int(res[0][2]), 5)
tdSql.checkEqual(int(res[1][1]), 2)
tdSql.checkEqual(int(res[1][2]), 2)
def queryMultiTb(self, tb_name):
## select from (condition_A or condition_B)
query_sql = f'select c10 from (select * from {tb_name} where c1 >1 or c2 >=3)'
res = tdSql.query(query_sql, True)
tdSql.checkRows(3)
tdSql.checkEqual(int(res[2][0]), 11)
## select from (condition_A or condition_B) where condition_A or condition_B
query_sql = f'select c10 from (select * from {tb_name} where c1 >1 or c2 >=3) where c1 =2 or c4 = 2'
res = tdSql.query(query_sql, True)
tdSql.checkRows(2)
tdSql.checkEqual(int(res[1][0]), 3)
## select from (condition_A or condition_B and like and in) where condition_A or condition_B or like and in
query_sql = f'select c10 from (select * from {tb_name} where c1 >1 or c2 = 2 and c7 like "binar_" and c4 in (3, 5)) where c1 != 2 or c3 = 1 or c8 like "ncha_" and c9 in (true)'
res = tdSql.query(query_sql, True)
tdSql.checkRows(7)
tdSql.checkEqual(int(res[6][0]), 10)
## select count avg sum from (condition_A or condition_B and like and in) where condition_A or condition_B or like and in interval
query_sql = f'select count(*), avg(c6), sum(c3) from (select * from {tb_name} where c1 >1 or c2 = 2 and c7 like "binar_" and c4 in (3, 5)) where c1 != 2 or c3 = 1 or c8 like "ncha_" and c9 in (true) interval(8d)'
res = tdSql.query(query_sql, True)
tdSql.checkRows(3)
tdSql.checkEqual(int(res[0][1]), 3)
tdSql.checkEqual(int(res[0][2]), 1)
tdSql.checkEqual(int(res[0][3]), 10)
tdSql.checkEqual(int(res[1][1]), 3)
tdSql.checkEqual(int(res[1][2]), 3)
tdSql.checkEqual(int(res[1][3]), 3)
tdSql.checkEqual(int(res[2][1]), 1)
tdSql.checkEqual(int(res[2][2]), 1)
tdSql.checkEqual(int(res[2][3]), 1)
## cname
query_sql = f'select c10 from (select * from {tb_name} where c1 >1 or c2 = 2 and c7 like "binar_" and c4 in (3, 5)) a where a.c1 != 2 or a.c3 = 1 or a.c8 like "ncha_" and a.c9 in (true)'
res = tdSql.query(query_sql, True)
tdSql.checkRows(7)
tdSql.checkEqual(int(res[6][0]), 10)
## multi cname
query_sql = f'select b.c10 from (select * from {tb_name} where c9 = true or c2 = 2) a, (select * from {tb_name} where c7 like "binar_" or c4 in (3, 5)) b where a.ts = b.ts'
res = tdSql.query(query_sql, True)
tdSql.checkRows(10)
tdSql.checkEqual(int(res[9][0]), 10)
def checkTbColTypeOperator(self):
'''
Ordinary table full column type and operator
'''
tb_name = self.initTb()
self.queryFullColType(tb_name)
def checkStbColTypeOperator(self):
'''
Super table full column type and operator
'''
tb_name = self.initStb()
self.queryFullColType(tb_name)
def checkTbMultiExpression(self):
'''
Ordinary table multiExpression
'''
tb_name = self.initTb()
self.queryMultiExpression(tb_name)
def checkStbMultiExpression(self):
'''
Super table multiExpression
'''
tb_name = self.initStb()
self.queryMultiExpression(tb_name)
def checkTbMultiIn(self):
'''
Ordinary table multiIn
'''
tb_name = self.initTb()
self.queryMultiIn(tb_name)
def checkStbMultiIn(self):
'''
Super table multiIn
'''
tb_name = self.initStb()
self.queryMultiIn(tb_name)
def checkTbMultiLike(self):
'''
Ordinary table multiLike
'''
tb_name = self.initTb()
self.queryMultiLike(tb_name)
def checkStbMultiLike(self):
'''
Super table multiLike
'''
tb_name = self.initStb()
self.queryMultiLike(tb_name)
def checkTbPreCal(self):
'''
Ordinary table precal
'''
tb_name = self.initTb()
self.queryPreCal(tb_name)
def checkStbPreCal(self):
'''
Super table precal
'''
tb_name = self.initStb()
self.queryPreCal(tb_name)
def checkMultiTb(self):
'''
test "or" in multi ordinary table
'''
tb_name = self.initTb()
self.queryMultiTb(tb_name)
def checkMultiStb(self):
'''
test "or" in multi super table
'''
tb_name = self.initStb()
self.queryMultiTb(tb_name)
# tb_name1 = tdCom.getLongName(8, "letters")
# tb_name2 = tdCom.getLongName(8, "letters")
# tb_name3 = tdCom.getLongName(8, "letters")
# tdSql.execute(
# f"CREATE TABLE {tb_name1} (ts timestamp, c1 tinyint, c2 smallint, c3 int)")
# tdSql.execute(
# f"CREATE TABLE {tb_name2} (ts timestamp, c1 tinyint, c2 smallint, c3 int)")
# tdSql.execute(
# f"CREATE TABLE {tb_name3} (ts timestamp, c1 tinyint, c2 smallint, c3 int)")
# insert_sql_list = [f'insert into {tb_name1} values ("2021-01-01 12:00:00", 1, 5, 1)',
# f'insert into {tb_name1} values ("2021-01-03 12:00:00", 2, 4, 1)',
# f'insert into {tb_name1} values ("2021-01-05 12:00:00", 3, 2, 1)',
# f'insert into {tb_name2} values ("2021-01-01 12:00:00", 4, 2, 1)',
# f'insert into {tb_name2} values ("2021-01-02 12:00:00", 5, 1, 1)',
# f'insert into {tb_name2} values ("2021-01-04 12:00:00", 1, 2, 1)',
# f'insert into {tb_name3} values ("2021-01-02 12:00:00", 4, 2, 1)',
# f'insert into {tb_name3} values ("2021-01-06 12:00:00", 5, 1, 1)',
# f'insert into {tb_name3} values ("2021-01-07 12:00:00", 1, 2, 1)',
# ]
# for sql in insert_sql_list:
# tdSql.execute(sql)
# tdSql.query(
# f'select * from {tb_name1} t1, {tb_name2}, {tb_name3} t3 t2 where (t1.ts=t2.ts or t2.ts=t3.ts)')
# tdSql.checkRows(4)
def run(self):
tdSql.prepare()
self.checkTbColTypeOperator()
self.checkStbColTypeOperator()
self.checkTbMultiExpression()
self.checkStbMultiExpression()
self.checkTbMultiIn()
self.checkStbMultiIn()
self.checkTbMultiLike()
self.checkStbMultiLike()
self.checkTbPreCal()
self.checkStbPreCal()
self.checkMultiTb()
self.checkMultiStb()
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
tdCases.addWindows(__file__, TDTestCase())
tdCases.addLinux(__file__, TDTestCase())

View File

@ -17,7 +17,6 @@ from util.log import *
from util.cases import * from util.cases import *
from util.sql import * from util.sql import *
class TDTestCase: class TDTestCase:
def init(self, conn, logSql): def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__) tdLog.debug("start to execute %s" % __file__)
@ -25,7 +24,8 @@ class TDTestCase:
def run(self): def run(self):
tdSql.prepare() tdSql.prepare()
tdSql.execute("drop database db ")
tdSql.execute("create database if not exists db ")
tdSql.execute("create table cars(ts timestamp, c nchar(2)) tags(t1 nchar(2))") tdSql.execute("create table cars(ts timestamp, c nchar(2)) tags(t1 nchar(2))")
tdSql.execute("insert into car0 using cars tags('aa') values(now, 'bb');") tdSql.execute("insert into car0 using cars tags('aa') values(now, 'bb');")
tdSql.query("select count(*) from cars where t1 like '%50 90 30 04 00 00%'") tdSql.query("select count(*) from cars where t1 like '%50 90 30 04 00 00%'")
@ -36,6 +36,132 @@ class TDTestCase:
tdSql.query("select * from test_cars where t1 like '%50 90 30 04 00 00%'") tdSql.query("select * from test_cars where t1 like '%50 90 30 04 00 00%'")
tdSql.checkRows(1) tdSql.checkRows(1)
tdSql.execute("create stable st (ts timestamp , id int , name binary(20), data double ) tags (ind int , tagg binary(20)) ")
# check escape about tbname by show tables like
tdSql.execute("create table tb_ using st tags (1 , 'tag_' ) ")
tdSql.execute("insert into tb_ values( now , 1 , 'tbname_' , 1.0)")
tdSql.execute("create table tba using st tags (1 , 'taga' ) ")
tdSql.execute("insert into tba values( now , 1 , 'tbnamea' , 1.0)")
tdSql.query("show tables like 'tb_'")
tdSql.checkRows(2)
tdSql.query("show tables like 'tb\_'")
tdSql.checkRows(1)
# check escape about tbname by show tables like
tdSql.query("select * from st where tbname like 'tb\_'")
tdSql.checkRows(1)
# check escape about regular cols
tdSql.query("select * from st where name like 'tbname\_';")
tdSql.checkRows(1)
# check escape about tags
tdSql.query("select * from st where tagg like 'tag\_';")
tdSql.checkRows(1)
# ======================= check multi escape ===================
tdSql.execute("create table tb_1 using st tags (1 , 'tag_1' ) ")
tdSql.execute("insert into tb_1 values( now , 1 , 'tbname_1' , 1.0)")
tdSql.execute("create table tb_2 using st tags (2 , 'tag_2' )")
tdSql.execute("insert into tb_2 values( now , 2 , 'tbname_2' , 2.0)")
tdSql.execute("create table tb__ using st tags (3 , 'tag__' )")
tdSql.execute("insert into tb__ values( now , 3 , 'tbname__' , 2.0)")
tdSql.execute("create table tb__1 using st tags (3 , 'tag__1' )")
tdSql.execute("insert into tb__1 values( now , 1 , 'tbname__1' , 1.0)")
tdSql.execute("create table tb__2 using st tags (4 , 'tag__2' )")
tdSql.execute("create table tb___ using st tags (5 , 'tag___' )")
tdSql.execute("insert into tb___ values( now , 1 , 'tbname___' , 1.0)")
tdSql.execute("create table tb_d_ using st tags (5 , 'tag_d_' )")
tdSql.execute("insert into tb_d_ values( now , 1 , 'tbname_d_' , 1.0)")
tdSql.execute("create table tb_d__ using st tags (5 , 'tag_d__' )")
tdSql.execute("insert into tb_d__ values( now , 1 , 'tbname_d__' , 1.0)")
tdSql.execute("create table tb____ using st tags (5 , 'tag____' )")
tdSql.execute("insert into tb____ values( now , 1 , 'tbname____' , 1.0)")
tdSql.execute("create table tb__a_ using st tags (5 , 'tag__a_' )")
tdSql.execute("insert into tb__a_ values( now , 1 , 'tbname__a_' , 1.0)")
tdSql.execute("create table tb__ab__ using st tags (5 , 'tag__ab__' )")
tdSql.execute("insert into tb__ab__ values( now , 1 , 'tbname__ab__' , 1.0)")
# check escape about tbname by show tables like
tdSql.query("select * from st where tbname like 'tb__'")
tdSql.checkRows(3)
tdSql.query("select * from st where tbname like 'tb_\_'")
tdSql.checkRows(1)
tdSql.query("select * from st where tbname like 'tb___'")
tdSql.checkRows(4)
tdSql.query("select * from st where tbname like 'tb_\__'")
tdSql.checkRows(3)
tdSql.query("select * from st where tbname like 'tb_\_\_'")
tdSql.checkRows(1)
tdSql.query("select * from st where tbname like 'tb\__\_'")
tdSql.checkRows(1)
tdSql.query("select * from st where tbname like 'tb\__\__'")
tdSql.checkRows(2)
tdSql.query("select * from st where tbname like 'tb\__\_\_'")
tdSql.checkRows(2)
tdSql.query("select * from st where tbname like 'tb\____'")
tdSql.checkRows(3)
tdSql.query("select * from st where tbname like 'tb\_\__\_'")
tdSql.checkRows(2)
tdSql.query("select * from st where tbname like 'tb\_\_\_\_'")
tdSql.checkRows(1)
# check escape about regular cols
tdSql.query("select * from st where name like 'tbname\_\_';")
tdSql.checkRows(1)
tdSql.query("select * from st where name like 'tbname\__';")
tdSql.checkRows(3)
tdSql.query("select * from st where name like 'tbname___';")
tdSql.checkRows(4)
tdSql.query("select * from st where name like 'tbname_\__';")
tdSql.checkRows(3)
tdSql.query("select * from st where name like 'tbname_\_\_';")
tdSql.checkRows(1)
tdSql.query("select * from st where name like 'tbname\_\__';")
tdSql.checkRows(2)
tdSql.query("select * from st where name like 'tbname____';")
tdSql.checkRows(3)
tdSql.query("select * from st where name like 'tbname\_\___';")
tdSql.checkRows(2)
tdSql.query("select * from st where name like 'tbname\_\_\__';")
tdSql.checkRows(1)
tdSql.query("select * from st where name like 'tbname\_\__\_';")
tdSql.checkRows(2)
tdSql.query("select name from st where name like 'tbname\_\_\__';")
tdSql.checkData(0,0 "tbname____")
# check escape about tags
tdSql.query("select * from st where tagg like 'tag\_';")
tdSql.checkRows(1)
tdSql.query("select * from st where tagg like 'tag\_\_';")
tdSql.checkRows(1)
tdSql.query("select * from st where tagg like 'tag\__';")
tdSql.checkRows(3)
tdSql.query("select * from st where tagg like 'tag___';")
tdSql.checkRows(4)
tdSql.query("select * from st where tagg like 'tag_\__';")
tdSql.checkRows(3)
tdSql.query("select * from st where tagg like 'tag_\_\_';")
tdSql.checkRows(1)
tdSql.query("select * from st where tagg like 'tag\_\__';")
tdSql.checkRows(2)
tdSql.query("select * from st where tagg like 'tag____';")
tdSql.checkRows(3)
tdSql.query("select * from st where tagg like 'tag\_\___';")
tdSql.checkRows(2)
tdSql.query("select * from st where tagg like 'tag\_\_\__';")
tdSql.checkRows(1)
tdSql.query("select * from st where tagg like 'tag\_\__\_';")
tdSql.checkRows(2)
tdSql.query("select * from st where tagg like 'tag\_\__\_';")
tdSql.checkData(0,0 "tag__a_")
os.system("rm -rf ./*.py.sql")
def stop(self): def stop(self):
tdSql.close() tdSql.close()
tdLog.success("%s successfully executed" % __file__) tdLog.success("%s successfully executed" % __file__)

View File

@ -17,6 +17,7 @@ import os
import taos import taos
import time import time
import argparse import argparse
import json
class taosdemoQueryPerformace: class taosdemoQueryPerformace:
@ -48,7 +49,7 @@ class taosdemoQueryPerformace:
cursor2 = self.conn2.cursor() cursor2 = self.conn2.cursor()
cursor2.execute("create database if not exists %s" % self.dbName) cursor2.execute("create database if not exists %s" % self.dbName)
cursor2.execute("use %s" % self.dbName) cursor2.execute("use %s" % self.dbName)
cursor2.execute("create table if not exists %s(ts timestamp, query_time float, commit_id binary(50), branch binary(50), type binary(20)) tags(query_id int, query_sql binary(300))" % self.stbName) cursor2.execute("create table if not exists %s(ts timestamp, query_time_avg float, query_time_max float, query_time_min float, commit_id binary(50), branch binary(50), type binary(20)) tags(query_id int, query_sql binary(300))" % self.stbName)
sql = "select count(*) from test.meters" sql = "select count(*) from test.meters"
tableid = 1 tableid = 1
@ -74,7 +75,7 @@ class taosdemoQueryPerformace:
tableid = 6 tableid = 6
cursor2.execute("create table if not exists %s%d using %s tags(%d, '%s')" % (self.tbPerfix, tableid, self.stbName, tableid, sql)) cursor2.execute("create table if not exists %s%d using %s tags(%d, '%s')" % (self.tbPerfix, tableid, self.stbName, tableid, sql))
sql = "select * from meters" sql = "select * from meters limit 10000"
tableid = 7 tableid = 7
cursor2.execute("create table if not exists %s%d using %s tags(%d, '%s')" % (self.tbPerfix, tableid, self.stbName, tableid, sql)) cursor2.execute("create table if not exists %s%d using %s tags(%d, '%s')" % (self.tbPerfix, tableid, self.stbName, tableid, sql))
@ -88,36 +89,95 @@ class taosdemoQueryPerformace:
cursor2.close() cursor2.close()
def generateQueryJson(self):
sqls = []
cursor2 = self.conn2.cursor()
cursor2.execute("select query_id, query_sql from %s.%s" % (self.dbName, self.stbName))
i = 0
for data in cursor2:
sql = {
"sql": data[1],
"result_mode": "onlyformat",
"result_file": "./query_sql_res%d.txt" % i
}
sqls.append(sql)
i += 1
query_data = {
"filetype": "query",
"cfgdir": "/etc/perf",
"host": "127.0.0.1",
"port": 6030,
"user": "root",
"password": "taosdata",
"databases": "test",
"specified_table_query": {
"query_times": 100,
"concurrent": 1,
"sqls": sqls
}
}
query_json_file = f"/tmp/query.json"
with open(query_json_file, 'w') as f:
json.dump(query_data, f)
return query_json_file
def getBuildPath(self):
selfPath = os.path.dirname(os.path.realpath(__file__))
if ("community" in selfPath):
projPath = selfPath[:selfPath.find("community")]
else:
projPath = selfPath[:selfPath.find("tests")]
for root, dirs, files in os.walk(projPath):
if ("taosdemo" in files):
rootRealPath = os.path.dirname(os.path.realpath(root))
if ("packaging" not in rootRealPath):
buildPath = root[:len(root) - len("/build/bin")]
break
return buildPath
def getCMDOutput(self, cmd):
cmd = os.popen(cmd)
output = cmd.read()
cmd.close()
return output
def query(self): def query(self):
cursor = self.conn.cursor() buildPath = self.getBuildPath()
if (buildPath == ""):
print("taosdemo not found!")
sys.exit(1)
binPath = buildPath + "/build/bin/"
os.system(
"%sperfMonitor -f %s > query_res.txt" %
(binPath, self.generateQueryJson()))
cursor = self.conn2.cursor()
print("==================== query performance ====================") print("==================== query performance ====================")
cursor.execute("use %s" % self.dbName) cursor.execute("use %s" % self.dbName)
cursor.execute("select tbname, query_id, query_sql from %s" % self.stbName) cursor.execute("select tbname, query_sql from %s" % self.stbName)
i = 0
for data in cursor: for data in cursor:
table_name = data[0] table_name = data[0]
query_id = data[1] sql = data[1]
sql = data[2]
totalTime = 0 self.avgDelay = self.getCMDOutput("grep 'avgDelay' query_res.txt | awk 'NR==%d{print $2}'" % (i + 1))
cursor2 = self.conn.cursor() self.maxDelay = self.getCMDOutput("grep 'avgDelay' query_res.txt | awk 'NR==%d{print $5}'" % (i + 1))
cursor2.execute("use test") self.minDelay = self.getCMDOutput("grep 'avgDelay' query_res.txt | awk 'NR==%d{print $8}'" % (i + 1))
for i in range(100): i += 1
if(self.clearCache == True):
# root permission is required
os.system("echo 3 > /proc/sys/vm/drop_caches")
startTime = time.time() print("query time for: %s %f seconds" % (sql, float(self.avgDelay)))
cursor2.execute(sql) c = self.conn2.cursor()
totalTime += time.time() - startTime c.execute("insert into %s.%s values(now, %f, %f, %f, '%s', '%s', '%s')" % (self.dbName, table_name, float(self.avgDelay), float(self.maxDelay), float(self.minDelay), self.commitID, self.branch, self.type))
cursor2.close()
print("query time for: %s %f seconds" % (sql, totalTime / 100))
cursor3 = self.conn2.cursor() c.close()
cursor3.execute("insert into %s.%s values(now, %f, '%s', '%s', '%s')" % (self.dbName, table_name, totalTime / 100, self.commitID, self.branch, self.type))
cursor3.close()
cursor.close() cursor.close()
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -0,0 +1,123 @@
# #################################################################
# 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 -*-
# TODO: after TD-4518 and TD-4510 is resolved, add the exception test case for these situations
from distutils.log import error
import sys
from requests.api import head
from requests.models import Response
from util.log import *
from util.cases import *
from util.sql import *
import time, datetime
import requests, json
import threading
import string
import random
def check_unbind_db(url, data, header):
resp = requests.post(url, data, headers = header )
resp.encoding='utf-8'
resp = eval(resp.text)
status = resp['status']
desc = resp['desc']
sqls = data
if status=="error" and desc == "invalid url format":
print(" %s : check pass" %sqls)
else:
printf(" error occured , ")
sys.exit()
def check_bind_db(url, data, header):
resp = requests.post(url, data, headers = header )
resp.encoding='utf-8'
resp_dict = eval(resp.text)
status = resp_dict['status']
if status =="succ":
print("%s run success!"%data)
# print(resp.text)
else :
print("%s run failed !"%data)
print(resp.text)
sys.exit()
class TDTestCase():
updatecfgDict={'httpDbNameMandatory':1}
def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor(), logSql)
def run(self):
tdSql.prepare()
tdSql.execute('reset query cache')
tdSql.execute('drop database if exists test')
tdSql.execute('drop database if exists db')
tdSql.execute('drop database if exists des')
tdSql.execute('create database test')
tdSql.execute('create database des')
header = {'Authorization': 'Basic cm9vdDp0YW9zZGF0YQ=='}
url = "http://127.0.0.1:6041/rest/sql/"
# test with no bind databases
sqls = ["show databases;",
"use test",
"show tables;",
"show dnodes;",
"show vgroups;",
"create database db;",
"drop database db;",
"select client_version();" ,
"use test",
"ALTER DATABASE test COMP 2;",
"create table tb (ts timestamp, id int , data double)",
"insert into tb values (now , 1, 1.0) ",
"select * from tb",
"show test.tables",
"show tables",
"insert into tb values (now , 2, 2.0) ",
"create table test.tb (ts timestamp, id int , data double)",
"insert into test.tb values (now , 2, 2.0) ",
"select * from tb",
"select * from test.tb"]
for sql in sqls:
print("===================")
check_unbind_db(url,sql,header)
print("==================="*5)
print(" check bind db about restful ")
print("==================="*5)
url = "http://127.0.0.1:6041/rest/sql/des"
for sql in sqls:
print("===================")
check_bind_db(url,sql,header)
# check data
tdSql.query("select * from test.tb")
tdSql.checkRows(1)
tdSql.query("select * from des.tb")
tdSql.checkRows(2)
os.system('sudo timedatectl set-ntp on')
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
tdCases.addWindows(__file__, TDTestCase())
tdCases.addLinux(__file__, TDTestCase())

View File

@ -0,0 +1,133 @@
# #################################################################
# 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 -*-
# TODO: after TD-4518 and TD-4510 is resolved, add the exception test case for these situations
from distutils.log import error
import sys
from requests.api import head
from requests.models import Response
from util.log import *
from util.cases import *
from util.sql import *
import time, datetime
import requests, json
import threading
import string
import random
def check_res(url, data, header):
resp = requests.post(url, data, headers = header )
resp.encoding='utf-8'
resp_dict = eval(resp.text)
status = resp_dict['status']
if status =="succ":
print("%s run success!"%data)
# print(resp.text)
else :
print("%s run failed !"%data)
print(resp.text)
sys.exit()
class TDTestCase():
# updatecfgDict={'httpDbNameMandatory':0}
def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor(), logSql)
def run(self):
tdSql.prepare()
tdSql.execute('reset query cache')
tdSql.execute('drop database if exists test')
tdSql.execute('drop database if exists db')
tdSql.execute('drop database if exists des')
tdSql.execute('create database test')
tdSql.execute('create database des')
header = {'Authorization': 'Basic cm9vdDp0YW9zZGF0YQ=='}
url = "http://127.0.0.1:6041/rest/sql/"
# test with no bind databases
sqls = ["show databases;",
"use test",
"show tables;",
"show dnodes;",
"show vgroups;",
"create database db;",
"drop database db;",
"select client_version();" ,
"use test",
"ALTER DATABASE test COMP 2;",
"create table tb (ts timestamp, id int , data double)",
"insert into tb values (now , 1, 1.0) ",
"select * from tb",
"show test.tables",
"show tables",
"insert into tb values (now , 2, 2.0) ",
"create table test.tb (ts timestamp, id int , data double)",
"insert into test.tb values (now , 3, 3.0) ",
"select * from tb",
"select * from test.tb",
"create table des.tb (ts timestamp, id int , data double)",
"insert into des.tb values (now , 3, 3.0)"]
for sql in sqls:
print("===================")
if sql == "create table test.tb (ts timestamp, id int , data double)":
resp = requests.post(url, sql, headers = header )
print(resp.text)
print ("%s run occur error as expect ,check pass!" %(sql))
else:
check_res(url,sql,header)
tdSql.query("select * from test.tb")
tdSql.checkRows(3)
tdSql.query("select * from des.tb")
tdSql.checkRows(1)
print("==================="*5)
print(" check bind db about restful ")
print("==================="*5)
tdSql.execute('reset query cache')
tdSql.execute('drop database if exists test')
tdSql.execute('drop database if exists db')
tdSql.execute('drop database if exists des')
tdSql.execute('create database test')
tdSql.execute('create database des')
url = "http://127.0.0.1:6041/rest/sql/des"
for sql in sqls:
print("===================")
if sql in ["create table des.tb (ts timestamp, id int , data double)"]:
resp = requests.post(url, sql, headers = header )
print(resp.text)
print ("%s run occur error as expect ,check pass!" %(sql))
else:
check_res(url,sql,header)
# check data
tdSql.query("select * from test.tb")
tdSql.checkRows(1)
tdSql.query("select * from des.tb")
tdSql.checkRows(3)
os.system('sudo timedatectl set-ntp on')
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
tdCases.addWindows(__file__, TDTestCase())
tdCases.addLinux(__file__, TDTestCase())

View File

@ -0,0 +1,301 @@
###################################################################
# Copyright (c) 2021 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 traceback
import random
import string
from taos.error import LinesError
import datetime
import time
from copy import deepcopy
import numpy as np
from util.log import *
from util.cases import *
from util.sql import *
from util.common import tdCom
import threading
class TDTestCase:
def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor(), logSql)
self._conn = conn
def genRandomTs(self):
year = random.randint(2000, 2021)
month = random.randint(10, 12)
day = random.randint(10, 29)
hour = random.randint(10, 24)
minute = random.randint(10, 59)
second = random.randint(10, 59)
m_second = random.randint(101, 199)
date_time = f'{year}-{month}-{day} {hour}:{minute}:{second}'
print(date_time)
timeArray = time.strptime(date_time, "%Y-%m-%d %H:%M:%S")
ts = int(time.mktime(timeArray))
print("------", ts)
# timestamp = time.mktime(datetime.datetime.strptime(date_time, "%Y-%m-%d %H:%M:%S.%f").timetuple())
return f'{ts}s'
def genMultiColStr(self, int_count=4, double_count=0, binary_count=0):
"""
genType must be tag/col
"""
col_str = ""
if double_count == 0 and binary_count == 0:
for i in range(0, int_count):
if i < (int_count-1):
col_str += f'c{i}={random.randint(0, 255)}i32,'
else:
col_str += f'c{i}={random.randint(0, 255)}i32 '
elif double_count > 0 and binary_count == 0:
for i in range(0, int_count):
col_str += f'c{i}={random.randint(0, 255)}i32,'
for i in range(0, double_count):
if i < (double_count-1):
col_str += f'c{i+int_count}={random.randint(1, 255)}.{i}f64,'
else:
col_str += f'c{i+int_count}={random.randint(1, 255)}.{i}f64 '
elif double_count == 0 and binary_count > 0:
for i in range(0, int_count):
col_str += f'c{i}={random.randint(0, 255)}i32,'
for i in range(0, binary_count):
if i < (binary_count-1):
col_str += f'c{i+int_count}=\"{tdCom.getLongName(5, "letters")}\",'
else:
col_str += f'c{i+int_count}=\"{tdCom.getLongName(5, "letters")}\" '
elif double_count > 0 and binary_count > 0:
for i in range(0, int_count):
col_str += f'c{i}={random.randint(0, 255)}i32,'
for i in range(0, double_count):
col_str += f'c{i+int_count}={random.randint(1, 255)}.{i}f64,'
for i in range(0, binary_count):
if i < (binary_count-1):
col_str += f'c{i+int_count+double_count}=\"{tdCom.getLongName(5, "letters")}\",'
else:
col_str += f'c{i+int_count+double_count}=\"{tdCom.getLongName(5, "letters")}\" '
return col_str
def genLongSql(self, int_count=4, double_count=0, binary_count=0, init=False):
if init:
tag_str = f'id="init",t0={random.randint(0, 65535)}i32,t1=\"{tdCom.getLongName(10, "letters")}\"'
else:
tag_str = f'id="sub_{tdCom.getLongName(5, "letters")}_{tdCom.getLongName(5, "letters")}",t0={random.randint(0, 65535)}i32,t1=\"{tdCom.getLongName(10, "letters")}\"'
col_str = self.genMultiColStr(int_count, double_count, binary_count)
long_sql = 'stb' + ',' + tag_str + ' ' + col_str + '0'
return long_sql
def getPerfSql(self, count=4, init=False):
if count == 4:
input_sql = self.genLongSql(init=init)
elif count == 1000:
input_sql = self.genLongSql(400, 400, 200, init=init)
elif count == 4000:
input_sql = self.genLongSql(1900, 1900, 200, init=init)
return input_sql
def tableGenerator(self, count=4, table_count=1000):
for i in range(table_count):
yield self.getPerfSql(count)
def genTableList(self, count=4, table_count=10000):
table_list = list()
for i in range(1, table_count+1):
table_list.append(self.getPerfSql(count))
return table_list
def splitTableList(self, count=4, thread_count=10, table_count=1000):
per_list_len = int(table_count/thread_count)
table_list = self.genTableList(count=count)
# ts = int(time.time())
list_of_group = zip(*(iter(table_list),) *per_list_len)
end_list = [list(i) for i in list_of_group] # i is a tuple
count = len(table_list) % per_list_len
end_list.append(table_list[-count:]) if count !=0 else end_list
return table_list, end_list
def rowsGenerator(self, end_list):
ts = int(time.time())
input_sql_list = list()
for elm_list in end_list:
for elm in elm_list:
for i in range(1, 10000):
ts -= 1
elm_new = self.replaceLastStr(elm, str(ts)) + 's'
input_sql_list.append(elm_new)
yield input_sql_list
# def insertRows(self, count=4, thread_count=10):
# table_list = self.splitTableList(count=count, thread_count=thread_count)[0]
# for
def replaceLastStr(self, str, new):
list_ori = list(str)
list_ori[-1] = new
return ''.join(list_ori)
def genDataList(self, table_list, row_count=10):
data_list = list()
ts = int(time.time())
for table_str in table_list:
for i in range(1, row_count+1):
ts -= 1
table_str_new = self.replaceLastStr(table_str, f'{str(ts)}s')
data_list.append(table_str_new)
print(data_list)
return data_list
def insertRows(self, count=4, table_count=1000):
table_generator = self.tableGenerator(count=count, table_count=table_count)
for table_name in table_generator:
pass
def perfTableInsert(self):
table_generator = self.tableGenerator()
for input_sql in table_generator:
self._conn.insert_lines([input_sql])
# for i in range(10):
# self._conn.insert_lines([input_sql])
def perfDataInsert(self, count=4):
table_generator = self.tableGenerator(count=count)
ts = int(time.time())
for input_sql in table_generator:
print("input_sql-----------", input_sql)
self._conn.insert_lines([input_sql])
for i in range(100000):
ts -= 1
input_sql_new = self.replaceLastStr(input_sql, str(ts)) + 's'
print("input_sql_new---------", input_sql_new)
self._conn.insert_lines([input_sql_new])
def batchInsertTable(self, batch_list):
for insert_list in batch_list:
print(threading.current_thread().name, "length=", len(insert_list))
print(threading.current_thread().name, 'firstline', insert_list[0])
print(threading.current_thread().name, 'lastline:', insert_list[-1])
self._conn.insert_lines(insert_list)
print(threading.current_thread().name, 'end')
def genTableThread(self, thread_count=10):
threads = list()
for i in range(thread_count):
t = threading.Thread(target=self.perfTableInsert)
threads.append(t)
return threads
def genMultiThread(self, count, thread_count=10):
threads = list()
for i in range(thread_count):
t = threading.Thread(target=self.perfDataInsert,args=(count,))
threads.append(t)
return threads
def multiThreadRun(self, threads):
for t in threads:
t.start()
for t in threads:
t.join()
def createStb(self, count=4):
input_sql = self.getPerfSql(count=count, init=True)
self._conn.insert_lines([input_sql])
def threadInsertTable(self, end_list, thread_count=10):
threads = list()
for i in range(thread_count):
t = threading.Thread(target=self.batchInsertTable, args=(end_list,))
threads.append(t)
return threads
def finalRun(self):
self.createStb()
table_list, end_list = self.splitTableList()
batchInsertTableThread = self.threadInsertTable(end_list=end_list)
self.multiThreadRun(batchInsertTableThread)
# print(end_list)
# def createTb(self, count=4):
# input_sql = self.getPerfSql(count=count)
# for i in range(10000):
# self._conn.insert_lines([input_sql])
# def createTb1(self, count=4):
# start_time = time.time()
# self.multiThreadRun(self.genMultiThread(input_sql))
# end_time = time.time()
# return end_time - start_time
# def calInsertTableTime(self):
# start_time = time.time()
# self.createStb()
# self.multiThreadRun(self.genMultiThread())
# end_time = time.time()
# return end_time - start_time
def calRunTime(self, count=4):
start_time = time.time()
self.createStb()
self.multiThreadRun(self.genMultiThread(count=count))
end_time = time.time()
return end_time - start_time
def calRunTime1(self, count=4):
start_time = time.time()
self.createStb()
self.multiThreadRun(self.perfTableInsert())
# self.perfTableInsert()
# def schemalessInsertPerfTest(self, count=4):
# input_sql = self.getPerfSql(count)
# self.calRunTime(input_sql)
# def test(self):
# sql1 = 'stb,id="init",t0=14865i32,t1="tvnqbjuqck" c0=37i32,c1=217i32,c2=3i32,c3=88i32 1626006833640ms'
# sql2 = 'stb,id="init",t0=14865i32,t1="tvnqbjuqck" c0=38i32,c1=217i32,c2=3i32,c3=88i32 1626006833641ms'
# self._conn.insert_lines([sql1])
# self._conn.insert_lines([sql2])
def run(self):
print("running {}".format(__file__))
tdSql.prepare()
self.finalRun()
# print(self.calRunTime1(count=4))
# print(self.calRunTime(count=4))
# print(self.genRandomTs())
# self.calInsertTableTime()
# self.test()
# table_list = self.splitTableList()[0]
# data_list = self.genDataList(table_list)
# print(len(data_list))
# end_list = [['stb,id="sub_vzvfx_dbuxp",t0=9961i32,t1="zjjfayhfep" c0=83i32,c1=169i32,c2=177i32,c3=4i32 0','stb,id="sub_vzvfx_dbuxp",t0=9961i32,t1="zjjfayhfep" c0=83i32,c1=169i32,c2=177i32,c3=4i32 0'], ['stb,id="sub_vzvfx_dbuxp",t0=9961i32,t1="zjjfayhfep" c0=83i32,c1=169i32,c2=177i32,c3=4i32 0','stb,id="sub_vzvfx_dbuxp",t0=9961i32,t1="zjjfayhfep" c0=83i32,c1=169i32,c2=177i32,c3=4i32 0']]
# rowsGenerator = self.rowsGenerator(end_list)
# for i in rowsGenerator:
# print(i)
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
tdCases.addWindows(__file__, TDTestCase())
tdCases.addLinux(__file__, TDTestCase())

View File

@ -49,24 +49,18 @@ class taosdemoPerformace:
def generateJson(self): def generateJson(self):
db = { db = {
"name": "%s" % self.insertDB, "name": "%s" % self.insertDB,
"drop": "yes", "drop": "yes"
"replica": 1
} }
stb = { stb = {
"name": "meters", "name": "meters",
"child_table_exists": "no",
"childtable_count": self.numOfTables, "childtable_count": self.numOfTables,
"childtable_prefix": "stb_", "childtable_prefix": "stb_",
"auto_create_table": "no",
"data_source": "rand",
"batch_create_tbl_num": 10, "batch_create_tbl_num": 10,
"insert_mode": "taosc", "insert_mode": "rand",
"insert_rows": self.numOfRows, "insert_rows": self.numOfRows,
"interlace_rows": 0, "batch_rows": 1000000,
"max_sql_len": 1024000, "max_sql_len": 1048576,
"disorder_ratio": 0,
"disorder_range": 1000,
"timestamp_step": 1, "timestamp_step": 1,
"start_timestamp": "2020-10-01 00:00:00.000", "start_timestamp": "2020-10-01 00:00:00.000",
"sample_format": "csv", "sample_format": "csv",
@ -100,11 +94,8 @@ class taosdemoPerformace:
"user": "root", "user": "root",
"password": "taosdata", "password": "taosdata",
"thread_count": 10, "thread_count": 10,
"thread_count_create_tbl": 10, "thread_count_create_tbl": 4,
"result_file": "./insert_res.txt", "result_file": "./insert_res.txt",
"confirm_parameter_prompt": "no",
"insert_interval": 0,
"num_of_records_per_req": 30000,
"databases": [db] "databases": [db]
} }
@ -145,7 +136,7 @@ class taosdemoPerformace:
binPath = buildPath + "/build/bin/" binPath = buildPath + "/build/bin/"
os.system( os.system(
"%staosdemo -f %s > /dev/null 2>&1" % "%sperfMonitor -f %s > /dev/null 2>&1" %
(binPath, self.generateJson())) (binPath, self.generateJson()))
self.createTableTime = self.getCMDOutput( self.createTableTime = self.getCMDOutput(
"grep 'Spent' insert_res.txt | awk 'NR==1{print $2}'") "grep 'Spent' insert_res.txt | awk 'NR==1{print $2}'")

View File

@ -1,4 +1,4 @@
################################################################### ###################################################################
# Copyright (c) 2016 by TAOS Technologies, Inc. # Copyright (c) 2016 by TAOS Technologies, Inc.
# All rights reserved. # All rights reserved.
# #

View File

@ -60,7 +60,7 @@ class TDSimClient:
self.cfgDict.update({option: value}) self.cfgDict.update({option: value})
def cfg(self, option, value): def cfg(self, option, value):
cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) cmd = "echo %s %s >> %s" % (option, value, self.cfgPath)
if os.system(cmd) != 0: if os.system(cmd) != 0:
tdLog.exit(cmd) tdLog.exit(cmd)
@ -320,7 +320,7 @@ class TDDnode:
tdLog.exit(cmd) tdLog.exit(cmd)
def cfg(self, option, value): def cfg(self, option, value):
cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) cmd = "echo %s %s >> %s" % (option, value, self.cfgPath)
if os.system(cmd) != 0: if os.system(cmd) != 0:
tdLog.exit(cmd) tdLog.exit(cmd)

View File

@ -58,7 +58,7 @@ class TDSimClient:
self.cfgDict.update({option: value}) self.cfgDict.update({option: value})
def cfg(self, option, value): def cfg(self, option, value):
cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) cmd = "echo %s %s >> %s" % (option, value, self.cfgPath)
if os.system(cmd) != 0: if os.system(cmd) != 0:
tdLog.exit(cmd) tdLog.exit(cmd)
@ -318,7 +318,7 @@ class TDDnode:
tdLog.exit(cmd) tdLog.exit(cmd)
def cfg(self, option, value): def cfg(self, option, value):
cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) cmd = "echo %s %s >> %s" % (option, value, self.cfgPath)
if os.system(cmd) != 0: if os.system(cmd) != 0:
tdLog.exit(cmd) tdLog.exit(cmd)

View File

@ -58,7 +58,7 @@ class TDSimClient:
self.cfgDict.update({option: value}) self.cfgDict.update({option: value})
def cfg(self, option, value): def cfg(self, option, value):
cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) cmd = "echo %s %s >> %s" % (option, value, self.cfgPath)
if os.system(cmd) != 0: if os.system(cmd) != 0:
tdLog.exit(cmd) tdLog.exit(cmd)
@ -318,7 +318,7 @@ class TDDnode:
tdLog.exit(cmd) tdLog.exit(cmd)
def cfg(self, option, value): def cfg(self, option, value):
cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) cmd = "echo %s %s >> %s" % (option, value, self.cfgPath)
if os.system(cmd) != 0: if os.system(cmd) != 0:
tdLog.exit(cmd) tdLog.exit(cmd)

View File

@ -14,6 +14,7 @@
import sys import sys
import os import os
import os.path import os.path
import platform
import subprocess import subprocess
from time import sleep from time import sleep
from util.log import * from util.log import *
@ -58,7 +59,7 @@ class TDSimClient:
self.cfgDict.update({option: value}) self.cfgDict.update({option: value})
def cfg(self, option, value): def cfg(self, option, value):
cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) cmd = "echo %s %s >> %s" % (option, value, self.cfgPath)
if os.system(cmd) != 0: if os.system(cmd) != 0:
tdLog.exit(cmd) tdLog.exit(cmd)
@ -122,7 +123,7 @@ class TDDnode:
"charset":"UTF-8", "charset":"UTF-8",
"asyncLog":"0", "asyncLog":"0",
"anyIp":"0", "anyIp":"0",
"tsEnableTelemetryReporting":"0", "telemetryReporting":"0",
"dDebugFlag":"135", "dDebugFlag":"135",
"tsdbDebugFlag":"135", "tsdbDebugFlag":"135",
"mDebugFlag":"135", "mDebugFlag":"135",
@ -243,7 +244,7 @@ class TDDnode:
projPath = selfPath[:selfPath.find("tests")] projPath = selfPath[:selfPath.find("tests")]
for root, dirs, files in os.walk(projPath): for root, dirs, files in os.walk(projPath):
if ("taosd" in files): if (("taosd") in files):
rootRealPath = os.path.dirname(os.path.realpath(root)) rootRealPath = os.path.dirname(os.path.realpath(root))
if ("packaging" not in rootRealPath): if ("packaging" not in rootRealPath):
buildPath = root[:len(root)-len("/build/bin")] buildPath = root[:len(root)-len("/build/bin")]
@ -401,7 +402,7 @@ class TDDnode:
tdLog.exit(cmd) tdLog.exit(cmd)
def cfg(self, option, value): def cfg(self, option, value):
cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) cmd = "echo %s %s >> %s" % (option, value, self.cfgPath)
if os.system(cmd) != 0: if os.system(cmd) != 0:
tdLog.exit(cmd) tdLog.exit(cmd)

View File

@ -6,7 +6,8 @@ TARGET=exe
LFLAGS = '-Wl,-rpath,/usr/local/taos/driver/' -ltaos -lpthread -lm -lrt LFLAGS = '-Wl,-rpath,/usr/local/taos/driver/' -ltaos -lpthread -lm -lrt
CFLAGS = -O0 -g -Wall -Wno-deprecated -fPIC -Wno-unused-result -Wconversion \ CFLAGS = -O0 -g -Wall -Wno-deprecated -fPIC -Wno-unused-result -Wconversion \
-Wno-char-subscripts -D_REENTRANT -Wno-format -D_REENTRANT -DLINUX \ -Wno-char-subscripts -D_REENTRANT -Wno-format -D_REENTRANT -DLINUX \
-Wno-unused-function -D_M_X64 -I/usr/local/taos/include -std=gnu99 -Wno-unused-function -D_M_X64 -I/usr/local/taos/include -std=gnu99 \
-fsanitize=address
all: $(TARGET) all: $(TARGET)
@ -14,8 +15,10 @@ exe:
gcc $(CFLAGS) ./batchprepare.c -o $(ROOT)batchprepare $(LFLAGS) gcc $(CFLAGS) ./batchprepare.c -o $(ROOT)batchprepare $(LFLAGS)
gcc $(CFLAGS) ./stmtBatchTest.c -o $(ROOT)stmtBatchTest $(LFLAGS) gcc $(CFLAGS) ./stmtBatchTest.c -o $(ROOT)stmtBatchTest $(LFLAGS)
gcc $(CFLAGS) ./stmtTest.c -o $(ROOT)stmtTest $(LFLAGS) gcc $(CFLAGS) ./stmtTest.c -o $(ROOT)stmtTest $(LFLAGS)
gcc $(CFLAGS) ./stmt_function.c -o $(ROOT)stmt_function $(LFLAGS)
clean: clean:
rm $(ROOT)batchprepare rm $(ROOT)batchprepare
rm $(ROOT)stmtBatchTest rm $(ROOT)stmtBatchTest
rm $(ROOT)stmtTest rm $(ROOT)stmtTest
rm $(ROOT)stmt_function

View File

@ -0,0 +1,502 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "taos.h"
#include <sys/time.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
void execute_simple_sql(void *taos, char *sql) {
TAOS_RES *result = taos_query(taos, sql);
if ( result == NULL || taos_errno(result) != 0) {
printf( "failed to %s, Reason: %s\n" , sql, taos_errstr(result));
taos_free_result(result);
exit(EXIT_FAILURE);
}
taos_free_result(result);
}
void print_result(TAOS_RES* res) {
if (res == NULL) {
exit(EXIT_FAILURE);
}
TAOS_ROW row = NULL;
int num_fields = taos_num_fields(res);
TAOS_FIELD* fields = taos_fetch_fields(res);
while ((row = taos_fetch_row(res))) {
char temp[256] = {0};
taos_print_row(temp, row, fields, num_fields);
printf("get result: %s\n", temp);
}
}
void taos_stmt_init_test() {
printf("start taos_stmt_init test \n");
void *taos = NULL;
TAOS_STMT *stmt = NULL;
stmt = taos_stmt_init(taos);
assert(stmt == NULL);
// ASM ERROR
// assert(taos_stmt_close(stmt) != 0);
taos = taos_connect("127.0.0.1","root","taosdata",NULL,0);
if(taos == NULL) {
printf("Cannot connect to tdengine server\n");
exit(EXIT_FAILURE);
}
stmt = taos_stmt_init(taos);
assert(stmt != NULL);
assert(taos_stmt_close(stmt) == 0);
printf("finish taos_stmt_init test\n");
}
void taos_stmt_preprare_test() {
printf("start taos_stmt_prepare test\n");
char *stmt_sql = calloc(1, 1048576);
TAOS_STMT *stmt = NULL;
assert(taos_stmt_prepare(stmt, stmt_sql, 0) != 0);
void *taos = NULL;
taos = taos_connect("127.0.0.1","root","taosdata",NULL,0);
if(taos == NULL) {
printf("Cannot connect to tdengine server\n");
exit(EXIT_FAILURE);
}
execute_simple_sql(taos, "drop database if exists stmt_test");
execute_simple_sql(taos, "create database stmt_test");
execute_simple_sql(taos, "use stmt_test");
execute_simple_sql(taos, "create table super(ts timestamp, c1 int, c2 bigint, c3 float, c4 double, c5 binary(8), c6 smallint, c7 tinyint, c8 bool, c9 nchar(8), c10 timestamp) tags (t1 int, t2 bigint, t3 float, t4 double, t5 binary(8), t6 smallint, t7 tinyint, t8 bool, t9 nchar(8))");
stmt = taos_stmt_init(taos);
assert(stmt != NULL);
// below will make client dead lock
assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0);
// assert(taos_stmt_close(stmt) == 0);
// stmt = taos_stmt_init(taos);
assert(stmt != NULL);
sprintf(stmt_sql, "select from ?");
assert(taos_stmt_prepare(stmt, stmt_sql, 0) != 0);
assert(taos_stmt_close(stmt) == 0);
stmt = taos_stmt_init(taos);
assert(stmt != NULL);
sprintf(stmt_sql, "insert into ? values (?,?,?,?,?,?,?,?,?,?,?)");
assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0);
assert(taos_stmt_close(stmt) == 0);
stmt = taos_stmt_init(taos);
assert(stmt != NULL);
sprintf(stmt_sql, "insert into super values (?,?,?,?,?,?,?,?,?,?,?)");
assert(taos_stmt_prepare(stmt, stmt_sql, 0) != 0);
assert(taos_stmt_close(stmt) == 0);
stmt = taos_stmt_init(taos);
assert(stmt != NULL);
sprintf(stmt_sql, "insert into ? values (?,?,?,?,?,?,?,?,1,?,?,?)");
assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0);
assert(taos_stmt_close(stmt) == 0);
free(stmt_sql);
printf("finish taos_stmt_prepare test\n");
}
void taos_stmt_set_tbname_test() {
printf("start taos_stmt_set_tbname test\n");
TAOS_STMT *stmt = NULL;
char *name = calloc(1, 200);
// ASM ERROR
// assert(taos_stmt_set_tbname(stmt, name) != 0);
void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0);
if(taos == NULL) {
printf("Cannot connect to tdengine server\n");
exit(EXIT_FAILURE);
}
execute_simple_sql(taos, "drop database if exists stmt_test");
execute_simple_sql(taos, "create database stmt_test");
execute_simple_sql(taos, "use stmt_test");
execute_simple_sql(taos, "create table super(ts timestamp, c1 int)");
stmt = taos_stmt_init(taos);
assert(stmt != NULL);
assert(taos_stmt_set_tbname(stmt, name) != 0);
char* stmt_sql = calloc(1, 1000);
sprintf(stmt_sql, "insert into ? values (?,?)");
assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0);
sprintf(name, "super");
assert(stmt != NULL);
assert(taos_stmt_set_tbname(stmt, name) == 0);
free(name);
free(stmt_sql);
taos_stmt_close(stmt);
printf("finish taos_stmt_set_tbname test\n");
}
void taos_stmt_set_tbname_tags_test() {
printf("start taos_stmt_set_tbname_tags test\n");
TAOS_STMT *stmt = NULL;
char *name = calloc(1,20);
TAOS_BIND *tags = calloc(1, sizeof(TAOS_BIND));
// ASM ERROR
// assert(taos_stmt_set_tbname_tags(stmt, name, tags) != 0);
void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0);
if(taos == NULL) {
printf("Cannot connect to tdengine server\n");
exit(EXIT_FAILURE);
}
execute_simple_sql(taos, "drop database if exists stmt_test");
execute_simple_sql(taos, "create database stmt_test");
execute_simple_sql(taos, "use stmt_test");
execute_simple_sql(taos, "create stable super(ts timestamp, c1 int) tags (id int)");
execute_simple_sql(taos, "create table tb using super tags (1)");
stmt = taos_stmt_init(taos);
assert(stmt != NULL);
char* stmt_sql = calloc(1, 1000);
sprintf(stmt_sql, "insert into ? using super tags (?) values (?,?)");
assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0);
assert(taos_stmt_set_tbname_tags(stmt, name, tags) != 0);
sprintf(name, "tb");
assert(taos_stmt_set_tbname_tags(stmt, name, tags) != 0);
int t = 1;
tags->buffer_length = TSDB_DATA_TYPE_INT;
tags->buffer_length = sizeof(uint32_t);
tags->buffer = &t;
tags->length = &tags->buffer_length;
tags->is_null = NULL;
assert(taos_stmt_set_tbname_tags(stmt, name, tags) == 0);
free(stmt_sql);
free(name);
free(tags);
taos_stmt_close(stmt);
printf("finish taos_stmt_set_tbname_tags test\n");
}
void taos_stmt_set_sub_tbname_test() {
printf("start taos_stmt_set_sub_tbname test\n");
TAOS_STMT *stmt = NULL;
char *name = calloc(1, 200);
// ASM ERROR
// assert(taos_stmt_set_sub_tbname(stmt, name) != 0);
void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0);
if(taos == NULL) {
printf("Cannot connect to tdengine server\n");
exit(EXIT_FAILURE);
}
execute_simple_sql(taos, "drop database if exists stmt_test");
execute_simple_sql(taos, "create database stmt_test");
execute_simple_sql(taos, "use stmt_test");
execute_simple_sql(taos, "create stable super(ts timestamp, c1 int) tags (id int)");
execute_simple_sql(taos, "create table tb using super tags (1)");
stmt = taos_stmt_init(taos);
assert(stmt != NULL);
char* stmt_sql = calloc(1, 1000);
sprintf(stmt_sql, "insert into ? values (?,?)");
assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0);
assert(taos_stmt_set_sub_tbname(stmt, name) != 0);
sprintf(name, "tb");
assert(taos_stmt_set_sub_tbname(stmt, name) == 0);
// assert(taos_load_table_info(taos, "super, tb") == 0);
// assert(taos_stmt_set_sub_tbname(stmt, name) == 0);
free(name);
free(stmt_sql);
assert(taos_stmt_close(stmt) == 0);
printf("finish taos_stmt_set_sub_tbname test\n");
}
void taos_stmt_bind_param_test() {
printf("start taos_stmt_bind_param test\n");
TAOS_STMT *stmt = NULL;
TAOS_BIND *binds = NULL;
assert(taos_stmt_bind_param(stmt, binds) != 0);
void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0);
if(taos == NULL) {
printf("Cannot connect to tdengine server\n");
exit(EXIT_FAILURE);
}
execute_simple_sql(taos, "drop database if exists stmt_test");
execute_simple_sql(taos, "create database stmt_test");
execute_simple_sql(taos, "use stmt_test");
execute_simple_sql(taos, "create table super(ts timestamp, c1 int)");
stmt = taos_stmt_init(taos);
char* stmt_sql = calloc(1, 1000);
sprintf(stmt_sql, "insert into ? values (?,?)");
assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0);
assert(taos_stmt_bind_param(stmt, binds) != 0);
free(binds);
TAOS_BIND *params = calloc(2, sizeof(TAOS_BIND));
int64_t ts = (int64_t)1591060628000;
params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
params[0].buffer_length = sizeof(uint64_t);
params[0].buffer = &ts;
params[0].length = &params[0].buffer_length;
params[0].is_null = NULL;
int32_t i = (int32_t)21474;
params[1].buffer_type = TSDB_DATA_TYPE_INT;
params[1].buffer_length = sizeof(int32_t);
params[1].buffer = &i;
params[1].length = &params[1].buffer_length;
params[1].is_null = NULL;
assert(taos_stmt_bind_param(stmt, params) != 0);
assert(taos_stmt_set_tbname(stmt, "super") == 0);
assert(taos_stmt_bind_param(stmt, params) == 0);
free(params);
free(stmt_sql);
taos_stmt_close(stmt);
printf("finish taos_stmt_bind_param test\n");
}
void taos_stmt_bind_single_param_batch_test() {
printf("start taos_stmt_bind_single_param_batch test\n");
TAOS_STMT *stmt = NULL;
TAOS_MULTI_BIND *bind = NULL;
assert(taos_stmt_bind_single_param_batch(stmt, bind, 0) != 0);
printf("finish taos_stmt_bind_single_param_batch test\n");
}
void taos_stmt_bind_param_batch_test() {
printf("start taos_stmt_bind_param_batch test\n");
TAOS_STMT *stmt = NULL;
TAOS_MULTI_BIND *bind = NULL;
assert(taos_stmt_bind_param_batch(stmt, bind) != 0);
printf("finish taos_stmt_bind_param_batch test\n");
}
void taos_stmt_add_batch_test() {
printf("start taos_stmt_add_batch test\n");
TAOS_STMT *stmt = NULL;
assert(taos_stmt_add_batch(stmt) != 0);
void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0);
if(taos == NULL) {
printf("Cannot connect to tdengine server\n");
exit(EXIT_FAILURE);
}
execute_simple_sql(taos, "drop database if exists stmt_test");
execute_simple_sql(taos, "create database stmt_test");
execute_simple_sql(taos, "use stmt_test");
execute_simple_sql(taos, "create table super(ts timestamp, c1 int)");
stmt = taos_stmt_init(taos);
assert(stmt != NULL);
char* stmt_sql = calloc(1, 1000);
sprintf(stmt_sql, "insert into ? values (?,?)");
assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0);
assert(taos_stmt_add_batch(stmt) != 0);
TAOS_BIND *params = calloc(2, sizeof(TAOS_BIND));
int64_t ts = (int64_t)1591060628000;
params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
params[0].buffer_length = sizeof(uint64_t);
params[0].buffer = &ts;
params[0].length = &params[0].buffer_length;
params[0].is_null = NULL;
int32_t i = (int32_t)21474;
params[1].buffer_type = TSDB_DATA_TYPE_INT;
params[1].buffer_length = sizeof(int32_t);
params[1].buffer = &i;
params[1].length = &params[1].buffer_length;
params[1].is_null = NULL;
assert(taos_stmt_set_tbname(stmt, "super") == 0);
assert(taos_stmt_bind_param(stmt, params) == 0);
assert(taos_stmt_add_batch(stmt) == 0);
free(params);
free(stmt_sql);
assert(taos_stmt_close(stmt) == 0);
printf("finish taos_stmt_add_batch test\n");
}
void taos_stmt_execute_test() {
printf("start taos_stmt_execute test\n");
TAOS_STMT *stmt = NULL;
assert(taos_stmt_execute(stmt) != 0);
void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0);
if(taos == NULL) {
printf("Cannot connect to tdengine server\n");
exit(EXIT_FAILURE);
}
execute_simple_sql(taos, "drop database if exists stmt_test");
execute_simple_sql(taos, "create database stmt_test");
execute_simple_sql(taos, "use stmt_test");
execute_simple_sql(taos, "create table super(ts timestamp, c1 int)");
stmt = taos_stmt_init(taos);
assert(stmt != NULL);
assert(taos_stmt_execute(stmt) != 0);
char* stmt_sql = calloc(1, 1000);
sprintf(stmt_sql, "insert into ? values (?,?)");
assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0);
assert(taos_stmt_execute(stmt) != 0);
TAOS_BIND *params = calloc(2, sizeof(TAOS_BIND));
int64_t ts = (int64_t)1591060628000;
params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
params[0].buffer_length = sizeof(uint64_t);
params[0].buffer = &ts;
params[0].length = &params[0].buffer_length;
params[0].is_null = NULL;
int32_t i = (int32_t)21474;
params[1].buffer_type = TSDB_DATA_TYPE_INT;
params[1].buffer_length = sizeof(int32_t);
params[1].buffer = &i;
params[1].length = &params[1].buffer_length;
params[1].is_null = NULL;
assert(taos_stmt_set_tbname(stmt, "super") == 0);
assert(taos_stmt_execute(stmt) != 0);
assert(taos_stmt_bind_param(stmt, params) == 0);
assert(taos_stmt_execute(stmt) != 0);
assert(taos_stmt_add_batch(stmt) == 0);
assert(taos_stmt_execute(stmt) == 0);
free(params);
free(stmt_sql);
assert(taos_stmt_close(stmt) == 0);
printf("finish taos_stmt_execute test\n");
}
void taos_stmt_use_result_query(void *taos, char *col, int type) {
TAOS_STMT *stmt = taos_stmt_init(taos);
assert(stmt != NULL);
char *stmt_sql = calloc(1, 1024);
struct {
int64_t c1;
int32_t c2;
int64_t c3;
float c4;
double c5;
char c6[8];
int16_t c7;
int8_t c8;
int8_t c9;
char c10[32];
} v = {0};
v.c1 = (int64_t)1591060628000;
v.c2 = (int32_t)1;
v.c3 = (int64_t)1;
v.c4 = (float)1;
v.c5 = (double)1;
strcpy(v.c6, "abcdefgh");
v.c7 = 1;
v.c8 = 1;
v.c9 = 1;
strcpy(v.c10, "一二三四五六七八");
uintptr_t c10len=strlen(v.c10);
sprintf(stmt_sql, "select * from stmt_test.t1 where %s = ?", col);
printf("stmt_sql: %s\n", stmt_sql);
assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0);
TAOS_BIND *params = calloc(1, sizeof(TAOS_BIND));
params->buffer_type = type;
params->is_null = NULL;
switch(type){
case TSDB_DATA_TYPE_TIMESTAMP:
params->buffer_length = sizeof(v.c1);
params->buffer = &v.c1;
params->length = &params->buffer_length;
break;
case TSDB_DATA_TYPE_INT:
params->buffer_length = sizeof(v.c2);
params->buffer = &v.c2;
params->length = &params->buffer_length;
case TSDB_DATA_TYPE_BIGINT:
params->buffer_length = sizeof(v.c3);
params->buffer = &v.c3;
params->length = &params->buffer_length;
break;
case TSDB_DATA_TYPE_FLOAT:
params->buffer_length = sizeof(v.c4);
params->buffer = &v.c4;
params->length = &params->buffer_length;
case TSDB_DATA_TYPE_DOUBLE:
params->buffer_length = sizeof(v.c5);
params->buffer = &v.c5;
params->length = &params->buffer_length;
break;
case TSDB_DATA_TYPE_BINARY:
params->buffer_length = sizeof(v.c6);
params->buffer = &v.c6;
params->length = &params->buffer_length;
break;
case TSDB_DATA_TYPE_SMALLINT:
params->buffer_length = sizeof(v.c7);
params->buffer = &v.c7;
params->length = &params->buffer_length;
break;
case TSDB_DATA_TYPE_TINYINT:
params->buffer_length = sizeof(v.c8);
params->buffer = &v.c8;
params->length = &params->buffer_length;
case TSDB_DATA_TYPE_BOOL:
params->buffer_length = sizeof(v.c9);
params->buffer = &v.c9;
params->length = &params->buffer_length;
break;
case TSDB_DATA_TYPE_NCHAR:
params->buffer_length = sizeof(v.c10);
params->buffer = &v.c10;
params->length = &c10len;
break;
default:
printf("Cannnot find type: %d\n", type);
break;
}
assert(taos_stmt_bind_param(stmt, params) == 0);
assert(taos_stmt_execute(stmt) == 0);
TAOS_RES* result = taos_stmt_use_result(stmt);
assert(result != NULL);
print_result(result);
assert(taos_stmt_close(stmt) == 0);
free(params);
free(stmt_sql);
taos_free_result(result);
}
void taos_stmt_use_result_test() {
printf("start taos_stmt_use_result test\n");
void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0);
if(taos == NULL) {
printf("Cannot connect to tdengine server\n");
exit(EXIT_FAILURE);
}
execute_simple_sql(taos, "drop database if exists stmt_test");
execute_simple_sql(taos, "create database stmt_test");
execute_simple_sql(taos, "use stmt_test");
execute_simple_sql(taos, "create table super(ts timestamp, c1 int, c2 bigint, c3 float, c4 double, c5 binary(8), c6 smallint, c7 tinyint, c8 bool, c9 nchar(8), c10 timestamp) tags (t1 int, t2 bigint, t3 float, t4 double, t5 binary(8), t6 smallint, t7 tinyint, t8 bool, t9 nchar(8))");
execute_simple_sql(taos, "create table t1 using super tags (1, 1, 1, 1, 'abcdefgh',1,1,1,'一二三四五六七八')");
execute_simple_sql(taos, "insert into t1 values (1591060628000, 1, 1, 1, 1, 'abcdefgh',1,1,1,'一二三四五六七八', now)");
execute_simple_sql(taos, "insert into t1 values (1591060628001, 1, 1, 1, 1, 'abcdefgh',1,1,1,'一二三四五六七八', now)");
taos_stmt_use_result_query(taos, "c1", TSDB_DATA_TYPE_INT);
taos_stmt_use_result_query(taos, "c2", TSDB_DATA_TYPE_BIGINT);
taos_stmt_use_result_query(taos, "c3", TSDB_DATA_TYPE_FLOAT);
taos_stmt_use_result_query(taos, "c4", TSDB_DATA_TYPE_DOUBLE);
taos_stmt_use_result_query(taos, "c5", TSDB_DATA_TYPE_BINARY);
taos_stmt_use_result_query(taos, "c6", TSDB_DATA_TYPE_SMALLINT);
taos_stmt_use_result_query(taos, "c7", TSDB_DATA_TYPE_TINYINT);
taos_stmt_use_result_query(taos, "c8", TSDB_DATA_TYPE_BOOL);
taos_stmt_use_result_query(taos, "c9", TSDB_DATA_TYPE_NCHAR);
printf("finish taos_stmt_use_result test\n");
}
void taos_stmt_close_test() {
printf("start taos_stmt_close test\n");
// ASM ERROR
// TAOS_STMT *stmt = NULL;
// assert(taos_stmt_close(stmt) != 0);
printf("finish taos_stmt_close test\n");
}
void test_api_reliability() {
// ASM catch memory leak
taos_stmt_init_test();
taos_stmt_preprare_test();
taos_stmt_set_tbname_test();
taos_stmt_set_tbname_tags_test();
taos_stmt_set_sub_tbname_test();
taos_stmt_bind_param_test();
taos_stmt_bind_single_param_batch_test();
taos_stmt_bind_param_batch_test();
taos_stmt_add_batch_test();
taos_stmt_execute_test();
taos_stmt_close_test();
}
void test_query() {
taos_stmt_use_result_test();
}
int main(int argc, char *argv[]) {
test_api_reliability();
test_query();
return 0;
}

View File

@ -221,3 +221,4 @@ run general/stream/table_replica1_vnoden.sim
run general/stream/metrics_replica1_vnoden.sim run general/stream/metrics_replica1_vnoden.sim
run general/db/show_create_db.sim run general/db/show_create_db.sim
run general/db/show_create_table.sim run general/db/show_create_table.sim
run general/parser/like.sim

View File

@ -0,0 +1,124 @@
system sh/stop_dnodes.sh
sleep 2000
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 http -v 1
system sh/cfg.sh -n dnode1 -c httpDbNameMandatory -v 1
system sh/exec.sh -n dnode1 -s start
sleep 2000
sql connect
sql drop database if exists db
print ============================ dnode1 start
print =============== step1 - login
system_content curl 127.0.0.1:7111/rest/login/root/taosdata
print curl 127.0.0.1:7111/rest/login/root/taosdata -----> $system_content
if $system_content != @{"status":"succ","code":0,"desc":"/KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04"}@ then
return -1
endi
print =============== step2 - execute sql without db_name
print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'show databases' 127.0.0.1:7111/rest/sql
system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'show databases' 127.0.0.1:7111/rest/sql
if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then
return -1
endi
print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create database if not exists db' 127.0.0.1:7111/rest/sql
system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create database if not exists db' 127.0.0.1:7111/rest/sql
if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then
return -1
endi
print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create table table_rest (ts timestamp, i int)' 127.0.0.1:7111/rest/sql
system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create table table_rest (ts timestamp, i int)' 127.0.0.1:7111/rest/sql
if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then
return -1
endi
print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'insert into table_rest (now, 1)' 127.0.0.1:7111/rest/sql
system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'insert into table_rest values (now, 1)' 127.0.0.1:7111/rest/sql
if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then
return -1
endi
print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'select * from table_rest' 127.0.0.1:7111/rest/sql
system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'select * from table_rest' 127.0.0.1:7111/rest/sql
if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then
return -1
endi
print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'drop database if exists db' 127.0.0.1:7111/rest/sql
system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'drop database if exists db' 127.0.0.1:7111/rest/sql
if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then
return -1
endi
print =============== step3 - execute sql with db_name
print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'show databases' 127.0.0.1:7111/rest/sql/databases
system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'show databases' 127.0.0.1:7111/rest/sql/databases
if $system_content != @{"status":"succ","head":["name","created_time","ntables","vgroups","replica","quorum","days","keep","cache(MB)","blocks","minrows","maxrows","wallevel","fsync","comp","cachelast","precision","update","status"],"column_meta":[["name",8,32],["created_time",9,8],["ntables",4,4],["vgroups",4,4],["replica",3,2],["quorum",3,2],["days",3,2],["keep",8,24],["cache(MB)",4,4],["blocks",4,4],["minrows",4,4],["maxrows",4,4],["wallevel",2,1],["fsync",4,4],["comp",2,1],["cachelast",2,1],["precision",8,3],["update",2,1],["status",8,10]],"data":[],"rows":0}@ then
return -1
endi
print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create database if not exists db' 127.0.0.1:7111/rest/sql/db
system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create database if not exists db' 127.0.0.1:7111/rest/sql/db
if $system_content != @{"status":"succ","head":["affected_rows"],"column_meta":[["affected_rows",4,4]],"data":[[0]],"rows":1}@ then
return -1
endi
print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create table table_rest (ts timestamp, i int)' 127.0.0.1:7111/rest/sql/db
system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create table table_rest (ts timestamp, i int)' 127.0.0.1:7111/rest/sql/db
if $system_content != @{"status":"succ","head":["affected_rows"],"column_meta":[["affected_rows",4,4]],"data":[[0]],"rows":1}@ then
return -1
endi
print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'insert into table_rest (now, 1)' 127.0.0.1:7111/rest/sql/db
system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'insert into table_rest values (1629904789233, 1)' 127.0.0.1:7111/rest/sql/db
if $system_content != @{"status":"succ","head":["affected_rows"],"column_meta":[["affected_rows",4,4]],"data":[[1]],"rows":1}@ then
return -1
endi
print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'select * from table_rest' 127.0.0.1:7111/rest/sql/db
system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'select * from table_rest' 127.0.0.1:7111/rest/sql/db
if $system_content != @{"status":"succ","head":["ts","i"],"column_meta":[["ts",9,8],["i",4,4]],"data":[["2021-08-25 23:19:49.233",1]],"rows":1}@ then
return -1
endi
print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'drop database if exists db' 127.0.0.1:7111/rest/sql/db
system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'drop database if exists db' 127.0.0.1:7111/rest/sql/db
if $system_content != @{"status":"succ","head":["affected_rows"],"column_meta":[["affected_rows",4,4]],"data":[[0]],"rows":1}@ then
return -1
endi
system sh/exec.sh -n dnode1 -s stop -x SIGINT

View File

@ -150,13 +150,13 @@ if $data00 != 0.00150 then
print expect 0.00150, actual: $data00 print expect 0.00150, actual: $data00
return -1 return -1
endi endi
sql create table st_float_15_0 using mt_float tags (3.40282347e+38) #sql create table st_float_15_0 using mt_float tags (3.40282347e+38)
sql select tagname from st_float_15_0 #sql select tagname from st_float_15_0
#if $data00 != 0.001500 then #if $data00 != 0.001500 then
# return -1 # return -1
#endi #endi
sql create table st_float_16_0 using mt_float tags (-3.40282347e+38) #sql create table st_float_16_0 using mt_float tags (-3.40282347e+38)
sql select tagname from st_float_16_0 #sql select tagname from st_float_16_0
#if $data00 != 0.001500 then #if $data00 != 0.001500 then
# return -1 # return -1
#endi #endi

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,61 @@
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 4
system sh/exec.sh -n dnode1 -s start
sleep 10
sql connect
print ======================== dnode1 start
$db = testdb
sql drop database if exists $db
sql create database $db cachelast 2
sql use $db
$table1 = table_name
$table2 = tablexname
sql create table $table1 (ts timestamp, b binary(20))
sql create table $table2 (ts timestamp, b binary(20))
sql insert into $table1 values(now, "table_name")
sql insert into $table1 values(now-1m, "tablexname")
sql insert into $table1 values(now-2m, "tablexxx")
sql insert into $table1 values(now-2m, "table")
sql select b from $table1
if $rows != 4 then
return -1
endi
sql select b from $table1 where b like 'table_name'
if $rows != 2 then
return -1
endi
sql select b from $table1 where b like 'table\_name'
if $rows != 1 then
return -1
endi
sql show tables;
if $rows != 2 then
return -1
endi
sql show tables like 'table_name'
if $rows != 2 then
return -1
endi
sql show tables like 'table\_name'
if $rows != 1 then
return -1
endi
system sh/exec.sh -n dnode1 -s stop -x SIGINT