Merge branch 'develop' into feature/TD-3188
This commit is contained in:
commit
003e6f4bd1
|
@ -42,17 +42,49 @@ def pre_test(){
|
|||
killall -9 taosd ||echo "no taosd running"
|
||||
killall -9 gdb || echo "no gdb running"
|
||||
cd ${WKC}
|
||||
git reset --hard HEAD~10 >/dev/null
|
||||
git checkout develop
|
||||
git reset --hard HEAD~10 >/dev/null
|
||||
'''
|
||||
script {
|
||||
if (env.CHANGE_TARGET == 'master') {
|
||||
sh '''
|
||||
cd ${WKC}
|
||||
git checkout master
|
||||
'''
|
||||
}
|
||||
else {
|
||||
sh '''
|
||||
cd ${WKC}
|
||||
git checkout develop
|
||||
'''
|
||||
}
|
||||
}
|
||||
sh'''
|
||||
cd ${WKC}
|
||||
git pull >/dev/null
|
||||
git fetch origin +refs/pull/${CHANGE_ID}/merge
|
||||
git checkout -qf FETCH_HEAD
|
||||
git clean -dfx
|
||||
cd ${WK}
|
||||
git reset --hard HEAD~10
|
||||
git checkout develop
|
||||
git pull >/dev/null
|
||||
'''
|
||||
script {
|
||||
if (env.CHANGE_TARGET == 'master') {
|
||||
sh '''
|
||||
cd ${WK}
|
||||
git checkout master
|
||||
'''
|
||||
}
|
||||
else {
|
||||
sh '''
|
||||
cd ${WK}
|
||||
git checkout develop
|
||||
'''
|
||||
}
|
||||
}
|
||||
sh '''
|
||||
cd ${WK}
|
||||
git pull >/dev/null
|
||||
|
||||
export TZ=Asia/Harbin
|
||||
date
|
||||
git clean -dfx
|
||||
|
@ -92,7 +124,8 @@ pipeline {
|
|||
git pull
|
||||
git fetch origin +refs/pull/${CHANGE_ID}/merge
|
||||
git checkout -qf FETCH_HEAD
|
||||
'''
|
||||
'''
|
||||
|
||||
script{
|
||||
env.skipstage=sh(script:"cd ${WORKSPACE}.tes && git --no-pager diff --name-only FETCH_HEAD develop|grep -v -E '.*md|//src//connector|Jenkinsfile|test-all.sh' || echo 0 ",returnStdout:true)
|
||||
}
|
||||
|
@ -185,14 +218,12 @@ pipeline {
|
|||
rm -rf /var/log/taos/*
|
||||
./handle_crash_gen_val_log.sh
|
||||
'''
|
||||
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
|
||||
sh '''
|
||||
cd ${WKC}/tests/pytest
|
||||
rm -rf /var/lib/taos/*
|
||||
rm -rf /var/log/taos/*
|
||||
./handle_taosd_val_log.sh
|
||||
'''
|
||||
}
|
||||
sh '''
|
||||
cd ${WKC}/tests/pytest
|
||||
rm -rf /var/lib/taos/*
|
||||
rm -rf /var/log/taos/*
|
||||
./handle_taosd_val_log.sh
|
||||
'''
|
||||
timeout(time: 45, unit: 'MINUTES'){
|
||||
sh '''
|
||||
date
|
||||
|
|
|
@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS)
|
|||
#INSTALL(TARGETS taos RUNTIME DESTINATION driver)
|
||||
#INSTALL(TARGETS shell RUNTIME DESTINATION .)
|
||||
IF (TD_MVN_INSTALLED)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.25-dist.jar DESTINATION connector/jdbc)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.27-dist.jar DESTINATION connector/jdbc)
|
||||
ENDIF ()
|
||||
ELSEIF (TD_DARWIN)
|
||||
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
|
||||
|
|
|
@ -4,7 +4,7 @@ PROJECT(TDengine)
|
|||
IF (DEFINED VERNUMBER)
|
||||
SET(TD_VER_NUMBER ${VERNUMBER})
|
||||
ELSE ()
|
||||
SET(TD_VER_NUMBER "2.0.18.0")
|
||||
SET(TD_VER_NUMBER "2.0.20.0")
|
||||
ENDIF ()
|
||||
|
||||
IF (DEFINED VERCOMPATIBLE)
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
# 通过 Docker 快速体验 TDengine
|
||||
|
||||
虽然并不推荐在生产环境中通过 Docker 来部署 TDengine 服务,但 Docker 工具能够很好地屏蔽底层操作系统的环境差异,很适合在开发测试或初次体验时用于安装运行 TDengine 的工具集。特别是,借助 Docker,能够比较方便地在 Mac OSX 和 Windows 系统上尝试 TDengine,而无需安装虚拟机或额外租用 Linux 服务器。
|
||||
|
||||
下文通过 Step by Step 风格的介绍,讲解如何通过 Docker 快速建立 TDengine 的单节点运行环境,以支持开发和测试。
|
||||
|
||||
## 下载 Docker
|
||||
|
||||
Docker 工具自身的下载请参考 [Docker官网文档](https://docs.docker.com/get-docker/)。
|
||||
|
||||
安装完毕后可以在命令行终端查看 Docker 版本。如果版本号正常输出,则说明 Docker 环境已经安装成功。
|
||||
|
||||
```bash
|
||||
$ docker -v
|
||||
Docker version 20.10.5, build 55c4c88
|
||||
```
|
||||
|
||||
## 在 Docker 容器中运行 TDengine
|
||||
|
||||
1,使用命令拉取 TDengine 镜像,并使它在后台运行。
|
||||
|
||||
```bash
|
||||
$ docker run -d tdengine/tdengine
|
||||
cdf548465318c6fc2ad97813f89cc60006393392401cae58a27b15ca9171f316
|
||||
```
|
||||
|
||||
- **docker run**:通过 Docker 运行一个容器。
|
||||
- **-d**:让容器在后台运行。
|
||||
- **tdengine/tdengine**:拉取的 TDengine 官方发布的应用镜像。
|
||||
- **cdf548465318c6fc2ad97813f89cc60006393392401cae58a27b15ca9171f316**:这个返回的长字符是容器 ID,我们可以通过容器 ID 来查看对应的容器。
|
||||
|
||||
2,确认容器是否已经正确运行。
|
||||
|
||||
```bash
|
||||
$ docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS ···
|
||||
cdf548465318 tdengine/tdengine "taosd" 14 minutes ago Up 14 minutes ···
|
||||
```
|
||||
|
||||
- **docker ps**:列出所有正在运行状态的容器信息。
|
||||
- **CONTAINER ID**:容器 ID。
|
||||
- **IMAGE**:使用的镜像。
|
||||
- **COMMAND**:启动容器时运行的命令。
|
||||
- **CREATED**:容器创建时间。
|
||||
- **STATUS**:容器状态。UP 表示运行中。
|
||||
|
||||
3,进入 Docker 容器内,使用 TDengine。
|
||||
|
||||
```bash
|
||||
$ docker exec -it cdf548465318 /bin/bash
|
||||
root@cdf548465318:~/TDengine-server-2.0.13.0#
|
||||
```
|
||||
|
||||
- **docker exec**:通过 docker exec 命令进入容器,如果退出,容器不会停止。
|
||||
- **-i**:进入交互模式。
|
||||
- **-t**:指定一个终端。
|
||||
- **cdf548465318**:容器 ID,需要根据 docker ps 指令返回的值进行修改。
|
||||
- **/bin/bash**:载入容器后运行 bash 来进行交互。
|
||||
|
||||
4,进入容器后,执行 taos shell 客户端程序。
|
||||
|
||||
```bash
|
||||
$ root@cdf548465318:~/TDengine-server-2.0.13.0# taos
|
||||
|
||||
Welcome to the TDengine shell from Linux, Client Version:2.0.13.0
|
||||
Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.
|
||||
|
||||
taos>
|
||||
```
|
||||
|
||||
TDengine 终端成功连接服务端,打印出了欢迎消息和版本信息。如果失败,会有错误信息打印出来。
|
||||
|
||||
在 TDengine 终端中,可以通过 SQL 命令来创建/删除数据库、表、超级表等,并可以进行插入和查询操作。具体可以参考 [TAOS SQL 说明文档](https://www.taosdata.com/cn/documentation/taos-sql)。
|
||||
|
||||
## 通过 taosdemo 进一步了解 TDengine
|
||||
|
||||
1,接上面的步骤,先退出 TDengine 终端程序。
|
||||
|
||||
```bash
|
||||
$ taos> q
|
||||
root@cdf548465318:~/TDengine-server-2.0.13.0#
|
||||
```
|
||||
|
||||
2,在命令行界面执行 taosdemo。
|
||||
|
||||
```bash
|
||||
$ root@cdf548465318:~/TDengine-server-2.0.13.0# taosdemo
|
||||
###################################################################
|
||||
# Server IP: localhost:0
|
||||
# User: root
|
||||
# Password: taosdata
|
||||
# Use metric: true
|
||||
# Datatype of Columns: int int int int int int int float
|
||||
# Binary Length(If applicable): -1
|
||||
# Number of Columns per record: 3
|
||||
# Number of Threads: 10
|
||||
# Number of Tables: 10000
|
||||
# Number of Data per Table: 100000
|
||||
# Records/Request: 1000
|
||||
# Database name: test
|
||||
# Table prefix: t
|
||||
# Delete method: 0
|
||||
# Test time: 2021-04-13 02:05:20
|
||||
###################################################################
|
||||
```
|
||||
|
||||
回车后,该命令将新建一个数据库 test,并且自动创建一张超级表 meters,并以超级表 meters 为模版创建了 1 万张表,表名从 "t0" 到 "t9999"。每张表有 10 万条记录,每条记录有 f1,f2,f3 三个字段,时间戳 ts 字段从 "2017-07-14 10:40:00 000" 到 "2017-07-14 10:41:39 999"。每张表带有 areaid 和 loc 两个标签 TAG,areaid 被设置为 1 到 10,loc 被设置为 "beijing" 或 "shanghai"。
|
||||
|
||||
3,进入 TDengine 终端,查看 taosdemo 生成的数据。
|
||||
|
||||
- **进入命令行。**
|
||||
|
||||
```bash
|
||||
$ root@cdf548465318:~/TDengine-server-2.0.13.0# taos
|
||||
|
||||
Welcome to the TDengine shell from Linux, Client Version:2.0.13.0
|
||||
Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.
|
||||
|
||||
taos>
|
||||
```
|
||||
|
||||
- **查看数据库。**
|
||||
|
||||
```bash
|
||||
$ taos> show databases;
|
||||
name | created_time | ntables | vgroups | ···
|
||||
test | 2021-04-13 02:14:15.950 | 10000 | 6 | ···
|
||||
log | 2021-04-12 09:36:37.549 | 4 | 1 | ···
|
||||
|
||||
```
|
||||
|
||||
- **查看超级表。**
|
||||
|
||||
```bash
|
||||
$ taos> use test;
|
||||
Database changed.
|
||||
|
||||
$ taos> show stables;
|
||||
name | created_time | columns | tags | tables |
|
||||
=====================================================================================
|
||||
meters | 2021-04-13 02:14:15.955 | 4 | 2 | 10000 |
|
||||
Query OK, 1 row(s) in set (0.001737s)
|
||||
|
||||
```
|
||||
|
||||
- **查看表,限制输出十条。**
|
||||
|
||||
```bash
|
||||
$ taos> select * from test.t0 limit 10;
|
||||
ts | f1 | f2 | f3 |
|
||||
====================================================================
|
||||
2017-07-14 02:40:01.000 | 3 | 9 | 0 |
|
||||
2017-07-14 02:40:02.000 | 0 | 1 | 2 |
|
||||
2017-07-14 02:40:03.000 | 7 | 2 | 3 |
|
||||
2017-07-14 02:40:04.000 | 9 | 4 | 5 |
|
||||
2017-07-14 02:40:05.000 | 1 | 2 | 5 |
|
||||
2017-07-14 02:40:06.000 | 6 | 3 | 2 |
|
||||
2017-07-14 02:40:07.000 | 4 | 7 | 8 |
|
||||
2017-07-14 02:40:08.000 | 4 | 6 | 6 |
|
||||
2017-07-14 02:40:09.000 | 5 | 7 | 7 |
|
||||
2017-07-14 02:40:10.000 | 1 | 5 | 0 |
|
||||
Query OK, 10 row(s) in set (0.003638s)
|
||||
|
||||
```
|
||||
|
||||
- **查看 t0 表的标签值。**
|
||||
|
||||
```bash
|
||||
$ taos> select areaid, loc from test.t0;
|
||||
areaid | loc |
|
||||
===========================
|
||||
10 | shanghai |
|
||||
Query OK, 1 row(s) in set (0.002904s)
|
||||
|
||||
```
|
||||
|
||||
## 停止正在 Docker 中运行的 TDengine 服务
|
||||
|
||||
```bash
|
||||
$ docker stop cdf548465318
|
||||
cdf548465318
|
||||
```
|
||||
|
||||
- **docker stop**:通过 docker stop 停止指定的正在运行中的 docker 镜像。
|
||||
- **cdf548465318**:容器 ID,根据 docker ps 指令返回的结果进行修改。
|
||||
|
||||
## 编程开发时连接在 Docker 中的 TDengine
|
||||
|
||||
从 Docker 之外连接使用在 Docker 容器内运行的 TDengine 服务,有以下两个思路:
|
||||
|
||||
1,通过端口映射(-p),将容器内部开放的网络端口映射到宿主机的指定端口上。通过挂载本地目录(-v),可以实现宿主机与容器内部的数据同步,防止容器删除后,数据丢失。
|
||||
|
||||
```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","keep1,keep2,keep(D)","cache(MB)","blocks","minrows","maxrows","wallevel","fsync","comp","precision","status"],"data":[],"rows":0}
|
||||
```
|
||||
|
||||
- 第一条命令,启动一个运行了 TDengine 的 docker 容器,并且将容器的 6041 端口映射到宿主机的 6041 端口上。
|
||||
- 第二条命令,通过 RESTful 接口访问 TDengine,这时连接的是本机的 6041 端口,可见连接成功。
|
||||
|
||||
注意:在这个示例中,出于方便性考虑,只映射了 RESTful 需要的 6041 端口。如果希望以非 RESTful 方式连接 TDengine 服务,则需要映射从 6030 开始的共 11 个端口(完整的端口情况请参见 [TDengine 2.0 端口说明](https://www.taosdata.com/cn/documentation/faq#port))。在例子中,挂载本地目录也只是处理了配置文件所在的 /etc/taos 目录,而没有挂载数据存储目录。
|
||||
|
||||
2,直接通过 exec 命令,进入到 docker 容器中去做开发。也即,把程序代码放在 TDengine 服务端所在的同一个 Docker 容器中,连接容器本地的 TDengine 服务。
|
||||
|
||||
```bash
|
||||
$ docker exec -it 526aa188da /bin/bash
|
||||
```
|
||||
|
|
@ -10,7 +10,9 @@ TDengine软件分为服务器、客户端和报警模块三部分,目前2.0版
|
|||
|
||||
### 通过Docker容器运行
|
||||
|
||||
请参考[TDengine官方Docker镜像的发布、下载和使用](https://www.taosdata.com/blog/2020/05/13/1509.html)
|
||||
暂时不建议生产环境采用 Docker 来部署 TDengine 的客户端或服务端,但在开发环境下或初次尝试时,使用 Docker 方式部署是十分方便的。特别是,利用 Docker,可以方便地在 Mac OSX 和 Windows 环境下尝试 TDengine。
|
||||
|
||||
详细操作方法请参照 [通过Docker快速体验TDengine](https://www.taosdata.com/cn/documentation/getting-started/docker)。
|
||||
|
||||
### <a class="anchor" id="package-install"></a>通过安装包安装
|
||||
|
||||
|
@ -212,7 +214,7 @@ taos> select avg(f1), max(f2), min(f3) from test.t10 interval(10s);
|
|||
| **Python** | ● | ● | ● | ○ | ● | ● | ● | -- | ● |
|
||||
| **Go** | ● | ● | ● | ○ | ● | ● | ○ | -- | -- |
|
||||
| **NodeJs** | ● | ● | ○ | ○ | ● | ● | ○ | -- | -- |
|
||||
| **C#** | ○ | ● | ● | ○ | ○ | ○ | ○ | -- | -- |
|
||||
| **C#** | ● | ● | ○ | ○ | ○ | ○ | ○ | -- | -- |
|
||||
| **RESTful** | ● | ● | ● | ● | ● | ● | ● | ● | ● |
|
||||
|
||||
注: ● 表示经过官方测试验证, ○ 表示非官方测试验证。
|
||||
|
|
|
@ -178,7 +178,7 @@ TDengine 分布式架构的逻辑结构图如下:
|
|||
|
||||
**FQDN配置**:一个数据节点有一个或多个FQDN,可以在系统配置文件taos.cfg通过参数“fqdn"进行指定,如果没有指定,系统将自动获取计算机的hostname作为其FQDN。如果节点没有配置FQDN,可以直接将该节点的配置参数fqdn设置为它的IP地址。但不建议使用IP,因为IP地址可变,一旦变化,将让集群无法正常工作。一个数据节点的EP(End Point)由FQDN + Port组成。采用FQDN,需要保证DNS服务正常工作,或者在节点以及应用所在的节点配置好hosts文件。
|
||||
|
||||
**端口配置:**一个数据节点对外的端口由TDengine的系统配置参数serverPort决定,对集群内部通讯的端口是serverPort+5。集群内数据节点之间的数据复制操作还占有一个TCP端口,是serverPort+10. 为支持多线程高效的处理UDP数据,每个对内和对外的UDP连接,都需要占用5个连续的端口。因此一个数据节点总的端口范围为serverPort到serverPort + 10,总共11个TCP/UDP端口。(另外还可能有 RESTful、Arbitrator 所使用的端口,那样的话就一共是 13 个。)使用时,需要确保防火墙将这些端口打开,以备使用。每个数据节点可以配置不同的serverPort。
|
||||
**端口配置:**一个数据节点对外的端口由TDengine的系统配置参数serverPort决定,对集群内部通讯的端口是serverPort+5。集群内数据节点之间的数据复制操作还占有一个TCP端口,是serverPort+10. 为支持多线程高效的处理UDP数据,每个对内和对外的UDP连接,都需要占用5个连续的端口。因此一个数据节点总的端口范围为serverPort到serverPort + 10,总共11个TCP/UDP端口。(另外还可能有 RESTful、Arbitrator 所使用的端口,那样的话就一共是 13 个。)使用时,需要确保防火墙将这些端口打开,以备使用。每个数据节点可以配置不同的serverPort。(详细的端口情况请参见 [TDengine 2.0 端口说明](https://www.taosdata.com/cn/documentation/faq#port))
|
||||
|
||||
**集群对外连接:** TDengine集群可以容纳单个、多个甚至几千个数据节点。应用只需要向集群中任何一个数据节点发起连接即可,连接需要提供的网络参数是一数据节点的End Point(FQDN加配置的端口号)。通过命令行CLI启动应用taos时,可以通过选项-h来指定数据节点的FQDN, -P来指定其配置的端口号,如果端口不配置,将采用TDengine的系统配置参数serverPort。
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ TDengine提供了丰富的应用程序开发接口,其中包括C/C++、Java、
|
|||
| **Python** | ● | ● | ● | ○ | ● | ● | ○ | -- | ○ |
|
||||
| **Go** | ● | ● | ● | ○ | ● | ● | ○ | -- | -- |
|
||||
| **NodeJs** | ● | ● | ○ | ○ | ● | ● | ○ | -- | -- |
|
||||
| **C#** | ○ | ● | ● | ○ | ○ | ○ | ○ | -- | -- |
|
||||
| **C#** | ● | ● | ○ | ○ | ○ | ○ | ○ | -- | -- |
|
||||
| **RESTful** | ● | ● | ● | ● | ● | ● | ○ | ○ | ○ |
|
||||
|
||||
其中 ● 表示经过官方测试验证, ○ 表示非官方测试验证。
|
||||
|
@ -23,7 +23,7 @@ TDengine提供了丰富的应用程序开发接口,其中包括C/C++、Java、
|
|||
|
||||
* 在没有安装TDengine服务端软件的系统中使用连接器(除RESTful外)访问 TDengine 数据库,需要安装相应版本的客户端安装包来使应用驱动(Linux系统中文件名为libtaos.so,Windows系统中为taos.dll)被安装在系统中,否则会产生无法找到相应库文件的错误。
|
||||
* 所有执行 SQL 语句的 API,例如 C/C++ Connector 中的 `tao_query`、`taos_query_a`、`taos_subscribe` 等,以及其它语言中与它们对应的API,每次都只能执行一条 SQL 语句,如果实际参数中包含了多条语句,它们的行为是未定义的。
|
||||
* 升级到TDengine到2.0.8.0版本的用户,必须更新JDBC连接TDengine必须升级taos-jdbcdriver到2.0.12及以上。
|
||||
* 升级到TDengine到2.0.8.0版本的用户,必须更新JDBC连接TDengine必须升级taos-jdbcdriver到2.0.12及以上。详细的版本依赖关系请参见 [taos-jdbcdriver 文档](https://www.taosdata.com/cn/documentation/connector/java#version)。
|
||||
* 无论选用何种编程语言的连接器,2.0 及以上版本的 TDengine 推荐数据库应用的每个线程都建立一个独立的连接,或基于线程建立连接池,以避免连接内的“USE statement”状态量在线程之间相互干扰(但连接的查询和写入操作都是线程安全的)。
|
||||
|
||||
## <a class="anchor" id="driver"></a>安装连接器驱动步骤
|
||||
|
@ -743,7 +743,7 @@ HTTP请求URL采用`sqlutc`时,返回结果集的时间戳将采用UTC时间
|
|||
|
||||
下面仅列出一些与RESTful接口有关的配置参数,其他系统参数请看配置文件里的说明。注意:配置修改后,需要重启taosd服务才能生效
|
||||
|
||||
- httpPort: 对外提供RESTful服务的端口号,默认绑定到6041
|
||||
- 对外提供RESTful服务的端口号,默认绑定到 6041(实际取值是 serverPort + 11,因此可以通过修改 serverPort 参数的设置来修改)
|
||||
- httpMaxThreads: 启动的线程数量,默认为2(2.0.17版本开始,默认值改为CPU核数的一半向下取整)
|
||||
- restfulRowLimit: 返回结果集(JSON格式)的最大条数,默认值为10240
|
||||
- httpEnableCompress: 是否支持压缩,默认不支持,目前TDengine仅支持gzip压缩格式
|
||||
|
|
|
@ -55,12 +55,11 @@ arbitrator ha.taosdata.com:6042
|
|||
| 4 | statusInterval | dnode向mnode报告状态时长 |
|
||||
| 5 | arbitrator | 系统中裁决器的end point |
|
||||
| 6 | timezone | 时区 |
|
||||
| 7 | locale | 系统区位信息及编码格式 |
|
||||
| 8 | charset | 字符集编码 |
|
||||
| 9 | balance | 是否启动负载均衡 |
|
||||
| 10 | maxTablesPerVnode | 每个vnode中能够创建的最大表个数 |
|
||||
| 11 | maxVgroupsPerDb | 每个DB中能够使用的最大vgroup个数 |
|
||||
| 7 | balance | 是否启动负载均衡 |
|
||||
| 8 | maxTablesPerVnode | 每个vnode中能够创建的最大表个数 |
|
||||
| 9 | maxVgroupsPerDb | 每个DB中能够使用的最大vgroup个数 |
|
||||
|
||||
备注:在 2.0.19.0 及更早的版本中,除以上 9 项参数外,dnode 加入集群时,还会要求 locale 和 charset 参数的取值也一致。
|
||||
|
||||
|
||||
## <a class="anchor" id="node-one"></a>启动第一个数据节点
|
||||
|
|
|
@ -100,8 +100,7 @@ taosd -C
|
|||
|
||||
- firstEp: taosd启动时,主动连接的集群中首个dnode的end point, 默认值为localhost:6030。
|
||||
- fqdn:数据节点的FQDN,缺省为操作系统配置的第一个hostname。如果习惯IP地址访问,可设置为该节点的IP地址。
|
||||
- serverPort:taosd启动后,对外服务的端口号,默认值为6030。
|
||||
- httpPort: RESTful服务使用的端口号,所有的HTTP请求(TCP)都需要向该接口发起查询/写入请求, 默认值为6041。
|
||||
- serverPort:taosd启动后,对外服务的端口号,默认值为6030。(RESTful服务使用的端口号是在此基础上+11,即默认值为6041。)
|
||||
- dataDir: 数据文件目录,所有的数据文件都将写入该目录。默认值:/var/lib/taos。
|
||||
- logDir:日志文件目录,客户端和服务器的运行日志文件将写入该目录。默认值:/var/log/taos。
|
||||
- arbitrator:系统中裁决器的end point, 缺省值为空。
|
||||
|
@ -115,7 +114,7 @@ taosd -C
|
|||
- queryBufferSize: 为所有并发查询占用保留的内存大小。计算规则可以根据实际应用可能的最大并发数和表的数字相乘,再乘 170 。单位为 MB(2.0.15 以前的版本中,此参数的单位是字节)。
|
||||
- ratioOfQueryCores: 设置查询线程的最大数量。最小值0 表示只有1个查询线程;最大值2表示最大建立2倍CPU核数的查询线程。默认为1,表示最大和CPU核数相等的查询线程。该值可以为小数,即0.5表示最大建立CPU核数一半的查询线程。
|
||||
|
||||
**注意:**对于端口,TDengine会使用从serverPort起13个连续的TCP和UDP端口号,请务必在防火墙打开。因此如果是缺省配置,需要打开从6030到6042共13个端口,而且必须TCP和UDP都打开。
|
||||
**注意:**对于端口,TDengine会使用从serverPort起13个连续的TCP和UDP端口号,请务必在防火墙打开。因此如果是缺省配置,需要打开从6030到6042共13个端口,而且必须TCP和UDP都打开。(详细的端口情况请参见 [TDengine 2.0 端口说明](https://www.taosdata.com/cn/documentation/faq#port))
|
||||
|
||||
不同应用场景的数据往往具有不同的数据特征,比如保留天数、副本数、采集频次、记录大小、采集点的数量、压缩等都可完全不同。为获得在存储上的最高效率,TDengine提供如下存储相关的系统配置参数:
|
||||
|
||||
|
@ -150,7 +149,7 @@ TDengine集群中加入一个新的dnode时,涉及集群相关的一些参数
|
|||
- maxTablesPerVnode: 每个vnode中能够创建的最大表个数。默认值:1000000。
|
||||
- maxVgroupsPerDb: 每个数据库中能够使用的最大vgroup个数。
|
||||
- arbitrator: 系统中裁决器的end point,缺省为空。
|
||||
- timezone、locale、charset 的配置见客户端配置。
|
||||
- timezone、locale、charset 的配置见客户端配置。(2.0.20.0 及以上的版本里,集群中加入新节点已不要求 locale 和 charset 参数取值一致)
|
||||
|
||||
为方便调试,可通过SQL语句临时调整每个dnode的日志配置,系统重启后会失效:
|
||||
|
||||
|
@ -463,41 +462,41 @@ TDengine的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下
|
|||
|
||||
| 关键字列表 | | | | |
|
||||
| ---------- | ----------- | ------------ | ---------- | --------- |
|
||||
| ABLOCKS | CONNECTIONS | GT | MNODES | SLIDING |
|
||||
| ABORT | COPY | ID | MODULES | SLIMIT |
|
||||
| ACCOUNT | COUNT | IF | NCHAR | SMALLINT |
|
||||
| ACCOUNTS | CREATE | IGNORE | NE | SPREAD |
|
||||
| ADD | CTIME | IMMEDIATE | NONE | STABLE |
|
||||
| AFTER | DATABASE | IMPORT | NOT | STABLES |
|
||||
| ALL | DATABASES | IN | NOTNULL | STAR |
|
||||
| ALTER | DAYS | INITIALLY | NOW | STATEMENT |
|
||||
| AND | DEFERRED | INSERT | OF | STDDEV |
|
||||
| AS | DELIMITERS | INSTEAD | OFFSET | STREAM |
|
||||
| ASC | DESC | INTEGER | OR | STREAMS |
|
||||
| ATTACH | DESCRIBE | INTERVAL | ORDER | STRING |
|
||||
| AVG | DETACH | INTO | PASS | SUM |
|
||||
| BEFORE | DIFF | IP | PERCENTILE | TABLE |
|
||||
| BEGIN | DISTINCT | IS | PLUS | TABLES |
|
||||
| BETWEEN | DIVIDE | ISNULL | PRAGMA | TAG |
|
||||
| BIGINT | DNODE | JOIN | PREV | TAGS |
|
||||
| BINARY | DNODES | KEEP | PRIVILEGE | TBLOCKS |
|
||||
| BITAND | DOT | KEY | QUERIES | TBNAME |
|
||||
| BITNOT | DOUBLE | KILL | QUERY | TIMES |
|
||||
| BITOR | DROP | LAST | RAISE | TIMESTAMP |
|
||||
| BOOL | EACH | LE | REM | TINYINT |
|
||||
| BOTTOM | END | LEASTSQUARES | REPLACE | TOP |
|
||||
| BY | EQ | LIKE | REPLICA | TRIGGER |
|
||||
| CACHE | EXISTS | LIMIT | RESET | UMINUS |
|
||||
| CASCADE | EXPLAIN | LINEAR | RESTRICT | UPLUS |
|
||||
| CHANGE | FAIL | LOCAL | ROW | USE |
|
||||
| CLOG | FILL | LP | ROWS | USER |
|
||||
| CLUSTER | FIRST | LSHIFT | RP | USERS |
|
||||
| COLON | FLOAT | LT | RSHIFT | USING |
|
||||
| COLUMN | FOR | MATCH | SCORES | VALUES |
|
||||
| COMMA | FROM | MAX | SELECT | VARIABLE |
|
||||
| COMP | GE | METRIC | SEMI | VGROUPS |
|
||||
| CONCAT | GLOB | METRICS | SET | VIEW |
|
||||
| CONFIGS | GRANTS | MIN | SHOW | WAVG |
|
||||
| CONFLICT | GROUP | MINUS | SLASH | WHERE |
|
||||
| CONNECTION | | | | |
|
||||
| ABLOCKS | CONNECTIONS | HAVING | MODULES | SLIMIT |
|
||||
| ABORT | COPY | ID | NCHAR | SMALLINT |
|
||||
| ACCOUNT | COUNT | IF | NE | SPREAD |
|
||||
| ACCOUNTS | CREATE | IGNORE | NONE | STABLE |
|
||||
| ADD | CTIME | IMMEDIATE | NOT | STABLES |
|
||||
| AFTER | DATABASE | IMPORT | NOTNULL | STAR |
|
||||
| ALL | DATABASES | IN | NOW | STATEMENT |
|
||||
| ALTER | DAYS | INITIALLY | OF | STDDEV |
|
||||
| AND | DEFERRED | INSERT | OFFSET | STREAM |
|
||||
| AS | DELIMITERS | INSTEAD | OR | STREAMS |
|
||||
| ASC | DESC | INTEGER | ORDER | STRING |
|
||||
| ATTACH | DESCRIBE | INTERVAL | PASS | SUM |
|
||||
| AVG | DETACH | INTO | PERCENTILE | TABLE |
|
||||
| BEFORE | DIFF | IP | PLUS | TABLES |
|
||||
| BEGIN | DISTINCT | IS | PRAGMA | TAG |
|
||||
| BETWEEN | DIVIDE | ISNULL | PREV | TAGS |
|
||||
| BIGINT | DNODE | JOIN | PRIVILEGE | TBLOCKS |
|
||||
| BINARY | DNODES | KEEP | QUERIES | TBNAME |
|
||||
| BITAND | DOT | KEY | QUERY | TIMES |
|
||||
| BITNOT | DOUBLE | KILL | RAISE | TIMESTAMP |
|
||||
| BITOR | DROP | LAST | REM | TINYINT |
|
||||
| BOOL | EACH | LE | REPLACE | TOP |
|
||||
| BOTTOM | END | LEASTSQUARES | REPLICA | TOPIC |
|
||||
| BY | EQ | LIKE | RESET | TRIGGER |
|
||||
| CACHE | EXISTS | LIMIT | RESTRICT | UMINUS |
|
||||
| CASCADE | EXPLAIN | LINEAR | ROW | UPLUS |
|
||||
| CHANGE | FAIL | LOCAL | ROWS | USE |
|
||||
| CLOG | FILL | LP | RP | USER |
|
||||
| CLUSTER | FIRST | LSHIFT | RSHIFT | USERS |
|
||||
| COLON | FLOAT | LT | SCORES | USING |
|
||||
| COLUMN | FOR | MATCH | SELECT | VALUES |
|
||||
| COMMA | FROM | MAX | SEMI | VARIABLE |
|
||||
| COMP | GE | METRIC | SET | VGROUPS |
|
||||
| CONCAT | GLOB | METRICS | SHOW | VIEW |
|
||||
| CONFIGS | GRANTS | MIN | SLASH | WAVG |
|
||||
| CONFLICT | GROUP | MINUS | SLIDING | WHERE |
|
||||
| CONNECTION | GT | MNODES | | |
|
||||
|
||||
|
|
|
@ -407,10 +407,10 @@ SELECT select_expr [, select_expr ...]
|
|||
[INTERVAL (interval_val [, interval_offset])]
|
||||
[SLIDING sliding_val]
|
||||
[FILL fill_val]
|
||||
[GROUP BY col_list]
|
||||
[GROUP BY col_list [HAVING having_condition]]
|
||||
[ORDER BY col_list { DESC | ASC }]
|
||||
[SLIMIT limit_val [, SOFFSET offset_val]]
|
||||
[LIMIT limit_val [, OFFSET offset_val]]
|
||||
[SLIMIT limit_val [SOFFSET offset_val]]
|
||||
[LIMIT limit_val [OFFSET offset_val]]
|
||||
[>> export_file];
|
||||
```
|
||||
|
||||
|
@ -626,7 +626,8 @@ Query OK, 1 row(s) in set (0.001091s)
|
|||
- WHERE 语句可以使用各种逻辑判断来过滤数字值,或使用通配符来过滤字符串
|
||||
- 输出结果缺省按首列时间戳升序排序,但可以指定按降序排序( _c0 指首列时间戳)。使用 ORDER BY 对其他字段进行排序为非法操作。
|
||||
- 参数 LIMIT 控制输出条数,OFFSET 指定从第几条开始输出。LIMIT/OFFSET 对结果集的执行顺序在 ORDER BY 之后。
|
||||
- 参数 SLIMIT 控制由 GROUP BY 指令划分的每个分组中的输出条数。
|
||||
* 在有 GROUP BY 子句的情况下,LIMIT 参数控制的是每个分组中至多允许输出的条数。
|
||||
- 参数 SLIMIT 控制由 GROUP BY 指令划分的分组中,至多允许输出几个分组的数据。
|
||||
- 通过”>>"输出结果可以导出到指定文件
|
||||
|
||||
### 支持的条件过滤操作
|
||||
|
@ -647,6 +648,15 @@ Query OK, 1 row(s) in set (0.001091s)
|
|||
2. 针对单一字段的过滤,如果是时间过滤条件,则一条语句中只支持设定一个;但针对其他的(普通)列或标签列,则可以使用 `OR` 关键字进行组合条件的查询过滤。例如:((value > 20 AND value < 30) OR (value < 12)) 。
|
||||
3. 从 2.0.17 版本开始,条件过滤开始支持 BETWEEN AND 语法,例如 `WHERE col2 BETWEEN 1.5 AND 3.25` 表示查询条件为“1.5 ≤ col2 ≤ 3.25”。
|
||||
|
||||
### GROUP BY 之后的 HAVING 过滤
|
||||
|
||||
从 2.0.20 版本开始,GROUP BY 之后允许再跟一个 HAVING 子句,对成组后的各组数据再做筛选。HAVING 子句可以使用聚合函数和选择函数作为过滤条件(但暂时不支持 LEASTSQUARES、TOP、BOTTOM、LAST_ROW)。
|
||||
|
||||
例如,如下语句只会输出 `AVG(f1) > 0` 的分组:
|
||||
```mysql
|
||||
SELECT AVG(f1), SPREAD(f1, f2, st2.f1) FROM st2 WHERE f1 > 0 GROUP BY f1 HAVING AVG(f1) > 0;
|
||||
```
|
||||
|
||||
### SQL 示例
|
||||
|
||||
- 对于下面的例子,表tb1用以下语句创建
|
||||
|
@ -950,7 +960,7 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
|
|||
```mysql
|
||||
SELECT TOP(field_name, K) FROM { tb_name | stb_name } [WHERE clause];
|
||||
```
|
||||
功能说明: 统计表/超级表中某列的值最大*k*个非NULL值。若多于k个列值并列最大,则返回时间戳小的。
|
||||
功能说明: 统计表/超级表中某列的值最大 *k* 个非 NULL 值。如果多条数据取值一样,全部取用又会超出 k 条限制时,系统会从相同值中随机选取符合要求的数量返回。
|
||||
|
||||
返回结果数据类型:同应用的字段。
|
||||
|
||||
|
@ -984,7 +994,7 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
|
|||
```mysql
|
||||
SELECT BOTTOM(field_name, K) FROM { tb_name | stb_name } [WHERE clause];
|
||||
```
|
||||
功能说明:统计表/超级表中某列的值最小*k*个非NULL值。若多于k个列值并列最小,则返回时间戳小的。
|
||||
功能说明:统计表/超级表中某列的值最小 *k* 个非 NULL 值。如果多条数据取值一样,全部取用又会超出 k 条限制时,系统会从相同值中随机选取符合要求的数量返回。
|
||||
|
||||
返回结果数据类型:同应用的字段。
|
||||
|
||||
|
@ -1216,6 +1226,7 @@ SELECT AVG(current), MAX(current), LEASTSQUARES(current, start_val, step_val), P
|
|||
- 列名最大长度为 64,最多允许 1024 列,最少需要 2 列,第一列必须是时间戳
|
||||
- 标签最多允许 128 个,可以 1 个,标签总长度不超过 16k 个字符
|
||||
- SQL 语句最大长度 65480 个字符,但可通过系统配置参数 maxSQLLength 修改,最长可配置为 1M
|
||||
- SELECT 语句的查询结果,最多允许返回 1024 列(语句中的函数调用可能也会占用一些列空间),超限时需要显式指定较少的返回数据列,以避免语句执行报错。
|
||||
- 库的数目,超级表的数目、表的数目,系统不做限制,仅受系统资源限制
|
||||
|
||||
## TAOS SQL其他约定
|
||||
|
|
|
@ -166,3 +166,18 @@ TDengine 中时间戳的时区总是由客户端进行处理,而与服务端
|
|||
2. 如果在 taos.cfg 中设置了 timezone 参数,则客户端会以这个配置文件中的设置为准。
|
||||
3. 如果在 C/C++/Java/Python 等各种编程语言的 Connector Driver 中,在建立数据库连接时显式指定了 timezone,那么会以这个指定的时区设置为准。例如 Java Connector 的 JDBC URL 中就有 timezone 参数。
|
||||
4. 在书写 SQL 语句时,也可以直接使用 Unix 时间戳(例如 `1554984068000`)或带有时区的时间戳字符串,也即以 RFC 3339 格式(例如 `2013-04-12T15:52:01.123+08:00`)或 ISO-8601 格式(例如 `2013-04-12T15:52:01.123+0800`)来书写时间戳,此时这些时间戳的取值将不再受其他时区设置的影响。
|
||||
|
||||
## <a class="anchor" id="port"></a>19. TDengine 都会用到哪些网络端口?
|
||||
|
||||
在 TDengine 2.0 版本中,会用到以下这些网络端口(以默认端口 6030 为前提进行说明,如果修改了配置文件中的设置,那么这里列举的端口都会出现变化),管理员可以参考这里的信息调整防火墙设置:
|
||||
|
||||
| 协议 | 默认端口 | 用途说明 | 修改方法 |
|
||||
| --- | --------- | ------------------------------- | ------------------------------ |
|
||||
| TCP | 6030 | 客户端与服务端之间通讯。 | 由配置文件设置 serverPort 决定。 |
|
||||
| TCP | 6035 | 多节点集群的节点间通讯。 | 随 serverPort 端口变化。 |
|
||||
| TCP | 6040 | 多节点集群的节点间数据同步。 | 随 serverPort 端口变化。 |
|
||||
| TCP | 6041 | 客户端与服务端之间的 RESTful 通讯。 | 随 serverPort 端口变化。 |
|
||||
| TCP | 6042 | Arbitrator 的服务端口。 | 因 Arbitrator 启动参数设置变化。 |
|
||||
| TCP | 6060 | 企业版内 Monitor 服务的网络端口。 | |
|
||||
| UDP | 6030-6034 | 客户端与服务端之间通讯。 | 随 serverPort 端口变化。 |
|
||||
| UDP | 6035-6039 | 多节点集群的节点间通讯。 | 随 serverPort 端口变化。 |
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: tdengine
|
||||
base: core18
|
||||
version: '2.0.18.0'
|
||||
version: '2.0.20.0'
|
||||
icon: snap/gui/t-dengine.svg
|
||||
summary: an open-source big data platform designed and optimized for IoT.
|
||||
description: |
|
||||
|
@ -72,7 +72,7 @@ parts:
|
|||
- usr/bin/taosd
|
||||
- usr/bin/taos
|
||||
- usr/bin/taosdemo
|
||||
- usr/lib/libtaos.so.2.0.18.0
|
||||
- usr/lib/libtaos.so.2.0.20.0
|
||||
- usr/lib/libtaos.so.1
|
||||
- usr/lib/libtaos.so
|
||||
|
||||
|
|
|
@ -96,6 +96,25 @@ typedef struct STableMetaInfo {
|
|||
SArray *tagColList; // SArray<SColumn*>, involved tag columns
|
||||
} STableMetaInfo;
|
||||
|
||||
|
||||
typedef struct SColumnIndex {
|
||||
int16_t tableIndex;
|
||||
int16_t columnIndex;
|
||||
} SColumnIndex;
|
||||
|
||||
|
||||
typedef struct SFieldInfo {
|
||||
int16_t numOfOutput; // number of column in result
|
||||
TAOS_FIELD* final;
|
||||
SArray *internalField; // SArray<SInternalField>
|
||||
} SFieldInfo;
|
||||
|
||||
typedef struct SColumn {
|
||||
SColumnIndex colIndex;
|
||||
int32_t numOfFilters;
|
||||
SColumnFilterInfo *filterInfo;
|
||||
} SColumn;
|
||||
|
||||
/* the structure for sql function in select clause */
|
||||
typedef struct SSqlExpr {
|
||||
char aliasName[TSDB_COL_NAME_LEN]; // as aliasName
|
||||
|
@ -109,32 +128,24 @@ typedef struct SSqlExpr {
|
|||
tVariant param[3]; // parameters are not more than 3
|
||||
int32_t offset; // sub result column value of arithmetic expression.
|
||||
int16_t resColId; // result column id
|
||||
SColumn *pFilter; // expr filter
|
||||
} SSqlExpr;
|
||||
|
||||
typedef struct SColumnIndex {
|
||||
int16_t tableIndex;
|
||||
int16_t columnIndex;
|
||||
} SColumnIndex;
|
||||
typedef struct SExprFilter {
|
||||
tSqlExpr *pExpr; //used for having parse
|
||||
SSqlExpr *pSqlExpr;
|
||||
SArray *fp;
|
||||
SColumn *pFilters; //having filter info
|
||||
}SExprFilter;
|
||||
|
||||
typedef struct SInternalField {
|
||||
TAOS_FIELD field;
|
||||
bool visible;
|
||||
SExprInfo *pArithExprInfo;
|
||||
SSqlExpr *pSqlExpr;
|
||||
SExprFilter *pFieldFilters;
|
||||
} SInternalField;
|
||||
|
||||
typedef struct SFieldInfo {
|
||||
int16_t numOfOutput; // number of column in result
|
||||
TAOS_FIELD* final;
|
||||
SArray *internalField; // SArray<SInternalField>
|
||||
} SFieldInfo;
|
||||
|
||||
typedef struct SColumn {
|
||||
SColumnIndex colIndex;
|
||||
int32_t numOfFilters;
|
||||
SColumnFilterInfo *filterInfo;
|
||||
} SColumn;
|
||||
|
||||
typedef struct SCond {
|
||||
uint64_t uid;
|
||||
int32_t len; // length of tag query condition data
|
||||
|
@ -243,6 +254,7 @@ typedef struct SQueryInfo {
|
|||
int32_t round; // 0/1/....
|
||||
int32_t bufLen;
|
||||
char* buf;
|
||||
int32_t havingFieldNum;
|
||||
} SQueryInfo;
|
||||
|
||||
typedef struct {
|
||||
|
@ -261,10 +273,10 @@ typedef struct {
|
|||
|
||||
char * curSql; // current sql, resume position of sql after parsing paused
|
||||
int8_t parseFinished;
|
||||
char reserve2[3]; // fix bus error on arm32
|
||||
char reserve2[3]; // fix bus error on arm32
|
||||
|
||||
int16_t numOfCols;
|
||||
char reserve3[2]; // fix bus error on arm32
|
||||
char reserve3[2]; // fix bus error on arm32
|
||||
uint32_t allocSize;
|
||||
char * payload;
|
||||
int32_t payloadLen;
|
||||
|
@ -317,6 +329,7 @@ typedef struct {
|
|||
char ** buffer; // Buffer used to put multibytes encoded using unicode (wchar_t)
|
||||
SColumnIndex* pColumnIndex;
|
||||
|
||||
TAOS_FIELD* final;
|
||||
SArithmeticSupport *pArithSup; // support the arithmetic expression calculation on agg functions
|
||||
struct SLocalMerger *pLocalMerger;
|
||||
} SSqlRes;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "tscUtil.h"
|
||||
#include "tschemautil.h"
|
||||
#include "tsclient.h"
|
||||
#include "qUtil.h"
|
||||
|
||||
typedef struct SCompareParam {
|
||||
SLocalDataSource **pLocalData;
|
||||
|
@ -1287,6 +1288,76 @@ static bool saveGroupResultInfo(SSqlObj *pSql) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool doFilterFieldData(char *input, SExprFilter* pFieldFilters, int16_t type, bool* notSkipped) {
|
||||
bool qualified = false;
|
||||
|
||||
for(int32_t k = 0; k < pFieldFilters->pFilters->numOfFilters; ++k) {
|
||||
__filter_func_t fp = taosArrayGetP(pFieldFilters->fp, k);
|
||||
SColumnFilterElem filterElem = {.filterInfo = pFieldFilters->pFilters->filterInfo[k]};
|
||||
|
||||
bool isnull = isNull(input, type);
|
||||
if (isnull) {
|
||||
if (fp == isNullOperator) {
|
||||
qualified = true;
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (fp == notNullOperator) {
|
||||
qualified = true;
|
||||
break;
|
||||
} else if (fp == isNullOperator) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (fp(&filterElem, input, input, type)) {
|
||||
qualified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*notSkipped = qualified;
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int32_t doHavingFilter(SQueryInfo* pQueryInfo, tFilePage* pOutput, bool* notSkipped) {
|
||||
*notSkipped = true;
|
||||
|
||||
if (pQueryInfo->havingFieldNum <= 0) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
//int32_t exprNum = (int32_t) tscSqlExprNumOfExprs(pQueryInfo);
|
||||
|
||||
size_t numOfOutput = tscNumOfFields(pQueryInfo);
|
||||
for(int32_t i = 0; i < numOfOutput; ++i) {
|
||||
SInternalField* pInterField = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i);
|
||||
SExprFilter* pFieldFilters = pInterField->pFieldFilters;
|
||||
|
||||
if (pFieldFilters == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t type = pInterField->field.type;
|
||||
|
||||
char* pInput = pOutput->data + pOutput->num* pFieldFilters->pSqlExpr->offset;
|
||||
|
||||
doFilterFieldData(pInput, pFieldFilters, type, notSkipped);
|
||||
if (*notSkipped == false) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pSql
|
||||
|
@ -1327,6 +1398,22 @@ bool genFinalResults(SSqlObj *pSql, SLocalMerger *pLocalMerge, bool noMoreCurren
|
|||
doArithmeticCalculate(pQueryInfo, pResBuf, pModel->rowSize, pLocalMerge->finalModel->rowSize);
|
||||
}
|
||||
|
||||
bool notSkipped = true;
|
||||
|
||||
doHavingFilter(pQueryInfo, pResBuf, ¬Skipped);
|
||||
|
||||
if (!notSkipped) {
|
||||
pRes->numOfRows = 0;
|
||||
pLocalMerge->discard = !noMoreCurrentGroupRes;
|
||||
|
||||
if (pLocalMerge->discard) {
|
||||
SColumnModel *pInternModel = pLocalMerge->pDesc->pColumnModel;
|
||||
tColModelAppend(pInternModel, pLocalMerge->discardData, pLocalMerge->pTempBuffer->data, 0, 1, 1);
|
||||
}
|
||||
|
||||
return notSkipped;
|
||||
}
|
||||
|
||||
// no interval query, no fill operation
|
||||
if (pQueryInfo->interval.interval == 0 || pQueryInfo->fillType == TSDB_FILL_NONE) {
|
||||
genFinalResWithoutFill(pRes, pLocalMerge, pQueryInfo);
|
||||
|
|
|
@ -937,6 +937,10 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql, char** boundC
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (sql == NULL) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
code = tscGetTableMetaEx(pSql, pTableMetaInfo, true);
|
||||
if (TSDB_CODE_TSC_ACTION_IN_PROGRESS == code) {
|
||||
return code;
|
||||
|
@ -945,6 +949,10 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql, char** boundC
|
|||
} else {
|
||||
sql = sToken.z;
|
||||
|
||||
if (sql == NULL) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
code = tscGetTableMetaEx(pSql, pTableMetaInfo, false);
|
||||
if (pCmd->curSql == NULL) {
|
||||
assert(code == TSDB_CODE_TSC_ACTION_IN_PROGRESS);
|
||||
|
@ -952,10 +960,6 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql, char** boundC
|
|||
}
|
||||
|
||||
*sqlstr = sql;
|
||||
|
||||
if (*sqlstr == NULL) {
|
||||
code = TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "tstrbuild.h"
|
||||
#include "ttokendef.h"
|
||||
#include "qScript.h"
|
||||
#include "qUtil.h"
|
||||
|
||||
#define DEFAULT_PRIMARY_TIMESTAMP_COL_NAME "_c0"
|
||||
|
||||
|
@ -1237,6 +1238,7 @@ static bool validateTableColumnInfo(SArray* pFieldList, SSqlCmd* pCmd) {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pCmd) {
|
||||
assert(pTagsList != NULL);
|
||||
|
||||
|
@ -1883,18 +1885,6 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, SArray* pSelectLis
|
|||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
|
||||
/*
|
||||
* transfer sql functions that need secondary merge into another format
|
||||
* in dealing with super table queries such as: count/first/last
|
||||
*/
|
||||
if (isSTable) {
|
||||
tscTansformFuncForSTableQuery(pQueryInfo);
|
||||
|
||||
if (hasUnsupportFunctionsForSTableQuery(pCmd, pQueryInfo)) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -3343,6 +3333,7 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd)
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static SColumnFilterInfo* addColumnFilterInfo(SColumn* pColumn) {
|
||||
if (pColumn == NULL) {
|
||||
return NULL;
|
||||
|
@ -3366,15 +3357,11 @@ static SColumnFilterInfo* addColumnFilterInfo(SColumn* pColumn) {
|
|||
}
|
||||
|
||||
static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnFilterInfo* pColumnFilter,
|
||||
SColumnIndex* columnIndex, tSqlExpr* pExpr) {
|
||||
int16_t colType, tSqlExpr* pExpr) {
|
||||
const char* msg = "not supported filter condition";
|
||||
|
||||
tSqlExpr* pRight = pExpr->pRight;
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, columnIndex->tableIndex);
|
||||
|
||||
SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, columnIndex->columnIndex);
|
||||
|
||||
int16_t colType = pSchema->type;
|
||||
if (colType >= TSDB_DATA_TYPE_TINYINT && colType <= TSDB_DATA_TYPE_BIGINT) {
|
||||
colType = TSDB_DATA_TYPE_BIGINT;
|
||||
} else if (colType == TSDB_DATA_TYPE_FLOAT || colType == TSDB_DATA_TYPE_DOUBLE) {
|
||||
|
@ -3579,7 +3566,10 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC
|
|||
}
|
||||
|
||||
pColumn->colIndex = *pIndex;
|
||||
return doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, pIndex, pExpr);
|
||||
|
||||
int16_t colType = pSchema->type;
|
||||
|
||||
return doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, colType, pExpr);
|
||||
}
|
||||
|
||||
static int32_t getTablenameCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pTableCond, SStringBuilder* sb) {
|
||||
|
@ -6326,7 +6316,7 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo
|
|||
|
||||
if (TSDB_COL_IS_TAG(pColIndex->flag)) {
|
||||
SColumnIndex index = {.tableIndex = pQueryInfo->groupbyExpr.tableIndex, .columnIndex = colIndex};
|
||||
SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TAG, &index, type, bytes, getNewResColId(pQueryInfo), bytes, true);
|
||||
SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, (int32_t)size - pQueryInfo->havingFieldNum, TSDB_FUNC_TAG, &index, type, bytes, getNewResColId(pQueryInfo), bytes, true);
|
||||
|
||||
memset(pExpr->aliasName, 0, sizeof(pExpr->aliasName));
|
||||
tstrncpy(pExpr->aliasName, name, sizeof(pExpr->aliasName));
|
||||
|
@ -6335,7 +6325,7 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo
|
|||
|
||||
// NOTE: tag column does not add to source column list
|
||||
SColumnList ids = getColumnList(1, 0, pColIndex->colIndex);
|
||||
insertResultField(pQueryInfo, (int32_t)size, &ids, bytes, (int8_t)type, name, pExpr);
|
||||
insertResultField(pQueryInfo, (int32_t)size - pQueryInfo->havingFieldNum, &ids, bytes, (int8_t)type, name, pExpr);
|
||||
} else {
|
||||
// if this query is "group by" normal column, time window query is not allowed
|
||||
if (isTimeWindowQuery(pQueryInfo)) {
|
||||
|
@ -7083,6 +7073,313 @@ static int32_t checkQueryRangeForFill(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int32_t tscInsertExprFields(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, SInternalField** interField) {
|
||||
tSqlExprItem item = {.pNode = pExpr, .aliasName = NULL, .distinct = false};
|
||||
|
||||
int32_t outputIndex = (int32_t)tscSqlExprNumOfExprs(pQueryInfo);
|
||||
|
||||
// ADD TRUE FOR TEST
|
||||
if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, &item, true) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
++pQueryInfo->havingFieldNum;
|
||||
|
||||
size_t n = tscSqlExprNumOfExprs(pQueryInfo);
|
||||
SSqlExpr* pSqlExpr = tscSqlExprGet(pQueryInfo, (int32_t)n - 1);
|
||||
|
||||
int32_t slot = tscNumOfFields(pQueryInfo) - 1;
|
||||
SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, slot);
|
||||
pInfo->visible = false;
|
||||
|
||||
if (pInfo->pFieldFilters == NULL) {
|
||||
SExprFilter* pFieldFilters = calloc(1, sizeof(SExprFilter));
|
||||
if (pFieldFilters == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
SColumn* pFilters = calloc(1, sizeof(SColumn));
|
||||
if (pFilters == NULL) {
|
||||
tfree(pFieldFilters);
|
||||
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
pFieldFilters->pFilters = pFilters;
|
||||
pFieldFilters->pSqlExpr = pSqlExpr;
|
||||
pSqlExpr->pFilter = pFilters;
|
||||
pInfo->pFieldFilters = pFieldFilters;
|
||||
}
|
||||
|
||||
pInfo->pFieldFilters->pExpr = pExpr;
|
||||
|
||||
*interField = pInfo;
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t tscGetExprFilters(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, SInternalField** pField) {
|
||||
SInternalField* pInfo = NULL;
|
||||
|
||||
for (int32_t i = pQueryInfo->havingFieldNum - 1; i >= 0; --i) {
|
||||
pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, pQueryInfo->fieldsInfo.numOfOutput - 1 - i);
|
||||
|
||||
if (pInfo->pFieldFilters && 0 == tSqlExprCompare(pInfo->pFieldFilters->pExpr, pExpr)) {
|
||||
*pField = pInfo;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t ret = tscInsertExprFields(pCmd, pQueryInfo, pExpr, &pInfo);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*pField = pInfo;
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t genExprFilter(SExprFilter * exprFilter) {
|
||||
exprFilter->fp = taosArrayInit(4, sizeof(__filter_func_t));
|
||||
if (exprFilter->fp == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < exprFilter->pFilters->numOfFilters; ++i) {
|
||||
SColumnFilterInfo *filterInfo = &exprFilter->pFilters->filterInfo[i];
|
||||
|
||||
int32_t lower = filterInfo->lowerRelOptr;
|
||||
int32_t upper = filterInfo->upperRelOptr;
|
||||
if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
|
||||
tscError("invalid rel optr");
|
||||
return TSDB_CODE_TSC_APP_ERROR;
|
||||
}
|
||||
|
||||
__filter_func_t ffp = getFilterOperator(lower, upper);
|
||||
if (ffp == NULL) {
|
||||
tscError("invalid filter info");
|
||||
return TSDB_CODE_TSC_APP_ERROR;
|
||||
}
|
||||
|
||||
taosArrayPush(exprFilter->fp, &ffp);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t handleExprInHavingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, int32_t sqlOptr) {
|
||||
const char* msg1 = "non binary column not support like operator";
|
||||
const char* msg2 = "invalid operator for binary column in having clause";
|
||||
const char* msg3 = "invalid operator for bool column in having clause";
|
||||
|
||||
SColumn* pColumn = NULL;
|
||||
SColumnFilterInfo* pColFilter = NULL;
|
||||
SInternalField* pInfo = NULL;
|
||||
|
||||
/*
|
||||
* in case of TK_AND filter condition, we first find the corresponding column and build the query condition together
|
||||
* the already existed condition.
|
||||
*/
|
||||
if (sqlOptr == TK_AND) {
|
||||
int32_t ret = tscGetExprFilters(pCmd, pQueryInfo, pExpr->pLeft, &pInfo);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
pColumn = pInfo->pFieldFilters->pFilters;
|
||||
|
||||
// this is a new filter condition on this column
|
||||
if (pColumn->numOfFilters == 0) {
|
||||
pColFilter = addColumnFilterInfo(pColumn);
|
||||
} else { // update the existed column filter information, find the filter info here
|
||||
pColFilter = &pColumn->filterInfo[0];
|
||||
}
|
||||
|
||||
if (pColFilter == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
} else if (sqlOptr == TK_OR) {
|
||||
int32_t ret = tscGetExprFilters(pCmd, pQueryInfo, pExpr->pLeft, &pInfo);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
pColumn = pInfo->pFieldFilters->pFilters;
|
||||
|
||||
// TODO fixme: failed to invalid the filter expression: "col1 = 1 OR col2 = 2"
|
||||
pColFilter = addColumnFilterInfo(pColumn);
|
||||
if (pColFilter == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
} else { // error;
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
pColFilter->filterstr =
|
||||
((pInfo->field.type == TSDB_DATA_TYPE_BINARY || pInfo->field.type == TSDB_DATA_TYPE_NCHAR) ? 1 : 0);
|
||||
|
||||
if (pColFilter->filterstr) {
|
||||
if (pExpr->tokenId != TK_EQ
|
||||
&& pExpr->tokenId != TK_NE
|
||||
&& pExpr->tokenId != TK_ISNULL
|
||||
&& pExpr->tokenId != TK_NOTNULL
|
||||
&& pExpr->tokenId != TK_LIKE
|
||||
) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
} else {
|
||||
if (pExpr->tokenId == TK_LIKE) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (pInfo->field.type == TSDB_DATA_TYPE_BOOL) {
|
||||
if (pExpr->tokenId != TK_EQ && pExpr->tokenId != TK_NE) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t ret = doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, pInfo->field.type, pExpr);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return genExprFilter(pInfo->pFieldFilters);
|
||||
}
|
||||
|
||||
int32_t getHavingExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, int32_t parentOptr) {
|
||||
if (pExpr == NULL) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
const char* msg1 = "invalid having clause";
|
||||
|
||||
tSqlExpr* pLeft = pExpr->pLeft;
|
||||
tSqlExpr* pRight = pExpr->pRight;
|
||||
|
||||
if (pExpr->tokenId == TK_AND || pExpr->tokenId == TK_OR) {
|
||||
int32_t ret = getHavingExpr(pCmd, pQueryInfo, pExpr->pLeft, pExpr->tokenId);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return getHavingExpr(pCmd, pQueryInfo, pExpr->pRight, pExpr->tokenId);
|
||||
}
|
||||
|
||||
if (pLeft == NULL || pRight == NULL) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (pLeft->type == pRight->type) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
exchangeExpr(pExpr);
|
||||
|
||||
pLeft = pExpr->pLeft;
|
||||
pRight = pExpr->pRight;
|
||||
|
||||
|
||||
if (pLeft->type != SQL_NODE_SQLFUNCTION) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (pRight->type != SQL_NODE_VALUE) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (pExpr->tokenId >= TK_BITAND) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
//if (pLeft->pParam == NULL || pLeft->pParam->nExpr < 1) {
|
||||
// return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
//}
|
||||
|
||||
if (pLeft->pParam) {
|
||||
size_t size = taosArrayGetSize(pLeft->pParam);
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
tSqlExprItem* pParamElem = taosArrayGet(pLeft->pParam, i);
|
||||
if (pParamElem->pNode->tokenId != TK_ALL &&
|
||||
pParamElem->pNode->tokenId != TK_ID &&
|
||||
pParamElem->pNode->tokenId != TK_STRING &&
|
||||
pParamElem->pNode->tokenId != TK_INTEGER &&
|
||||
pParamElem->pNode->tokenId != TK_FLOAT) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (pParamElem->pNode->tokenId == TK_ID && (pParamElem->pNode->colInfo.z == NULL && pParamElem->pNode->colInfo.n == 0)) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (pParamElem->pNode->tokenId == TK_ID) {
|
||||
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
|
||||
if ((getColumnIndexByName(pCmd, &pParamElem->pNode->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS)) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
|
||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
|
||||
if (index.columnIndex <= 0 ||
|
||||
index.columnIndex >= tscGetNumOfColumns(pTableMeta)) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pLeft->functionId = isValidFunction(pLeft->operand.z, pLeft->operand.n);
|
||||
if (pLeft->functionId < 0) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
return handleExprInHavingClause(pCmd, pQueryInfo, pExpr, parentOptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t parseHavingClause(SQueryInfo* pQueryInfo, tSqlExpr* pExpr, SSqlCmd* pCmd, bool isSTable, int32_t joinQuery, int32_t timeWindowQuery) {
|
||||
const char* msg1 = "having only works with group by";
|
||||
const char* msg2 = "functions or others can not be mixed up";
|
||||
const char* msg3 = "invalid expression in having clause";
|
||||
|
||||
if (pExpr == NULL) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (pQueryInfo->groupbyExpr.numOfGroupCols <= 0) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (pExpr->pLeft == NULL || pExpr->pRight == NULL) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
}
|
||||
|
||||
if (pQueryInfo->colList == NULL) {
|
||||
pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES);
|
||||
}
|
||||
|
||||
int32_t ret = 0;
|
||||
|
||||
if ((ret = getHavingExpr(pCmd, pQueryInfo, pExpr, TK_AND)) != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
//REDO function check
|
||||
if (!functionCompatibleCheck(pQueryInfo, joinQuery, timeWindowQuery)) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int32_t doValidateSqlNode(SSqlObj* pSql, SQuerySqlNode* pQuerySqlNode, int32_t index) {
|
||||
assert(pQuerySqlNode != NULL && (pQuerySqlNode->from == NULL || taosArrayGetSize(pQuerySqlNode->from->tableList) > 0));
|
||||
|
||||
|
@ -7255,6 +7552,23 @@ int32_t doValidateSqlNode(SSqlObj* pSql, SQuerySqlNode* pQuerySqlNode, int32_t i
|
|||
}
|
||||
}
|
||||
|
||||
// parse the having clause in the first place
|
||||
if (parseHavingClause(pQueryInfo, pQuerySqlNode->pHaving, pCmd, isSTable, joinQuery, timeWindowQuery) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
/*
|
||||
* transfer sql functions that need secondary merge into another format
|
||||
* in dealing with super table queries such as: count/first/last
|
||||
*/
|
||||
if (isSTable) {
|
||||
tscTansformFuncForSTableQuery(pQueryInfo);
|
||||
|
||||
if (hasUnsupportFunctionsForSTableQuery(pCmd, pQueryInfo)) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
}
|
||||
|
||||
if (parseSessionClause(pCmd, pQueryInfo, pQuerySqlNode) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
@ -7446,3 +7760,10 @@ bool hasNormalColumnFilter(SQueryInfo* pQueryInfo) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -144,8 +144,9 @@ SNewVgroupInfo createNewVgroupInfo(SVgroupMsg *pVgroupMsg) {
|
|||
SNewVgroupInfo info = {0};
|
||||
info.numOfEps = pVgroupMsg->numOfEps;
|
||||
info.vgId = pVgroupMsg->vgId;
|
||||
info.inUse = 0;
|
||||
info.inUse = 0; // 0 is the default value of inUse in case of multiple replica
|
||||
|
||||
assert(info.numOfEps >= 1 && info.vgId >= 1);
|
||||
for(int32_t i = 0; i < pVgroupMsg->numOfEps; ++i) {
|
||||
tstrncpy(info.ep[i].fqdn, pVgroupMsg->epAddr[i].fqdn, TSDB_FQDN_LEN);
|
||||
info.ep[i].port = pVgroupMsg->epAddr[i].port;
|
||||
|
|
|
@ -34,6 +34,7 @@ int tscKeepConn[TSDB_SQL_MAX] = {0};
|
|||
TSKEY tscGetSubscriptionProgress(void* sub, int64_t uid, TSKEY dflt);
|
||||
void tscUpdateSubscriptionProgress(void* sub, int64_t uid, TSKEY ts);
|
||||
void tscSaveSubscriptionProgress(void* sub);
|
||||
static int32_t extractSTableQueryVgroupId(STableMetaInfo* pTableMetaInfo);
|
||||
|
||||
static int32_t minMsgSize() { return tsRpcHeadSize + 100; }
|
||||
static int32_t getWaitingTimeInterval(int32_t count) {
|
||||
|
@ -78,7 +79,8 @@ static void tscEpSetHtons(SRpcEpSet *s) {
|
|||
for (int32_t i = 0; i < s->numOfEps; i++) {
|
||||
s->port[i] = htons(s->port[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool tscEpSetIsEqual(SRpcEpSet *s1, SRpcEpSet *s2) {
|
||||
if (s1->numOfEps != s2->numOfEps || s1->inUse != s2->inUse) {
|
||||
return false;
|
||||
|
@ -111,19 +113,22 @@ static void tscDumpEpSetFromVgroupInfo(SRpcEpSet *pEpSet, SNewVgroupInfo *pVgrou
|
|||
}
|
||||
}
|
||||
|
||||
static void tscUpdateVgroupInfo(SSqlObj *pObj, SRpcEpSet *pEpSet) {
|
||||
SSqlCmd *pCmd = &pObj->cmd;
|
||||
static void tscUpdateVgroupInfo(SSqlObj *pSql, SRpcEpSet *pEpSet) {
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
|
||||
if (pTableMetaInfo == NULL || pTableMetaInfo->pTableMeta == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t vgId = pTableMetaInfo->pTableMeta->vgId;
|
||||
int32_t vgId = -1;
|
||||
if (pTableMetaInfo->pTableMeta->tableType == TSDB_SUPER_TABLE) {
|
||||
assert(vgId == 0);
|
||||
return;
|
||||
vgId = extractSTableQueryVgroupId(pTableMetaInfo);
|
||||
} else {
|
||||
vgId = pTableMetaInfo->pTableMeta->vgId;
|
||||
}
|
||||
|
||||
assert(vgId > 0);
|
||||
|
||||
SNewVgroupInfo vgroupInfo = {.vgId = -1};
|
||||
taosHashGetClone(tscVgroupMap, &vgId, sizeof(vgId), NULL, &vgroupInfo, sizeof(SNewVgroupInfo));
|
||||
assert(vgroupInfo.numOfEps > 0 && vgroupInfo.vgId > 0);
|
||||
|
@ -138,6 +143,33 @@ static void tscUpdateVgroupInfo(SSqlObj *pObj, SRpcEpSet *pEpSet) {
|
|||
|
||||
tscDebug("after: EndPoint in use:%d, numOfEps:%d", vgroupInfo.inUse, vgroupInfo.numOfEps);
|
||||
taosHashPut(tscVgroupMap, &vgId, sizeof(vgId), &vgroupInfo, sizeof(SNewVgroupInfo));
|
||||
|
||||
// Update the local cached epSet info cached by SqlObj
|
||||
int32_t inUse = pSql->epSet.inUse;
|
||||
tscDumpEpSetFromVgroupInfo(&pSql->epSet, &vgroupInfo);
|
||||
tscDebug("%p update the epSet in SqlObj, in use before:%d, after:%d", pSql, inUse, pSql->epSet.inUse);
|
||||
|
||||
}
|
||||
|
||||
int32_t extractSTableQueryVgroupId(STableMetaInfo* pTableMetaInfo) {
|
||||
assert(pTableMetaInfo != NULL);
|
||||
|
||||
int32_t vgIndex = pTableMetaInfo->vgroupIndex;
|
||||
int32_t vgId = -1;
|
||||
|
||||
if (pTableMetaInfo->pVgroupTables == NULL) {
|
||||
SVgroupsInfo *pVgroupInfo = pTableMetaInfo->vgroupList;
|
||||
assert(pVgroupInfo->vgroups[vgIndex].vgId > 0 && vgIndex < pTableMetaInfo->vgroupList->numOfVgroups);
|
||||
vgId = pVgroupInfo->vgroups[vgIndex].vgId;
|
||||
} else {
|
||||
int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables);
|
||||
assert(vgIndex >= 0 && vgIndex < numOfVgroups);
|
||||
|
||||
SVgroupTableInfo *pTableIdList = taosArrayGet(pTableMetaInfo->pVgroupTables, vgIndex);
|
||||
vgId = pTableIdList->vgInfo.vgId;
|
||||
}
|
||||
|
||||
return vgId;
|
||||
}
|
||||
|
||||
void tscProcessHeartBeatRsp(void *param, TAOS_RES *tres, int code) {
|
||||
|
@ -516,21 +548,22 @@ int tscBuildFetchMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
|
||||
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
||||
int32_t vgIndex = pTableMetaInfo->vgroupIndex;
|
||||
int32_t vgId = -1;
|
||||
|
||||
if (pTableMetaInfo->pVgroupTables == NULL) {
|
||||
SVgroupsInfo *pVgroupInfo = pTableMetaInfo->vgroupList;
|
||||
assert(pVgroupInfo->vgroups[vgIndex].vgId > 0 && vgIndex < pTableMetaInfo->vgroupList->numOfVgroups);
|
||||
|
||||
pRetrieveMsg->header.vgId = htonl(pVgroupInfo->vgroups[vgIndex].vgId);
|
||||
tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d, qhandle:%" PRIX64, pSql, pVgroupInfo->vgroups[vgIndex].vgId, vgIndex, pSql->res.qId);
|
||||
vgId = pVgroupInfo->vgroups[vgIndex].vgId;
|
||||
} else {
|
||||
int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables);
|
||||
assert(vgIndex >= 0 && vgIndex < numOfVgroups);
|
||||
|
||||
SVgroupTableInfo* pTableIdList = taosArrayGet(pTableMetaInfo->pVgroupTables, vgIndex);
|
||||
|
||||
pRetrieveMsg->header.vgId = htonl(pTableIdList->vgInfo.vgId);
|
||||
tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d, qId:%" PRIu64, pSql, pTableIdList->vgInfo.vgId, vgIndex, pSql->res.qId);
|
||||
vgId = pTableIdList->vgInfo.vgId;
|
||||
}
|
||||
|
||||
pRetrieveMsg->header.vgId = htonl(vgId);
|
||||
tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d, qId:%" PRIu64, pSql, vgId, vgIndex, pSql->res.qId);
|
||||
} else {
|
||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
pRetrieveMsg->header.vgId = htonl(pTableMeta->vgId);
|
||||
|
@ -869,8 +902,44 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
pSqlFuncExpr->functionId = htons(pExpr->functionId);
|
||||
pSqlFuncExpr->numOfParams = htons(pExpr->numOfParams);
|
||||
pSqlFuncExpr->resColId = htons(pExpr->resColId);
|
||||
if (pTableMeta->tableType != TSDB_SUPER_TABLE && pExpr->pFilter && pExpr->pFilter->numOfFilters > 0) {
|
||||
pSqlFuncExpr->filterNum = htonl(pExpr->pFilter->numOfFilters);
|
||||
} else {
|
||||
pSqlFuncExpr->filterNum = 0;
|
||||
}
|
||||
|
||||
pMsg += sizeof(SSqlFuncMsg);
|
||||
|
||||
if (pSqlFuncExpr->filterNum) {
|
||||
pMsg += sizeof(SColumnFilterInfo) * pExpr->pFilter->numOfFilters;
|
||||
|
||||
// append the filter information after the basic column information
|
||||
for (int32_t f = 0; f < pExpr->pFilter->numOfFilters; ++f) {
|
||||
SColumnFilterInfo *pColFilter = &pExpr->pFilter->filterInfo[f];
|
||||
|
||||
SColumnFilterInfo *pFilterMsg = &pSqlFuncExpr->filterInfo[f];
|
||||
pFilterMsg->filterstr = htons(pColFilter->filterstr);
|
||||
|
||||
if (pColFilter->filterstr) {
|
||||
pFilterMsg->len = htobe64(pColFilter->len);
|
||||
memcpy(pMsg, (void *)pColFilter->pz, (size_t)(pColFilter->len + 1));
|
||||
pMsg += (pColFilter->len + 1); // append the additional filter binary info
|
||||
} else {
|
||||
pFilterMsg->lowerBndi = htobe64(pColFilter->lowerBndi);
|
||||
pFilterMsg->upperBndi = htobe64(pColFilter->upperBndi);
|
||||
}
|
||||
|
||||
pFilterMsg->lowerRelOptr = htons(pColFilter->lowerRelOptr);
|
||||
pFilterMsg->upperRelOptr = htons(pColFilter->upperRelOptr);
|
||||
|
||||
if (pColFilter->lowerRelOptr == TSDB_RELATION_INVALID && pColFilter->upperRelOptr == TSDB_RELATION_INVALID) {
|
||||
tscError("invalid filter info");
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int32_t j = 0; j < pExpr->numOfParams; ++j) { // todo add log
|
||||
pSqlFuncExpr->arg[j].argType = htons((uint16_t)pExpr->param[j].nType);
|
||||
pSqlFuncExpr->arg[j].argBytes = htons(pExpr->param[j].nLen);
|
||||
|
@ -2029,7 +2098,7 @@ int tscProcessTableMetaRsp(SSqlObj *pSql) {
|
|||
(vgroupInfo.inUse < 0)) { // vgroup info exists, compare with it
|
||||
vgroupInfo = createNewVgroupInfo(&pMetaMsg->vgroup);
|
||||
taosHashPut(tscVgroupMap, &vgId, sizeof(vgId), &vgroupInfo, sizeof(vgroupInfo));
|
||||
tscDebug("add new VgroupInfo, vgId:%d, total:%d", vgId, (int32_t) taosHashGetSize(tscVgroupMap));
|
||||
tscDebug("add new VgroupInfo, vgId:%d, total cached:%d", vgId, (int32_t) taosHashGetSize(tscVgroupMap));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2227,18 +2296,33 @@ int tscProcessSTableVgroupRsp(SSqlObj *pSql) {
|
|||
tscError("%p empty vgroup info", pSql);
|
||||
} else {
|
||||
for (int32_t j = 0; j < pInfo->vgroupList->numOfVgroups; ++j) {
|
||||
//just init, no need to lock
|
||||
SVgroupInfo *pVgroups = &pInfo->vgroupList->vgroups[j];
|
||||
// just init, no need to lock
|
||||
SVgroupInfo *pVgroup = &pInfo->vgroupList->vgroups[j];
|
||||
|
||||
SVgroupMsg *vmsg = &pVgroupMsg->vgroups[j];
|
||||
pVgroups->vgId = htonl(vmsg->vgId);
|
||||
pVgroups->numOfEps = vmsg->numOfEps;
|
||||
vmsg->vgId = htonl(vmsg->vgId);
|
||||
vmsg->numOfEps = vmsg->numOfEps;
|
||||
for (int32_t k = 0; k < vmsg->numOfEps; ++k) {
|
||||
vmsg->epAddr[k].port = htons(vmsg->epAddr[k].port);
|
||||
}
|
||||
|
||||
assert(pVgroups->numOfEps >= 1 && pVgroups->vgId >= 1);
|
||||
SNewVgroupInfo newVi = createNewVgroupInfo(vmsg);
|
||||
pVgroup->numOfEps = newVi.numOfEps;
|
||||
pVgroup->vgId = newVi.vgId;
|
||||
for (int32_t k = 0; k < vmsg->numOfEps; ++k) {
|
||||
pVgroup->epAddr[k].port = newVi.ep[k].port;
|
||||
pVgroup->epAddr[k].fqdn = strndup(newVi.ep[k].fqdn, TSDB_FQDN_LEN);
|
||||
}
|
||||
|
||||
for (int32_t k = 0; k < pVgroups->numOfEps; ++k) {
|
||||
pVgroups->epAddr[k].port = htons(vmsg->epAddr[k].port);
|
||||
pVgroups->epAddr[k].fqdn = strndup(vmsg->epAddr[k].fqdn, tListLen(vmsg->epAddr[k].fqdn));
|
||||
// check if current buffer contains the vgroup info.
|
||||
// If not, add it
|
||||
SNewVgroupInfo existVgroupInfo = {.inUse = -1};
|
||||
taosHashGetClone(tscVgroupMap, &newVi.vgId, sizeof(newVi.vgId), NULL, &existVgroupInfo, sizeof(SNewVgroupInfo));
|
||||
|
||||
if (((existVgroupInfo.inUse >= 0) && !vgroupInfoIdentical(&existVgroupInfo, vmsg)) ||
|
||||
(existVgroupInfo.inUse < 0)) { // vgroup info exists, compare with it
|
||||
taosHashPut(tscVgroupMap, &newVi.vgId, sizeof(newVi.vgId), &newVi, sizeof(newVi));
|
||||
tscDebug("add new VgroupInfo, vgId:%d, total cached:%d", newVi.vgId, (int32_t) taosHashGetSize(tscVgroupMap));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -405,6 +405,7 @@ int taos_affected_rows(TAOS_RES *tres) {
|
|||
|
||||
TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
|
||||
SSqlObj *pSql = (SSqlObj *)res;
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
if (pSql == NULL || pSql->signature != pSql) return 0;
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
|
@ -419,7 +420,7 @@ TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
|
|||
|
||||
SFieldInfo *pFieldInfo = &pQueryInfo->fieldsInfo;
|
||||
|
||||
if (pFieldInfo->final == NULL) {
|
||||
if (pRes->final == NULL) {
|
||||
TAOS_FIELD* f = calloc(pFieldInfo->numOfOutput, sizeof(TAOS_FIELD));
|
||||
|
||||
int32_t j = 0;
|
||||
|
@ -439,10 +440,10 @@ TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
|
|||
}
|
||||
}
|
||||
|
||||
pFieldInfo->final = f;
|
||||
pRes->final = f;
|
||||
}
|
||||
|
||||
return pFieldInfo->final;
|
||||
return pRes->final;
|
||||
}
|
||||
|
||||
static bool needToFetchNewBlock(SSqlObj* pSql) {
|
||||
|
|
|
@ -3004,7 +3004,7 @@ void tscRetrieveDataRes(void *param, TAOS_RES *tres, int code) {
|
|||
}
|
||||
|
||||
tscDebug("%p sub:%p query complete, ep:%s, vgId:%d, orderOfSub:%d, retrieve data", trsupport->pParentSql, pSql,
|
||||
pVgroup->epAddr[0].fqdn, pVgroup->vgId, trsupport->subqueryIndex);
|
||||
pVgroup->epAddr[pSql->epSet.inUse].fqdn, pVgroup->vgId, trsupport->subqueryIndex);
|
||||
|
||||
if (pSql->res.qId == 0) { // qhandle is NULL, code is TSDB_CODE_SUCCESS means no results generated from this vnode
|
||||
tscRetrieveFromDnodeCallBack(param, pSql, 0);
|
||||
|
|
|
@ -447,6 +447,8 @@ static void tscDestroyResPointerInfo(SSqlRes* pRes) {
|
|||
tfree(pRes->pArithSup->data);
|
||||
tfree(pRes->pArithSup);
|
||||
}
|
||||
|
||||
tfree(pRes->final);
|
||||
|
||||
pRes->data = NULL; // pRes->data points to the buffer of pRsp, no need to free
|
||||
}
|
||||
|
@ -1105,6 +1107,7 @@ SInternalField* tscFieldInfoAppend(SFieldInfo* pFieldInfo, TAOS_FIELD* pField) {
|
|||
.pSqlExpr = NULL,
|
||||
.pArithExprInfo = NULL,
|
||||
.visible = true,
|
||||
.pFieldFilters = NULL,
|
||||
};
|
||||
|
||||
info.field = *pField;
|
||||
|
@ -1117,6 +1120,7 @@ SInternalField* tscFieldInfoInsert(SFieldInfo* pFieldInfo, int32_t index, TAOS_F
|
|||
.pSqlExpr = NULL,
|
||||
.pArithExprInfo = NULL,
|
||||
.visible = true,
|
||||
.pFieldFilters = NULL,
|
||||
};
|
||||
|
||||
info.field = *field;
|
||||
|
@ -1190,6 +1194,22 @@ int32_t tscGetResRowLength(SArray* pExprList) {
|
|||
return size;
|
||||
}
|
||||
|
||||
static void destroyFilterInfo(SColumnFilterInfo* pFilterInfo, int32_t numOfFilters) {
|
||||
for(int32_t i = 0; i < numOfFilters; ++i) {
|
||||
if (pFilterInfo[i].filterstr) {
|
||||
tfree(pFilterInfo[i].pz);
|
||||
}
|
||||
}
|
||||
|
||||
tfree(pFilterInfo);
|
||||
}
|
||||
|
||||
static void tscColumnDestroy(SColumn* pCol) {
|
||||
destroyFilterInfo(pCol->filterInfo, pCol->numOfFilters);
|
||||
free(pCol);
|
||||
}
|
||||
|
||||
|
||||
void tscFieldInfoClear(SFieldInfo* pFieldInfo) {
|
||||
if (pFieldInfo == NULL) {
|
||||
return;
|
||||
|
@ -1210,10 +1230,14 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo) {
|
|||
|
||||
tfree(pInfo->pArithExprInfo);
|
||||
}
|
||||
|
||||
if (pInfo->pFieldFilters != NULL) {
|
||||
tscColumnDestroy(pInfo->pFieldFilters->pFilters);
|
||||
tfree(pInfo->pFieldFilters);
|
||||
}
|
||||
}
|
||||
|
||||
taosArrayDestroy(pFieldInfo->internalField);
|
||||
tfree(pFieldInfo->final);
|
||||
|
||||
memset(pFieldInfo, 0, sizeof(SFieldInfo));
|
||||
}
|
||||
|
@ -1471,15 +1495,7 @@ SColumn* tscColumnListInsert(SArray* pColumnList, SColumnIndex* pColIndex) {
|
|||
return taosArrayGetP(pColumnList, i);
|
||||
}
|
||||
|
||||
static void destroyFilterInfo(SColumnFilterInfo* pFilterInfo, int32_t numOfFilters) {
|
||||
for(int32_t i = 0; i < numOfFilters; ++i) {
|
||||
if (pFilterInfo[i].filterstr) {
|
||||
tfree(pFilterInfo[i].pz);
|
||||
}
|
||||
}
|
||||
|
||||
tfree(pFilterInfo);
|
||||
}
|
||||
|
||||
|
||||
SColumn* tscColumnClone(const SColumn* src) {
|
||||
assert(src != NULL);
|
||||
|
@ -1496,10 +1512,6 @@ SColumn* tscColumnClone(const SColumn* src) {
|
|||
return dst;
|
||||
}
|
||||
|
||||
static void tscColumnDestroy(SColumn* pCol) {
|
||||
destroyFilterInfo(pCol->filterInfo, pCol->numOfFilters);
|
||||
free(pCol);
|
||||
}
|
||||
|
||||
void tscColumnListCopy(SArray* dst, const SArray* src, int16_t tableIndex) {
|
||||
assert(src != NULL && dst != NULL);
|
||||
|
|
|
@ -39,6 +39,7 @@ extern int8_t tsEnableTelemetryReporting;
|
|||
extern char tsEmail[];
|
||||
extern char tsArbitrator[];
|
||||
extern int8_t tsArbOnline;
|
||||
extern int32_t tsDnodeId;
|
||||
|
||||
// common
|
||||
extern int tsRpcTimer;
|
||||
|
|
|
@ -43,6 +43,7 @@ int8_t tsEnableVnodeBak = 1;
|
|||
int8_t tsEnableTelemetryReporting = 1;
|
||||
int8_t tsArbOnline = 0;
|
||||
char tsEmail[TSDB_FQDN_LEN] = {0};
|
||||
int32_t tsDnodeId = 0;
|
||||
|
||||
// common
|
||||
int32_t tsRpcTimer = 1000;
|
||||
|
@ -212,7 +213,7 @@ float tsAvailTmpDirectorySpace = 0;
|
|||
float tsAvailDataDirGB = 0;
|
||||
float tsUsedDataDirGB = 0;
|
||||
float tsReservedTmpDirectorySpace = 1.0f;
|
||||
float tsMinimalDataDirGB = 1.0f;
|
||||
float tsMinimalDataDirGB = 2.0f;
|
||||
int32_t tsTotalMemoryMB = 0;
|
||||
uint32_t tsVersion = 0;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 050667e5b4d0eafa5387e4283e713559b421203f
|
||||
Subproject commit d99751356e285696f57bc604304ffafd10287439
|
|
@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED)
|
|||
ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME}
|
||||
POST_BUILD
|
||||
COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.25-dist.jar ${LIBRARY_OUTPUT_PATH}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.27-dist.jar ${LIBRARY_OUTPUT_PATH}
|
||||
COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
|
||||
COMMENT "build jdbc driver")
|
||||
ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME})
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>2.0.25</version>
|
||||
<version>2.0.27</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>JDBCDriver</name>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>2.0.25</version>
|
||||
<version>2.0.27</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>JDBCDriver</name>
|
||||
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
|
||||
|
|
|
@ -4,13 +4,23 @@ import java.sql.*;
|
|||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public abstract class AbstractConnection extends WrapperImpl implements Connection {
|
||||
|
||||
protected volatile boolean isClosed;
|
||||
protected volatile String catalog;
|
||||
protected volatile Properties clientInfoProps = new Properties();
|
||||
protected final Properties clientInfoProps = new Properties();
|
||||
|
||||
protected AbstractConnection(Properties properties) {
|
||||
Set<String> propNames = properties.stringPropertyNames();
|
||||
for (String propName : propNames) {
|
||||
clientInfoProps.setProperty(propName, properties.getProperty(propName));
|
||||
}
|
||||
String timestampFormat = properties.getProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, "STRING");
|
||||
clientInfoProps.setProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, timestampFormat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract Statement createStatement() throws SQLException;
|
||||
|
@ -35,7 +45,6 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
|
|||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setAutoCommit(boolean autoCommit) throws SQLException {
|
||||
if (isClosed())
|
||||
|
@ -441,9 +450,8 @@ public abstract class AbstractConnection extends WrapperImpl implements Connecti
|
|||
if (isClosed)
|
||||
throw (SQLClientInfoException) TSDBError.createSQLException(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED);
|
||||
|
||||
if (clientInfoProps == null)
|
||||
clientInfoProps = new Properties();
|
||||
clientInfoProps.setProperty(name, value);
|
||||
if (clientInfoProps != null)
|
||||
clientInfoProps.setProperty(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,6 +28,7 @@ public class TSDBConnection extends AbstractConnection {
|
|||
}
|
||||
|
||||
public TSDBConnection(Properties info, TSDBDatabaseMetaData meta) throws SQLException {
|
||||
super(info);
|
||||
this.databaseMetaData = meta;
|
||||
connect(info.getProperty(TSDBDriver.PROPERTY_KEY_HOST),
|
||||
Integer.parseInt(info.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "0")),
|
||||
|
|
|
@ -95,6 +95,11 @@ public class TSDBDriver extends AbstractDriver {
|
|||
*/
|
||||
public static final String PROPERTY_KEY_BATCH_LOAD = "batchfetch";
|
||||
|
||||
/**
|
||||
* timestamp format for JDBC-RESTful,should one of the options: string or timestamp or utc
|
||||
*/
|
||||
public static final String PROPERTY_KEY_TIMESTAMP_FORMAT = "timestampFormat";
|
||||
|
||||
private TSDBDatabaseMetaData dbMetaData = null;
|
||||
|
||||
static {
|
||||
|
|
|
@ -33,17 +33,9 @@ import java.util.regex.Pattern;
|
|||
public class TSDBPreparedStatement extends TSDBStatement implements PreparedStatement {
|
||||
|
||||
private String rawSql;
|
||||
private String sql;
|
||||
// private ArrayList<Object> parameters = new ArrayList<>();
|
||||
private Object[] parameters;
|
||||
private boolean isPrepared;
|
||||
|
||||
//start with insert or import and is case-insensitive
|
||||
private static Pattern savePattern = Pattern.compile("(?i)^\\s*(insert|import)");
|
||||
// is insert or import
|
||||
private boolean isSaved;
|
||||
|
||||
// private SavedPreparedStatement savedPreparedStatement;
|
||||
private volatile TSDBParameterMetaData parameterMetaData;
|
||||
|
||||
TSDBPreparedStatement(TSDBConnection connection, TSDBJNIConnector connecter, String sql) {
|
||||
|
@ -65,35 +57,11 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
private void init(String sql) {
|
||||
this.rawSql = sql;
|
||||
preprocessSql();
|
||||
// this.isSaved = isSavedSql(this.rawSql);
|
||||
// if (this.isSaved) {
|
||||
// try {
|
||||
// this.savedPreparedStatement = new SavedPreparedStatement(this.rawSql, this);
|
||||
// } catch (SQLException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* if the precompiled sql is insert or import
|
||||
*
|
||||
* @param sql
|
||||
* @return
|
||||
*/
|
||||
private boolean isSavedSql(String sql) {
|
||||
Matcher matcher = savePattern.matcher(sql);
|
||||
return matcher.find();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] executeBatch() throws SQLException {
|
||||
// if (isSaved) {
|
||||
// return this.savedPreparedStatement.executeBatch();
|
||||
// } else {
|
||||
return super.executeBatch();
|
||||
// }
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -157,23 +125,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
*
|
||||
* @return a string of the native sql statement for TSDB
|
||||
*/
|
||||
// private String getNativeSql(String rawSql) {
|
||||
// for (int i = 0; i < parameters.length; i++) {
|
||||
// Object para = parameters[i];
|
||||
// if (para != null) {
|
||||
// String paraStr = para.toString();
|
||||
// if (para instanceof Timestamp || para instanceof String) {
|
||||
// paraStr = "'" + paraStr + "'";
|
||||
// }
|
||||
// this.sql = this.sql.replaceFirst("[?]", paraStr);
|
||||
// } else {
|
||||
// this.sql = this.sql.replaceFirst("[?]", "NULL");
|
||||
// }
|
||||
// }
|
||||
// parameters = new Object[parameters.length];
|
||||
// return sql;
|
||||
// }
|
||||
|
||||
private String getNativeSql(String rawSql) throws SQLException {
|
||||
String sql = rawSql;
|
||||
for (int i = 0; i < parameters.length; ++i) {
|
||||
|
@ -201,108 +152,58 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
|
||||
@Override
|
||||
public ResultSet executeQuery() throws SQLException {
|
||||
// if (isSaved) {
|
||||
// this.savedPreparedStatement.executeBatchInternal();
|
||||
// return null;
|
||||
// } else {
|
||||
|
||||
if (!isPrepared)
|
||||
return executeQuery(this.rawSql);
|
||||
|
||||
final String sql = getNativeSql(this.rawSql);
|
||||
return executeQuery(sql);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public int executeUpdate() throws SQLException {
|
||||
// if (isSaved) {
|
||||
// return this.savedPreparedStatement.executeBatchInternal();
|
||||
// } else {
|
||||
if (!isPrepared)
|
||||
return executeUpdate(this.rawSql);
|
||||
String sql = getNativeSql(this.rawSql);
|
||||
return executeUpdate(sql);
|
||||
// }
|
||||
}
|
||||
|
||||
private boolean isSupportedSQLType(int sqlType) {
|
||||
switch (sqlType) {
|
||||
case Types.TIMESTAMP:
|
||||
case Types.INTEGER:
|
||||
case Types.BIGINT:
|
||||
case Types.FLOAT:
|
||||
case Types.DOUBLE:
|
||||
case Types.SMALLINT:
|
||||
case Types.TINYINT:
|
||||
case Types.BOOLEAN:
|
||||
case Types.BINARY:
|
||||
case Types.NCHAR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNull(int parameterIndex, int sqlType) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
if (!isSupportedSQLType(sqlType) || parameterIndex < 0)
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE);
|
||||
// if (parameterIndex >= parameters.size())
|
||||
// throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_BOUNDARY);
|
||||
|
||||
setObject(parameterIndex, "NULL");
|
||||
setObject(parameterIndex, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoolean(int parameterIndex, boolean x) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
|
||||
setObject(parameterIndex, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setByte(int parameterIndex, byte x) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
setObject(parameterIndex,x);
|
||||
setObject(parameterIndex, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShort(int parameterIndex, short x) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
setObject(parameterIndex, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInt(int parameterIndex, int x) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
setObject(parameterIndex, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLong(int parameterIndex, long x) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
setObject(parameterIndex, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloat(int parameterIndex, float x) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
setObject(parameterIndex, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(int parameterIndex, double x) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
setObject(parameterIndex, x);
|
||||
}
|
||||
|
||||
|
@ -315,17 +216,12 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
|
||||
@Override
|
||||
public void setString(int parameterIndex, String x) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
setObject(parameterIndex, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBytes(int parameterIndex, byte[] x) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
|
||||
setObject(parameterIndex,x);
|
||||
setObject(parameterIndex, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -344,8 +240,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
|
||||
@Override
|
||||
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
setObject(parameterIndex, x);
|
||||
}
|
||||
|
||||
|
@ -360,7 +254,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
|
||||
}
|
||||
|
||||
|
@ -375,8 +268,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
public void clearParameters() throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
|
||||
// parameters.clear();
|
||||
parameters = new Object[parameters.length];
|
||||
}
|
||||
|
||||
|
@ -384,43 +275,29 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
|
||||
setObject(parameterIndex,x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setObject(int parameterIndex, Object x) throws SQLException {
|
||||
// if (isSaved) {
|
||||
// this.savedPreparedStatement.setParam(parameterIndex, x);
|
||||
// } else {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
if (parameterIndex < 1 && parameterIndex >= parameters.length)
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE);
|
||||
|
||||
parameters[parameterIndex - 1] = x;
|
||||
// parameters.add(x);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute() throws SQLException {
|
||||
// if (isSaved) {
|
||||
// int result = this.savedPreparedStatement.executeBatchInternal();
|
||||
// return result > 0;
|
||||
// } else {
|
||||
if (!isPrepared)
|
||||
return execute(this.rawSql);
|
||||
|
||||
final String sql = getNativeSql(this.rawSql);
|
||||
|
||||
return execute(sql);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBatch() throws SQLException {
|
||||
// if (isSaved) {
|
||||
// this.savedPreparedStatement.addBatch();
|
||||
// } else {
|
||||
if (this.batchedArgs == null) {
|
||||
batchedArgs = new ArrayList<>();
|
||||
}
|
||||
|
@ -431,7 +308,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
String sql = this.getConnection().nativeSQL(this.rawSql);
|
||||
addBatch(sql);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -475,7 +351,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat
|
|||
public ResultSetMetaData getMetaData() throws SQLException {
|
||||
if (isClosed())
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||
// return this.getResultSet().getMetaData();
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
|
||||
}
|
||||
|
||||
|
|
|
@ -203,7 +203,11 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
|
|||
|
||||
this.lastWasNull = this.rowData.wasNull(columnIndex - 1);
|
||||
if (!lastWasNull) {
|
||||
res = this.rowData.getLong(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType());
|
||||
Object value = this.rowData.get(columnIndex - 1);
|
||||
if (value instanceof Timestamp)
|
||||
res = ((Timestamp) value).getTime();
|
||||
else
|
||||
res = this.rowData.getLong(columnIndex - 1, this.columnMetaDataList.get(columnIndex - 1).getColType());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -273,7 +277,6 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
|
|||
checkAvailability(columnIndex, this.columnMetaDataList.size());
|
||||
|
||||
Timestamp res = null;
|
||||
|
||||
if (this.getBatchFetch())
|
||||
return this.blockData.getTimestamp(columnIndex - 1);
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ package com.taosdata.jdbc;
|
|||
import java.math.BigDecimal;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
|
@ -299,7 +300,19 @@ public class TSDBResultSetRowData {
|
|||
}
|
||||
|
||||
public void setTimestamp(int col, long ts) {
|
||||
data.set(col, new Timestamp(ts));
|
||||
//TODO: this implementation contains logical error
|
||||
// when precision is us the (long ts) is 16 digital number
|
||||
// when precision is ms, the (long ts) is 13 digital number
|
||||
// we need a JNI function like this:
|
||||
// public void setTimestamp(int col, long epochSecond, long nanoAdjustment)
|
||||
if (ts < 1_0000_0000_0000_0L) {
|
||||
data.set(col, new Timestamp(ts));
|
||||
} else {
|
||||
long epochSec = ts / 1000_000l;
|
||||
long nanoAdjustment = ts % 1000_000l * 1000l;
|
||||
Timestamp timestamp = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
data.set(col, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
public Timestamp getTimestamp(int col) {
|
||||
|
|
|
@ -22,6 +22,7 @@ public class RestfulConnection extends AbstractConnection {
|
|||
private final DatabaseMetaData metadata;
|
||||
|
||||
public RestfulConnection(String host, String port, Properties props, String database, String url) {
|
||||
super(props);
|
||||
this.host = host;
|
||||
this.port = Integer.parseInt(port);
|
||||
this.database = database;
|
||||
|
|
|
@ -5,13 +5,14 @@ import com.alibaba.fastjson.JSONObject;
|
|||
import com.google.common.primitives.Ints;
|
||||
import com.google.common.primitives.Longs;
|
||||
import com.google.common.primitives.Shorts;
|
||||
import com.taosdata.jdbc.AbstractResultSet;
|
||||
import com.taosdata.jdbc.TSDBConstants;
|
||||
import com.taosdata.jdbc.TSDBError;
|
||||
import com.taosdata.jdbc.TSDBErrorNumbers;
|
||||
import com.taosdata.jdbc.*;
|
||||
import com.taosdata.jdbc.utils.UtcTimestampUtil;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.*;
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
|
||||
|
@ -19,6 +20,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
private volatile boolean isClosed;
|
||||
private int pos = -1;
|
||||
|
||||
|
||||
private final String database;
|
||||
private final Statement statement;
|
||||
// data
|
||||
|
@ -65,7 +67,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
}
|
||||
}
|
||||
|
||||
private Object parseColumnData(JSONArray row, int colIndex, int taosType) {
|
||||
private Object parseColumnData(JSONArray row, int colIndex, int taosType) throws SQLException {
|
||||
switch (taosType) {
|
||||
case TSDBConstants.TSDB_DATA_TYPE_BOOL:
|
||||
return row.getBoolean(colIndex);
|
||||
|
@ -81,8 +83,44 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
return row.getFloat(colIndex);
|
||||
case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
|
||||
return row.getDouble(colIndex);
|
||||
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
|
||||
return new Timestamp(row.getDate(colIndex).getTime());
|
||||
case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: {
|
||||
if (row.get(colIndex) == null)
|
||||
return null;
|
||||
String timestampFormat = this.statement.getConnection().getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT);
|
||||
if ("TIMESTAMP".equalsIgnoreCase(timestampFormat)) {
|
||||
Long value = row.getLong(colIndex);
|
||||
//TODO:
|
||||
if (value < 1_0000_0000_0000_0L)
|
||||
return new Timestamp(value);
|
||||
long epochSec = value / 1000_000l;
|
||||
long nanoAdjustment = value % 1000_000l * 1000l;
|
||||
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
}
|
||||
if ("UTC".equalsIgnoreCase(timestampFormat)) {
|
||||
String value = row.getString(colIndex);
|
||||
long epochSec = Timestamp.valueOf(value.substring(0, 19).replace("T", " ")).getTime() / 1000;
|
||||
int fractionalSec = Integer.parseInt(value.substring(20, value.length() - 5));
|
||||
long nanoAdjustment = 0;
|
||||
if (value.length() > 28) {
|
||||
// ms timestamp: yyyy-MM-ddTHH:mm:ss.SSSSSS+0x00
|
||||
nanoAdjustment = fractionalSec * 1000l;
|
||||
} else {
|
||||
// ms timestamp: yyyy-MM-ddTHH:mm:ss.SSS+0x00
|
||||
nanoAdjustment = fractionalSec * 1000_000l;
|
||||
}
|
||||
ZoneOffset zoneOffset = ZoneOffset.of(value.substring(value.length() - 5));
|
||||
Instant instant = Instant.ofEpochSecond(epochSec, nanoAdjustment).atOffset(zoneOffset).toInstant();
|
||||
return Timestamp.from(instant);
|
||||
}
|
||||
String value = row.getString(colIndex);
|
||||
if (value.length() <= 23) // ms timestamp: yyyy-MM-dd HH:mm:ss.SSS
|
||||
return row.getTimestamp(colIndex);
|
||||
// us timestamp: yyyy-MM-dd HH:mm:ss.SSSSSS
|
||||
long epochSec = Timestamp.valueOf(value.substring(0, 19)).getTime() / 1000;
|
||||
long nanoAdjustment = Integer.parseInt(value.substring(20)) * 1000l;
|
||||
Timestamp timestamp = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
return timestamp;
|
||||
}
|
||||
case TSDBConstants.TSDB_DATA_TYPE_BINARY:
|
||||
return row.getString(colIndex) == null ? null : row.getString(colIndex).getBytes();
|
||||
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
|
||||
|
@ -215,6 +253,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
Object value = resultSet.get(pos).get(columnIndex - 1);
|
||||
if (value == null)
|
||||
return 0;
|
||||
if (value instanceof Timestamp) {
|
||||
return ((Timestamp) value).getTime();
|
||||
}
|
||||
|
||||
long valueAsLong = 0;
|
||||
try {
|
||||
|
@ -307,6 +348,13 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
return null;
|
||||
if (value instanceof Timestamp)
|
||||
return (Timestamp) value;
|
||||
// if (value instanceof Long) {
|
||||
// if (1_0000_0000_0000_0L > (long) value)
|
||||
// return Timestamp.from(Instant.ofEpochMilli((long) value));
|
||||
// long epochSec = (long) value / 1000_000L;
|
||||
// long nanoAdjustment = (long) ((long) value % 1000_000L * 1000);
|
||||
// return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
// }
|
||||
return Timestamp.valueOf(value.toString());
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
|
|||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.taosdata.jdbc.AbstractStatement;
|
||||
import com.taosdata.jdbc.TSDBDriver;
|
||||
import com.taosdata.jdbc.TSDBError;
|
||||
import com.taosdata.jdbc.TSDBErrorNumbers;
|
||||
import com.taosdata.jdbc.utils.HttpClientPoolUtil;
|
||||
|
@ -34,14 +35,11 @@ public class RestfulStatement extends AbstractStatement {
|
|||
if (!SqlSyntaxValidator.isValidForExecuteQuery(sql))
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: " + sql);
|
||||
|
||||
final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
|
||||
if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) {
|
||||
return executeOneQuery(url, sql);
|
||||
return executeOneQuery(sql);
|
||||
}
|
||||
|
||||
// if (this.database != null && !this.database.trim().replaceAll("\\s","").isEmpty())
|
||||
// HttpClientPoolUtil.execute(url, "use " + this.database);
|
||||
return executeOneQuery(url, sql);
|
||||
return executeOneQuery(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,8 +54,6 @@ public class RestfulStatement extends AbstractStatement {
|
|||
return executeOneUpdate(url, sql);
|
||||
}
|
||||
|
||||
// if (this.database != null && !this.database.trim().replaceAll("\\s", "").isEmpty())
|
||||
// HttpClientPoolUtil.execute(url, "use " + this.database);
|
||||
return executeOneUpdate(url, sql);
|
||||
}
|
||||
|
||||
|
@ -78,14 +74,21 @@ public class RestfulStatement extends AbstractStatement {
|
|||
|
||||
//如果执行了use操作应该将当前Statement的catalog设置为新的database
|
||||
boolean result = true;
|
||||
final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
|
||||
String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
|
||||
if (conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).equals("TIMESTAMP")) {
|
||||
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt";
|
||||
}
|
||||
if (conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).equals("UTC")) {
|
||||
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc";
|
||||
}
|
||||
|
||||
if (SqlSyntaxValidator.isUseSql(sql)) {
|
||||
HttpClientPoolUtil.execute(url, sql);
|
||||
this.database = sql.trim().replace("use", "").trim();
|
||||
this.conn.setCatalog(this.database);
|
||||
result = false;
|
||||
} else if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) {
|
||||
executeOneQuery(url, sql);
|
||||
executeOneQuery(sql);
|
||||
} else if (SqlSyntaxValidator.isDatabaseUnspecifiedUpdate(sql)) {
|
||||
executeOneUpdate(url, sql);
|
||||
result = false;
|
||||
|
@ -101,11 +104,18 @@ public class RestfulStatement extends AbstractStatement {
|
|||
return result;
|
||||
}
|
||||
|
||||
private ResultSet executeOneQuery(String url, String sql) throws SQLException {
|
||||
private ResultSet executeOneQuery(String sql) throws SQLException {
|
||||
if (!SqlSyntaxValidator.isValidForExecuteQuery(sql))
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: " + sql);
|
||||
|
||||
// row data
|
||||
String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
|
||||
String timestampFormat = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT);
|
||||
if ("TIMESTAMP".equalsIgnoreCase(timestampFormat))
|
||||
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt";
|
||||
if ("UTC".equalsIgnoreCase(timestampFormat))
|
||||
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc";
|
||||
|
||||
String result = HttpClientPoolUtil.execute(url, sql);
|
||||
JSONObject resultJson = JSON.parseObject(result);
|
||||
if (resultJson.getString("status").equals("error")) {
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package com.taosdata.jdbc.utils;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
|
||||
public class UtcTimestampUtil {
|
||||
public static final DateTimeFormatter formatter = new DateTimeFormatterBuilder()
|
||||
.appendPattern("yyyy-MM-ddTHH:mm:ss.SSS+")
|
||||
// .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
|
||||
.toFormatter();
|
||||
|
||||
}
|
|
@ -50,6 +50,51 @@ public class TSDBPreparedStatementTest {
|
|||
pstmt_insert.setNull(2, Types.INTEGER);
|
||||
int result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(3, Types.BIGINT);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(4, Types.FLOAT);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(5, Types.DOUBLE);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(6, Types.SMALLINT);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(7, Types.TINYINT);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(8, Types.BOOLEAN);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(9, Types.BINARY);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(10, Types.NCHAR);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(10, Types.OTHER);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -129,7 +174,7 @@ public class TSDBPreparedStatementTest {
|
|||
Assert.assertFalse(pstmt_insert.execute());
|
||||
}
|
||||
|
||||
class Person implements Serializable {
|
||||
class Person {
|
||||
String name;
|
||||
int age;
|
||||
boolean sex;
|
||||
|
|
|
@ -160,6 +160,7 @@ public class TSDBResultSetTest {
|
|||
@Test
|
||||
public void getTime() throws SQLException {
|
||||
Time f1 = rs.getTime("f1");
|
||||
Assert.assertNotNull(f1);
|
||||
Assert.assertEquals("00:00:00", f1.toString());
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ public class DriverAutoloadTest {
|
|||
final String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata";
|
||||
Connection conn = DriverManager.getConnection(url, properties);
|
||||
Assert.assertNotNull(conn);
|
||||
conn.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -27,6 +28,7 @@ public class DriverAutoloadTest {
|
|||
final String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata";
|
||||
Connection conn = DriverManager.getConnection(url, properties);
|
||||
Assert.assertNotNull(conn);
|
||||
conn.close();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package com.taosdata.jdbc.cases;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.*;
|
||||
|
||||
public class NullValueInResultSetForJdbcJniTest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
Connection conn;
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("select * from weather");
|
||||
ResultSetMetaData meta = rs.getMetaData();
|
||||
while (rs.next()) {
|
||||
for (int i = 1; i <= meta.getColumnCount(); i++) {
|
||||
Object value = rs.getObject(i);
|
||||
System.out.print(meta.getColumnLabel(i) + ": " + value + "\t");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() throws SQLException {
|
||||
final String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata";
|
||||
conn = DriverManager.getConnection(url);
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.execute("drop database if exists test_null");
|
||||
stmt.execute("create database if not exists test_null");
|
||||
stmt.execute("use test_null");
|
||||
stmt.execute("create table weather(ts timestamp, f1 int, f2 bigint, f3 float, f4 double, f5 smallint, f6 tinyint, f7 bool, f8 binary(64), f9 nchar(64))");
|
||||
stmt.executeUpdate("insert into weather(ts, f1) values(now+1s, 1)");
|
||||
stmt.executeUpdate("insert into weather(ts, f2) values(now+2s, 2)");
|
||||
stmt.executeUpdate("insert into weather(ts, f3) values(now+3s, 3.0)");
|
||||
stmt.executeUpdate("insert into weather(ts, f4) values(now+4s, 4.0)");
|
||||
stmt.executeUpdate("insert into weather(ts, f5) values(now+5s, 5)");
|
||||
stmt.executeUpdate("insert into weather(ts, f6) values(now+6s, 6)");
|
||||
stmt.executeUpdate("insert into weather(ts, f7) values(now+7s, true)");
|
||||
stmt.executeUpdate("insert into weather(ts, f8) values(now+8s, 'hello')");
|
||||
stmt.executeUpdate("insert into weather(ts, f9) values(now+9s, '涛思数据')");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
try {
|
||||
if (conn != null)
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package com.taosdata.jdbc.cases;
|
||||
|
||||
|
||||
import com.taosdata.jdbc.TSDBDriver;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class TwoTypeTimestampPercisionInJniTest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
private static final String ms_timestamp_db = "ms_precision_test";
|
||||
private static final String us_timestamp_db = "us_precision_test";
|
||||
private static final long timestamp1 = System.currentTimeMillis();
|
||||
private static final long timestamp2 = timestamp1 * 1000 + 123;
|
||||
|
||||
private static Connection conn;
|
||||
|
||||
@Test
|
||||
public void testCase1() {
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + ms_timestamp_db + ".weather");
|
||||
rs.next();
|
||||
long ts = rs.getTimestamp(1).getTime();
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
ts = rs.getLong(1);
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase2() {
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + us_timestamp_db + ".weather");
|
||||
rs.next();
|
||||
|
||||
Timestamp timestamp = rs.getTimestamp(1);
|
||||
System.out.println(timestamp);
|
||||
long ts = timestamp.getTime();
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
int nanos = timestamp.getNanos();
|
||||
Assert.assertEquals(timestamp2 % 1000_000l * 1000, nanos);
|
||||
|
||||
ts = rs.getLong(1);
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws SQLException {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||||
|
||||
String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata";
|
||||
conn = DriverManager.getConnection(url, properties);
|
||||
|
||||
Statement stmt = conn.createStatement();
|
||||
stmt.execute("drop database if exists " + ms_timestamp_db);
|
||||
stmt.execute("create database if not exists " + ms_timestamp_db + " precision 'ms'");
|
||||
stmt.execute("create table " + ms_timestamp_db + ".weather(ts timestamp, f1 int)");
|
||||
stmt.executeUpdate("insert into " + ms_timestamp_db + ".weather(ts,f1) values(" + timestamp1 + ", 127)");
|
||||
|
||||
stmt.execute("drop database if exists " + us_timestamp_db);
|
||||
stmt.execute("create database if not exists " + us_timestamp_db + " precision 'us'");
|
||||
stmt.execute("create table " + us_timestamp_db + ".weather(ts timestamp, f1 int)");
|
||||
stmt.executeUpdate("insert into " + us_timestamp_db + ".weather(ts,f1) values(" + timestamp2 + ", 127)");
|
||||
stmt.close();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
try {
|
||||
if (conn != null)
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
package com.taosdata.jdbc.cases;
|
||||
|
||||
|
||||
import com.taosdata.jdbc.TSDBDriver;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class TwoTypeTimestampPercisionInRestfulTest {
|
||||
|
||||
private static final String host = "127.0.0.1";
|
||||
private static final String ms_timestamp_db = "ms_precision_test";
|
||||
private static final String us_timestamp_db = "us_precision_test";
|
||||
private static final long timestamp1 = System.currentTimeMillis();
|
||||
private static final long timestamp2 = timestamp1 * 1000 + 123;
|
||||
|
||||
private static Connection conn1;
|
||||
private static Connection conn2;
|
||||
private static Connection conn3;
|
||||
|
||||
@Test
|
||||
public void testCase1() {
|
||||
try (Statement stmt = conn1.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + ms_timestamp_db + ".weather");
|
||||
rs.next();
|
||||
long ts = rs.getTimestamp(1).getTime();
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
ts = rs.getLong(1);
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase2() {
|
||||
try (Statement stmt = conn1.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + us_timestamp_db + ".weather");
|
||||
rs.next();
|
||||
|
||||
Timestamp timestamp = rs.getTimestamp(1);
|
||||
long ts = timestamp.getTime();
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
int nanos = timestamp.getNanos();
|
||||
Assert.assertEquals(timestamp2 % 1000_000l * 1000, nanos);
|
||||
|
||||
ts = rs.getLong(1);
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase3() {
|
||||
try (Statement stmt = conn2.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + ms_timestamp_db + ".weather");
|
||||
rs.next();
|
||||
Timestamp rsTimestamp = rs.getTimestamp(1);
|
||||
long ts = rsTimestamp.getTime();
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
ts = rs.getLong(1);
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase4() {
|
||||
try (Statement stmt = conn2.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + us_timestamp_db + ".weather");
|
||||
rs.next();
|
||||
|
||||
Timestamp timestamp = rs.getTimestamp(1);
|
||||
long ts = timestamp.getTime();
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
int nanos = timestamp.getNanos();
|
||||
Assert.assertEquals(timestamp2 % 1000_000l * 1000, nanos);
|
||||
|
||||
ts = rs.getLong(1);
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase5() {
|
||||
try (Statement stmt = conn3.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + ms_timestamp_db + ".weather");
|
||||
rs.next();
|
||||
long ts = rs.getTimestamp(1).getTime();
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
ts = rs.getLong(1);
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase6() {
|
||||
try (Statement stmt = conn3.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery("select last_row(ts) from " + us_timestamp_db + ".weather");
|
||||
rs.next();
|
||||
|
||||
Timestamp timestamp = rs.getTimestamp(1);
|
||||
long ts = timestamp.getTime();
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
int nanos = timestamp.getNanos();
|
||||
Assert.assertEquals(timestamp2 % 1000_000l * 1000, nanos);
|
||||
|
||||
ts = rs.getLong(1);
|
||||
Assert.assertEquals(timestamp1, ts);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws SQLException {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||||
// properties.setProperty(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT, "TIMESTAMP");
|
||||
|
||||
String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata";
|
||||
conn1 = DriverManager.getConnection(url, properties);
|
||||
|
||||
url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata×tampFormat=timestamp";
|
||||
conn2 = DriverManager.getConnection(url, properties);
|
||||
|
||||
url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata×tampFormat=utc";
|
||||
conn3 = DriverManager.getConnection(url, properties);
|
||||
|
||||
Statement stmt = conn1.createStatement();
|
||||
stmt.execute("drop database if exists " + ms_timestamp_db);
|
||||
stmt.execute("create database if not exists " + ms_timestamp_db + " precision 'ms'");
|
||||
stmt.execute("create table " + ms_timestamp_db + ".weather(ts timestamp, f1 int)");
|
||||
stmt.executeUpdate("insert into " + ms_timestamp_db + ".weather(ts,f1) values(" + timestamp1 + ", 127)");
|
||||
|
||||
stmt.execute("drop database if exists " + us_timestamp_db);
|
||||
stmt.execute("create database if not exists " + us_timestamp_db + " precision 'us'");
|
||||
stmt.execute("create table " + us_timestamp_db + ".weather(ts timestamp, f1 int)");
|
||||
stmt.executeUpdate("insert into " + us_timestamp_db + ".weather(ts,f1) values(" + timestamp2 + ", 127)");
|
||||
stmt.close();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
try {
|
||||
if (conn1 != null)
|
||||
conn1.close();
|
||||
if (conn2 != null)
|
||||
conn2.close();
|
||||
if (conn3 != null)
|
||||
conn3.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -50,6 +50,51 @@ public class RestfulPreparedStatementTest {
|
|||
pstmt_insert.setNull(2, Types.INTEGER);
|
||||
int result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(3, Types.BIGINT);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(4, Types.FLOAT);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(5, Types.DOUBLE);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(6, Types.SMALLINT);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(7, Types.TINYINT);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(8, Types.BOOLEAN);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(9, Types.BINARY);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(10, Types.NCHAR);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
|
||||
pstmt_insert.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
|
||||
pstmt_insert.setNull(10, Types.OTHER);
|
||||
result = pstmt_insert.executeUpdate();
|
||||
Assert.assertEquals(1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -129,7 +174,7 @@ public class RestfulPreparedStatementTest {
|
|||
Assert.assertFalse(pstmt_insert.execute());
|
||||
}
|
||||
|
||||
class Person implements Serializable {
|
||||
private class Person {
|
||||
String name;
|
||||
int age;
|
||||
boolean sex;
|
||||
|
|
|
@ -160,6 +160,7 @@ public class RestfulResultSetTest {
|
|||
@Test
|
||||
public void getTime() throws SQLException {
|
||||
Time f1 = rs.getTime("f1");
|
||||
Assert.assertNotNull(f1);
|
||||
Assert.assertEquals("00:00:00", f1.toString());
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ static void cqProcessStreamRes(void *param, TAOS_RES *tres, TAOS_ROW row);
|
|||
static void cqCreateStream(SCqContext *pContext, SCqObj *pObj);
|
||||
|
||||
int32_t cqObjRef = -1;
|
||||
int32_t cqVnodeNum = 0;
|
||||
|
||||
void cqRmFromList(SCqObj *pObj) {
|
||||
//LOCK in caller
|
||||
|
@ -166,6 +167,8 @@ void *cqOpen(void *ahandle, const SCqCfg *pCfg) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
atomic_add_fetch_32(&cqVnodeNum, 1);
|
||||
|
||||
cqCreateRef();
|
||||
|
||||
pContext->tmrCtrl = taosTmrInit(0, 0, 0, "CQ");
|
||||
|
@ -240,6 +243,13 @@ void cqClose(void *handle) {
|
|||
if (hasCq == 0) {
|
||||
freeSCqContext(pContext);
|
||||
}
|
||||
|
||||
int32_t remainn = atomic_sub_fetch_32(&cqVnodeNum, 1);
|
||||
if (remainn <= 0) {
|
||||
int32_t ref = cqObjRef;
|
||||
cqObjRef = -1;
|
||||
taosCloseRef(ref);
|
||||
}
|
||||
}
|
||||
|
||||
void cqStart(void *handle) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "os.h"
|
||||
#include "cJSON.h"
|
||||
#include "dnodeCfg.h"
|
||||
#include "tglobal.h"
|
||||
|
||||
static SDnodeCfg tsCfg = {0};
|
||||
static pthread_mutex_t tsCfgMutex;
|
||||
|
@ -70,6 +71,7 @@ static void dnodeResetCfg(SDnodeCfg *cfg) {
|
|||
|
||||
pthread_mutex_lock(&tsCfgMutex);
|
||||
tsCfg.dnodeId = cfg->dnodeId;
|
||||
tsDnodeId = cfg->dnodeId;
|
||||
tstrncpy(tsCfg.clusterId, cfg->clusterId, TSDB_CLUSTER_ID_LEN);
|
||||
dnodePrintCfg(cfg);
|
||||
dnodeWriteCfg();
|
||||
|
|
|
@ -88,10 +88,11 @@ void* qOpenQueryMgmt(int32_t vgId);
|
|||
void qQueryMgmtNotifyClosed(void* pExecutor);
|
||||
void qQueryMgmtReOpen(void *pExecutor);
|
||||
void qCleanupQueryMgmt(void* pExecutor);
|
||||
void** qRegisterQInfo(void* pMgmt, uint64_t qId, uint64_t qInfo);
|
||||
void** qRegisterQInfo(void* pMgmt, uint64_t qId, void *qInfo);
|
||||
void** qAcquireQInfo(void* pMgmt, uint64_t key);
|
||||
void** qReleaseQInfo(void* pMgmt, void* pQInfo, bool freeHandle);
|
||||
bool checkQIdEqual(void *qHandle, uint64_t qId);
|
||||
int64_t genQueryId(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -164,6 +164,7 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_MND_INVALID_TABLE_NAME TAOS_DEF_ERROR_CODE(0, 0x0362) //"Table does not exist")
|
||||
#define TSDB_CODE_MND_INVALID_TABLE_TYPE TAOS_DEF_ERROR_CODE(0, 0x0363) //"Invalid table type in tsdb")
|
||||
#define TSDB_CODE_MND_TOO_MANY_TAGS TAOS_DEF_ERROR_CODE(0, 0x0364) //"Too many tags")
|
||||
#define TSDB_CODE_MND_TOO_MANY_COLUMNS TAOS_DEF_ERROR_CODE(0, 0x0365) //"Too many columns")
|
||||
#define TSDB_CODE_MND_TOO_MANY_TIMESERIES TAOS_DEF_ERROR_CODE(0, 0x0366) //"Too many time series")
|
||||
#define TSDB_CODE_MND_NOT_SUPER_TABLE TAOS_DEF_ERROR_CODE(0, 0x0367) //"Not super table") // operation only available for super table
|
||||
#define TSDB_CODE_MND_COL_NAME_TOO_LONG TAOS_DEF_ERROR_CODE(0, 0x0368) //"Tag name too long")
|
||||
|
|
|
@ -402,36 +402,6 @@ typedef struct SColIndex {
|
|||
char name[TSDB_COL_NAME_LEN]; // TODO remove it
|
||||
} SColIndex;
|
||||
|
||||
/* sql function msg, to describe the message to vnode about sql function
|
||||
* operations in select clause */
|
||||
typedef struct SSqlFuncMsg {
|
||||
int16_t functionId;
|
||||
int16_t numOfParams;
|
||||
|
||||
int16_t resColId; // result column id, id of the current output column
|
||||
int16_t colType;
|
||||
int16_t colBytes;
|
||||
|
||||
SColIndex colInfo;
|
||||
struct ArgElem {
|
||||
int16_t argType;
|
||||
int16_t argBytes;
|
||||
union {
|
||||
double d;
|
||||
int64_t i64;
|
||||
char * pz;
|
||||
} argValue;
|
||||
} arg[3];
|
||||
} SSqlFuncMsg;
|
||||
|
||||
typedef struct SExprInfo {
|
||||
SSqlFuncMsg base;
|
||||
struct tExprNode* pExpr;
|
||||
int16_t bytes;
|
||||
int16_t type;
|
||||
int32_t interBytes;
|
||||
int64_t uid;
|
||||
} SExprInfo;
|
||||
|
||||
typedef struct SColumnFilterInfo {
|
||||
int16_t lowerRelOptr;
|
||||
|
@ -454,6 +424,42 @@ typedef struct SColumnFilterInfo {
|
|||
};
|
||||
} SColumnFilterInfo;
|
||||
|
||||
/* sql function msg, to describe the message to vnode about sql function
|
||||
* operations in select clause */
|
||||
typedef struct SSqlFuncMsg {
|
||||
int16_t functionId;
|
||||
int16_t numOfParams;
|
||||
|
||||
int16_t resColId; // result column id, id of the current output column
|
||||
int16_t colType;
|
||||
int16_t colBytes;
|
||||
|
||||
SColIndex colInfo;
|
||||
struct ArgElem {
|
||||
int16_t argType;
|
||||
int16_t argBytes;
|
||||
union {
|
||||
double d;
|
||||
int64_t i64;
|
||||
char * pz;
|
||||
} argValue;
|
||||
} arg[3];
|
||||
|
||||
int32_t filterNum;
|
||||
SColumnFilterInfo filterInfo[];
|
||||
} SSqlFuncMsg;
|
||||
|
||||
|
||||
typedef struct SExprInfo {
|
||||
SColumnFilterInfo * pFilter;
|
||||
struct tExprNode* pExpr;
|
||||
int16_t bytes;
|
||||
int16_t type;
|
||||
int32_t interBytes;
|
||||
int64_t uid;
|
||||
SSqlFuncMsg base;
|
||||
} SExprInfo;
|
||||
|
||||
/*
|
||||
* for client side struct, we only need the column id, type, bytes are not necessary
|
||||
* But for data in vnode side, we need all the following information.
|
||||
|
|
|
@ -221,6 +221,12 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define TK_SPACE 300
|
||||
#define TK_COMMENT 301
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define MAX_IP_SIZE 20
|
||||
#define MAX_PASSWORD_SIZE 20
|
||||
#define MAX_HISTORY_SIZE 1000
|
||||
#define MAX_COMMAND_SIZE 65536
|
||||
#define MAX_COMMAND_SIZE 1048586
|
||||
#define HISTORY_FILE ".taos_history"
|
||||
|
||||
#define DEFAULT_RES_SHOW_NUM 100
|
||||
|
|
|
@ -238,7 +238,7 @@ void resetCommand(Command *cmd, const char s[]) {
|
|||
clearScreen(cmd->endOffset + prompt_size, cmd->screenOffset + prompt_size);
|
||||
memset(cmd->buffer, 0, MAX_COMMAND_SIZE);
|
||||
memset(cmd->command, 0, MAX_COMMAND_SIZE);
|
||||
strcpy(cmd->command, s);
|
||||
strncpy(cmd->command, s, MAX_COMMAND_SIZE);
|
||||
int size = 0;
|
||||
int width = 0;
|
||||
getMbSizeInfo(s, &size, &width);
|
||||
|
|
|
@ -37,7 +37,7 @@ static struct argp_option options[] = {
|
|||
{"password", 'p', "PASSWORD", OPTION_ARG_OPTIONAL, "The password to use when connecting to the server."},
|
||||
{"port", 'P', "PORT", 0, "The TCP/IP port number to use for the connection."},
|
||||
{"user", 'u', "USER", 0, "The user name to use when connecting to the server."},
|
||||
{"user", 'A', "Auth", 0, "The user auth to use when connecting to the server."},
|
||||
{"auth", 'A', "Auth", 0, "The auth string to use when connecting to the server."},
|
||||
{"config-dir", 'c', "CONFIG_DIR", 0, "Configuration directory."},
|
||||
{"dump-config", 'C', 0, 0, "Dump configuration."},
|
||||
{"commands", 's', "COMMANDS", 0, "Commands to run without enter the shell."},
|
||||
|
|
|
@ -9,19 +9,18 @@ IF (GIT_FOUND)
|
|||
EXECUTE_PROCESS(
|
||||
COMMAND ${GIT_EXECUTABLE} log --pretty=oneline -n 1 ${CMAKE_CURRENT_LIST_DIR}/taosdemo.c
|
||||
RESULT_VARIABLE RESULT
|
||||
OUTPUT_VARIABLE TAOSDEMO_COMMIT)
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND bash "-c" "echo '${TAOSDEMO_COMMIT}' | awk '{print $1}' | cut -c -9"
|
||||
RESULT_VARIABLE RESULT
|
||||
OUTPUT_VARIABLE TAOSDEMO_COMMIT_SHA1)
|
||||
STRING(SUBSTRING "${TAOSDEMO_COMMIT_SHA1}" 0 7 TAOSDEMO_COMMIT_SHA1)
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND ${GIT_EXECUTABLE} status -z -s ${CMAKE_CURRENT_LIST_DIR}/taosdemo.c
|
||||
RESULT_VARIABLE RESULT
|
||||
OUTPUT_VARIABLE TAOSDEMO_STATUS)
|
||||
EXECUTE_PROCESS(
|
||||
IF (TD_LINUX)
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND bash "-c" "echo '${TAOSDEMO_STATUS}' | awk '{print $1}'"
|
||||
RESULT_VARIABLE RESULT
|
||||
OUTPUT_VARIABLE TAOSDEMO_STATUS)
|
||||
ENDIF (TD_LINUX)
|
||||
MESSAGE("taosdemo.c status: " ${TAOSDEMO_STATUS})
|
||||
ELSE()
|
||||
MESSAGE("Git not found")
|
||||
|
@ -29,9 +28,9 @@ ELSE()
|
|||
SET(TAOSDEMO_STATUS "unknown")
|
||||
ENDIF (GIT_FOUND)
|
||||
|
||||
STRING(STRIP ${TAOSDEMO_COMMIT_SHA1} TAOSDEMO_COMMIT_SHA1)
|
||||
STRING(STRIP "${TAOSDEMO_COMMIT_SHA1}" TAOSDEMO_COMMIT_SHA1)
|
||||
MESSAGE("taosdemo's latest commit in short is:" ${TAOSDEMO_COMMIT_SHA1})
|
||||
STRING(STRIP ${TAOSDEMO_STATUS} TAOSDEMO_STATUS)
|
||||
STRING(STRIP "${TAOSDEMO_STATUS}" TAOSDEMO_STATUS)
|
||||
|
||||
IF (TAOSDEMO_STATUS MATCHES "M")
|
||||
SET(TAOSDEMO_STATUS "modified")
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
"data_source": "rand",
|
||||
"insert_mode": "taosc",
|
||||
"insert_rows": 1000,
|
||||
"multi_thread_write_one_tbl": "no",
|
||||
"interlace_rows": 20,
|
||||
"max_sql_len": 1024000,
|
||||
"disorder_ratio": 0,
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
"data_source": "rand",
|
||||
"insert_mode": "taosc",
|
||||
"insert_rows": 100000,
|
||||
"multi_thread_write_one_tbl": "no",
|
||||
"interlace_rows": 0,
|
||||
"max_sql_len": 1024000,
|
||||
"disorder_ratio": 0,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"filetype":"query",
|
||||
"filetype": "query",
|
||||
"cfgdir": "/etc/taos",
|
||||
"host": "127.0.0.1",
|
||||
"port": 6030,
|
||||
|
@ -7,13 +7,30 @@
|
|||
"password": "taosdata",
|
||||
"confirm_parameter_prompt": "yes",
|
||||
"databases": "dbx",
|
||||
"specified_table_query":
|
||||
{"query_interval":1, "concurrent":4,
|
||||
"sqls": [{"sql": "select last_row(*) from stb where color='red'", "result": "./query_res0.txt"},
|
||||
{"sql": "select count(*) from stb_01", "result": "./query_res1.txt"}]
|
||||
},
|
||||
"super_table_query":
|
||||
{"stblname": "stb", "query_interval":1, "threads":4,
|
||||
"sqls": [{"sql": "select last_row(*) from xxxx", "result": "./query_res2.txt"}]
|
||||
}
|
||||
"query_times": 1,
|
||||
"specified_table_query": {
|
||||
"query_interval": 1,
|
||||
"concurrent": 4,
|
||||
"sqls": [
|
||||
{
|
||||
"sql": "select last_row(*) from stb where color='red'",
|
||||
"result": "./query_res0.txt"
|
||||
},
|
||||
{
|
||||
"sql": "select count(*) from stb_01",
|
||||
"result": "./query_res1.txt"
|
||||
}
|
||||
]
|
||||
},
|
||||
"super_table_query": {
|
||||
"stblname": "stb",
|
||||
"query_interval": 1,
|
||||
"threads": 4,
|
||||
"sqls": [
|
||||
{
|
||||
"sql": "select last_row(*) from xxxx",
|
||||
"result": "./query_res2.txt"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -484,24 +484,33 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) {
|
|||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-E") == 0) {
|
||||
if (argv[i+1]) {
|
||||
char *tmp = argv[++i];
|
||||
int64_t tmpEpoch;
|
||||
if (strchr(tmp, ':') && strchr(tmp, '-')) {
|
||||
if (TSDB_CODE_SUCCESS != taosParseTime(
|
||||
tmp, &tmpEpoch, strlen(tmp), TSDB_TIME_PRECISION_MILLI, 0)) {
|
||||
fprintf(stderr, "Input end time error!\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
tmpEpoch = atoll(tmp);
|
||||
}
|
||||
char *tmp = strdup(argv[++i]);
|
||||
|
||||
sprintf(argv[i], "%"PRId64"", tmpEpoch);
|
||||
debugPrint("%s() LN%d, tmp is: %s, argv[%d]: %s\n",
|
||||
__func__, __LINE__, tmp, i, argv[i]);
|
||||
if (tmp) {
|
||||
int64_t tmpEpoch;
|
||||
if (strchr(tmp, ':') && strchr(tmp, '-')) {
|
||||
if (TSDB_CODE_SUCCESS != taosParseTime(
|
||||
tmp, &tmpEpoch, strlen(tmp), TSDB_TIME_PRECISION_MILLI, 0)) {
|
||||
fprintf(stderr, "Input end time error!\n");
|
||||
free(tmp);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
tmpEpoch = atoll(tmp);
|
||||
}
|
||||
|
||||
sprintf(argv[i], "%"PRId64"", tmpEpoch);
|
||||
debugPrint("%s() LN%d, tmp is: %s, argv[%d]: %s\n",
|
||||
__func__, __LINE__, tmp, i, argv[i]);
|
||||
|
||||
free(tmp);
|
||||
} else {
|
||||
errorPrint("%s() LN%d, strdup() cannot allocate memory\n", __func__, __LINE__);
|
||||
exit(-1);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Input end time error!\n");
|
||||
return;
|
||||
errorPrint("%s() LN%d, -E need a valid value following!\n", __func__, __LINE__);
|
||||
exit(-1);
|
||||
}
|
||||
} else if (strcmp(argv[i], "-g") == 0) {
|
||||
arguments->debug_print = true;
|
||||
|
|
|
@ -437,14 +437,14 @@ static int32_t mnodeCheckClusterCfgPara(const SClusterCfg *clusterCfg) {
|
|||
return TAOS_DN_OFF_TIME_ZONE_NOT_MATCH;
|
||||
}
|
||||
|
||||
if (0 != strncasecmp(clusterCfg->locale, tsLocale, strlen(tsLocale))) {
|
||||
mError("\"locale\"[%s - %s] cfg parameters inconsistent", clusterCfg->locale, tsLocale);
|
||||
return TAOS_DN_OFF_LOCALE_NOT_MATCH;
|
||||
}
|
||||
if (0 != strncasecmp(clusterCfg->charset, tsCharset, strlen(tsCharset))) {
|
||||
mError("\"charset\"[%s - %s] cfg parameters inconsistent.", clusterCfg->charset, tsCharset);
|
||||
return TAOS_DN_OFF_CHARSET_NOT_MATCH;
|
||||
}
|
||||
// if (0 != strncasecmp(clusterCfg->locale, tsLocale, strlen(tsLocale))) {
|
||||
// mError("\"locale\"[%s - %s] cfg parameters inconsistent", clusterCfg->locale, tsLocale);
|
||||
// return TAOS_DN_OFF_LOCALE_NOT_MATCH;
|
||||
// }
|
||||
// if (0 != strncasecmp(clusterCfg->charset, tsCharset, strlen(tsCharset))) {
|
||||
// mError("\"charset\"[%s - %s] cfg parameters inconsistent.", clusterCfg->charset, tsCharset);
|
||||
// return TAOS_DN_OFF_CHARSET_NOT_MATCH;
|
||||
// }
|
||||
|
||||
if (clusterCfg->enableBalance != tsEnableBalance) {
|
||||
mError("\"balance\"[%d - %d] cfg parameters inconsistent", clusterCfg->enableBalance, tsEnableBalance);
|
||||
|
|
|
@ -315,6 +315,10 @@ void sdbUpdateAsync() {
|
|||
taosTmrReset(sdbUpdateSyncTmrFp, 200, NULL, tsMnodeTmr, &tsSdbTmr);
|
||||
}
|
||||
|
||||
static int node_cmp(const void *l, const void *r) {
|
||||
return ((SNodeInfo *)l)->nodeId - ((SNodeInfo *)r)->nodeId;
|
||||
}
|
||||
|
||||
int32_t sdbUpdateSync(void *pMnodes) {
|
||||
SMInfos *pMinfos = pMnodes;
|
||||
if (!mnodeIsRunning()) {
|
||||
|
@ -382,6 +386,8 @@ int32_t sdbUpdateSync(void *pMnodes) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
qsort(syncCfg.nodeInfo, syncCfg.replica, sizeof(syncCfg.nodeInfo[0]), node_cmp);
|
||||
|
||||
sdbInfo("vgId:1, work as mnode, replica:%d", syncCfg.replica);
|
||||
for (int32_t i = 0; i < syncCfg.replica; ++i) {
|
||||
sdbInfo("vgId:1, mnode:%d, %s:%d", syncCfg.nodeInfo[i].nodeId, syncCfg.nodeInfo[i].nodeFqdn,
|
||||
|
@ -1019,7 +1025,7 @@ static int32_t sdbWriteToQueue(SSdbRow *pRow, int32_t qtype) {
|
|||
|
||||
int32_t queued = atomic_add_fetch_32(&tsSdbMgmt.queuedMsg, 1);
|
||||
if (queued > MAX_QUEUED_MSG_NUM) {
|
||||
sdbDebug("vgId:1, too many msg:%d in sdb queue, flow control", queued);
|
||||
sdbInfo("vgId:1, too many msg:%d in sdb queue, flow control", queued);
|
||||
taosMsleep(1);
|
||||
}
|
||||
|
||||
|
@ -1131,4 +1137,4 @@ static void *sdbWorkerFp(void *pWorker) {
|
|||
|
||||
int32_t sdbGetReplicaNum() {
|
||||
return tsSdbMgmt.cfg.replica;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1037,6 +1037,19 @@ static int32_t mnodeProcessCreateSuperTableMsg(SMnodeMsg *pMsg) {
|
|||
|
||||
SCreateTableMsg* pCreate = (SCreateTableMsg*)((char*)pCreate1 + sizeof(SCMCreateTableMsg));
|
||||
|
||||
int16_t numOfTags = htons(pCreate->numOfTags);
|
||||
if (numOfTags > TSDB_MAX_TAGS) {
|
||||
mError("msg:%p, app:%p table:%s, failed to create, too many tags", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableName);
|
||||
return TSDB_CODE_MND_TOO_MANY_TAGS;
|
||||
}
|
||||
|
||||
int16_t numOfColumns = htons(pCreate->numOfColumns);
|
||||
int32_t numOfCols = numOfColumns + numOfTags;
|
||||
if (numOfCols > TSDB_MAX_COLUMNS) {
|
||||
mError("msg:%p, app:%p table:%s, failed to create, too many columns", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableName);
|
||||
return TSDB_CODE_MND_TOO_MANY_COLUMNS;
|
||||
}
|
||||
|
||||
SSTableObj * pStable = calloc(1, sizeof(SSTableObj));
|
||||
if (pStable == NULL) {
|
||||
mError("msg:%p, app:%p table:%s, failed to create, no enough memory", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableName);
|
||||
|
@ -1050,10 +1063,9 @@ static int32_t mnodeProcessCreateSuperTableMsg(SMnodeMsg *pMsg) {
|
|||
pStable->uid = (us << 24) + ((sdbGetVersion() & ((1ul << 16) - 1ul)) << 8) + (taosRand() & ((1ul << 8) - 1ul));
|
||||
pStable->sversion = 0;
|
||||
pStable->tversion = 0;
|
||||
pStable->numOfColumns = htons(pCreate->numOfColumns);
|
||||
pStable->numOfTags = htons(pCreate->numOfTags);
|
||||
pStable->numOfColumns = numOfColumns;
|
||||
pStable->numOfTags = numOfTags;
|
||||
|
||||
int32_t numOfCols = pStable->numOfColumns + pStable->numOfTags;
|
||||
int32_t schemaSize = numOfCols * sizeof(SSchema);
|
||||
pStable->schema = (SSchema *)calloc(1, schemaSize);
|
||||
if (pStable->schema == NULL) {
|
||||
|
@ -1064,11 +1076,6 @@ static int32_t mnodeProcessCreateSuperTableMsg(SMnodeMsg *pMsg) {
|
|||
|
||||
memcpy(pStable->schema, pCreate->schema, numOfCols * sizeof(SSchema));
|
||||
|
||||
if (pStable->numOfColumns > TSDB_MAX_COLUMNS || pStable->numOfTags > TSDB_MAX_TAGS) {
|
||||
mError("msg:%p, app:%p table:%s, failed to create, too many columns", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableName);
|
||||
return TSDB_CODE_MND_INVALID_TABLE_NAME;
|
||||
}
|
||||
|
||||
pStable->nextColId = 0;
|
||||
|
||||
for (int32_t col = 0; col < numOfCols; col++) {
|
||||
|
@ -1340,6 +1347,11 @@ static int32_t mnodeAddSuperTableColumn(SMnodeMsg *pMsg, SSchema schema[], int32
|
|||
return TSDB_CODE_MND_APP_ERROR;
|
||||
}
|
||||
|
||||
if (pStable->numOfColumns + ncols + pStable->numOfTags > TSDB_MAX_COLUMNS) {
|
||||
mError("msg:%p, app:%p stable:%s, add column, too many columns", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId);
|
||||
return TSDB_CODE_MND_TOO_MANY_COLUMNS;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < ncols; i++) {
|
||||
if (mnodeFindSuperTableColumnIndex(pStable, schema[i].name) > 0) {
|
||||
mError("msg:%p, app:%p stable:%s, add column, column:%s already exist", pMsg, pMsg->rpcMsg.ahandle,
|
||||
|
|
|
@ -994,6 +994,7 @@ void mnodeSendSyncVgroupMsg(SVgObj *pVgroup) {
|
|||
mDebug("vgId:%d, send sync all vnodes msg, numOfVnodes:%d db:%s", pVgroup->vgId, pVgroup->numOfVnodes,
|
||||
pVgroup->dbName);
|
||||
for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) {
|
||||
if (pVgroup->vnodeGid[i].role != TAOS_SYNC_ROLE_SLAVE) continue;
|
||||
SRpcEpSet epSet = mnodeGetEpSetFromIp(pVgroup->vnodeGid[i].pDnode->dnodeEp);
|
||||
mDebug("vgId:%d, index:%d, send sync vnode msg to dnode %s", pVgroup->vgId, i,
|
||||
pVgroup->vnodeGid[i].pDnode->dnodeEp);
|
||||
|
|
|
@ -191,6 +191,8 @@ typedef struct SQuery {
|
|||
bool stabledev; // super table stddev query
|
||||
int32_t interBufSize; // intermediate buffer sizse
|
||||
|
||||
int32_t havingNum; // having expr number
|
||||
|
||||
SOrderVal order;
|
||||
int16_t numOfCols;
|
||||
int16_t numOfTags;
|
||||
|
@ -287,6 +289,7 @@ enum OPERATOR_TYPE_E {
|
|||
OP_Fill = 13,
|
||||
OP_MultiTableAggregate = 14,
|
||||
OP_MultiTableTimeInterval = 15,
|
||||
OP_Having = 16,
|
||||
};
|
||||
|
||||
typedef struct SOperatorInfo {
|
||||
|
@ -405,6 +408,11 @@ typedef struct SOffsetOperatorInfo {
|
|||
int64_t offset;
|
||||
} SOffsetOperatorInfo;
|
||||
|
||||
typedef struct SHavingOperatorInfo {
|
||||
SArray* fp;
|
||||
} SHavingOperatorInfo;
|
||||
|
||||
|
||||
typedef struct SFillOperatorInfo {
|
||||
SFillInfo *pFillInfo;
|
||||
SSDataBlock *pRes;
|
||||
|
|
|
@ -98,6 +98,7 @@ typedef struct SQuerySqlNode {
|
|||
SLimitVal limit; // limit offset [optional]
|
||||
SLimitVal slimit; // group limit offset [optional]
|
||||
SStrToken sqlstr; // sql string in select clause
|
||||
struct tSqlExpr *pHaving; // having clause [optional]
|
||||
} SQuerySqlNode;
|
||||
|
||||
typedef struct STableNamePair {
|
||||
|
@ -262,6 +263,11 @@ SArray *tVariantListAppend(SArray *pList, tVariant *pVar, uint8_t sortOrder);
|
|||
SArray *tVariantListInsert(SArray *pList, tVariant *pVar, uint8_t sortOrder, int32_t index);
|
||||
SArray *tVariantListAppendToken(SArray *pList, SStrToken *pAliasToken, uint8_t sortOrder);
|
||||
|
||||
tSqlExpr *tSqlExprCreate(tSqlExpr *pLeft, tSqlExpr *pRight, int32_t optrType);
|
||||
|
||||
int32_t tSqlExprCompare(tSqlExpr *left, tSqlExpr *right);
|
||||
|
||||
tSqlExpr *tSqlExprClone(tSqlExpr *pSrc);
|
||||
SFromInfo *setTableNameList(SFromInfo* pFromInfo, SStrToken *pName, SStrToken* pAlias);
|
||||
SFromInfo *setSubquery(SFromInfo* pFromInfo, SQuerySqlNode *pSqlNode);
|
||||
void *destroyFromInfo(SFromInfo* pFromInfo);
|
||||
|
@ -281,7 +287,7 @@ void tSqlExprListDestroy(SArray *pList);
|
|||
|
||||
SQuerySqlNode *tSetQuerySqlNode(SStrToken *pSelectToken, SArray *pSelectList, SFromInfo *pFrom, tSqlExpr *pWhere,
|
||||
SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval, SSessionWindowVal *ps,
|
||||
SStrToken *pSliding, SArray *pFill, SLimitVal *pLimit, SLimitVal *pgLimit);
|
||||
SStrToken *pSliding, SArray *pFill, SLimitVal *pLimit, SLimitVal *pgLimit, tSqlExpr *pHaving);
|
||||
|
||||
SCreateTableSql *tSetCreateTableInfo(SArray *pCols, SArray *pTags, SQuerySqlNode *pSelect, int32_t type);
|
||||
|
||||
|
|
|
@ -52,11 +52,20 @@ static FORCE_INLINE SResultRow *getResultRow(SResultRowInfo *pResultRowInfo, int
|
|||
return pResultRowInfo->pResult[slot];
|
||||
}
|
||||
|
||||
static FORCE_INLINE char *getPosInResultPage(SQuery *pQuery, tFilePage* page, int32_t rowOffset, int16_t offset) {
|
||||
assert(rowOffset >= 0 && pQuery != NULL);
|
||||
static FORCE_INLINE char* getPosInResultPage(SQueryRuntimeEnv* pRuntimeEnv, tFilePage* page, int32_t rowOffset,
|
||||
int16_t offset, int32_t size) {
|
||||
assert(rowOffset >= 0 && pRuntimeEnv != NULL);
|
||||
|
||||
SQuery* pQuery = pRuntimeEnv->pQuery;
|
||||
int64_t pageSize = pRuntimeEnv->pResultBuf->pageSize;
|
||||
|
||||
int32_t numOfRows = (int32_t)GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery);
|
||||
return ((char *)page->data) + rowOffset + offset * numOfRows;
|
||||
|
||||
// buffer overflow check
|
||||
int64_t bufEnd = (rowOffset + offset * numOfRows + size);
|
||||
assert(page->num <= pageSize && bufEnd <= page->num);
|
||||
|
||||
return ((char*)page->data) + rowOffset + offset * numOfRows;
|
||||
}
|
||||
|
||||
bool isNullOperator(SColumnFilterElem *pFilter, const char* minval, const char* maxval, int16_t type);
|
||||
|
|
|
@ -457,7 +457,7 @@ tagitem(A) ::= PLUS(X) FLOAT(Y). {
|
|||
%type select {SQuerySqlNode*}
|
||||
%destructor select {destroyQuerySqlNode($$);}
|
||||
select(A) ::= SELECT(T) selcollist(W) from(X) where_opt(Y) interval_opt(K) session_option(H) fill_opt(F) sliding_opt(S) groupby_opt(P) orderby_opt(Z) having_opt(N) slimit_opt(G) limit_opt(L). {
|
||||
A = tSetQuerySqlNode(&T, W, X, Y, P, Z, &K, &H, &S, F, &L, &G);
|
||||
A = tSetQuerySqlNode(&T, W, X, Y, P, Z, &K, &H, &S, F, &L, &G, N);
|
||||
}
|
||||
|
||||
select(A) ::= LP select(B) RP. {A = B;}
|
||||
|
@ -475,7 +475,7 @@ cmd ::= union(X). { setSqlInfo(pInfo, X, NULL, TSDB_SQL_SELECT); }
|
|||
// select client_version()
|
||||
// select server_state()
|
||||
select(A) ::= SELECT(T) selcollist(W). {
|
||||
A = tSetQuerySqlNode(&T, W, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
A = tSetQuerySqlNode(&T, W, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
// selcollist is a list of expressions that are to become the return
|
||||
|
|
|
@ -2773,14 +2773,16 @@ static void percentile_function(SQLFunctionCtx *pCtx) {
|
|||
SPercentileInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
|
||||
|
||||
if (pCtx->currentStage == REPEAT_SCAN && pInfo->stage == 0) {
|
||||
pInfo->stage += 1;
|
||||
|
||||
// all data are null, set it completed
|
||||
if (pInfo->numOfElems == 0) {
|
||||
pResInfo->complete = true;
|
||||
|
||||
return;
|
||||
} else {
|
||||
pInfo->pMemBucket = tMemBucketCreate(pCtx->inputBytes, pCtx->inputType, pInfo->minval, pInfo->maxval);
|
||||
}
|
||||
|
||||
pInfo->stage += 1;
|
||||
}
|
||||
|
||||
// the first stage, only acquire the min/max value
|
||||
|
@ -2859,14 +2861,16 @@ static void percentile_function_f(SQLFunctionCtx *pCtx, int32_t index) {
|
|||
SPercentileInfo *pInfo = (SPercentileInfo *)GET_ROWCELL_INTERBUF(pResInfo);
|
||||
|
||||
if (pCtx->currentStage == REPEAT_SCAN && pInfo->stage == 0) {
|
||||
pInfo->stage += 1;
|
||||
|
||||
// all data are null, set it completed
|
||||
if (pInfo->numOfElems == 0) {
|
||||
pResInfo->complete = true;
|
||||
|
||||
return;
|
||||
} else {
|
||||
pInfo->pMemBucket = tMemBucketCreate(pCtx->inputBytes, pCtx->inputType, pInfo->minval, pInfo->maxval);
|
||||
}
|
||||
|
||||
pInfo->stage += 1;
|
||||
}
|
||||
|
||||
if (pInfo->stage == 0) {
|
||||
|
|
|
@ -98,6 +98,30 @@ int32_t getMaximumIdleDurationSec() {
|
|||
return tsShellActivityTimer * 2;
|
||||
}
|
||||
|
||||
|
||||
int64_t genQueryId(void) {
|
||||
int64_t uid = 0;
|
||||
int64_t did = tsDnodeId;
|
||||
|
||||
uid = did << 54;
|
||||
|
||||
int64_t pid = ((int64_t)taosGetPId()) & 0x3FF;
|
||||
|
||||
uid |= pid << 44;
|
||||
|
||||
int64_t ts = taosGetTimestampMs() & 0x1FFFFFFFF;
|
||||
|
||||
uid |= ts << 11;
|
||||
|
||||
int64_t sid = atomic_add_fetch_64(&queryHandleId, 1) & 0x7FF;
|
||||
|
||||
uid |= sid;
|
||||
|
||||
return uid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void getNextTimeWindow(SQuery* pQuery, STimeWindow* tw) {
|
||||
int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
|
||||
if (pQuery->interval.intervalUnit != 'n' && pQuery->interval.intervalUnit != 'y') {
|
||||
|
@ -175,6 +199,7 @@ static SOperatorInfo* createMultiTableAggOperatorInfo(SQueryRuntimeEnv* pRuntime
|
|||
static SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
|
||||
static SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput);
|
||||
static SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv);
|
||||
static SOperatorInfo* createHavingOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
|
||||
|
||||
static void destroyBasicOperatorInfo(void* param, int32_t numOfOutput);
|
||||
static void destroySFillOperatorInfo(void* param, int32_t numOfOutput);
|
||||
|
@ -1863,6 +1888,10 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf
|
|||
|
||||
}
|
||||
|
||||
if (pQuery->havingNum > 0) {
|
||||
pRuntimeEnv->proot = createHavingOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr1, pQuery->numOfOutput);
|
||||
}
|
||||
|
||||
if (pQuery->limit.offset > 0) {
|
||||
pRuntimeEnv->proot = createOffsetOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot);
|
||||
}
|
||||
|
@ -1893,6 +1922,17 @@ static void doFreeQueryHandle(SQueryRuntimeEnv* pRuntimeEnv) {
|
|||
assert(pMemRef->ref == 0 && pMemRef->snapshot.imem == NULL && pMemRef->snapshot.mem == NULL);
|
||||
}
|
||||
|
||||
static void destroyTsComp(SQueryRuntimeEnv *pRuntimeEnv, SQuery *pQuery) {
|
||||
if (isTsCompQuery(pQuery)) {
|
||||
SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
|
||||
FILE *f = *(FILE **)pColInfoData->pData; // TODO refactor
|
||||
if (f) {
|
||||
fclose(f);
|
||||
*(FILE **)pColInfoData->pData = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
|
||||
SQuery *pQuery = pRuntimeEnv->pQuery;
|
||||
SQInfo* pQInfo = (SQInfo*) pRuntimeEnv->qinfo;
|
||||
|
@ -1913,6 +1953,8 @@ static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
|
|||
destroyResultBuf(pRuntimeEnv->pResultBuf);
|
||||
doFreeQueryHandle(pRuntimeEnv);
|
||||
|
||||
destroyTsComp(pRuntimeEnv, pQuery);
|
||||
|
||||
pRuntimeEnv->pTsBuf = tsBufDestroy(pRuntimeEnv->pTsBuf);
|
||||
|
||||
tfree(pRuntimeEnv->keyBuf);
|
||||
|
@ -2160,6 +2202,40 @@ static bool onlyFirstQuery(SQuery *pQuery) { return onlyOneQueryType(pQuery, TSD
|
|||
|
||||
static bool onlyLastQuery(SQuery *pQuery) { return onlyOneQueryType(pQuery, TSDB_FUNC_LAST, TSDB_FUNC_LAST_DST); }
|
||||
|
||||
static int32_t updateBlockLoadStatus(SQuery *pQuery, int32_t status) {
|
||||
bool hasFirstLastFunc = false;
|
||||
bool hasOtherFunc = false;
|
||||
|
||||
if (status == BLK_DATA_ALL_NEEDED || status == BLK_DATA_DISCARD) {
|
||||
return status;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
|
||||
int32_t functionId = pQuery->pExpr1[i].base.functionId;
|
||||
|
||||
if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG ||
|
||||
functionId == TSDB_FUNC_TAG_DUMMY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_LAST_DST) {
|
||||
hasFirstLastFunc = true;
|
||||
} else {
|
||||
hasOtherFunc = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasFirstLastFunc && status == BLK_DATA_NO_NEEDED) {
|
||||
if(!hasOtherFunc) {
|
||||
return BLK_DATA_DISCARD;
|
||||
} else{
|
||||
return BLK_DATA_ALL_NEEDED;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void doExchangeTimeWindow(SQInfo* pQInfo, STimeWindow* win) {
|
||||
SQuery* pQuery = &pQInfo->query;
|
||||
size_t t = taosArrayGetSize(pQuery->tableGroupInfo.pGroupList);
|
||||
|
@ -2606,11 +2682,12 @@ int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTa
|
|||
pBlock->pDataBlock = NULL;
|
||||
pBlock->pBlockStatis = NULL;
|
||||
|
||||
SQInfo* pQInfo = pRuntimeEnv->qinfo;
|
||||
SQuery* pQuery = pRuntimeEnv->pQuery;
|
||||
|
||||
int64_t groupId = pQuery->current->groupIndex;
|
||||
bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);
|
||||
|
||||
SQInfo* pQInfo = pRuntimeEnv->qinfo;
|
||||
SQueryCostInfo* pCost = &pQInfo->summary;
|
||||
|
||||
if (pRuntimeEnv->pTsBuf != NULL) {
|
||||
|
@ -2667,7 +2744,9 @@ int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTa
|
|||
}
|
||||
|
||||
SDataBlockInfo* pBlockInfo = &pBlock->info;
|
||||
if ((*status) == BLK_DATA_NO_NEEDED) {
|
||||
*status = updateBlockLoadStatus(pRuntimeEnv->pQuery, *status);
|
||||
|
||||
if ((*status) == BLK_DATA_NO_NEEDED || (*status) == BLK_DATA_DISCARD) {
|
||||
qDebug("QInfo:%"PRIu64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
|
||||
pBlockInfo->window.ekey, pBlockInfo->rows);
|
||||
pCost->discardBlocks += 1;
|
||||
|
@ -3334,7 +3413,7 @@ void setResultRowOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pRe
|
|||
continue;
|
||||
}
|
||||
|
||||
pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQuery, bufPage, pResult->offset, offset);
|
||||
pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv, bufPage, pResult->offset, offset, pCtx[i].outputBytes);
|
||||
offset += pCtx[i].outputBytes;
|
||||
|
||||
int32_t functionId = pCtx[i].functionId;
|
||||
|
@ -3396,7 +3475,7 @@ void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLF
|
|||
|
||||
int16_t offset = 0;
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQuery, page, pResult->offset, offset);
|
||||
pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv, page, pResult->offset, offset, pCtx[i].outputBytes);
|
||||
offset += pCtx[i].outputBytes;
|
||||
|
||||
int32_t functionId = pCtx[i].functionId;
|
||||
|
@ -3604,8 +3683,6 @@ void setIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key) {
|
|||
*/
|
||||
|
||||
static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock) {
|
||||
SQuery *pQuery = pRuntimeEnv->pQuery;
|
||||
|
||||
int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
|
||||
int32_t numOfResult = pBlock->info.rows; // there are already exists result rows
|
||||
|
||||
|
@ -3640,7 +3717,7 @@ static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo*
|
|||
int32_t bytes = pColInfoData->info.bytes;
|
||||
|
||||
char *out = pColInfoData->pData + numOfResult * bytes;
|
||||
char *in = getPosInResultPage(pQuery, page, pRow->offset, offset);
|
||||
char *in = getPosInResultPage(pRuntimeEnv, page, pRow->offset, offset, bytes);
|
||||
memcpy(out, in, bytes * numOfRowsToCopy);
|
||||
|
||||
offset += bytes;
|
||||
|
@ -4110,7 +4187,7 @@ static SFillColInfo* createFillColInfo(SExprInfo* pExpr, int32_t numOfOutput, in
|
|||
return pFillCol;
|
||||
}
|
||||
|
||||
int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, SArray* prevResult, void *tsdb, int32_t vgId, bool isSTableQuery) {
|
||||
int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bool isSTableQuery) {
|
||||
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
|
||||
|
||||
SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
|
||||
|
@ -4121,8 +4198,6 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, SArray* prevResult, void *ts
|
|||
pQuery->timeWindowInterpo = timeWindowInterpoRequired(pQuery);
|
||||
pQuery->stabledev = isStabledev(pQuery);
|
||||
|
||||
pRuntimeEnv->prevResult = prevResult;
|
||||
|
||||
setScanLimitationByResultBuffer(pQuery);
|
||||
|
||||
int32_t code = setupQueryHandle(tsdb, pQInfo, isSTableQuery);
|
||||
|
@ -4764,6 +4839,111 @@ static SSDataBlock* doOffset(void* param) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool doFilterData(SColumnInfoData* p, int32_t rid, SColumnFilterElem *filterElem, __filter_func_t fp) {
|
||||
char* input = p->pData + p->info.bytes * rid;
|
||||
bool isnull = isNull(input, p->info.type);
|
||||
if (isnull) {
|
||||
return (fp == isNullOperator) ? true : false;
|
||||
} else {
|
||||
if (fp == notNullOperator) {
|
||||
return true;
|
||||
} else if (fp == isNullOperator) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fp(filterElem, input, input, p->info.type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void doHavingImpl(SOperatorInfo *pOperator, SSDataBlock *pBlock) {
|
||||
SHavingOperatorInfo* pInfo = pOperator->info;
|
||||
int32_t f = 0;
|
||||
int32_t allQualified = 1;
|
||||
int32_t exprQualified = 0;
|
||||
|
||||
for (int32_t r = 0; r < pBlock->info.rows; ++r) {
|
||||
allQualified = 1;
|
||||
|
||||
for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
|
||||
SExprInfo* pExprInfo = &(pOperator->pExpr[i]);
|
||||
if (pExprInfo->pFilter == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SArray* es = taosArrayGetP(pInfo->fp, i);
|
||||
assert(es);
|
||||
|
||||
size_t fpNum = taosArrayGetSize(es);
|
||||
|
||||
exprQualified = 0;
|
||||
for (int32_t m = 0; m < fpNum; ++m) {
|
||||
__filter_func_t fp = taosArrayGetP(es, m);
|
||||
|
||||
assert(fp);
|
||||
|
||||
//SColIndex* colIdx = &pExprInfo->base.colInfo;
|
||||
SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, i);
|
||||
|
||||
SColumnFilterElem filterElem = {.filterInfo = pExprInfo->pFilter[m]};
|
||||
|
||||
if (doFilterData(p, r, &filterElem, fp)) {
|
||||
exprQualified = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (exprQualified == 0) {
|
||||
allQualified = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allQualified == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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 + f * bytes, pColInfoData->pData + bytes * r, bytes);
|
||||
}
|
||||
|
||||
++f;
|
||||
}
|
||||
|
||||
pBlock->info.rows = f;
|
||||
}
|
||||
|
||||
static SSDataBlock* doHaving(void* param) {
|
||||
SOperatorInfo *pOperator = (SOperatorInfo *)param;
|
||||
if (pOperator->status == OP_EXEC_DONE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
|
||||
|
||||
while (1) {
|
||||
SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
|
||||
if (pBlock == NULL) {
|
||||
setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
|
||||
pOperator->status = OP_EXEC_DONE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
doHavingImpl(pOperator, pBlock);
|
||||
|
||||
return pBlock;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static SSDataBlock* doIntervalAgg(void* param) {
|
||||
SOperatorInfo* pOperator = (SOperatorInfo*) param;
|
||||
if (pOperator->status == OP_EXEC_DONE) {
|
||||
|
@ -5114,6 +5294,13 @@ static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) {
|
|||
pInfo->pRes = destroyOutputBuf(pInfo->pRes);
|
||||
}
|
||||
|
||||
static void destroyHavingOperatorInfo(void* param, int32_t numOfOutput) {
|
||||
SHavingOperatorInfo* pInfo = (SHavingOperatorInfo*) param;
|
||||
if (pInfo->fp) {
|
||||
taosArrayDestroy(pInfo->fp);
|
||||
}
|
||||
}
|
||||
|
||||
SOperatorInfo* createMultiTableAggOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
|
||||
SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo));
|
||||
|
||||
|
@ -5170,6 +5357,83 @@ SOperatorInfo* createArithOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorI
|
|||
return pOperator;
|
||||
}
|
||||
|
||||
|
||||
int32_t initFilterFp(SExprInfo* pExpr, int32_t numOfOutput, SArray** fps) {
|
||||
__filter_func_t fp = NULL;
|
||||
|
||||
*fps = taosArrayInit(numOfOutput, sizeof(SArray*));
|
||||
if (*fps == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < numOfOutput; ++i) {
|
||||
SExprInfo* pExprInfo = &(pExpr[i]);
|
||||
SColIndex* colIdx = &pExprInfo->base.colInfo;
|
||||
|
||||
if (pExprInfo->pFilter == NULL || !TSDB_COL_IS_NORMAL_COL(colIdx->flag)) {
|
||||
taosArrayPush(*fps, &fp);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t filterNum = pExprInfo->base.filterNum;
|
||||
SColumnFilterInfo *filterInfo = pExprInfo->pFilter;
|
||||
|
||||
SArray* es = taosArrayInit(filterNum, sizeof(__filter_func_t));
|
||||
|
||||
for (int32_t j = 0; j < filterNum; ++j) {
|
||||
int32_t lower = filterInfo->lowerRelOptr;
|
||||
int32_t upper = filterInfo->upperRelOptr;
|
||||
if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
|
||||
qError("invalid rel optr");
|
||||
taosArrayDestroy(es);
|
||||
return TSDB_CODE_QRY_APP_ERROR;
|
||||
}
|
||||
|
||||
__filter_func_t ffp = getFilterOperator(lower, upper);
|
||||
if (ffp == NULL) {
|
||||
qError("invalid filter info");
|
||||
taosArrayDestroy(es);
|
||||
return TSDB_CODE_QRY_APP_ERROR;
|
||||
}
|
||||
|
||||
taosArrayPush(es, &ffp);
|
||||
|
||||
filterInfo += 1;
|
||||
}
|
||||
|
||||
taosArrayPush(*fps, &es);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
SOperatorInfo* createHavingOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
|
||||
SHavingOperatorInfo* pInfo = calloc(1, sizeof(SHavingOperatorInfo));
|
||||
|
||||
initFilterFp(pExpr, numOfOutput, &pInfo->fp);
|
||||
|
||||
assert(pInfo->fp);
|
||||
|
||||
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
||||
|
||||
pOperator->name = "HavingOperator";
|
||||
pOperator->operatorType = OP_Having;
|
||||
pOperator->blockingOptr = false;
|
||||
pOperator->status = OP_IN_EXECUTING;
|
||||
pOperator->numOfOutput = numOfOutput;
|
||||
pOperator->pExpr = pExpr;
|
||||
pOperator->upstream = upstream;
|
||||
pOperator->exec = doHaving;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->pRuntimeEnv = pRuntimeEnv;
|
||||
pOperator->cleanup = destroyHavingOperatorInfo;
|
||||
|
||||
return pOperator;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
|
||||
SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo));
|
||||
pInfo->limit = pRuntimeEnv->pQuery->limit.limit;
|
||||
|
@ -5744,9 +6008,35 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
|
|||
pExprMsg->functionId = htons(pExprMsg->functionId);
|
||||
pExprMsg->numOfParams = htons(pExprMsg->numOfParams);
|
||||
pExprMsg->resColId = htons(pExprMsg->resColId);
|
||||
pExprMsg->filterNum = htonl(pExprMsg->filterNum);
|
||||
|
||||
pMsg += sizeof(SSqlFuncMsg);
|
||||
|
||||
SColumnFilterInfo* pExprFilterInfo = pExprMsg->filterInfo;
|
||||
|
||||
pMsg += sizeof(SColumnFilterInfo) * pExprMsg->filterNum;
|
||||
|
||||
for (int32_t f = 0; f < pExprMsg->filterNum; ++f) {
|
||||
SColumnFilterInfo *pFilterMsg = (SColumnFilterInfo *)pExprFilterInfo;
|
||||
|
||||
pFilterMsg->filterstr = htons(pFilterMsg->filterstr);
|
||||
|
||||
if (pFilterMsg->filterstr) {
|
||||
pFilterMsg->len = htobe64(pFilterMsg->len);
|
||||
|
||||
pFilterMsg->pz = (int64_t)pMsg;
|
||||
pMsg += (pFilterMsg->len + 1);
|
||||
} else {
|
||||
pFilterMsg->lowerBndi = htobe64(pFilterMsg->lowerBndi);
|
||||
pFilterMsg->upperBndi = htobe64(pFilterMsg->upperBndi);
|
||||
}
|
||||
|
||||
pFilterMsg->lowerRelOptr = htons(pFilterMsg->lowerRelOptr);
|
||||
pFilterMsg->upperRelOptr = htons(pFilterMsg->upperRelOptr);
|
||||
|
||||
pExprFilterInfo++;
|
||||
}
|
||||
|
||||
for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
|
||||
pExprMsg->arg[j].argType = htons(pExprMsg->arg[j].argType);
|
||||
pExprMsg->arg[j].argBytes = htons(pExprMsg->arg[j].argBytes);
|
||||
|
@ -5955,6 +6245,42 @@ _cleanup:
|
|||
return code;
|
||||
}
|
||||
|
||||
int32_t cloneExprFilterInfo(SColumnFilterInfo **dst, SColumnFilterInfo* src, int32_t filterNum) {
|
||||
if (filterNum <= 0) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
*dst = calloc(filterNum, sizeof(*src));
|
||||
if (*dst == NULL) {
|
||||
return TSDB_CODE_QRY_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(*dst, src, sizeof(*src) * filterNum);
|
||||
|
||||
for (int32_t i = 0; i < filterNum; i++) {
|
||||
if ((*dst)[i].filterstr && dst[i]->len > 0) {
|
||||
void *pz = calloc(1, (size_t)(*dst)[i].len + 1);
|
||||
|
||||
if (pz == NULL) {
|
||||
if (i == 0) {
|
||||
free(*dst);
|
||||
} else {
|
||||
freeColumnFilterInfo(*dst, i);
|
||||
}
|
||||
|
||||
return TSDB_CODE_QRY_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(pz, (void *)src->pz, (size_t)src->len + 1);
|
||||
|
||||
(*dst)[i].pz = (int64_t)pz;
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int32_t buildArithmeticExprFromMsg(SExprInfo *pArithExprInfo, SQueryTableMsg *pQueryMsg) {
|
||||
qDebug("qmsg:%p create arithmetic expr from binary", pQueryMsg);
|
||||
|
||||
|
@ -6187,6 +6513,13 @@ int32_t createQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutpu
|
|||
type = s->type;
|
||||
bytes = s->bytes;
|
||||
}
|
||||
|
||||
if (pExprs[i].base.filterNum > 0) {
|
||||
int32_t ret = cloneExprFilterInfo(&pExprs[i].pFilter, pExprMsg[i]->filterInfo, pExprMsg[i]->filterNum);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t param = (int32_t)pExprs[i].base.arg[0].argValue.i64;
|
||||
|
@ -6432,6 +6765,8 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr
|
|||
goto _cleanup_qinfo;
|
||||
}
|
||||
|
||||
pQInfo->qId = *qId;
|
||||
|
||||
// to make sure third party won't overwrite this structure
|
||||
pQInfo->signature = pQInfo;
|
||||
SQuery* pQuery = &pQInfo->query;
|
||||
|
@ -6482,6 +6817,10 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr
|
|||
if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) {
|
||||
pQuery->tagLen += pExprs[col].bytes;
|
||||
}
|
||||
|
||||
if (pExprs[col].pFilter) {
|
||||
++pQuery->havingNum;
|
||||
}
|
||||
}
|
||||
|
||||
if (pSecExprs != NULL) {
|
||||
|
@ -6579,8 +6918,6 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr
|
|||
// todo refactor
|
||||
pQInfo->query.queryBlockDist = (numOfOutput == 1 && pExprs[0].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
|
||||
|
||||
pQInfo->qId = atomic_add_fetch_64(&queryHandleId, 1);
|
||||
*qId = pQInfo->qId;
|
||||
qDebug("qmsg:%p QInfo:%" PRIu64 "-%p created", pQueryMsg, pQInfo->qId, pQInfo);
|
||||
return pQInfo;
|
||||
|
||||
|
@ -6599,6 +6936,10 @@ _cleanup_qinfo:
|
|||
tExprTreeDestroy(pExprInfo->pExpr, NULL);
|
||||
pExprInfo->pExpr = NULL;
|
||||
}
|
||||
|
||||
if (pExprInfo->pFilter) {
|
||||
freeColumnFilterInfo(pExprInfo->pFilter, pExprInfo->base.filterNum);
|
||||
}
|
||||
}
|
||||
|
||||
tfree(pExprs);
|
||||
|
@ -6644,6 +6985,8 @@ int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQInfo *p
|
|||
SArray* prevResult = NULL;
|
||||
if (pQueryMsg->prevResultLen > 0) {
|
||||
prevResult = interResFromBinary(param->prevResult, pQueryMsg->prevResultLen);
|
||||
|
||||
pRuntimeEnv->prevResult = prevResult;
|
||||
}
|
||||
|
||||
pQuery->precision = tsdbGetCfg(tsdb)->precision;
|
||||
|
@ -6665,7 +7008,7 @@ int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQInfo *p
|
|||
}
|
||||
|
||||
// filter the qualified
|
||||
if ((code = doInitQInfo(pQInfo, pTsBuf, prevResult, tsdb, vgId, isSTable)) != TSDB_CODE_SUCCESS) {
|
||||
if ((code = doInitQInfo(pQInfo, pTsBuf, tsdb, vgId, isSTable)) != TSDB_CODE_SUCCESS) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
|
@ -6683,7 +7026,7 @@ void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
|
|||
}
|
||||
|
||||
for (int32_t i = 0; i < numOfFilters; i++) {
|
||||
if (pFilter[i].filterstr) {
|
||||
if (pFilter[i].filterstr && pFilter[i].pz) {
|
||||
free((void*)(pFilter[i].pz));
|
||||
}
|
||||
}
|
||||
|
@ -6725,6 +7068,10 @@ static void* destroyQueryFuncExpr(SExprInfo* pExprInfo, int32_t numOfExpr) {
|
|||
if (pExprInfo[i].pExpr != NULL) {
|
||||
tExprTreeDestroy(pExprInfo[i].pExpr, NULL);
|
||||
}
|
||||
|
||||
if (pExprInfo[i].pFilter) {
|
||||
freeColumnFilterInfo(pExprInfo[i].pFilter, pExprInfo[i].base.filterNum);
|
||||
}
|
||||
}
|
||||
|
||||
tfree(pExprInfo);
|
||||
|
@ -6827,6 +7174,7 @@ int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
|
|||
}
|
||||
|
||||
fclose(f);
|
||||
*(FILE **)pColInfoData->pData = NULL;
|
||||
}
|
||||
|
||||
// all data returned, set query over
|
||||
|
|
|
@ -266,6 +266,7 @@ int32_t tExtMemBufferFlush(tExtMemBuffer *pMemBuffer) {
|
|||
size_t retVal = fwrite((char *)&(first->item), pMemBuffer->pageSize, 1, pMemBuffer->file);
|
||||
if (retVal <= 0) { // failed to write to buffer, may be not enough space
|
||||
ret = TAOS_SYSTEM_ERROR(errno);
|
||||
pMemBuffer->pHead = first;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ bool greaterEqualOperator(SColumnFilterElem *pFilter, const char *minval, const
|
|||
bool equalOperator(SColumnFilterElem *pFilter, const char *minval, const char *maxval, int16_t type) {
|
||||
SColumnFilterInfo *pFilterInfo = &pFilter->filterInfo;
|
||||
|
||||
if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
|
||||
if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL || type == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
int64_t minv = -1, maxv = -1;
|
||||
GET_TYPED_DATA(minv, int64_t, type, minval);
|
||||
GET_TYPED_DATA(maxv, int64_t, type, maxval);
|
||||
|
@ -202,7 +202,7 @@ bool likeOperator(SColumnFilterElem *pFilter, const char *minval, const char *ma
|
|||
bool notEqualOperator(SColumnFilterElem *pFilter, const char *minval, const char *maxval, int16_t type) {
|
||||
SColumnFilterInfo *pFilterInfo = &pFilter->filterInfo;
|
||||
|
||||
if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
|
||||
if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL || type == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
int64_t minv = -1, maxv = -1;
|
||||
GET_TYPED_DATA(minv, int64_t, type, minval);
|
||||
GET_TYPED_DATA(maxv, int64_t, type, maxval);
|
||||
|
|
|
@ -287,6 +287,10 @@ static void lruListMoveToFront(SList *pList, SPageInfo* pi) {
|
|||
tdListPrependNode(pList, pi->pn);
|
||||
}
|
||||
|
||||
static FORCE_INLINE size_t getAllocPageSize(int32_t pageSize) {
|
||||
return pageSize + POINTER_BYTES + 2 + sizeof(tFilePage);
|
||||
}
|
||||
|
||||
tFilePage* getNewDataBuf(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32_t* pageId) {
|
||||
pResultBuf->statis.getPages += 1;
|
||||
|
||||
|
@ -311,7 +315,7 @@ tFilePage* getNewDataBuf(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32
|
|||
|
||||
// allocate buf
|
||||
if (availablePage == NULL) {
|
||||
pi->pData = calloc(1, pResultBuf->pageSize + POINTER_BYTES + 2); // add extract bytes in case of zipped buffer increased.
|
||||
pi->pData = calloc(1, getAllocPageSize(pResultBuf->pageSize)); // add extract bytes in case of zipped buffer increased.
|
||||
} else {
|
||||
pi->pData = availablePage;
|
||||
}
|
||||
|
@ -355,7 +359,7 @@ tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id) {
|
|||
}
|
||||
|
||||
if (availablePage == NULL) {
|
||||
(*pi)->pData = calloc(1, pResultBuf->pageSize + POINTER_BYTES);
|
||||
(*pi)->pData = calloc(1, getAllocPageSize(pResultBuf->pageSize));
|
||||
} else {
|
||||
(*pi)->pData = availablePage;
|
||||
}
|
||||
|
|
|
@ -310,6 +310,77 @@ tSqlExpr *tSqlExprCreate(tSqlExpr *pLeft, tSqlExpr *pRight, int32_t optrType) {
|
|||
return pExpr;
|
||||
}
|
||||
|
||||
static FORCE_INLINE int32_t tStrTokenCompare(SStrToken* left, SStrToken* right) {
|
||||
return (left->type == right->type && left->n == right->n && strncasecmp(left->z, right->z, left->n) == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
int32_t tSqlExprCompare(tSqlExpr *left, tSqlExpr *right) {
|
||||
if ((left == NULL && right) || (left && right == NULL)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (left->type != right->type) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (left->tokenId != right->tokenId) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (left->functionId != right->functionId) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((left->pLeft && right->pLeft == NULL)
|
||||
|| (left->pLeft == NULL && right->pLeft)
|
||||
|| (left->pRight && right->pRight == NULL)
|
||||
|| (left->pRight == NULL && right->pRight)
|
||||
|| (left->pParam && right->pParam == NULL)
|
||||
|| (left->pParam == NULL && right->pParam)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (tVariantCompare(&left->value, &right->value)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (tStrTokenCompare(&left->colInfo, &right->colInfo)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if (right->pParam && left->pParam) {
|
||||
size_t size = taosArrayGetSize(right->pParam);
|
||||
if (left->pParam && taosArrayGetSize(left->pParam) != size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
tSqlExprItem* pLeftElem = taosArrayGet(left->pParam, i);
|
||||
tSqlExpr* pSubLeft = pLeftElem->pNode;
|
||||
tSqlExprItem* pRightElem = taosArrayGet(left->pParam, i);
|
||||
tSqlExpr* pSubRight = pRightElem->pNode;
|
||||
|
||||
if (tSqlExprCompare(pSubLeft, pSubRight)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (left->pLeft && tSqlExprCompare(left->pLeft, right->pLeft)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (left->pRight && tSqlExprCompare(left->pRight, right->pRight)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
tSqlExpr *tSqlExprClone(tSqlExpr *pSrc) {
|
||||
tSqlExpr *pExpr = calloc(1, sizeof(tSqlExpr));
|
||||
|
||||
|
@ -640,7 +711,7 @@ void tSetColumnType(TAOS_FIELD *pField, SStrToken *type) {
|
|||
SQuerySqlNode *tSetQuerySqlNode(SStrToken *pSelectToken, SArray *pSelectList, SFromInfo *pFrom, tSqlExpr *pWhere,
|
||||
SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval,
|
||||
SSessionWindowVal *pSession, SStrToken *pSliding, SArray *pFill, SLimitVal *pLimit,
|
||||
SLimitVal *psLimit) {
|
||||
SLimitVal *psLimit, tSqlExpr *pHaving) {
|
||||
assert(pSelectList != NULL);
|
||||
|
||||
SQuerySqlNode *pSqlNode = calloc(1, sizeof(SQuerySqlNode));
|
||||
|
@ -655,6 +726,7 @@ SQuerySqlNode *tSetQuerySqlNode(SStrToken *pSelectToken, SArray *pSelectList, SF
|
|||
pSqlNode->pSortOrder = pSortOrder;
|
||||
pSqlNode->pWhere = pWhere;
|
||||
pSqlNode->fillType = pFill;
|
||||
pSqlNode->pHaving = pHaving;
|
||||
|
||||
if (pLimit != NULL) {
|
||||
pSqlNode->limit = *pLimit;
|
||||
|
@ -717,6 +789,9 @@ void destroyQuerySqlNode(SQuerySqlNode *pQuerySql) {
|
|||
|
||||
tSqlExprDestroy(pQuerySql->pWhere);
|
||||
pQuerySql->pWhere = NULL;
|
||||
|
||||
tSqlExprDestroy(pQuerySql->pHaving);
|
||||
pQuerySql->pHaving = NULL;
|
||||
|
||||
taosArrayDestroyEx(pQuerySql->pSortOrder, freeVariant);
|
||||
pQuerySql->pSortOrder = NULL;
|
||||
|
|
|
@ -140,7 +140,7 @@ void clearResultRow(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResultRow, int16
|
|||
SResultRowCellInfo *pResultInfo = &pResultRow->pCellInfo[i];
|
||||
|
||||
int16_t size = pRuntimeEnv->pQuery->pExpr1[i].bytes;
|
||||
char * s = getPosInResultPage(pRuntimeEnv->pQuery, page, pResultRow->offset, offset);
|
||||
char * s = getPosInResultPage(pRuntimeEnv, page, pResultRow->offset, offset, size);
|
||||
memset(s, 0, size);
|
||||
|
||||
offset += size;
|
||||
|
|
|
@ -200,6 +200,7 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, qi
|
|||
return code;
|
||||
}
|
||||
|
||||
|
||||
bool qTableQuery(qinfo_t qinfo, uint64_t *qId) {
|
||||
SQInfo *pQInfo = (SQInfo *)qinfo;
|
||||
assert(pQInfo && pQInfo->signature == pQInfo);
|
||||
|
@ -478,7 +479,7 @@ void qCleanupQueryMgmt(void* pQMgmt) {
|
|||
qDebug("vgId:%d, queryMgmt cleanup completed", vgId);
|
||||
}
|
||||
|
||||
void** qRegisterQInfo(void* pMgmt, uint64_t qId, uint64_t qInfo) {
|
||||
void** qRegisterQInfo(void* pMgmt, uint64_t qId, void *qInfo) {
|
||||
if (pMgmt == NULL) {
|
||||
terrno = TSDB_CODE_VND_INVALID_VGROUP_ID;
|
||||
return NULL;
|
||||
|
@ -519,8 +520,7 @@ void** qAcquireQInfo(void* pMgmt, uint64_t _key) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
TSDB_CACHE_PTR_TYPE key = (TSDB_CACHE_PTR_TYPE)_key;
|
||||
void** handle = taosCacheAcquireByKey(pQueryMgmt->qinfoPool, &key, sizeof(TSDB_CACHE_PTR_TYPE));
|
||||
void** handle = taosCacheAcquireByKey(pQueryMgmt->qinfoPool, &_key, sizeof(_key));
|
||||
if (handle == NULL || *handle == NULL) {
|
||||
terrno = TSDB_CODE_QRY_INVALID_QHANDLE;
|
||||
return NULL;
|
||||
|
|
|
@ -2925,7 +2925,7 @@ static YYACTIONTYPE yy_reduce(
|
|||
break;
|
||||
case 160: /* select ::= SELECT selcollist from where_opt interval_opt session_option fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */
|
||||
{
|
||||
yylhsminor.yy286 = tSetQuerySqlNode(&yymsp[-12].minor.yy0, yymsp[-11].minor.yy193, yymsp[-10].minor.yy370, yymsp[-9].minor.yy454, yymsp[-4].minor.yy193, yymsp[-3].minor.yy193, &yymsp[-8].minor.yy392, &yymsp[-7].minor.yy447, &yymsp[-5].minor.yy0, yymsp[-6].minor.yy193, &yymsp[0].minor.yy482, &yymsp[-1].minor.yy482);
|
||||
yylhsminor.yy286 = tSetQuerySqlNode(&yymsp[-12].minor.yy0, yymsp[-11].minor.yy193, yymsp[-10].minor.yy370, yymsp[-9].minor.yy454, yymsp[-4].minor.yy193, yymsp[-3].minor.yy193, &yymsp[-8].minor.yy392, &yymsp[-7].minor.yy447, &yymsp[-5].minor.yy0, yymsp[-6].minor.yy193, &yymsp[0].minor.yy482, &yymsp[-1].minor.yy482, yymsp[-2].minor.yy454);
|
||||
}
|
||||
yymsp[-12].minor.yy286 = yylhsminor.yy286;
|
||||
break;
|
||||
|
@ -2945,7 +2945,7 @@ static YYACTIONTYPE yy_reduce(
|
|||
break;
|
||||
case 165: /* select ::= SELECT selcollist */
|
||||
{
|
||||
yylhsminor.yy286 = tSetQuerySqlNode(&yymsp[-1].minor.yy0, yymsp[0].minor.yy193, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
yylhsminor.yy286 = tSetQuerySqlNode(&yymsp[-1].minor.yy0, yymsp[0].minor.yy193, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
yymsp[-1].minor.yy286 = yylhsminor.yy286;
|
||||
break;
|
||||
|
|
|
@ -295,7 +295,7 @@ void *rpcOpen(const SRpcInit *pInit) {
|
|||
return NULL;
|
||||
}
|
||||
} else {
|
||||
pRpc->pCache = rpcOpenConnCache(pRpc->sessions, rpcCloseConn, pRpc->tmrCtrl, pRpc->idleTime);
|
||||
pRpc->pCache = rpcOpenConnCache(pRpc->sessions, rpcCloseConn, pRpc->tmrCtrl, pRpc->idleTime * 30);
|
||||
if ( pRpc->pCache == NULL ) {
|
||||
tError("%s failed to init connection cache", pRpc->label);
|
||||
rpcClose(pRpc);
|
||||
|
@ -470,7 +470,7 @@ void rpcSendResponse(const SRpcMsg *pRsp) {
|
|||
taosTmrStopA(&pConn->pTimer);
|
||||
|
||||
// set the idle timer to monitor the activity
|
||||
taosTmrReset(rpcProcessIdleTimer, pRpc->idleTime, pConn, pRpc->tmrCtrl, &pConn->pIdleTimer);
|
||||
taosTmrReset(rpcProcessIdleTimer, pRpc->idleTime * 30, pConn, pRpc->tmrCtrl, &pConn->pIdleTimer);
|
||||
rpcSendMsgToPeer(pConn, msg, msgLen);
|
||||
|
||||
// if not set to secured, set it expcet NOT_READY case, since client wont treat it as secured
|
||||
|
@ -997,8 +997,8 @@ static SRpcConn *rpcProcessMsgHead(SRpcInfo *pRpc, SRecvInfo *pRecv, SRpcReqCont
|
|||
}
|
||||
|
||||
if ( rpcIsReq(pHead->msgType) ) {
|
||||
terrno = rpcProcessReqHead(pConn, pHead);
|
||||
pConn->connType = pRecv->connType;
|
||||
terrno = rpcProcessReqHead(pConn, pHead);
|
||||
|
||||
// stop idle timer
|
||||
taosTmrStopA(&pConn->pIdleTimer);
|
||||
|
@ -1367,7 +1367,7 @@ static void rpcProcessConnError(void *param, void *id) {
|
|||
|
||||
tDebug("%s %p, connection error happens", pRpc->label, pContext->ahandle);
|
||||
|
||||
if (pContext->numOfTry >= pContext->epSet.numOfEps) {
|
||||
if (pContext->numOfTry >= pContext->epSet.numOfEps || pContext->msgType == TSDB_MSG_TYPE_FETCH) {
|
||||
rpcMsg.msgType = pContext->msgType+1;
|
||||
rpcMsg.ahandle = pContext->ahandle;
|
||||
rpcMsg.code = pContext->code;
|
||||
|
|
|
@ -35,7 +35,7 @@ extern "C" {
|
|||
#define SYNC_MAX_SIZE (TSDB_MAX_WAL_SIZE + sizeof(SWalHead) + sizeof(SSyncHead) + 16)
|
||||
#define SYNC_RECV_BUFFER_SIZE (5*1024*1024)
|
||||
|
||||
#define SYNC_MAX_FWDS 1024
|
||||
#define SYNC_MAX_FWDS 4096
|
||||
#define SYNC_FWD_TIMER 300
|
||||
#define SYNC_ROLE_TIMER 15000 // ms
|
||||
#define SYNC_CHECK_INTERVAL 1000 // ms
|
||||
|
|
|
@ -409,23 +409,22 @@ void syncConfirmForward(int64_t rid, uint64_t version, int32_t code, bool force)
|
|||
syncReleaseNode(pNode);
|
||||
}
|
||||
|
||||
#if 1
|
||||
void syncRecover(int64_t rid) {
|
||||
SSyncPeer *pPeer;
|
||||
|
||||
SSyncNode *pNode = syncAcquireNode(rid);
|
||||
if (pNode == NULL) return;
|
||||
|
||||
// to do: add a few lines to check if recover is OK
|
||||
// if take this node to unsync state, the whole system may not work
|
||||
|
||||
nodeRole = TAOS_SYNC_ROLE_UNSYNCED;
|
||||
(*pNode->notifyRoleFp)(pNode->vgId, nodeRole);
|
||||
nodeVersion = 0;
|
||||
|
||||
pthread_mutex_lock(&pNode->mutex);
|
||||
|
||||
nodeVersion = 0;
|
||||
|
||||
for (int32_t i = 0; i < pNode->replica; ++i) {
|
||||
if (i == pNode->selfIndex) continue;
|
||||
|
||||
pPeer = pNode->peerInfo[i];
|
||||
if (pPeer->peerFd >= 0) {
|
||||
syncRestartConnection(pPeer);
|
||||
|
@ -436,7 +435,6 @@ void syncRecover(int64_t rid) {
|
|||
|
||||
syncReleaseNode(pNode);
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t syncGetNodesRole(int64_t rid, SNodesRole *pNodesRole) {
|
||||
SSyncNode *pNode = syncAcquireNode(rid);
|
||||
|
@ -551,7 +549,10 @@ static void syncClosePeerConn(SSyncPeer *pPeer) {
|
|||
if (pPeer->peerFd >= 0) {
|
||||
pPeer->peerFd = -1;
|
||||
void *pConn = pPeer->pConn;
|
||||
if (pConn != NULL) syncFreeTcpConn(pPeer->pConn);
|
||||
if (pConn != NULL) {
|
||||
syncFreeTcpConn(pPeer->pConn);
|
||||
pPeer->pConn = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -997,17 +998,24 @@ static void syncProcessForwardFromPeer(char *cont, SSyncPeer *pPeer) {
|
|||
|
||||
sTrace("%s, forward is received, hver:%" PRIu64 ", len:%d", pPeer->id, pHead->version, pHead->len);
|
||||
|
||||
int32_t code = 0;
|
||||
if (nodeRole == TAOS_SYNC_ROLE_SLAVE) {
|
||||
// nodeVersion = pHead->version;
|
||||
(*pNode->writeToCacheFp)(pNode->vgId, pHead, TAOS_QTYPE_FWD, NULL);
|
||||
code = (*pNode->writeToCacheFp)(pNode->vgId, pHead, TAOS_QTYPE_FWD, NULL);
|
||||
} else {
|
||||
if (nodeSStatus != TAOS_SYNC_STATUS_INIT) {
|
||||
syncSaveIntoBuffer(pPeer, pHead);
|
||||
code = syncSaveIntoBuffer(pPeer, pHead);
|
||||
} else {
|
||||
sError("%s, forward discarded since sstatus:%s, hver:%" PRIu64, pPeer->id, syncStatus[nodeSStatus],
|
||||
pHead->version);
|
||||
code = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (code != 0) {
|
||||
sError("%s, failed to process fwd msg, hver:%" PRIu64 ", len:%d", pPeer->id, pHead->version, pHead->len);
|
||||
syncRestartConnection(pPeer);
|
||||
}
|
||||
}
|
||||
|
||||
static void syncProcessPeersStatusMsg(SPeersStatus *pPeersStatus, SSyncPeer *pPeer) {
|
||||
|
|
|
@ -2861,12 +2861,6 @@ int32_t tsdbRetrieveDataBlockStatisInfo(TsdbQueryHandleT* pQueryHandle, SDataSta
|
|||
if (pHandle->statis[i].numOfNull == -1) { // set the column data are all NULL
|
||||
pHandle->statis[i].numOfNull = pBlockInfo->compBlock->numOfRows;
|
||||
}
|
||||
|
||||
SColumnInfo* pColInfo = taosArrayGet(pHandle->pColumns, i);
|
||||
if (pColInfo->type == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
pHandle->statis[i].min = pBlockInfo->compBlock->keyFirst;
|
||||
pHandle->statis[i].max = pBlockInfo->compBlock->keyLast;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t elapsed = taosGetTimestampUs() - stime;
|
||||
|
|
|
@ -176,6 +176,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_TABLE_ID, "Table name too long")
|
|||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_TABLE_NAME, "Table does not exist")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_TABLE_TYPE, "Invalid table type in tsdb")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOO_MANY_TAGS, "Too many tags")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOO_MANY_COLUMNS, "Too many columns")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOO_MANY_TIMESERIES, "Too many time series")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_NOT_SUPER_TABLE, "Not super table") // operation only available for super table
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_COL_NAME_TOO_LONG, "Tag name too long")
|
||||
|
|
|
@ -37,6 +37,7 @@ extern int32_t vDebugFlag;
|
|||
typedef struct {
|
||||
int32_t vgId; // global vnode group ID
|
||||
int32_t refCount; // reference count
|
||||
int64_t queuedWMsgSize;
|
||||
int32_t queuedWMsg;
|
||||
int32_t queuedRMsg;
|
||||
int32_t flowctrlLevel;
|
||||
|
|
|
@ -99,8 +99,13 @@ int32_t vnodeSync(int32_t vgId) {
|
|||
return TSDB_CODE_VND_INVALID_VGROUP_ID;
|
||||
}
|
||||
|
||||
if (pVnode->role != TAOS_SYNC_ROLE_MASTER) {
|
||||
if (pVnode->role == TAOS_SYNC_ROLE_SLAVE) {
|
||||
vInfo("vgId:%d, vnode will sync, refCount:%d pVnode:%p", pVnode->vgId, pVnode->refCount, pVnode);
|
||||
|
||||
pVnode->version = 0;
|
||||
pVnode->fversion = 0;
|
||||
walResetVersion(pVnode->wal, pVnode->fversion);
|
||||
|
||||
syncRecover(pVnode->sync);
|
||||
}
|
||||
|
||||
|
@ -227,9 +232,28 @@ int32_t vnodeAlter(void *vparam, SCreateVnodeMsg *pVnodeCfg) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static void vnodeFindWalRootDir(int32_t vgId, char *walRootDir) {
|
||||
char vnodeDir[TSDB_FILENAME_LEN] = "\0";
|
||||
snprintf(vnodeDir, TSDB_FILENAME_LEN, "/vnode/vnode%d/wal", vgId);
|
||||
|
||||
TDIR *tdir = tfsOpendir(vnodeDir);
|
||||
if (!tdir) return;
|
||||
|
||||
const TFILE *tfile = tfsReaddir(tdir);
|
||||
if (!tfile) {
|
||||
tfsClosedir(tdir);
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(walRootDir, "%s/vnode/vnode%d", TFS_DISK_PATH(tfile->level, tfile->id), vgId);
|
||||
|
||||
tfsClosedir(tdir);
|
||||
}
|
||||
|
||||
int32_t vnodeOpen(int32_t vgId) {
|
||||
char temp[TSDB_FILENAME_LEN * 3];
|
||||
char rootDir[TSDB_FILENAME_LEN * 2];
|
||||
char walRootDir[TSDB_FILENAME_LEN * 2] = {0};
|
||||
snprintf(rootDir, TSDB_FILENAME_LEN * 2, "%s/vnode%d", tsVnodeDir, vgId);
|
||||
|
||||
SVnodeObj *pVnode = calloc(sizeof(SVnodeObj), 1);
|
||||
|
@ -316,7 +340,21 @@ int32_t vnodeOpen(int32_t vgId) {
|
|||
}
|
||||
}
|
||||
|
||||
sprintf(temp, "%s/wal", rootDir);
|
||||
// walRootDir for wal & syncInfo.path (not empty dir of /vnode/vnode{pVnode->vgId}/wal)
|
||||
vnodeFindWalRootDir(pVnode->vgId, walRootDir);
|
||||
if (walRootDir[0] == 0) {
|
||||
int level = -1, id = -1;
|
||||
|
||||
tfsAllocDisk(TFS_PRIMARY_LEVEL, &level, &id);
|
||||
if (level < 0 || id < 0) {
|
||||
vnodeCleanUp(pVnode);
|
||||
return terrno;
|
||||
}
|
||||
|
||||
sprintf(walRootDir, "%s/vnode/vnode%d", TFS_DISK_PATH(level, id), vgId);
|
||||
}
|
||||
|
||||
sprintf(temp, "%s/wal", walRootDir);
|
||||
pVnode->walCfg.vgId = pVnode->vgId;
|
||||
pVnode->wal = walOpen(temp, &pVnode->walCfg);
|
||||
if (pVnode->wal == NULL) {
|
||||
|
@ -348,7 +386,7 @@ int32_t vnodeOpen(int32_t vgId) {
|
|||
|
||||
pVnode->events = NULL;
|
||||
|
||||
vDebug("vgId:%d, vnode is opened in %s, pVnode:%p", pVnode->vgId, rootDir, pVnode);
|
||||
vDebug("vgId:%d, vnode is opened in %s - %s, pVnode:%p", pVnode->vgId, rootDir, walRootDir, pVnode);
|
||||
|
||||
vnodeAddIntoHash(pVnode);
|
||||
|
||||
|
@ -356,7 +394,7 @@ int32_t vnodeOpen(int32_t vgId) {
|
|||
syncInfo.vgId = pVnode->vgId;
|
||||
syncInfo.version = pVnode->version;
|
||||
syncInfo.syncCfg = pVnode->syncCfg;
|
||||
tstrncpy(syncInfo.path, rootDir, TSDB_FILENAME_LEN);
|
||||
tstrncpy(syncInfo.path, walRootDir, TSDB_FILENAME_LEN);
|
||||
syncInfo.getWalInfoFp = vnodeGetWalInfo;
|
||||
syncInfo.writeToCacheFp = vnodeWriteToCache;
|
||||
syncInfo.confirmForward = vnodeConfirmForard;
|
||||
|
|
|
@ -208,6 +208,7 @@ static void vnodeBuildNoResultQueryRsp(SRspRet *pRet) {
|
|||
pRsp->completed = true;
|
||||
}
|
||||
|
||||
|
||||
static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SVReadMsg *pRead) {
|
||||
void * pCont = pRead->pCont;
|
||||
int32_t contLen = pRead->contLen;
|
||||
|
@ -226,7 +227,7 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SVReadMsg *pRead) {
|
|||
|
||||
if (contLen != 0) {
|
||||
qinfo_t pQInfo = NULL;
|
||||
uint64_t qId = 0;
|
||||
uint64_t qId = genQueryId();
|
||||
code = qCreateQueryInfo(pVnode->tsdb, pVnode->vgId, pQueryTableMsg, &pQInfo, &qId);
|
||||
|
||||
SQueryTableRsp *pRsp = (SQueryTableRsp *)rpcMallocCont(sizeof(SQueryTableRsp));
|
||||
|
@ -239,7 +240,7 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SVReadMsg *pRead) {
|
|||
|
||||
// current connect is broken
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
handle = qRegisterQInfo(pVnode->qMgmt, qId, (uint64_t)pQInfo);
|
||||
handle = qRegisterQInfo(pVnode->qMgmt, qId, pQInfo);
|
||||
if (handle == NULL) { // failed to register qhandle
|
||||
pRsp->code = terrno;
|
||||
terrno = 0;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "vnodeStatus.h"
|
||||
|
||||
#define MAX_QUEUED_MSG_NUM 100000
|
||||
#define MAX_QUEUED_MSG_SIZE 1024*1024*1024 //1GB
|
||||
|
||||
extern void * tsDnodeTmr;
|
||||
static int32_t (*vnodeProcessWriteMsgFp[TSDB_MSG_TYPE_MAX])(SVnodeObj *, void *pCont, SRspRet *);
|
||||
|
@ -269,6 +270,13 @@ static int32_t vnodeWriteToWQueueImp(SVWriteMsg *pWrite) {
|
|||
}
|
||||
}
|
||||
|
||||
if (tsAvailDataDirGB <= tsMinimalDataDirGB) {
|
||||
vError("vgId:%d, failed to write into vwqueue since no diskspace, avail:%fGB", pVnode->vgId, tsAvailDataDirGB);
|
||||
taosFreeQitem(pWrite);
|
||||
vnodeRelease(pVnode);
|
||||
return TSDB_CODE_VND_NO_DISKSPACE;
|
||||
}
|
||||
|
||||
if (!vnodeInReadyOrUpdatingStatus(pVnode)) {
|
||||
vError("vgId:%d, failed to write into vwqueue, vstatus is %s, refCount:%d pVnode:%p", pVnode->vgId,
|
||||
vnodeStatus[pVnode->status], pVnode->refCount, pVnode);
|
||||
|
@ -278,14 +286,17 @@ static int32_t vnodeWriteToWQueueImp(SVWriteMsg *pWrite) {
|
|||
}
|
||||
|
||||
int32_t queued = atomic_add_fetch_32(&pVnode->queuedWMsg, 1);
|
||||
if (queued > MAX_QUEUED_MSG_NUM) {
|
||||
int64_t queuedSize = atomic_add_fetch_64(&pVnode->queuedWMsgSize, pWrite->pHead.len);
|
||||
|
||||
if (queued > MAX_QUEUED_MSG_NUM || queuedSize > MAX_QUEUED_MSG_SIZE) {
|
||||
int32_t ms = (queued / MAX_QUEUED_MSG_NUM) * 10 + 3;
|
||||
if (ms > 100) ms = 100;
|
||||
vDebug("vgId:%d, too many msg:%d in vwqueue, flow control %dms", pVnode->vgId, queued, ms);
|
||||
taosMsleep(ms);
|
||||
}
|
||||
|
||||
vTrace("vgId:%d, write into vwqueue, refCount:%d queued:%d", pVnode->vgId, pVnode->refCount, pVnode->queuedWMsg);
|
||||
vTrace("vgId:%d, write into vwqueue, refCount:%d queued:%d size:%" PRId64, pVnode->vgId, pVnode->refCount,
|
||||
pVnode->queuedWMsg, pVnode->queuedWMsgSize);
|
||||
|
||||
taosWriteQitem(pVnode->wqueue, pWrite->qtype, pWrite);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -308,7 +319,10 @@ void vnodeFreeFromWQueue(void *vparam, SVWriteMsg *pWrite) {
|
|||
SVnodeObj *pVnode = vparam;
|
||||
|
||||
int32_t queued = atomic_sub_fetch_32(&pVnode->queuedWMsg, 1);
|
||||
vTrace("vgId:%d, msg:%p, app:%p, free from vwqueue, queued:%d", pVnode->vgId, pWrite, pWrite->rpcMsg.ahandle, queued);
|
||||
int64_t queuedSize = atomic_sub_fetch_64(&pVnode->queuedWMsgSize, pWrite->pHead.len);
|
||||
|
||||
vTrace("vgId:%d, msg:%p, app:%p, free from vwqueue, queued:%d size:%" PRId64, pVnode->vgId, pWrite,
|
||||
pWrite->rpcMsg.ahandle, queued, queuedSize);
|
||||
|
||||
taosFreeQitem(pWrite);
|
||||
vnodeRelease(pVnode);
|
||||
|
@ -344,7 +358,9 @@ static void vnodeFlowCtrlMsgToWQueue(void *param, void *tmrId) {
|
|||
static int32_t vnodePerformFlowCtrl(SVWriteMsg *pWrite) {
|
||||
SVnodeObj *pVnode = pWrite->pVnode;
|
||||
if (pWrite->qtype != TAOS_QTYPE_RPC) return 0;
|
||||
if (pVnode->queuedWMsg < MAX_QUEUED_MSG_NUM && pVnode->flowctrlLevel <= 0) return 0;
|
||||
if (pVnode->queuedWMsg < MAX_QUEUED_MSG_NUM && pVnode->queuedWMsgSize < MAX_QUEUED_MSG_SIZE &&
|
||||
pVnode->flowctrlLevel <= 0)
|
||||
return 0;
|
||||
|
||||
if (tsEnableFlowCtrl == 0) {
|
||||
int32_t ms = (int32_t)pow(2, pVnode->flowctrlLevel + 2);
|
||||
|
|
|
@ -104,7 +104,7 @@ int32_t walAlter(void *handle, SWalCfg *pCfg) {
|
|||
|
||||
pWal->level = pCfg->walLevel;
|
||||
pWal->fsyncPeriod = pCfg->fsyncPeriod;
|
||||
pWal->fsyncSeq = pCfg->fsyncPeriod % 1000;
|
||||
pWal->fsyncSeq = pCfg->fsyncPeriod / 1000;
|
||||
if (pWal->fsyncSeq <= 0) pWal->fsyncSeq = 1;
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
|
|
@ -227,11 +227,11 @@ pipeline {
|
|||
}
|
||||
|
||||
}
|
||||
post {
|
||||
post {
|
||||
success {
|
||||
emailext (
|
||||
subject: "SUCCESSFUL: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'",
|
||||
body: '''<!DOCTYPE html>
|
||||
subject: "PR-result: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' SUCCESS",
|
||||
body: """<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
@ -247,29 +247,29 @@ pipeline {
|
|||
<td>
|
||||
<ul>
|
||||
<div style="font-size:18px">
|
||||
<li>构建名称>>分支:${PROJECT_NAME}</li>
|
||||
<li>构建名称>>分支:${env.BRANCH_NAME}</li>
|
||||
<li>构建结果:<span style="color:green"> Successful </span></li>
|
||||
<li>构建编号:${BUILD_NUMBER}</li>
|
||||
<li>触发用户:${CAUSE}</li>
|
||||
<li>变更概要:${CHANGES}</li>
|
||||
<li>触发用户:${env.CHANGE_AUTHOR}</li>
|
||||
<li>提交信息:${env.CHANGE_TITLE}</li>
|
||||
<li>构建地址:<a href=${BUILD_URL}>${BUILD_URL}</a></li>
|
||||
<li>构建日志:<a href=${BUILD_URL}console>${BUILD_URL}console</a></li>
|
||||
<li>变更集:${JELLY_SCRIPT}</li>
|
||||
|
||||
</div>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table></font>
|
||||
</body>
|
||||
</html>''',
|
||||
</html>""",
|
||||
to: "yqliu@taosdata.com,pxiao@taosdata.com",
|
||||
from: "support@taosdata.com"
|
||||
)
|
||||
}
|
||||
failure {
|
||||
emailext (
|
||||
subject: "FAILED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'",
|
||||
body: '''<!DOCTYPE html>
|
||||
subject: "PR-result: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' FAIL",
|
||||
body: """<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
@ -285,21 +285,21 @@ pipeline {
|
|||
<td>
|
||||
<ul>
|
||||
<div style="font-size:18px">
|
||||
<li>构建名称>>分支:${PROJECT_NAME}</li>
|
||||
<li>构建结果:<span style="color:green"> Successful </span></li>
|
||||
<li>构建名称>>分支:${env.BRANCH_NAME}</li>
|
||||
<li>构建结果:<span style="color:red"> Failure </span></li>
|
||||
<li>构建编号:${BUILD_NUMBER}</li>
|
||||
<li>触发用户:${CAUSE}</li>
|
||||
<li>变更概要:${CHANGES}</li>
|
||||
<li>触发用户:${env.CHANGE_AUTHOR}</li>
|
||||
<li>提交信息:${env.CHANGE_TITLE}</li>
|
||||
<li>构建地址:<a href=${BUILD_URL}>${BUILD_URL}</a></li>
|
||||
<li>构建日志:<a href=${BUILD_URL}console>${BUILD_URL}console</a></li>
|
||||
<li>变更集:${JELLY_SCRIPT}</li>
|
||||
|
||||
</div>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table></font>
|
||||
</body>
|
||||
</html>''',
|
||||
</html>""",
|
||||
to: "yqliu@taosdata.com,pxiao@taosdata.com",
|
||||
from: "support@taosdata.com"
|
||||
)
|
||||
|
|
|
@ -31,7 +31,11 @@ namespace TDengineDriver
|
|||
TSDB_DATA_TYPE_DOUBLE = 7, // 8 bytes
|
||||
TSDB_DATA_TYPE_BINARY = 8, // string
|
||||
TSDB_DATA_TYPE_TIMESTAMP = 9,// 8 bytes
|
||||
TSDB_DATA_TYPE_NCHAR = 10 // unicode string
|
||||
TSDB_DATA_TYPE_NCHAR = 10, // unicode string
|
||||
TSDB_DATA_TYPE_UTINYINT = 11,// 1 byte
|
||||
TSDB_DATA_TYPE_USMALLINT= 12,// 2 bytes
|
||||
TSDB_DATA_TYPE_UINT = 13, // 4 bytes
|
||||
TSDB_DATA_TYPE_UBIGINT= 14 // 8 bytes
|
||||
}
|
||||
|
||||
enum TDengineInitOption
|
||||
|
@ -53,15 +57,23 @@ namespace TDengineDriver
|
|||
switch ((TDengineDataType)type)
|
||||
{
|
||||
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
|
||||
return "BOOLEAN";
|
||||
return "BOOL";
|
||||
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
|
||||
return "BYTE";
|
||||
return "TINYINT";
|
||||
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
|
||||
return "SHORT";
|
||||
return "SMALLINT";
|
||||
case TDengineDataType.TSDB_DATA_TYPE_INT:
|
||||
return "INT";
|
||||
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
|
||||
return "LONG";
|
||||
return "BIGINT";
|
||||
case TDengineDataType.TSDB_DATA_TYPE_UTINYINT:
|
||||
return "TINYINT UNSIGNED";
|
||||
case TDengineDataType.TSDB_DATA_TYPE_USMALLINT:
|
||||
return "SMALLINT UNSIGNED";
|
||||
case TDengineDataType.TSDB_DATA_TYPE_UINT:
|
||||
return "INT UNSIGNED";
|
||||
case TDengineDataType.TSDB_DATA_TYPE_UBIGINT:
|
||||
return "BIGINT UNSIGNED";
|
||||
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
|
||||
return "FLOAT";
|
||||
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace TDengineDriver
|
|||
static void HelpPrint(string arg, string desc)
|
||||
{
|
||||
string indent = " ";
|
||||
Console.WriteLine("{0}{1}", indent, arg.PadRight(25)+desc);
|
||||
Console.WriteLine("{0}{1}", indent, arg.PadRight(25) + desc);
|
||||
}
|
||||
|
||||
static void PrintHelp(String[] argv)
|
||||
|
@ -142,33 +142,33 @@ namespace TDengineDriver
|
|||
verbose = this.GetArgumentAsFlag(argv, "-v", true);
|
||||
debug = this.GetArgumentAsFlag(argv, "-g", true);
|
||||
|
||||
VerbosePrint ("###################################################################\n");
|
||||
VerbosePrintFormat ("# Server IP: {0}\n", host);
|
||||
VerbosePrintFormat ("# User: {0}\n", user);
|
||||
VerbosePrintFormat ("# Password: {0}\n", password);
|
||||
VerbosePrintFormat ("# Number of Columns per record: {0}\n", colsPerRecord);
|
||||
VerbosePrintFormat ("# Number of Threads: {0}\n", numOfThreads);
|
||||
VerbosePrintFormat ("# Number of Tables: {0}\n", numOfTables);
|
||||
VerbosePrintFormat ("# Number of records per Table: {0}\n", recordsPerTable);
|
||||
VerbosePrintFormat ("# Records/Request: {0}\n", recordsPerRequest);
|
||||
VerbosePrintFormat ("# Database name: {0}\n", dbName);
|
||||
VerbosePrintFormat ("# Replica: {0}\n", replica);
|
||||
VerbosePrintFormat ("# Use STable: {0}\n", useStable);
|
||||
VerbosePrintFormat ("# Table prefix: {0}\n", tablePrefix);
|
||||
VerbosePrint("###################################################################\n");
|
||||
VerbosePrintFormat("# Server IP: {0}\n", host);
|
||||
VerbosePrintFormat("# User: {0}\n", user);
|
||||
VerbosePrintFormat("# Password: {0}\n", password);
|
||||
VerbosePrintFormat("# Number of Columns per record: {0}\n", colsPerRecord);
|
||||
VerbosePrintFormat("# Number of Threads: {0}\n", numOfThreads);
|
||||
VerbosePrintFormat("# Number of Tables: {0}\n", numOfTables);
|
||||
VerbosePrintFormat("# Number of records per Table: {0}\n", recordsPerTable);
|
||||
VerbosePrintFormat("# Records/Request: {0}\n", recordsPerRequest);
|
||||
VerbosePrintFormat("# Database name: {0}\n", dbName);
|
||||
VerbosePrintFormat("# Replica: {0}\n", replica);
|
||||
VerbosePrintFormat("# Use STable: {0}\n", useStable);
|
||||
VerbosePrintFormat("# Table prefix: {0}\n", tablePrefix);
|
||||
if (useStable == true)
|
||||
{
|
||||
VerbosePrintFormat("# STable prefix: {0}\n", stablePrefix);
|
||||
}
|
||||
VerbosePrintFormat ("# Data order: {0}\n", order);
|
||||
VerbosePrintFormat ("# Data out of order rate: {0}\n", rateOfOutorder);
|
||||
VerbosePrintFormat ("# Delete method: {0}\n", methodOfDelete);
|
||||
VerbosePrintFormat ("# Query command: {0}\n", query);
|
||||
VerbosePrintFormat ("# Query Mode: {0}\n", queryMode);
|
||||
VerbosePrintFormat ("# Insert Only: {0}\n", isInsertOnly);
|
||||
VerbosePrintFormat ("# Verbose output {0}\n", verbose);
|
||||
VerbosePrintFormat ("# Test time: {0}\n", DateTime.Now.ToString("h:mm:ss tt"));
|
||||
VerbosePrintFormat("# Data order: {0}\n", order);
|
||||
VerbosePrintFormat("# Data out of order rate: {0}\n", rateOfOutorder);
|
||||
VerbosePrintFormat("# Delete method: {0}\n", methodOfDelete);
|
||||
VerbosePrintFormat("# Query command: {0}\n", query);
|
||||
VerbosePrintFormat("# Query Mode: {0}\n", queryMode);
|
||||
VerbosePrintFormat("# Insert Only: {0}\n", isInsertOnly);
|
||||
VerbosePrintFormat("# Verbose output {0}\n", verbose);
|
||||
VerbosePrintFormat("# Test time: {0}\n", DateTime.Now.ToString("h:mm:ss tt"));
|
||||
|
||||
VerbosePrint ("###################################################################\n");
|
||||
VerbosePrint("###################################################################\n");
|
||||
|
||||
if (skipReadKey == false)
|
||||
{
|
||||
|
@ -385,7 +385,7 @@ namespace TDengineDriver
|
|||
public void CreateDb()
|
||||
{
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.Append("CREATE DATABASE IF NOT EXISTS ").Append(this.dbName).Append(" replica ").Append(this.replica);
|
||||
sql.Append("CREATE DATABASE IF NOT EXISTS ").Append(this.dbName).Append(" replica ").Append(this.replica).Append(" keep 36500");
|
||||
IntPtr res = TDengine.Query(this.conn, sql.ToString());
|
||||
if (res != IntPtr.Zero)
|
||||
{
|
||||
|
@ -406,7 +406,7 @@ namespace TDengineDriver
|
|||
sql.Clear();
|
||||
sql.Append("CREATE TABLE IF NOT EXISTS ").
|
||||
Append(this.dbName).Append(".").Append(this.stablePrefix).
|
||||
Append("(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 float, v7 double, v8 binary(10), v9 nchar(10)) tags(t1 int)");
|
||||
Append("(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 float, v7 double, v8 binary(10), v9 nchar(10), v10 tinyint unsigned, v11 smallint unsigned, v12 int unsigned, v13 bigint unsigned) tags(t1 int)");
|
||||
IntPtr res = TDengine.Query(this.conn, sql.ToString());
|
||||
if (res != IntPtr.Zero)
|
||||
{
|
||||
|
@ -523,7 +523,7 @@ namespace TDengineDriver
|
|||
int offset = IntPtr.Size * fields;
|
||||
IntPtr data = Marshal.ReadIntPtr(rowdata, offset);
|
||||
|
||||
builder.Append("---");
|
||||
builder.Append(" | ");
|
||||
|
||||
if (data == IntPtr.Zero)
|
||||
{
|
||||
|
@ -538,7 +538,7 @@ namespace TDengineDriver
|
|||
builder.Append(v1);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
|
||||
byte v2 = Marshal.ReadByte(data);
|
||||
sbyte v2 = (sbyte)Marshal.ReadByte(data);
|
||||
builder.Append(v2);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
|
||||
|
@ -573,9 +573,25 @@ namespace TDengineDriver
|
|||
string v10 = Marshal.PtrToStringAnsi(data);
|
||||
builder.Append(v10);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_UTINYINT:
|
||||
byte v11 = Marshal.ReadByte(data);
|
||||
builder.Append(v11);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_USMALLINT:
|
||||
ushort v12 = (ushort)Marshal.ReadInt16(data);
|
||||
builder.Append(v12);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_UINT:
|
||||
uint v13 = (uint)Marshal.ReadInt32(data);
|
||||
builder.Append(v13);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_UBIGINT:
|
||||
ulong v14 = (ulong)Marshal.ReadInt64(data);
|
||||
builder.Append(v14);
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.Append("---");
|
||||
builder.Append(" | ");
|
||||
|
||||
VerbosePrint(builder.ToString() + "\n");
|
||||
builder.Clear();
|
||||
|
@ -642,8 +658,8 @@ namespace TDengineDriver
|
|||
tester.ExecuteQuery();
|
||||
watch.Stop();
|
||||
elapsedMs = watch.Elapsed.TotalMilliseconds;
|
||||
Console.WriteLine("C# taosdemo: Spent {0} seconds to query {1} records.\n",
|
||||
elapsedMs/1000,
|
||||
Console.WriteLine("C# taosdemo: Spent {0} seconds to query {1} records.\n",
|
||||
elapsedMs / 1000,
|
||||
tester.recordsPerTable * tester.numOfTables
|
||||
);
|
||||
}
|
||||
|
@ -712,9 +728,9 @@ namespace TDengineDriver
|
|||
int m = now.Minute;
|
||||
int s = now.Second;
|
||||
|
||||
long baseTimestamp = 1609430400000; // 2021/01/01 0:0:0
|
||||
long baseTimestamp = -16094340000; // 1969-06-29 01:21:00
|
||||
VerbosePrintFormat("beginTime is {0} + {1}h:{2}m:{3}s\n", baseTimestamp, h, m, s);
|
||||
long beginTimestamp = baseTimestamp + ((h*60 + m) * 60 + s) * 1000;
|
||||
long beginTimestamp = baseTimestamp + ((h * 60 + m) * 60 + s) * 1000;
|
||||
Random random = new Random();
|
||||
|
||||
long rowsInserted = 0;
|
||||
|
@ -755,11 +771,16 @@ namespace TDengineDriver
|
|||
|
||||
sql.Append("(")
|
||||
.Append(writeTimeStamp)
|
||||
.Append(", 1, 2, 3,")
|
||||
.Append(i + batch)
|
||||
.Append(", 5, 6, 7, 'abc', 'def')");
|
||||
.Append(", 1, -2, -3,")
|
||||
.Append(i + batch - 127)
|
||||
.Append(", -5, -6, -7, 'abc', 'def', 254, 65534,")
|
||||
.Append(4294967294 - (uint)i - (uint)batch)
|
||||
.Append(",")
|
||||
.Append(18446744073709551614 - (ulong)i - (ulong)batch)
|
||||
.Append(")");
|
||||
|
||||
}
|
||||
VerbosePrint(sql.ToString() + "\n");
|
||||
IntPtr res = TDengine.Query(this.conn, sql.ToString());
|
||||
if (res == IntPtr.Zero)
|
||||
{
|
||||
|
@ -837,7 +858,7 @@ namespace TDengineDriver
|
|||
}
|
||||
else
|
||||
{
|
||||
sql = sql.Append("(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 float, v7 double, v8 binary(10), v9 nchar(10))");
|
||||
sql = sql.Append("(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 float, v7 double, v8 binary(10), v9 nchar(10), v10 tinyint unsigned, v11 smallint unsigned, v12 int unsigned, v13 bigint unsigned)");
|
||||
}
|
||||
IntPtr res = TDengine.Query(this.conn, sql.ToString());
|
||||
if (res != IntPtr.Zero)
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
"insert_mode": "taosc",
|
||||
"insert_rate": 0,
|
||||
"insert_rows": 100,
|
||||
"multi_thread_write_one_tbl": "no",
|
||||
"number_of_tbl_in_one_sql": 0,
|
||||
"interlace_rows": 3,
|
||||
"max_sql_len": 1024,
|
||||
"disorder_ratio": 0,
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
|
||||
int points = 5;
|
||||
int numOfTables = 3;
|
||||
int tablesProcessed = 0;
|
||||
int tablesInsertProcessed = 0;
|
||||
int tablesSelectProcessed = 0;
|
||||
int64_t st, et;
|
||||
|
||||
typedef struct {
|
||||
|
@ -134,6 +135,9 @@ int main(int argc, char *argv[])
|
|||
gettimeofday(&systemTime, NULL);
|
||||
st = systemTime.tv_sec * 1000000 + systemTime.tv_usec;
|
||||
|
||||
tablesInsertProcessed = 0;
|
||||
tablesSelectProcessed = 0;
|
||||
|
||||
for (i = 0; i<numOfTables; ++i) {
|
||||
// insert records in asynchronous API
|
||||
sprintf(sql, "insert into %s values(%ld, 0)", tableList[i].name, 1546300800000 + i);
|
||||
|
@ -143,10 +147,20 @@ int main(int argc, char *argv[])
|
|||
printf("once insert finished, presse any key to query\n");
|
||||
getchar();
|
||||
|
||||
while(1) {
|
||||
if (tablesInsertProcessed < numOfTables) {
|
||||
printf("wait for process finished\n");
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
printf("start to query...\n");
|
||||
gettimeofday(&systemTime, NULL);
|
||||
st = systemTime.tv_sec * 1000000 + systemTime.tv_usec;
|
||||
tablesProcessed = 0;
|
||||
|
||||
|
||||
for (i = 0; i < numOfTables; ++i) {
|
||||
// select records in asynchronous API
|
||||
|
@ -157,14 +171,8 @@ int main(int argc, char *argv[])
|
|||
printf("\nonce finished, press any key to exit\n");
|
||||
getchar();
|
||||
|
||||
for (i = 0; i<numOfTables; ++i) {
|
||||
printf("%s inserted:%d retrieved:%d\n", tableList[i].name, tableList[i].rowsInserted, tableList[i].rowsRetrieved);
|
||||
}
|
||||
|
||||
getchar();
|
||||
|
||||
while(1) {
|
||||
if (tablesProcessed < numOfTables) {
|
||||
if (tablesSelectProcessed < numOfTables) {
|
||||
printf("wait for process finished\n");
|
||||
sleep(1);
|
||||
continue;
|
||||
|
@ -173,6 +181,10 @@ int main(int argc, char *argv[])
|
|||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i<numOfTables; ++i) {
|
||||
printf("%s inserted:%d retrieved:%d\n", tableList[i].name, tableList[i].rowsInserted, tableList[i].rowsRetrieved);
|
||||
}
|
||||
|
||||
taos_close(taos);
|
||||
free(tableList);
|
||||
|
||||
|
@ -214,8 +226,8 @@ void taos_insert_call_back(void *param, TAOS_RES *tres, int code)
|
|||
}
|
||||
else {
|
||||
printf("%d rows data are inserted into %s\n", points, pTable->name);
|
||||
tablesProcessed++;
|
||||
if (tablesProcessed >= numOfTables) {
|
||||
tablesInsertProcessed++;
|
||||
if (tablesInsertProcessed >= numOfTables) {
|
||||
gettimeofday(&systemTime, NULL);
|
||||
et = systemTime.tv_sec * 1000000 + systemTime.tv_usec;
|
||||
printf("%lld mseconds to insert %d data points\n", (et - st) / 1000, points*numOfTables);
|
||||
|
@ -251,15 +263,17 @@ void taos_retrieve_call_back(void *param, TAOS_RES *tres, int numOfRows)
|
|||
//taos_free_result(tres);
|
||||
printf("%d rows data retrieved from %s\n", pTable->rowsRetrieved, pTable->name);
|
||||
|
||||
tablesProcessed++;
|
||||
if (tablesProcessed >= numOfTables) {
|
||||
tablesSelectProcessed++;
|
||||
if (tablesSelectProcessed >= numOfTables) {
|
||||
gettimeofday(&systemTime, NULL);
|
||||
et = systemTime.tv_sec * 1000000 + systemTime.tv_usec;
|
||||
printf("%lld mseconds to query %d data rows\n", (et - st) / 1000, points * numOfTables);
|
||||
}
|
||||
|
||||
taos_free_result(tres);
|
||||
}
|
||||
|
||||
taos_free_result(tres);
|
||||
|
||||
}
|
||||
|
||||
void taos_select_call_back(void *param, TAOS_RES *tres, int code)
|
||||
|
@ -276,6 +290,4 @@ void taos_select_call_back(void *param, TAOS_RES *tres, int code)
|
|||
taos_cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
taos_free_result(tres);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ int main(int argc, char *argv[]) {
|
|||
printf("failed to connect to server, reason:%s\n", "null taos"/*taos_errstr(taos)*/);
|
||||
exit(1);
|
||||
}
|
||||
for (int i = 0; i < 4000000; i++) {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
Test(taos, qstr, i);
|
||||
}
|
||||
taos_close(taos);
|
||||
|
|
|
@ -19,6 +19,10 @@ Run lua sample:
|
|||
lua test.lua
|
||||
```
|
||||
|
||||
## Run performance test:
|
||||
```
|
||||
time lua benchmark.lua
|
||||
```
|
||||
## OpenResty Dependencies
|
||||
- OpenResty:
|
||||
```
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
local driver = require "luaconnector"
|
||||
|
||||
local config = {
|
||||
password = "taosdata",
|
||||
host = "127.0.0.1",
|
||||
port = 6030,
|
||||
database = "",
|
||||
user = "root",
|
||||
|
||||
max_packet_size = 1024 * 1024
|
||||
}
|
||||
|
||||
local conn
|
||||
local res = driver.connect(config)
|
||||
if res.code ~=0 then
|
||||
print("connect--- failed: "..res.error)
|
||||
return
|
||||
else
|
||||
conn = res.conn
|
||||
print("connect--- pass.")
|
||||
end
|
||||
|
||||
local res = driver.query(conn,"drop database if exists demo")
|
||||
|
||||
res = driver.query(conn,"create database demo")
|
||||
if res.code ~=0 then
|
||||
print("create db--- failed: "..res.error)
|
||||
return
|
||||
else
|
||||
print("create db--- pass.")
|
||||
end
|
||||
|
||||
res = driver.query(conn,"use demo")
|
||||
if res.code ~=0 then
|
||||
print("select db--- failed: "..res.error)
|
||||
return
|
||||
else
|
||||
print("select db--- pass.")
|
||||
end
|
||||
|
||||
res = driver.query(conn,"create table m1 (ts timestamp, speed int,owner binary(20))")
|
||||
if res.code ~=0 then
|
||||
print("create table---failed: "..res.error)
|
||||
return
|
||||
else
|
||||
print("create table--- pass.")
|
||||
end
|
||||
|
||||
local base = 1617330000000
|
||||
local index =0
|
||||
local count = 100000
|
||||
local t
|
||||
while( index < count )
|
||||
do
|
||||
t = base + index
|
||||
local q=string.format([[insert into m1 values (%d,0,'robotspace')]],t)
|
||||
res = driver.query(conn,q)
|
||||
if res.code ~=0 then
|
||||
print("insert records failed: "..res.error)
|
||||
return
|
||||
else
|
||||
|
||||
end
|
||||
index = index+1
|
||||
end
|
||||
print(string.format([["Done. %d records has been stored."]],count))
|
||||
driver.close(conn)
|
|
@ -1,2 +1,2 @@
|
|||
gcc lua_connector.c -fPIC -shared -o luaconnector.so -Wall -ltaos
|
||||
gcc -std=c99 lua_connector.c -fPIC -shared -o luaconnector.so -Wall -ltaos
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
gcc lua_connector51.c -fPIC -shared -o luaconnector51.so -Wall -ltaos
|
||||
gcc -std=c99 lua_connector51.c -fPIC -shared -o luaconnector51.so -Wall -ltaos
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ static int l_connect(lua_State *L){
|
|||
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
||||
lua_getfield(L,-1,"host");
|
||||
lua_getfield(L,1,"host");
|
||||
if (lua_isstring(L,-1)){
|
||||
host = lua_tostring(L, -1);
|
||||
// printf("host = %s\n", host);
|
||||
|
|
|
@ -40,8 +40,8 @@ function buildTDengine {
|
|||
|
||||
git remote update > /dev/null
|
||||
git reset --hard HEAD
|
||||
git checkout develop
|
||||
REMOTE_COMMIT=`git rev-parse --short remotes/origin/develop`
|
||||
git checkout master
|
||||
REMOTE_COMMIT=`git rev-parse --short remotes/origin/master`
|
||||
LOCAL_COMMIT=`git rev-parse --short @`
|
||||
|
||||
echo " LOCAL: $LOCAL_COMMIT"
|
||||
|
@ -73,6 +73,9 @@ function runQueryPerfTest {
|
|||
python3 insert/insertFromCSVPerformance.py -c $LOCAL_COMMIT | tee -a $PERFORMANCE_TEST_REPORT
|
||||
|
||||
python3 tools/taosdemoPerformance.py -c $LOCAL_COMMIT | tee -a $PERFORMANCE_TEST_REPORT
|
||||
|
||||
python3 perfbenchmark/joinPerformance.py | tee -a $PERFORMANCE_TEST_REPORT
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
"insert_mode": "taosc",
|
||||
"insert_rate": 0,
|
||||
"insert_rows": 100000,
|
||||
"multi_thread_write_one_tbl": "no",
|
||||
"number_of_tbl_in_one_sql": 1,
|
||||
"interlace_rows": 100,
|
||||
"max_sql_len": 1024000,
|
||||
"disorder_ratio": 0,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue