diff --git a/.travis.yml b/.travis.yml
index d814a465e67468fc05c2d03b62c092a9c5130e22..0617d759768251fcf09aa2316f3556f20c1718d8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -171,6 +171,8 @@ matrix:
- build-essential
- cmake
- binutils-2.26
+ - unixodbc
+ - unixodbc-dev
env:
- DESC="trusty/gcc-4.8/bintuils-2.26 build"
@@ -198,6 +200,8 @@ matrix:
packages:
- build-essential
- cmake
+ - unixodbc
+ - unixodbc-dev
before_script:
- export TZ=Asia/Harbin
@@ -252,6 +256,8 @@ matrix:
packages:
- build-essential
- cmake
+ - unixodbc
+ - unixodbc-dev
env:
- DESC="arm64 xenial build"
@@ -280,6 +286,7 @@ matrix:
addons:
homebrew:
- cmake
+ - unixodbc
script:
- cd ${TRAVIS_BUILD_DIR}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7bb36fe1b001473cf5641ad195959581affeb2cb..e0d6e82923ce66abccefda6ee685ec98d6450d2e 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,6 +16,8 @@ SET(TD_GRANT FALSE)
SET(TD_MQTT FALSE)
SET(TD_TSDB_PLUGINS FALSE)
SET(TD_STORAGE FALSE)
+SET(TD_TOPIC FALSE)
+SET(TD_MODULE FALSE)
SET(TD_COVER FALSE)
SET(TD_MEM_CHECK FALSE)
diff --git a/Jenkinsfile b/Jenkinsfile
index 8d2429c137414fdb63260f94c0c99a6d264d8c48..daae5a5ad09f24a980bdcea5f5551b53a24c02aa 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -6,6 +6,7 @@ node {
}
def skipstage=0
+
def abortPreviousBuilds() {
def currentJobName = env.JOB_NAME
def currentBuildNumber = env.BUILD_NUMBER.toInteger()
@@ -24,7 +25,7 @@ def abortPreviousBuilds() {
build.doKill() //doTerm(),doKill(),doTerm()
}
}
-//abort previous build
+// abort previous build
abortPreviousBuilds()
def abort_previous(){
def buildNumber = env.BUILD_NUMBER as int
@@ -32,24 +33,25 @@ def abort_previous(){
milestone(buildNumber)
}
def pre_test(){
- catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
- sh '''
- sudo rmtaos
- '''
- }
- sh '''
+
+ sh '''
+ sudo rmtaos || echo "taosd has not installed"
+ '''
+ sh '''
+ killall -9 taosd ||echo "no taosd running"
+ killall -9 gdb || echo "no gdb running"
cd ${WKC}
git checkout develop
git reset --hard HEAD~10 >/dev/null
- git pull
+ git pull >/dev/null
git fetch origin +refs/pull/${CHANGE_ID}/merge
git checkout -qf FETCH_HEAD
- git --no-pager diff --name-only FETCH_HEAD $(git merge-base FETCH_HEAD develop)|grep -v -E '.*md|//src//connector|Jenkinsfile' || exit 0
+ find ${WKC}/tests/pytest -name \'*\'.sql -exec rm -rf {} \\;
cd ${WK}
git reset --hard HEAD~10
- git checkout develop
- git pull
+ git checkout develop
+ git pull >/dev/null
cd ${WK}
export TZ=Asia/Harbin
date
@@ -79,6 +81,10 @@ pipeline {
changeRequest()
}
steps {
+ script{
+ abort_previous()
+ abortPreviousBuilds()
+ }
sh'''
cp -r ${WORKSPACE} ${WORKSPACE}.tes
cd ${WORKSPACE}.tes
@@ -115,7 +121,6 @@ pipeline {
sh '''
date
cd ${WKC}/tests
- find pytest -name '*'sql|xargs rm -rf
./test-all.sh p1
date'''
}
@@ -131,7 +136,6 @@ pipeline {
sh '''
date
cd ${WKC}/tests
- find pytest -name '*'sql|xargs rm -rf
./test-all.sh p2
date'''
}
diff --git a/README-CN.md b/README-CN.md
new file mode 100644
index 0000000000000000000000000000000000000000..d4c10e71d684ab5d21c1c767c398707956946232
--- /dev/null
+++ b/README-CN.md
@@ -0,0 +1,273 @@
+[](https://travis-ci.org/taosdata/TDengine)
+[](https://ci.appveyor.com/project/sangshuduo/tdengine-2n8ge/branch/master)
+[](https://coveralls.io/github/taosdata/TDengine?branch=develop)
+[](https://bestpractices.coreinfrastructure.org/projects/4201)
+[](https://snapcraft.io/tdengine)
+
+[](https://www.taosdata.com)
+
+简体中文 | [English](./README.md)
+
+# TDengine 简介
+
+TDengine是涛思数据专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的复杂度,且核心代码,包括集群功能全部开源(开源协议,AGPL v3.0)。
+
+- 10 倍以上性能提升。定义了创新的数据存储结构,单核每秒就能处理至少2万次请求,插入数百万个数据点,读出一千万以上数据点,比现有通用数据库快了十倍以上。
+- 硬件或云服务成本降至1/5。由于超强性能,计算资源不到通用大数据方案的1/5;通过列式存储和先进的压缩算法,存储空间不到通用数据库的1/10。
+- 全栈时序数据处理引擎。将数据库、消息队列、缓存、流式计算等功能融合一起,应用无需再集成Kafka/Redis/HBase/Spark等软件,大幅降低应用开发和维护成本。
+- 强大的分析功能。无论是十年前还是一秒钟前的数据,指定时间范围即可查询。数据可在时间轴上或多个设备上进行聚合。即席查询可通过Shell/Python/R/Matlab随时进行。
+- 与第三方工具无缝连接。不用一行代码,即可与Telegraf, Grafana, EMQ X, Prometheus, Matlab, R集成。后续还将支持MQTT, OPC, Hadoop,Spark等, BI工具也将无缝连接。
+- 零运维成本、零学习成本。安装、集群一秒搞定,无需分库分表,实时备份。标准SQL,支持JDBC,RESTful,支持Python/Java/C/C++/Go/Node.JS, 与MySQL相似,零学习成本。
+
+# 文档
+
+TDengine是一个高效的存储、查询、分析时序大数据的平台,专为物联网、车联网、工业互联网、运维监测等优化而设计。您可以像使用关系型数据库MySQL一样来使用它,但建议您在使用前仔细阅读一遍下面的文档,特别是 [数据模型](https://www.taosdata.com/cn/documentation/architecture) 与 [数据建模](https://www.taosdata.com/cn/documentation/model)。除本文档之外,欢迎 [下载产品白皮书](https://www.taosdata.com/downloads/TDengine%20White%20Paper.pdf)。
+
+# 生成
+
+TDengine目前2.0版服务器仅能在Linux系统上安装和运行,后续会支持Windows、macOS等系统。客户端可以在Windows或Linux上安装和运行。任何OS的应用也可以选择RESTful接口连接服务器taosd。CPU支持X64/ARM64/MIPS64/Alpha64,后续会支持ARM32、RISC-V等CPU架构。用户可根据需求选择通过[源码](https://www.taosdata.com/cn/getting-started/#通过源码安装)或者[安装包](https://www.taosdata.com/cn/getting-started/#通过安装包安装)来安装。本快速指南仅适用于通过源码安装。
+
+## 安装工具
+
+### Ubuntu 16.04 及以上版本 & Debian:
+
+```bash
+sudo apt-get install -y gcc cmake build-essential git
+```
+
+### Ubuntu 14.04:
+
+```bash
+sudo apt-get install -y gcc cmake3 build-essential git binutils-2.26
+export PATH=/usr/lib/binutils-2.26/bin:$PATH
+```
+
+编译或打包 JDBC 驱动源码,需安装 Java JDK 8 或以上版本和 Apache Maven 2.7 或以上版本。
+
+安装 OpenJDK 8:
+
+```bash
+sudo apt-get install -y openjdk-8-jdk
+```
+
+安装 Apache Maven:
+
+```bash
+sudo apt-get install -y maven
+```
+
+### CentOS 7:
+
+```bash
+sudo yum install -y gcc gcc-c++ make cmake git
+```
+
+安装 OpenJDK 8:
+
+```bash
+sudo yum install -y java-1.8.0-openjdk
+```
+
+安装 Apache Maven:
+
+```bash
+sudo yum install -y maven
+```
+
+### CentOS 8 & Fedora:
+
+```bash
+sudo dnf install -y gcc gcc-c++ make cmake epel-release git
+```
+
+安装 OpenJDK 8:
+
+```bash
+sudo dnf install -y java-1.8.0-openjdk
+```
+
+安装 Apache Maven:
+
+```bash
+sudo dnf install -y maven
+```
+
+## 获取源码
+
+首先,你需要从 GitHub 克隆源码:
+
+```bash
+git clone https://github.com/taosdata/TDengine.git
+cd TDengine
+```
+
+Go 连接器和 Grafana 插件在其他独立仓库,如果安装它们的话,需要在 TDengine 目录下通过此命令安装:
+
+```bash
+git submodule update --init --recursive
+```
+
+## 生成 TDengine
+
+### Linux 系统
+
+```bash
+mkdir debug && cd debug
+cmake .. && cmake --build .
+```
+
+在X86-64、X86、arm64 和 arm32 平台上,TDengine 生成脚本可以自动检测机器架构。也可以手动配置 CPUTYPE 参数来指定 CPU 类型,如 aarch64 或 aarch32 等。
+
+aarch64:
+
+```bash
+cmake .. -DCPUTYPE=aarch64 && cmake --build .
+```
+
+aarch32:
+
+```bash
+cmake .. -DCPUTYPE=aarch32 && cmake --build .
+```
+
+### Windows 系统
+
+如果你使用的是 Visual Studio 2013 版本:
+
+打开 cmd.exe,执行 vcvarsall.bat 时,为 64 位操作系统指定“x86_amd64”,为 32 位操作系统指定“x86”。
+
+```bash
+mkdir debug && cd debug
+"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" < x86_amd64 | x86 >
+cmake .. -G "NMake Makefiles"
+nmake
+```
+
+如果你使用的是 Visual Studio 2019 或 2017 版本:
+
+打开cmd.exe,执行 vcvarsall.bat 时,为 64 位操作系统指定“x64”,为 32 位操作系统指定“x86”。
+
+```bash
+mkdir debug && cd debug
+"c:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" < x64 | x86 >
+cmake .. -G "NMake Makefiles"
+nmake
+```
+
+你也可以从开始菜单中找到"Visual Studio < 2019 | 2017 >"菜单项,根据你的系统选择"x64 Native Tools Command Prompt for VS < 2019 | 2017 >"或"x86 Native Tools Command Prompt for VS < 2019 | 2017 >",打开命令行窗口,执行:
+
+```bash
+mkdir debug && cd debug
+cmake .. -G "NMake Makefiles"
+nmake
+```
+
+### Mac OS X 系统
+
+安装 Xcode 命令行工具和 cmake. 在 Catalina 和 Big Sur 操作系统上,需要安装 XCode 11.4+ 版本。
+
+```bash
+mkdir debug && cd debug
+cmake .. && cmake --build .
+```
+
+# 安装
+
+如果你不想安装,可以直接在shell中运行。生成完成后,安装 TDengine:
+```bash
+make install
+```
+
+用户可以在[文件目录结构](https://www.taosdata.com/cn/documentation/administrator#directories)中了解更多在操作系统中生成的目录或文件。
+
+安装成功后,在终端中启动 TDengine 服务:
+
+```bash
+taosd
+```
+
+用户可以使用 TDengine Shell 来连接 TDengine 服务,在终端中,输入:
+
+```bash
+taos
+```
+
+如果 TDengine Shell 连接服务成功,将会打印出欢迎消息和版本信息。如果失败,则会打印出错误消息。
+
+## 快速运行
+
+TDengine 生成后,在终端执行以下命令:
+
+```bash
+./build/bin/taosd -c test/cfg
+```
+
+在另一个终端,使用 TDengine shell 连接服务器:
+
+```bash
+./build/bin/taos -c test/cfg
+```
+
+"-c test/cfg"指定系统配置文件所在目录。
+
+# 体验 TDengine
+
+在TDengine终端中,用户可以通过SQL命令来创建/删除数据库、表等,并进行插入查询操作。
+
+```bash
+create database demo;
+use demo;
+create table t (ts timestamp, speed int);
+insert into t values ('2019-07-15 00:00:00', 10);
+insert into t values ('2019-07-15 01:00:00', 20);
+select * from t;
+ ts | speed |
+===================================
+ 19-07-15 00:00:00.000| 10|
+ 19-07-15 01:00:00.000| 20|
+Query OK, 2 row(s) in set (0.001700s)
+```
+
+# 应用开发
+
+## 官方连接器
+
+TDengine 提供了丰富的应用程序开发接口,其中包括C/C++、Java、Python、Go、Node.js、C# 、RESTful 等,便于用户快速开发应用:
+
+- Java
+
+- C/C++
+
+- Python
+
+- Go
+
+- RESTful API
+
+- Node.js
+
+## 第三方连接器
+
+TDengine 社区生态中也有一些非常友好的第三方连接器,可以通过以下链接访问它们的源码。
+
+- [Rust Connector](https://github.com/taosdata/TDengine/tree/master/tests/examples/rust)
+- [.Net Core Connector](https://github.com/maikebing/Maikebing.EntityFrameworkCore.Taos)
+- [Lua Connector](https://github.com/taosdata/TDengine/tree/develop/tests/examples/lua)
+
+# 运行和添加测试例
+
+TDengine 的测试框架和所有测试例全部开源。
+
+点击 [这里](tests/How-To-Run-Test-And-How-To-Add-New-Test-Case.md),了解如何运行测试例和添加新的测试例。
+
+# 成为社区贡献者
+
+点击 [这里](https://www.taosdata.com/cn/contributor/),了解如何成为 TDengine 的贡献者。
+
+# 加入技术交流群
+
+TDengine 官方社群「物联网大数据群」对外开放,欢迎您加入讨论。搜索微信号 "tdengine",加小T为好友,即可入群。
+
+# [谁在使用TDengine](https://github.com/taosdata/TDengine/issues/2432)
+
+欢迎所有 TDengine 用户及贡献者在 [这里](https://github.com/taosdata/TDengine/issues/2432) 分享您在当前工作中开发/使用 TDengine 的故事。
diff --git a/README.md b/README.md
index 489b6d0a4e12db06c9f2c1274e7a87f22cf76655..45a955f458c953af3e4135430d6cce3f56017c1a 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,8 @@
[](https://www.taosdata.com)
+English | [简体中文](./README-CN.md)
+
# What is TDengine?
TDengine is an open-sourced big data platform under [GNU AGPL v3.0](http://www.gnu.org/licenses/agpl-3.0.html), designed and optimized for the Internet of Things (IoT), Connected Cars, Industrial IoT, and IT Infrastructure and Application Monitoring. Besides the 10x faster time-series database, it provides caching, stream computing, message queuing and other functionalities to reduce the complexity and cost of development and operation.
@@ -29,7 +31,7 @@ For user manual, system design and architecture, engineering blogs, refer to [TD
# Building
At the moment, TDengine only supports building and running on Linux systems. You can choose to [install from packages](https://www.taosdata.com/en/getting-started/#Install-from-Package) or from the source code. This quick guide is for installation from the source only.
-To build TDengine, use [CMake](https://cmake.org/) 3.5 or higher versions in the project directory.
+To build TDengine, use [CMake](https://cmake.org/) 2.8.12.x or higher versions in the project directory.
## Install tools
@@ -160,39 +162,42 @@ mkdir debug && cd debug
cmake .. && cmake --build .
```
-# Quick Run
-
-# Quick Run
-To quickly start a TDengine server after building, run the command below in terminal:
-```bash
-./build/bin/taosd -c test/cfg
-```
-In another terminal, use the TDengine shell to connect the server:
-```bash
-./build/bin/taos -c test/cfg
-```
-option "-c test/cfg" specifies the system configuration file directory.
-
# Installing
+
After building successfully, TDengine can be installed by:
```bash
-make install
+sudo make install
```
-Users can find more information about directories installed on the system in the [directory and files](https://www.taosdata.com/en/documentation/administrator/#Directory-and-Files) section. It should be noted that installing from source code does not configure service management for TDengine.
+
+Users can find more information about directories installed on the system in the [directory and files](https://www.taosdata.com/en/documentation/administrator/#Directory-and-Files) section. Since version 2.0, installing from source code will also configure service management for TDengine.
Users can also choose to [install from packages](https://www.taosdata.com/en/getting-started/#Install-from-Package) for it.
To start the service after installation, in a terminal, use:
-```cmd
-taosd
+```bash
+sudo systemctl start taosd
```
Then users can use the [TDengine shell](https://www.taosdata.com/en/getting-started/#TDengine-Shell) to connect the TDengine server. In a terminal, use:
-```cmd
+```bash
taos
```
If TDengine shell connects the server successfully, welcome messages and version info are printed. Otherwise, an error message is shown.
+## Quick Run
+
+If you don't want to run TDengine as a service, you can run it in current shell. For example, to quickly start a TDengine server after building, run the command below in terminal:
+```bash
+./build/bin/taosd -c test/cfg
+```
+
+In another terminal, use the TDengine shell to connect the server:
+```bash
+./build/bin/taos -c test/cfg
+```
+
+option "-c test/cfg" specifies the system configuration file directory.
+
# Try TDengine
It is easy to run SQL commands from TDengine shell which is the same as other SQL databases.
```sql
@@ -245,3 +250,6 @@ Please follow the [contribution guidelines](CONTRIBUTING.md) to contribute to th
Add WeChat “tdengine” to join the group,you can communicate with other users.
+# [User List](https://github.com/taosdata/TDengine/issues/2432)
+
+If you are using TDengine and feel it helps or you'd like to do some contributions, please add your company to [user list](https://github.com/taosdata/TDengine/issues/2432) and let us know your needs.
diff --git a/cmake/define.inc b/cmake/define.inc
index ae90410f2d6873b60ee0e355f18462983e615545..6f49630d5c25d0f1519f3e6c606fe28a026add2d 100755
--- a/cmake/define.inc
+++ b/cmake/define.inc
@@ -25,6 +25,14 @@ IF (TD_STORAGE)
ADD_DEFINITIONS(-D_STORAGE)
ENDIF ()
+IF (TD_TOPIC)
+ ADD_DEFINITIONS(-D_TOPIC)
+ENDIF ()
+
+IF (TD_MODULE)
+ ADD_DEFINITIONS(-D_MODULE)
+ENDIF ()
+
IF (TD_GODLL)
ADD_DEFINITIONS(-D_TD_GO_DLL_)
ENDIF ()
diff --git a/cmake/input.inc b/cmake/input.inc
index e8324887a051ae6ac27eff6b748c824d1f0a3fa5..00e0e1bc0f00fd8ba8e679f93d5f75e1b75e6bcd 100755
--- a/cmake/input.inc
+++ b/cmake/input.inc
@@ -9,6 +9,22 @@ ELSEIF (${ACCOUNT} MATCHES "false")
MESSAGE(STATUS "Build without account plugins")
ENDIF ()
+IF (${TOPIC} MATCHES "true")
+ SET(TD_TOPIC TRUE)
+ MESSAGE(STATUS "Build with topic plugins")
+ELSEIF (${TOPIC} MATCHES "false")
+ SET(TD_TOPIC FALSE)
+ MESSAGE(STATUS "Build without topic plugins")
+ENDIF ()
+
+IF (${TD_MODULE} MATCHES "true")
+ SET(TD_MODULE TRUE)
+ MESSAGE(STATUS "Build with module plugins")
+ELSEIF (${TOPIC} MATCHES "false")
+ SET(TD_MODULE FALSE)
+ MESSAGE(STATUS "Build without module plugins")
+ENDIF ()
+
IF (${COVER} MATCHES "true")
SET(TD_COVER TRUE)
MESSAGE(STATUS "Build with test coverage")
diff --git a/cmake/install.inc b/cmake/install.inc
index 0ea79589caef1bf3ec72f4234f99e87328759c33..1d50ca292d902461e0f77732da83076954224f06 100755
--- a/cmake/install.inc
+++ b/cmake/install.inc
@@ -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.21-dist.jar DESTINATION connector/jdbc)
+ INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.22-dist.jar DESTINATION connector/jdbc)
ENDIF ()
ELSEIF (TD_DARWIN)
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
diff --git a/cmake/version.inc b/cmake/version.inc
index 05fbef5b87a85168f43f3445acc3e5567c92fbd9..b1e09c9532ef8193b32c99180d35946cc6ef5c7e 100755
--- a/cmake/version.inc
+++ b/cmake/version.inc
@@ -4,7 +4,7 @@ PROJECT(TDengine)
IF (DEFINED VERNUMBER)
SET(TD_VER_NUMBER ${VERNUMBER})
ELSE ()
- SET(TD_VER_NUMBER "2.0.17.0")
+ SET(TD_VER_NUMBER "2.0.18.0")
ENDIF ()
IF (DEFINED VERCOMPATIBLE)
diff --git a/documentation20/cn/00.index/docs.md b/documentation20/cn/00.index/docs.md
index c16673cba59d42ab00aa2975cfa2341ede9e5fbb..aba10a14e327ff104eb997b1ad6af29e3de6cad1 100644
--- a/documentation20/cn/00.index/docs.md
+++ b/documentation20/cn/00.index/docs.md
@@ -120,7 +120,7 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专
* [TDengine性能对比测试工具](https://www.taosdata.com/blog/2020/01/18/1166.html)
* [IDEA数据库管理工具可视化使用TDengine](https://www.taosdata.com/blog/2020/08/27/1767.html)
* [基于eletron开发的跨平台TDengine图形化管理工具](https://github.com/skye0207/TDengineGUI)
-* [DataX,支持TDengine的离线数据采集/同步工具](https://github.com/alibaba/DataX)
+* [DataX,支持TDengine的离线数据采集/同步工具](https://github.com/wgzhao/DataX)(文档:[读取插件](https://github.com/wgzhao/DataX/blob/master/docs/src/main/sphinx/reader/tdenginereader.md)、[写入插件](https://github.com/wgzhao/DataX/blob/master/docs/src/main/sphinx/writer/tdenginewriter.md))
## TDengine与其他数据库的对比测试
diff --git a/documentation20/cn/03.architecture/docs.md b/documentation20/cn/03.architecture/docs.md
index 26d8bc55c29d283511080f420663c5fa32bf43fe..87553fa8ad9760ecdb6d1667823d336189542331 100644
--- a/documentation20/cn/03.architecture/docs.md
+++ b/documentation20/cn/03.architecture/docs.md
@@ -145,7 +145,7 @@ TDengine 建议用数据采集点的名字(如上表中的D1001)来做表名。
在TDengine的设计里,**表用来代表一个具体的数据采集点,超级表用来代表一组相同类型的数据采集点集合**。当为某个具体数据采集点创建表时,用户使用超级表的定义做模板,同时指定该具体采集点(表)的标签值。与传统的关系型数据库相比,表(一个数据采集点)是带有静态标签的,而且这些标签可以事后增加、删除、修改。**一张超级表包含有多张表,这些表具有相同的时序数据schema,但带有不同的标签值**。
-当对多个具有相同数据类型的数据采集点进行聚合操作时,TDengine将先把满足标签过滤条件的表从超级表的中查找出来,然后再扫描这些表的时序数据,进行聚合操作,这样能将需要扫描的数据集大幅减少,从而大幅提高聚合计算的性能。
+当对多个具有相同数据类型的数据采集点进行聚合操作时,TDengine会先把满足标签过滤条件的表从超级表中找出来,然后再扫描这些表的时序数据,进行聚合操作,这样需要扫描的数据集会大幅减少,从而显著提高聚合计算的性能。
## 集群与基本逻辑单元
diff --git a/documentation20/cn/08.connector/01.java/docs.md b/documentation20/cn/08.connector/01.java/docs.md
index c39f6ffb4c98e97c21369b5767eff38f0fa9fe3c..3ed7343579ef7dc9c774367a8d9b41e2dabb7561 100644
--- a/documentation20/cn/08.connector/01.java/docs.md
+++ b/documentation20/cn/08.connector/01.java/docs.md
@@ -451,7 +451,8 @@ Query OK, 1 row(s) in set (0.000141s)
| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
| -------------------- | ----------------- | -------- |
-| 2.0.12 及以上 | 2.0.8.0 及以上 | 1.8.x |
+| 2.0.22 | 2.0.18.0 及以上 | 1.8.x |
+| 2.0.12 - 2.0.21 | 2.0.8.0 - 2.0.17.0 | 1.8.x |
| 2.0.4 - 2.0.11 | 2.0.0.0 - 2.0.7.x | 1.8.x |
| 1.0.3 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
diff --git a/documentation20/cn/10.cluster/docs.md b/documentation20/cn/10.cluster/docs.md
index 7b4073a8836da7b14a50afee5c243d0916bc9270..a430ce8277b49a3dbf7062fc078a47a3d848f8d8 100644
--- a/documentation20/cn/10.cluster/docs.md
+++ b/documentation20/cn/10.cluster/docs.md
@@ -111,9 +111,10 @@ taos>
**提示:**
-- 任何已经加入集群在线的数据节点,都可以作为后续待加入节点的firstEP。
-- firstEp这个参数仅仅在该数据节点首次加入集群时有作用,加入集群后,该数据节点会保存最新的mnode的End Point列表,不再依赖这个参数。
-- 两个没有配置firstEp参数的数据节点dnode启动后,会独立运行起来。这个时候,无法将其中一个数据节点加入到另外一个数据节点,形成集群。**无法将两个独立的集群合并成为新的集群**。
+- 任何已经加入集群在线的数据节点,都可以作为后续待加入节点的 firstEP。
+- firstEp 这个参数仅仅在该数据节点首次加入集群时有作用,加入集群后,该数据节点会保存最新的 mnode 的 End Point 列表,不再依赖这个参数。
+ - 接下来,配置文件中的 firstEp 参数就主要在客户端连接的时候使用了,例如 taos shell 如果不加参数,会默认连接由 firstEp 指定的节点。
+- 两个没有配置 firstEp 参数的数据节点 dnode 启动后,会独立运行起来。这个时候,无法将其中一个数据节点加入到另外一个数据节点,形成集群。**无法将两个独立的集群合并成为新的集群**。
## 数据节点管理
diff --git a/documentation20/cn/11.administrator/docs.md b/documentation20/cn/11.administrator/docs.md
index 52a0da6551a332b9b578d3830d1bb8135eb30692..c2c2927387449290dc892205561b59317c4ecf67 100644
--- a/documentation20/cn/11.administrator/docs.md
+++ b/documentation20/cn/11.administrator/docs.md
@@ -6,17 +6,27 @@
### 内存需求
-每个 DB 可以创建固定数目的 vgroup,默认与 CPU 核数相同,可通过 maxVgroupsPerDb 配置;vgroup 中的每个副本会是一个 vnode;每个 vnode 会占用固定大小的内存(大小与数据库的配置参数 blocks 和 cache 有关);每个 Table 会占用与标签总长度有关的内存;此外,系统会有一些固定的内存开销。因此,每个 DB 需要的系统内存可通过如下公式计算:
+每个 Database 可以创建固定数目的 vgroup,默认与 CPU 核数相同,可通过 maxVgroupsPerDb 配置;vgroup 中的每个副本会是一个 vnode;每个 vnode 会占用固定大小的内存(大小与数据库的配置参数 blocks 和 cache 有关);每个 Table 会占用与标签总长度有关的内存;此外,系统会有一些固定的内存开销。因此,每个 DB 需要的系统内存可通过如下公式计算:
```
-Memory Size = maxVgroupsPerDb * (blocks * cache + 10MB) + numOfTables * (tagSizePerTable + 0.5KB)
+Database Memory Size = maxVgroupsPerDb * (blocks * cache + 10MB) + numOfTables * (tagSizePerTable + 0.5KB)
```
-示例:假设是 4 核机器,cache 是缺省大小 16M, blocks 是缺省值 6,假设有 10 万张表,标签总长度是 256 字节,则总的内存需求为:4 \* (16 \* 6 + 10) + 100000 \* (0.25 + 0.5) / 1000 = 499M。
+示例:假设是 4 核机器,cache 是缺省大小 16M, blocks 是缺省值 6,并且一个 DB 中有 10 万张表,标签总长度是 256 字节,则这个 DB 总的内存需求为:4 \* (16 \* 6 + 10) + 100000 \* (0.25 + 0.5) / 1000 = 499M。
-实际运行的系统往往会根据数据特点的不同,将数据存放在不同的 DB 里。因此做规划时,也需要考虑。
+在实际的系统运维中,我们通常会更关心 TDengine 服务进程(taosd)会占用的内存量。
+```
+taosd 内存总量 = vnode 内存 + mnode 内存 + 查询内存
+```
+
+其中:
+1. “vnode 内存”指的是集群中所有的 Database 存储分摊到当前 taosd 节点上所占用的内存资源。可以按上文“Database Memory Size”计算公式估算每个 DB 的内存占用量进行加总,再按集群中总共的 TDengine 节点数做平均(如果设置为多副本,则还需要乘以对应的副本倍数)。
+2. “mnode 内存”指的是集群中管理节点所占用的资源。如果一个 taosd 节点上分布有 mnode 管理节点,则内存消耗还需要增加“0.2KB * 集群中数据表总数”。
+3. “查询内存”指的是服务端处理查询请求时所需要占用的内存。单条查询语句至少会占用“0.2KB * 查询涉及的数据表总数”的内存量。
+
+注意:以上内存估算方法,主要讲解了系统的“必须内存需求”,而不是“内存总数上限”。在实际运行的生产环境中,由于操作系统缓存、资源管理调度等方面的原因,内存规划应当在估算结果的基础上保留一定冗余,以维持系统状态和系统性能的稳定性。并且,生产环境通常会配置系统资源的监控工具,以便及时发现硬件资源的紧缺情况。
-如果内存充裕,可以加大 Blocks 的配置,这样更多数据将保存在内存里,提高查询速度。
+最后,如果内存充裕,可以考虑加大 Blocks 的配置,这样更多数据将保存在内存里,提高查询速度。
### CPU 需求
diff --git a/documentation20/cn/12.taos-sql/docs.md b/documentation20/cn/12.taos-sql/docs.md
index c89dbda7a02c243e62d6bd81b6c0d78b14f67d2c..b4fa2b160aa8ec04ba3a45db0fbbca17022cbd23 100644
--- a/documentation20/cn/12.taos-sql/docs.md
+++ b/documentation20/cn/12.taos-sql/docs.md
@@ -125,7 +125,7 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic
```mysql
ALTER DATABASE db_name CACHELAST 0;
```
- CACHELAST 参数控制是否在内存中缓存数据子表的 last_row。缺省值为 0,取值范围 [0, 1]。其中 0 表示不启用、1 表示启用。(从 2.0.11 版本开始支持)
+ CACHELAST 参数控制是否在内存中缓存数据子表的 last_row。缺省值为 0,取值范围 [0, 1]。其中 0 表示不启用、1 表示启用。(从 2.0.11 版本开始支持,修改后需要重启服务器生效。)
**Tips**: 以上所有参数修改后都可以用show databases来确认是否修改成功。
@@ -249,7 +249,7 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic
3) TAGS 列名不能为预留关键字;
- 4) TAGS 最多允许128个,至少1个,总长度不超过16k个字符。
+ 4) TAGS 最多允许 128 个,至少 1 个,总长度不超过 16 KB。
- **删除超级表**
@@ -331,7 +331,8 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic
```mysql
INSERT INTO tb_name VALUES (field1_value1, ...) (field1_value2, ...) ...;
```
- 向表tb_name中插入多条记录
+ 向表tb_name中插入多条记录
+ **注意**:在使用“插入多条记录”方式写入数据时,不能把第一列的时间戳取值都设为now,否则会导致语句中的多条记录使用相同的时间戳,于是就可能出现相互覆盖以致这些数据行无法全部被正确保存。
- **按指定的列插入多条记录**
```mysql
diff --git a/documentation20/cn/13.faq/docs.md b/documentation20/cn/13.faq/docs.md
index d3169d507ac69d6d40eec698edf76a69a929bda2..e2285b29e244641566661cf102c7b17616a6780a 100644
--- a/documentation20/cn/13.faq/docs.md
+++ b/documentation20/cn/13.faq/docs.md
@@ -16,13 +16,13 @@
## 1. TDengine2.0之前的版本升级到2.0及以上的版本应该注意什么?☆☆☆
-2.0版本在之前版本的基础上,进行了完全的重构,配置文件和数据文件是不兼容的。在升级之前务必进行如下操作:
+2.0版在之前版本的基础上,进行了完全的重构,配置文件和数据文件是不兼容的。在升级之前务必进行如下操作:
-1. 删除配置文件,执行 sudo rm -rf /etc/taos/taos.cfg
-2. 删除日志文件,执行 sudo rm -rf /var/log/taos/
-3. 确保数据已经不再需要的前提下,删除数据文件,执行 sudo rm -rf /var/lib/taos/
-4. 安装最新稳定版本的TDengine
-5. 如果数据需要迁移数据或者数据文件损坏,请联系涛思数据官方技术支持团队,进行协助解决
+1. 删除配置文件,执行 `sudo rm -rf /etc/taos/taos.cfg`
+2. 删除日志文件,执行 `sudo rm -rf /var/log/taos/`
+3. 确保数据已经不再需要的前提下,删除数据文件,执行 `sudo rm -rf /var/lib/taos/`
+4. 安装最新稳定版本的 TDengine
+5. 如果需要迁移数据或者数据文件损坏,请联系涛思数据官方技术支持团队,进行协助解决
## 2. Windows平台下JDBCDriver找不到动态链接库,怎么办?
diff --git a/packaging/tools/remove.sh b/packaging/tools/remove.sh
index 2f2660d44635c86df3b51d2b86e37b3399869a88..e63889aff1a6eceebfc9624576270200f6e79fa7 100755
--- a/packaging/tools/remove.sh
+++ b/packaging/tools/remove.sh
@@ -213,10 +213,10 @@ fi
if echo $osinfo | grep -qwi "ubuntu" ; then
# echo "this is ubuntu system"
- ${csudo} rm -f /var/lib/dpkg/info/tdengine* || :
+ ${csudo} dpkg --force-all -P tdengine || :
elif echo $osinfo | grep -qwi "debian" ; then
# echo "this is debian system"
- ${csudo} rm -f /var/lib/dpkg/info/tdengine* || :
+ ${csudo} dpkg --force-all -P tdengine || :
elif echo $osinfo | grep -qwi "centos" ; then
# echo "this is centos system"
${csudo} rpm -e --noscripts tdengine || :
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index c7ed621815c6f4ba5553210ccac18929fb550631..88628b4db6cfafa2a9815489313ced1345f2b600 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -1,6 +1,6 @@
name: tdengine
base: core18
-version: '2.0.17.0'
+version: '2.0.18.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.17.0
+ - usr/lib/libtaos.so.2.0.18.0
- usr/lib/libtaos.so.1
- usr/lib/libtaos.so
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b0f2cc0a48f906b40d7be5185ae5f081c2ed4418..8cc5cee3b51675b2d42ad62c442b2b030e802cbb 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -19,6 +19,6 @@ ADD_SUBDIRECTORY(tsdb)
ADD_SUBDIRECTORY(wal)
ADD_SUBDIRECTORY(cq)
ADD_SUBDIRECTORY(dnode)
-#ADD_SUBDIRECTORY(connector/odbc)
+ADD_SUBDIRECTORY(connector/odbc)
ADD_SUBDIRECTORY(connector/jdbc)
diff --git a/src/balance/src/bnMain.c b/src/balance/src/bnMain.c
index 236b22afafb9ed6ee13acfaf6b831520f2b4d2f6..3055f77e81021c4877d97147033fc34f4c525df9 100644
--- a/src/balance/src/bnMain.c
+++ b/src/balance/src/bnMain.c
@@ -425,7 +425,7 @@ static bool bnMonitorVgroups() {
while (1) {
pIter = mnodeGetNextVgroup(pIter, &pVgroup);
- if (pVgroup == NULL) break;
+ if (pVgroup == NULL || pVgroup->pDb == NULL) break;
int32_t dbReplica = pVgroup->pDb->cfg.replications;
int32_t vgReplica = pVgroup->numOfVnodes;
@@ -721,4 +721,4 @@ int32_t bnAlterDnode(struct SDnodeObj *pSrcDnode, int32_t vnodeId, int32_t dnode
mnodeDecDnodeRef(pDestDnode);
return code;
-}
\ No newline at end of file
+}
diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h
index 502d044d7540169497b682df96424ca3304f4668..3eba5d579bf05a8d6336b1a1212faa2cb920108a 100644
--- a/src/client/inc/tscUtil.h
+++ b/src/client/inc/tscUtil.h
@@ -83,6 +83,22 @@ typedef struct SJoinSupporter {
SArray* pVgroupTables;
} SJoinSupporter;
+
+typedef struct SMergeCtx {
+ SJoinSupporter* p;
+ int32_t idx;
+ SArray* res;
+ int8_t compared;
+}SMergeCtx;
+
+typedef struct SMergeTsCtx {
+ SJoinSupporter* p;
+ STSBuf* res;
+ int64_t numOfInput;
+ int8_t compared;
+}SMergeTsCtx;
+
+
typedef struct SVgroupTableInfo {
SVgroupInfo vgInfo;
SArray* itemList; //SArray
@@ -123,6 +139,7 @@ int32_t tscGetDataBlockFromList(SHashObj* pHashList, int64_t id, int32_t size, i
bool tscIsPointInterpQuery(SQueryInfo* pQueryInfo);
bool tscIsTWAQuery(SQueryInfo* pQueryInfo);
bool tscIsSecondStageQuery(SQueryInfo* pQueryInfo);
+bool tscGroupbyColumn(SQueryInfo* pQueryInfo);
bool tscNonOrderedProjectionQueryOnSTable(SQueryInfo *pQueryInfo, int32_t tableIndex);
bool tscOrderedProjectionQueryOnSTable(SQueryInfo* pQueryInfo, int32_t tableIndex);
@@ -133,6 +150,7 @@ bool tscIsProjectionQuery(SQueryInfo* pQueryInfo);
bool tscIsTwoStageSTableQuery(SQueryInfo* pQueryInfo, int32_t tableIndex);
bool tscQueryTags(SQueryInfo* pQueryInfo);
bool tscMultiRoundQuery(SQueryInfo* pQueryInfo, int32_t tableIndex);
+bool tscQueryBlockInfo(SQueryInfo* pQueryInfo);
SSqlExpr* tscAddFuncInSelectClause(SQueryInfo* pQueryInfo, int32_t outputColIndex, int16_t functionId,
SColumnIndex* pIndex, SSchema* pColSchema, int16_t colType);
@@ -152,7 +170,6 @@ SInternalField* tscFieldInfoInsert(SFieldInfo* pFieldInfo, int32_t index, TAOS_F
SInternalField* tscFieldInfoGetInternalField(SFieldInfo* pFieldInfo, int32_t index);
TAOS_FIELD* tscFieldInfoGetField(SFieldInfo* pFieldInfo, int32_t index);
-void tscFieldInfoUpdateOffset(SQueryInfo* pQueryInfo);
void tscFieldInfoUpdateOffset(SQueryInfo* pQueryInfo);
int16_t tscFieldInfoGetOffset(SQueryInfo* pQueryInfo, int32_t index);
@@ -182,6 +199,7 @@ int32_t tscSqlExprCopy(SArray* dst, const SArray* src, uint64_t uid, bool deep
void tscSqlExprInfoDestroy(SArray* pExprInfo);
SColumn* tscColumnClone(const SColumn* src);
+bool tscColumnExists(SArray* pColumnList, SColumnIndex* pColIndex);
SColumn* tscColumnListInsert(SArray* pColList, SColumnIndex* colIndex);
SArray* tscColumnListClone(const SArray* src, int16_t tableIndex);
void tscColumnListDestroy(SArray* pColList);
diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h
index 2466262e7b55cbe1468b097e4b07043e7cca2e4c..446658e38b34b4a6ed6bd2c60bd61f9949117983 100644
--- a/src/client/inc/tsclient.h
+++ b/src/client/inc/tsclient.h
@@ -153,15 +153,15 @@ typedef struct SCond {
} SCond;
typedef struct SJoinNode {
- char tableName[TSDB_TABLE_FNAME_LEN];
uint64_t uid;
int16_t tagColId;
+ SArray* tsJoin;
+ SArray* tagJoin;
} SJoinNode;
typedef struct SJoinInfo {
- bool hasJoin;
- SJoinNode left;
- SJoinNode right;
+ bool hasJoin;
+ SJoinNode* joinTables[TSDB_MAX_JOIN_TABLE_NUM];
} SJoinInfo;
typedef struct STagCond {
@@ -209,9 +209,10 @@ typedef struct STableDataBlocks {
typedef struct SQueryInfo {
int16_t command; // the command may be different for each subclause, so keep it seperately.
uint32_t type; // query/insert type
+ STimeWindow window; // the whole query time window
- STimeWindow window; // query time window
- SInterval interval;
+ SInterval interval; // tumble time window
+ SSessionWindow sessionWindow; // session time window
SSqlGroupbyExpr groupbyExpr; // group by tags info
SArray * colList; // SArray
@@ -244,6 +245,7 @@ typedef struct SQueryInfo {
typedef struct {
int command;
uint8_t msgType;
+ char reserve1[3]; // fix bus error on arm32
bool autoCreated; // create table if it is not existed during retrieve table meta in mnode
union {
@@ -256,8 +258,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
int16_t numOfCols;
+ char reserve3[2]; // fix bus error on arm32
uint32_t allocSize;
char * payload;
int32_t payloadLen;
@@ -267,7 +271,9 @@ typedef struct {
int32_t numOfParams;
int8_t dataSourceType; // load data from file or not
+ char reserve4[3]; // fix bus error on arm32
int8_t submitSchema; // submit block is built with table schema
+ char reserve5[3]; // fix bus error on arm32
STagData tagData; // NOTE: pTagData->data is used as a variant length array
SName **pTableNameList; // all involved tableMeta list of current insert sql statement.
@@ -290,7 +296,7 @@ typedef struct {
char * pRsp;
int32_t rspType;
int32_t rspLen;
- uint64_t qhandle;
+ uint64_t qId;
int64_t useconds;
int64_t offset; // offset value from vnode during projection query of stable
int32_t row;
@@ -373,7 +379,7 @@ typedef struct SSqlObj {
int64_t svgroupRid;
int64_t squeryLock;
-
+ int32_t retryReason; // previous error code
struct SSqlObj *prev, *next;
int64_t self;
} SSqlObj;
@@ -409,7 +415,6 @@ typedef struct SSqlStream {
void tscSetStreamDestTable(SSqlStream* pStream, const char* dstTable);
-
int tscAcquireRpc(const char *key, const char *user, const char *secret,void **pRpcObj);
void tscReleaseRpc(void *param);
void tscInitMsgsFp();
diff --git a/src/client/src/TSDBJNIConnector.c b/src/client/src/TSDBJNIConnector.c
index a8829499a324605036beefad62d83eccf4d1c65b..56e155311e60dd0a30d3f6b5dce99c9d4c76ec7f 100644
--- a/src/client/src/TSDBJNIConnector.c
+++ b/src/client/src/TSDBJNIConnector.c
@@ -481,15 +481,19 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
case TSDB_DATA_TYPE_BOOL:
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetBooleanFp, i, (jboolean)(*((char *)row[i]) == 1));
break;
+ case TSDB_DATA_TYPE_UTINYINT:
case TSDB_DATA_TYPE_TINYINT:
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetByteFp, i, (jbyte) * ((int8_t *)row[i]));
break;
+ case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_SMALLINT:
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetShortFp, i, (jshort) * ((int16_t *)row[i]));
break;
+ case TSDB_DATA_TYPE_UINT:
case TSDB_DATA_TYPE_INT:
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetIntFp, i, (jint) * (int32_t *)row[i]);
break;
+ case TSDB_DATA_TYPE_UBIGINT:
case TSDB_DATA_TYPE_BIGINT:
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetLongFp, i, (jlong) * ((int64_t *)row[i]));
break;
diff --git a/src/client/src/tscAsync.c b/src/client/src/tscAsync.c
index 5cba897b3028a2d6301e9363ca6180f6b41022f8..3249529b34580b519ef1c6dbe9bfe7e76e0cb7cc 100644
--- a/src/client/src/tscAsync.c
+++ b/src/client/src/tscAsync.c
@@ -160,8 +160,8 @@ static void tscProcessAsyncRetrieveImpl(void *param, TAOS_RES *tres, int numOfRo
SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res;
- if ((pRes->qhandle == 0 || numOfRows != 0) && pCmd->command < TSDB_SQL_LOCAL) {
- if (pRes->qhandle == 0 && numOfRows != 0) {
+ if ((pRes->qId == 0 || numOfRows != 0) && pCmd->command < TSDB_SQL_LOCAL) {
+ if (pRes->qId == 0 && numOfRows != 0) {
tscError("qhandle is NULL");
} else {
pRes->code = numOfRows;
@@ -208,7 +208,7 @@ void taos_fetch_rows_a(TAOS_RES *taosa, __async_cb_func_t fp, void *param) {
pSql->fetchFp = fp;
pSql->fp = tscAsyncFetchRowsProxy;
- if (pRes->qhandle == 0) {
+ if (pRes->qId == 0) {
tscError("qhandle is NULL");
pRes->code = TSDB_CODE_TSC_INVALID_QHANDLE;
pSql->param = param;
@@ -281,7 +281,7 @@ void tscQueueAsyncError(void(*fp), void *param, int32_t code) {
}
static void tscAsyncResultCallback(SSchedMsg *pMsg) {
- SSqlObj* pSql = pMsg->ahandle;
+ SSqlObj* pSql = (SSqlObj*)taosAcquireRef(tscObjRef, (int64_t)pMsg->ahandle);
if (pSql == NULL || pSql->signature != pSql) {
tscDebug("%p SqlObj is freed, not add into queue async res", pSql);
return;
@@ -292,25 +292,69 @@ static void tscAsyncResultCallback(SSchedMsg *pMsg) {
SSqlRes *pRes = &pSql->res;
if (pSql->fp == NULL || pSql->fetchFp == NULL){
+ taosReleaseRef(tscObjRef, pSql->self);
return;
}
pSql->fp = pSql->fetchFp;
(*pSql->fp)(pSql->param, pSql, pRes->code);
+ taosReleaseRef(tscObjRef, pSql->self);
}
void tscAsyncResultOnError(SSqlObj* pSql) {
SSchedMsg schedMsg = {0};
schedMsg.fp = tscAsyncResultCallback;
- schedMsg.ahandle = pSql;
+ schedMsg.ahandle = (void *)pSql->self;
schedMsg.thandle = (void *)1;
schedMsg.msg = 0;
taosScheduleTask(tscQhandle, &schedMsg);
}
-
int tscSendMsgToServer(SSqlObj *pSql);
+static int32_t updateMetaBeforeRetryQuery(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SQueryInfo* pQueryInfo) {
+ // handle the invalid table error code for super table.
+ // update the pExpr info, colList info, number of table columns
+ // TODO Re-parse this sql and issue the corresponding subquery as an alternative for this case.
+ if (pSql->retryReason == TSDB_CODE_TDB_INVALID_TABLE_ID) {
+ int32_t numOfExprs = (int32_t) tscSqlExprNumOfExprs(pQueryInfo);
+ int32_t numOfCols = tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
+ int32_t numOfTags = tscGetNumOfTags(pTableMetaInfo->pTableMeta);
+
+ SSchema *pSchema = tscGetTableSchema(pTableMetaInfo->pTableMeta);
+ for (int32_t i = 0; i < numOfExprs; ++i) {
+ SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, i);
+ pExpr->uid = pTableMetaInfo->pTableMeta->id.uid;
+
+ if (pExpr->colInfo.colIndex >= 0) {
+ int32_t index = pExpr->colInfo.colIndex;
+
+ if ((TSDB_COL_IS_NORMAL_COL(pExpr->colInfo.flag) && index >= numOfCols) ||
+ (TSDB_COL_IS_TAG(pExpr->colInfo.flag) && (index < numOfCols || index >= (numOfCols + numOfTags)))) {
+ return pSql->retryReason;
+ }
+
+ if ((pSchema[pExpr->colInfo.colIndex].colId != pExpr->colInfo.colId) &&
+ strcasecmp(pExpr->colInfo.name, pSchema[pExpr->colInfo.colIndex].name) != 0) {
+ return pSql->retryReason;
+ }
+ }
+ }
+
+ // validate the table columns information
+ for (int32_t i = 0; i < taosArrayGetSize(pQueryInfo->colList); ++i) {
+ SColumn *pCol = taosArrayGetP(pQueryInfo->colList, i);
+ if (pCol->colIndex.columnIndex >= numOfCols) {
+ return pSql->retryReason;
+ }
+ }
+ } else {
+ // do nothing
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
SSqlObj* pSql = (SSqlObj*)taosAcquireRef(tscObjRef, (int64_t)param);
if (pSql == NULL) return;
@@ -336,7 +380,8 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, (TSDB_QUERY_TYPE_STABLE_SUBQUERY|TSDB_QUERY_TYPE_SUBQUERY|TSDB_QUERY_TYPE_TAG_FILTER_QUERY))) {
tscDebug("%p update local table meta, continue to process sql and send the corresponding query", pSql);
- STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+ STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+
code = tscGetTableMeta(pSql, pTableMetaInfo);
assert(code == TSDB_CODE_TSC_ACTION_IN_PROGRESS || code == TSDB_CODE_SUCCESS);
@@ -346,6 +391,10 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
}
assert((tscGetNumOfTags(pTableMetaInfo->pTableMeta) != 0));
+ code = updateMetaBeforeRetryQuery(pSql, pTableMetaInfo, pQueryInfo);
+ if (code != TSDB_CODE_SUCCESS) {
+ goto _error;
+ }
// tscProcessSql can add error into async res
tscProcessSql(pSql);
diff --git a/src/client/src/tscLocal.c b/src/client/src/tscLocal.c
index 820572859e88540656b8ce42dc3a6e77467c1423..188ba29a97c244ce5c5027c459fabc303ed85c0f 100644
--- a/src/client/src/tscLocal.c
+++ b/src/client/src/tscLocal.c
@@ -309,7 +309,7 @@ TAOS_ROW tscFetchRow(void *param) {
SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res;
- if (pRes->qhandle == 0 ||
+ if (pRes->qId == 0 ||
pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
pCmd->command == TSDB_SQL_INSERT) {
return NULL;
@@ -905,7 +905,7 @@ int tscProcessLocalCmd(SSqlObj *pSql) {
* set the qhandle to be 1 in order to pass the qhandle check, and to call partial release function to
* free allocated resources and remove the SqlObj from sql query linked list
*/
- pRes->qhandle = 0x1;
+ pRes->qId = 0x1;
pRes->numOfRows = 0;
} else if (pCmd->command == TSDB_SQL_SHOW_CREATE_TABLE) {
pRes->code = tscProcessShowCreateTable(pSql);
diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c
index 9870830d2e17d1f6a5f1ec31d1473e68888f1597..65fa825a279438d5b28ad0852a70fdb53c8abc2c 100644
--- a/src/client/src/tscLocalMerge.c
+++ b/src/client/src/tscLocalMerge.c
@@ -101,6 +101,10 @@ static void tscInitSqlContext(SSqlCmd *pCmd, SLocalMerger *pReducer, tOrderDescr
} else if (functionId == TSDB_FUNC_APERCT) {
pCtx->param[0].i64 = pExpr->param[0].i64;
pCtx->param[0].nType = pExpr->param[0].nType;
+ } else if (functionId == TSDB_FUNC_BLKINFO) {
+ pCtx->param[0].i64 = pExpr->param[0].i64;
+ pCtx->param[0].nType = pExpr->param[0].nType;
+ pCtx->numOfParams = 1;
}
pCtx->interBufBytes = pExpr->interBytes;
@@ -952,10 +956,10 @@ static void doFillResult(SSqlObj *pSql, SLocalMerger *pLocalMerge, bool doneOutp
// todo extract function
int64_t actualETime = (pQueryInfo->order.order == TSDB_ORDER_ASC)? pQueryInfo->window.ekey: pQueryInfo->window.skey;
- tFilePage **pResPages = malloc(POINTER_BYTES * pQueryInfo->fieldsInfo.numOfOutput);
+ void** pResPages = malloc(POINTER_BYTES * pQueryInfo->fieldsInfo.numOfOutput);
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
- pResPages[i] = calloc(1, sizeof(tFilePage) + pField->bytes * pLocalMerge->resColModel->capacity);
+ pResPages[i] = calloc(1, pField->bytes * pLocalMerge->resColModel->capacity);
}
while (1) {
@@ -967,7 +971,7 @@ static void doFillResult(SSqlObj *pSql, SLocalMerger *pLocalMerge, bool doneOutp
if (pQueryInfo->limit.offset > 0) {
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
- memmove(pResPages[i]->data, pResPages[i]->data + pField->bytes * pQueryInfo->limit.offset,
+ memmove(pResPages[i], ((char*)pResPages[i]) + pField->bytes * pQueryInfo->limit.offset,
(size_t)(newRows * pField->bytes));
}
}
@@ -1011,7 +1015,7 @@ static void doFillResult(SSqlObj *pSql, SLocalMerger *pLocalMerge, bool doneOutp
int32_t offset = 0;
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
- memcpy(pRes->data + offset * pRes->numOfRows, pResPages[i]->data, (size_t)(pField->bytes * pRes->numOfRows));
+ memcpy(pRes->data + offset * pRes->numOfRows, pResPages[i], (size_t)(pField->bytes * pRes->numOfRows));
offset += pField->bytes;
}
@@ -1690,7 +1694,7 @@ void tscInitResObjForLocalQuery(SSqlObj *pObj, int32_t numOfRes, int32_t rowLen)
tscDestroyLocalMerger(pObj);
}
- pRes->qhandle = 1; // hack to pass the safety check in fetch_row function
+ pRes->qId = 1; // hack to pass the safety check in fetch_row function
pRes->numOfRows = 0;
pRes->row = 0;
diff --git a/src/client/src/tscParseInsert.c b/src/client/src/tscParseInsert.c
index a5906f5539a8d40b055f580933feb4b1184331f1..2b962333d588117ba54f363b7da586b6f04e3d47 100644
--- a/src/client/src/tscParseInsert.c
+++ b/src/client/src/tscParseInsert.c
@@ -307,7 +307,8 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SStrToken *pToken, char *payload,
return tscInvalidSQLErrMsg(msg, "illegal float data", pToken->z);
}
- *((float *)payload) = (float)dv;
+// *((float *)payload) = (float)dv;
+ SET_FLOAT_VAL(payload, dv);
}
break;
@@ -393,7 +394,7 @@ static int32_t tsCheckTimestamp(STableDataBlocks *pDataBlocks, const char *start
TSKEY k = *(TSKEY *)start;
- if (k == 0) {
+ if (k == INT64_MIN) {
if (pDataBlocks->tsSource == TSDB_USE_CLI_TS) {
return -1;
} else if (pDataBlocks->tsSource == -1) {
@@ -1359,7 +1360,7 @@ int tsParseSql(SSqlObj *pSql, bool initial) {
}
}
} else {
- SSqlInfo SQLInfo = qSQLParse(pSql->sqlstr);
+ SSqlInfo SQLInfo = qSqlParse(pSql->sqlstr);
ret = tscToSQLCmd(pSql, &SQLInfo);
if (ret == TSDB_CODE_TSC_INVALID_SQL && pSql->parseRetry == 0 && SQLInfo.type == TSDB_SQL_NULL) {
tscResetSqlCmd(pCmd, true);
diff --git a/src/client/src/tscPrepare.c b/src/client/src/tscPrepare.c
index c5f06a52f342b5726321925c1864d58c41afbeb4..4efaf7c2b516019052018c508306e4736322a284 100644
--- a/src/client/src/tscPrepare.c
+++ b/src/client/src/tscPrepare.c
@@ -261,7 +261,7 @@ static int doBindParam(char* data, SParamInfo* param, TAOS_BIND* bind) {
return TSDB_CODE_SUCCESS;
}
- if (1) {
+ if (0) {
// allow user bind param data with different type
union {
int8_t v1;
@@ -903,7 +903,7 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
- pRes->qhandle = 0;
+ pRes->qId = 0;
pRes->numOfRows = 1;
strtolower(pSql->sqlstr, sql);
@@ -1057,14 +1057,28 @@ int taos_stmt_get_param(TAOS_STMT *stmt, int idx, int *type, int *bytes) {
}
if (pStmt->isInsert) {
- SSqlObj* pSql = pStmt->pSql;
- SSqlCmd *pCmd = &pSql->cmd;
- STableDataBlocks* pBlock = taosArrayGetP(pCmd->pDataBlocks, 0);
+ SSqlCmd* pCmd = &pStmt->pSql->cmd;
+ STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, 0, 0);
+ STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
+ if (pCmd->pTableBlockHashList == NULL) {
+ pCmd->pTableBlockHashList = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false);
+ }
+
+ STableDataBlocks* pBlock = NULL;
- assert(pCmd->numOfParams == pBlock->numOfParams);
- if (idx < 0 || idx >= pBlock->numOfParams) return -1;
+ int32_t ret =
+ tscGetDataBlockFromList(pCmd->pTableBlockHashList, pTableMeta->id.uid, TSDB_PAYLOAD_SIZE, sizeof(SSubmitBlk),
+ pTableMeta->tableInfo.rowSize, &pTableMetaInfo->name, pTableMeta, &pBlock, NULL);
+ if (ret != 0) {
+ // todo handle error
+ }
+
+ if (idx<0 || idx>=pBlock->numOfParams) {
+ tscError("param %d: out of range", idx);
+ abort();
+ }
- SParamInfo* param = pBlock->params + idx;
+ SParamInfo* param = &pBlock->params[idx];
if (type) *type = param->type;
if (bytes) *bytes = param->bytes;
diff --git a/src/client/src/tscProfile.c b/src/client/src/tscProfile.c
index 9203dcfbbab8d4b512b490bf13ab91fe1b475c22..3b0e1b5775f13e619995ef8145ba4a09533f7a49 100644
--- a/src/client/src/tscProfile.c
+++ b/src/client/src/tscProfile.c
@@ -249,8 +249,8 @@ int tscBuildQueryStreamDesc(void *pMsg, STscObj *pObj) {
pQdesc->stime = htobe64(pSql->stime);
pQdesc->queryId = htonl(pSql->queryId);
//pQdesc->useconds = htobe64(pSql->res.useconds);
- pQdesc->useconds = htobe64(now - pSql->stime);
- pQdesc->qHandle = htobe64(pSql->res.qhandle);
+ pQdesc->useconds = htobe64(now - pSql->stime); // use local time instead of sever rsp elapsed time
+ pQdesc->qHandle = htobe64(pSql->res.qId);
pHeartbeat->numOfQueries++;
pQdesc++;
diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c
index 0ea053e8ea283f9509b013167e1ee945b9034bc6..efd3c7bb93a2f7253d470ee60750661b53f2aa1c 100644
--- a/src/client/src/tscSQLParser.c
+++ b/src/client/src/tscSQLParser.c
@@ -76,32 +76,31 @@ static int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int3
static int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnList* pIdList, int16_t bytes,
int8_t type, char* fieldName, SSqlExpr* pSqlExpr);
-static int32_t convertFunctionId(int32_t optr, int16_t* functionId);
static uint8_t convertOptr(SStrToken *pToken);
-static int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery, bool intervalQuery);
+static int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, SArray* pSelectList, bool isSTable, bool joinQuery, bool timeWindowQuery);
static bool validateIpAddress(const char* ip, size_t size);
static bool hasUnsupportFunctionsForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo);
-static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery, bool intervalQuery);
+static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery, bool twQuery);
static int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd);
-static int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
-static int32_t parseOffsetClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
-static int32_t parseSlidingClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
+static int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySqlNode* pQuerySqlNode);
+static int32_t parseIntervalOffset(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SStrToken* offsetToken);
+static int32_t parseSlidingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SStrToken* pSliding);
static int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExprItem* pItem);
-static int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlObj* pSql);
-static int32_t parseFillClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySQL);
-static int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql, SSchema* pSchema);
+static int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql);
+static int32_t parseFillClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySqlNode* pQuerySQL);
+static int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySqlNode* pQuerySqlNode, SSchema* pSchema);
static int32_t tsRewriteFieldNameIfNecessary(SSqlCmd* pCmd, SQueryInfo* pQueryInfo);
static int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo);
static int32_t validateSqlFunctionInStreamSql(SSqlCmd* pCmd, SQueryInfo* pQueryInfo);
static int32_t validateFunctionsInIntervalOrGroupbyQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo);
-static int32_t validateArithmeticSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, int32_t* type);
+static int32_t validateArithmeticSQLExpr(SSqlCmd* pCmd, tSqlExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, int32_t* type);
static int32_t validateEp(char* ep);
static int32_t validateDNodeConfig(SMiscInfo* pOptions);
static int32_t validateLocalConfig(SMiscInfo* pOptions);
@@ -112,15 +111,14 @@ static bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField);
static bool hasTimestampForPointInterpQuery(SQueryInfo* pQueryInfo);
static bool hasNormalColumnFilter(SQueryInfo* pQueryInfo);
-static int32_t parseLimitClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t index, SQuerySQL* pQuerySql, SSqlObj* pSql);
+static int32_t parseLimitClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t index, SQuerySqlNode* pQuerySqlNode, SSqlObj* pSql);
static int32_t parseCreateDBOptions(SSqlCmd* pCmd, SCreateDbInfo* pCreateDbSql);
static int32_t getColumnIndexByName(SSqlCmd* pCmd, const SStrToken* pToken, SQueryInfo* pQueryInfo, SColumnIndex* pIndex);
static int32_t getTableIndexByName(SStrToken* pToken, SQueryInfo* pQueryInfo, SColumnIndex* pIndex);
-static int32_t optrToString(tSQLExpr* pExpr, char** exprString);
static int32_t getTableIndexImpl(SStrToken* pTableToken, SQueryInfo* pQueryInfo, SColumnIndex* pIndex);
static int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo);
-static int32_t doLocalQueryProcess(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
+static int32_t doLocalQueryProcess(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySqlNode* pQuerySqlNode);
static int32_t tscCheckCreateDbParams(SSqlCmd* pCmd, SCreateDbMsg* pCreate);
static SColumnList getColumnList(int32_t num, int16_t tableIndex, int32_t columnIndex);
@@ -128,9 +126,13 @@ static SColumnList getColumnList(int32_t num, int16_t tableIndex, int32_t column
static int32_t doCheckForCreateTable(SSqlObj* pSql, int32_t subClauseIndex, SSqlInfo* pInfo);
static int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo);
static int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo);
-static int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index);
-static int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pSqlExpr, SQueryInfo* pQueryInfo, SArray* pCols, int64_t *uid);
-static bool validateDebugFlag(int32_t flag);
+static int32_t doValidateSqlNode(SSqlObj* pSql, SQuerySqlNode* pQuerySqlNode, int32_t index);
+static int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryInfo* pQueryInfo, SArray* pCols, int64_t *uid);
+static bool validateDebugFlag(int32_t v);
+
+static bool isTimeWindowQuery(SQueryInfo* pQueryInfo) {
+ return pQueryInfo->interval.interval > 0 || pQueryInfo->sessionWindow.gap > 0;
+}
int16_t getNewResColId(SQueryInfo* pQueryInfo) {
return pQueryInfo->resColumnId--;
@@ -177,11 +179,11 @@ static uint8_t convertOptr(SStrToken *pToken) {
static bool validateDebugFlag(int32_t v) {
const static int validFlag[] = {131, 135, 143};
-
+
for (int i = 0; i < tListLen(validFlag); i++) {
if (v == validFlag[i]) {
return true;
- }
+ }
}
return false;
}
@@ -585,12 +587,12 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
SStrToken* t1 = taosArrayGet(pMiscInfo->a, 1);
pCmd->payload[t->n] = ' '; // add sep
strncpy(&pCmd->payload[t->n + 1], t1->z, t1->n);
- }
- return TSDB_CODE_SUCCESS;
+ }
+ return TSDB_CODE_SUCCESS;
}
case TSDB_SQL_CREATE_TABLE: {
- SCreateTableSQL* pCreateTable = pInfo->pCreateTableInfo;
+ SCreateTableSql* pCreateTable = pInfo->pCreateTableInfo;
if (pCreateTable->type == TSQL_CREATE_TABLE || pCreateTable->type == TSQL_CREATE_STABLE) {
if ((code = doCheckForCreateTable(pSql, 0, pInfo)) != TSDB_CODE_SUCCESS) {
@@ -625,9 +627,9 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
assert(pCmd->numOfClause == pInfo->subclauseInfo.numOfClause);
for (int32_t i = pCmd->clauseIndex; i < pInfo->subclauseInfo.numOfClause; ++i) {
- SQuerySQL* pQuerySql = pInfo->subclauseInfo.pClause[i];
+ SQuerySqlNode* pQuerySqlNode = pInfo->subclauseInfo.pClause[i];
tscTrace("%p start to parse %dth subclause, total:%d", pSql, i, pInfo->subclauseInfo.numOfClause);
- if ((code = doCheckForQuery(pSql, pQuerySql, i)) != TSDB_CODE_SUCCESS) {
+ if ((code = doValidateSqlNode(pSql, pQuerySqlNode, i)) != TSDB_CODE_SUCCESS) {
return code;
}
@@ -669,7 +671,18 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
if ((code = setKillInfo(pSql, pInfo, pInfo->type)) != TSDB_CODE_SUCCESS) {
return code;
}
+ break;
+ }
+ case TSDB_SQL_SYNC_DB_REPLICA: {
+ const char* msg1 = "invalid db name";
+ SStrToken* pzName = taosArrayGet(pInfo->pMiscInfo->a, 0);
+
+ assert(taosArrayGetSize(pInfo->pMiscInfo->a) == 1);
+ code = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pzName);
+ if (code != TSDB_CODE_SUCCESS) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
+ }
break;
}
@@ -703,21 +716,86 @@ static bool isTopBottomQuery(SQueryInfo* pQueryInfo) {
return false;
}
-int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
+// need to add timestamp column in result set, if it is a time window query
+static int32_t addPrimaryTsColumnForTimeWindowQuery(SQueryInfo* pQueryInfo) {
+ uint64_t uid = tscSqlExprGet(pQueryInfo, 0)->uid;
+
+ int32_t tableIndex = COLUMN_INDEX_INITIAL_VAL;
+ for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
+ STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, i);
+ if (pTableMetaInfo->pTableMeta->id.uid == uid) {
+ tableIndex = i;
+ break;
+ }
+ }
+
+ if (tableIndex == COLUMN_INDEX_INITIAL_VAL) {
+ return TSDB_CODE_TSC_INVALID_SQL;
+ }
+
+ SSchema s = {.bytes = TSDB_KEYSIZE, .type = TSDB_DATA_TYPE_TIMESTAMP, .colId = PRIMARYKEY_TIMESTAMP_COL_INDEX};
+ tstrncpy(s.name, aAggs[TSDB_FUNC_TS].name, sizeof(s.name));
+
+ SColumnIndex index = {tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
+ tscAddFuncInSelectClause(pQueryInfo, 0, TSDB_FUNC_TS, &index, &s, TSDB_COL_NORMAL);
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t checkInvalidExprForTimeWindow(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
const char* msg1 = "invalid query expression";
+ const char* msg2 = "top/bottom query does not support order by value in time window query";
+
+ // for top/bottom + interval query, we do not add additional timestamp column in the front
+ if (isTopBottomQuery(pQueryInfo)) {
+
+ // invalid sql:
+ // top(col, k) from table_name [interval(1d)|session(ts, 1d)] order by k asc
+ // order by normal column is not supported
+ int32_t colId = pQueryInfo->order.orderColId;
+ if (isTimeWindowQuery(pQueryInfo) && colId != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
+ }
+
+ return TSDB_CODE_SUCCESS;
+ }
+
+ /*
+ * invalid sql:
+ * select count(tbname)/count(tag1)/count(tag2) from super_table_name [interval(1d)|session(ts, 1d)];
+ */
+ size_t size = tscSqlExprNumOfExprs(pQueryInfo);
+ for (int32_t i = 0; i < size; ++i) {
+ SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
+ if (pExpr->functionId == TSDB_FUNC_COUNT && TSDB_COL_IS_TAG(pExpr->colInfo.flag)) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
+ }
+ }
+
+ /*
+ * invalid sql:
+ * select tbname, tags_fields from super_table_name [interval(1s)|session(ts,1s)]
+ */
+ if (tscQueryTags(pQueryInfo) && isTimeWindowQuery(pQueryInfo)) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
+ }
+
+ return addPrimaryTsColumnForTimeWindowQuery(pQueryInfo);
+}
+
+int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySqlNode* pQuerySqlNode) {
const char* msg2 = "interval cannot be less than 10 ms";
const char* msg3 = "sliding cannot be used without interval";
- const char* msg4 = "top/bottom query does not support order by value in interval query";
SSqlCmd* pCmd = &pSql->cmd;
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
- if (pQuerySql->interval.type == 0 || pQuerySql->interval.n == 0) {
- if (pQuerySql->sliding.n > 0) {
+ if (!TPARSER_HAS_TOKEN(pQuerySqlNode->interval.interval)) {
+ if (TPARSER_HAS_TOKEN(pQuerySqlNode->sliding)) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
+
return TSDB_CODE_SUCCESS;
}
@@ -727,7 +805,7 @@ int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQ
}
// interval is not null
- SStrToken* t = &pQuerySql->interval;
+ SStrToken *t = &pQuerySqlNode->interval.interval;
if (parseNatualDuration(t->z, t->n, &pQueryInfo->interval.interval, &pQueryInfo->interval.intervalUnit) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
@@ -744,78 +822,64 @@ int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQ
}
}
- // for top/bottom + interval query, we do not add additional timestamp column in the front
- if (isTopBottomQuery(pQueryInfo)) {
- if (parseOffsetClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
- return TSDB_CODE_TSC_INVALID_SQL;
- }
+ if (parseIntervalOffset(pCmd, pQueryInfo, &pQuerySqlNode->interval.offset) != TSDB_CODE_SUCCESS) {
+ return TSDB_CODE_TSC_INVALID_SQL;
+ }
- if (parseSlidingClause(pSql, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
- return TSDB_CODE_TSC_INVALID_SQL;
- }
+ if (parseSlidingClause(pCmd, pQueryInfo, &pQuerySqlNode->sliding) != TSDB_CODE_SUCCESS) {
+ return TSDB_CODE_TSC_INVALID_SQL;
+ }
- int32_t colId = pQueryInfo->order.orderColId;
- if (pQueryInfo->interval.interval > 0 && colId != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
- }
+ // The following part is used to check for the invalid query expression.
+ return checkInvalidExprForTimeWindow(pCmd, pQueryInfo);
+}
+int32_t parseSessionClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySqlNode * pQuerySqlNode) {
+ const char* msg1 = "gap should be fixed time window";
+ const char* msg2 = "only one type time window allowed";
+ const char* msg3 = "invalid column name";
+ const char* msg4 = "invalid time window";
+
+ // no session window
+ if (!TPARSER_HAS_TOKEN(pQuerySqlNode->sessionVal.gap)) {
return TSDB_CODE_SUCCESS;
}
- /*
- * check invalid SQL:
- * select count(tbname)/count(tag1)/count(tag2) from super_table_name interval(1d);
- */
- size_t size = tscSqlExprNumOfExprs(pQueryInfo);
- for (int32_t i = 0; i < size; ++i) {
- SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
- if (pExpr->functionId == TSDB_FUNC_COUNT && TSDB_COL_IS_TAG(pExpr->colInfo.flag)) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
- }
+ SStrToken* col = &pQuerySqlNode->sessionVal.col;
+ SStrToken* gap = &pQuerySqlNode->sessionVal.gap;
+
+ char timeUnit = 0;
+ if (parseNatualDuration(gap->z, gap->n, &pQueryInfo->sessionWindow.gap, &timeUnit) != TSDB_CODE_SUCCESS) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
}
- /*
- * check invalid SQL:
- * select tbname, tags_fields from super_table_name interval(1s)
- */
- if (tscQueryTags(pQueryInfo) && pQueryInfo->interval.interval > 0) {
+ if (timeUnit == 'y' || timeUnit == 'n') {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
- // need to add timestamp column in result set, if interval is existed
- uint64_t uid = tscSqlExprGet(pQueryInfo, 0)->uid;
-
- int32_t tableIndex = COLUMN_INDEX_INITIAL_VAL;
- for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
- pTableMetaInfo = tscGetMetaInfo(pQueryInfo, i);
- if (pTableMetaInfo->pTableMeta->id.uid == uid) {
- tableIndex = i;
- break;
- }
+ // if the unit of time window value is millisecond, change the value from microsecond
+ STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+ STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
+ if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) {
+ pQueryInfo->sessionWindow.gap = pQueryInfo->sessionWindow.gap / 1000;
}
- if (tableIndex == COLUMN_INDEX_INITIAL_VAL) {
- return TSDB_CODE_TSC_INVALID_SQL;
+ if (pQueryInfo->sessionWindow.gap != 0 && pQueryInfo->interval.interval != 0) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- SSchema s = {.bytes = TSDB_KEYSIZE, .type = TSDB_DATA_TYPE_TIMESTAMP, .colId = PRIMARYKEY_TIMESTAMP_COL_INDEX};
- tstrncpy(s.name, aAggs[TSDB_FUNC_TS].name, sizeof(s.name));
-
- SColumnIndex index = {tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
- tscAddFuncInSelectClause(pQueryInfo, 0, TSDB_FUNC_TS, &index, &s, TSDB_COL_NORMAL);
-
- if (parseOffsetClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
- return TSDB_CODE_TSC_INVALID_SQL;
+ SColumnIndex index = COLUMN_INDEX_INITIALIZER;
+ if (getColumnIndexByName(pCmd, col, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
- if (parseSlidingClause(pSql, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
- return TSDB_CODE_TSC_INVALID_SQL;
- }
+ pQueryInfo->sessionWindow.primaryColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
- return TSDB_CODE_SUCCESS;
+ // The following part is used to check for the invalid query expression.
+ return checkInvalidExprForTimeWindow(pCmd, pQueryInfo);
}
-int32_t parseOffsetClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
+int32_t parseIntervalOffset(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SStrToken* offsetToken) {
const char* msg1 = "interval offset cannot be negative";
const char* msg2 = "interval offset should be shorter than interval";
const char* msg3 = "cannot use 'year' as offset when interval is 'month'";
@@ -823,7 +887,7 @@ int32_t parseOffsetClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQue
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
- SStrToken* t = &pQuerySql->offset;
+ SStrToken* t = offsetToken;
if (t->n == 0) {
pQueryInfo->interval.offsetUnit = pQueryInfo->interval.intervalUnit;
pQueryInfo->interval.offset = 0;
@@ -866,20 +930,17 @@ int32_t parseOffsetClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQue
return TSDB_CODE_SUCCESS;
}
-int32_t parseSlidingClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
+int32_t parseSlidingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SStrToken* pSliding) {
const char* msg0 = "sliding value too small";
const char* msg1 = "sliding value no larger than the interval value";
const char* msg2 = "sliding value can not less than 1% of interval value";
const char* msg3 = "does not support sliding when interval is natural month/year";
-// const char* msg4 = "sliding not support yet in ordinary query";
const static int32_t INTERVAL_SLIDING_FACTOR = 100;
- SSqlCmd* pCmd = &pSql->cmd;
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
- SStrToken* pSliding = &pQuerySql->sliding;
if (pSliding->n == 0) {
pQueryInfo->interval.slidingUnit = pQueryInfo->interval.intervalUnit;
pQueryInfo->interval.sliding = pQueryInfo->interval.interval;
@@ -917,12 +978,18 @@ int32_t parseSlidingClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQu
int32_t tscSetTableFullName(STableMetaInfo* pTableMetaInfo, SStrToken* pTableName, SSqlObj* pSql) {
const char* msg1 = "name too long";
const char* msg2 = "acctId too long";
+ const char* msg3 = "no acctId";
SSqlCmd* pCmd = &pSql->cmd;
int32_t code = TSDB_CODE_SUCCESS;
if (hasSpecifyDB(pTableName)) { // db has been specified in sql string so we ignore current db path
- code = tNameSetAcctId(&pTableMetaInfo->name, getAccountId(pSql));
+ char* acctId = getAccountId(pSql);
+ if (acctId == NULL || strlen(acctId) <= 0) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
+ }
+
+ code = tNameSetAcctId(&pTableMetaInfo->name, acctId);
if (code != 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
@@ -971,7 +1038,7 @@ static bool validateTableColumnInfo(SArray* pFieldList, SSqlCmd* pCmd) {
const char* msg1 = "first column must be timestamp";
const char* msg2 = "row length exceeds max length";
const char* msg3 = "duplicated column names";
- const char* msg4 = "invalid data types";
+ const char* msg4 = "invalid data type";
const char* msg5 = "invalid binary/nchar column length";
const char* msg6 = "invalid column name";
@@ -992,14 +1059,13 @@ static bool validateTableColumnInfo(SArray* pFieldList, SSqlCmd* pCmd) {
int32_t nLen = 0;
for (int32_t i = 0; i < numOfCols; ++i) {
pField = taosArrayGet(pFieldList, i);
-
- if (pField->bytes == 0) {
- invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
+ if (!isValidDataType(pField->type)) {
+ invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
return false;
}
- if (!isValidDataType(pField->type)) {
- invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
+ if (pField->bytes == 0) {
+ invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
return false;
}
@@ -1227,7 +1293,7 @@ bool validateOneColumn(SSqlCmd* pCmd, TAOS_FIELD* pColField) {
const char* msg1 = "too many columns";
const char* msg2 = "duplicated column names";
const char* msg3 = "column length too long";
- const char* msg4 = "invalid data types";
+ const char* msg4 = "invalid data type";
const char* msg5 = "invalid column name";
const char* msg6 = "invalid column length";
@@ -1573,8 +1639,9 @@ bool isValidDistinctSql(SQueryInfo* pQueryInfo) {
}
return false;
}
-int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery, bool intervalQuery) {
- assert(pSelection != NULL && pCmd != NULL);
+
+int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, SArray* pSelectList, bool isSTable, bool joinQuery, bool timeWindowQuery) {
+ assert(pSelectList != NULL && pCmd != NULL);
const char* msg2 = "functions or others can not be mixed up";
const char* msg3 = "not support query expression";
@@ -1586,34 +1653,35 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
if (pQueryInfo->colList == NULL) {
pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES);
}
+
bool hasDistinct = false;
- for (int32_t i = 0; i < pSelection->nExpr; ++i) {
+ size_t numOfExpr = taosArrayGetSize(pSelectList);
+ for (int32_t i = 0; i < numOfExpr; ++i) {
int32_t outputIndex = (int32_t)tscSqlExprNumOfExprs(pQueryInfo);
- tSqlExprItem* pItem = &pSelection->a[i];
+ tSqlExprItem* pItem = taosArrayGet(pSelectList, i);
if (hasDistinct == false) {
hasDistinct = (pItem->distinct == true);
}
- // project on all fields
- int32_t optr = pItem->pNode->nSQLOptr;
- if (optr == TK_ALL || optr == TK_ID || optr == TK_STRING || optr == TK_INTEGER || optr == TK_FLOAT) {
- // it is actually a function, but the function name is invalid
- if (pItem->pNode->nSQLOptr == TK_ID && (pItem->pNode->colInfo.z == NULL && pItem->pNode->colInfo.n == 0)) {
+ int32_t type = pItem->pNode->type;
+ if (type == SQL_NODE_SQLFUNCTION) {
+ pItem->pNode->functionId = isValidFunction(pItem->pNode->operand.z, pItem->pNode->operand.n);
+ if (pItem->pNode->functionId < 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
- // select table_name1.field_name1, table_name2.field_name2 from table_name1, table_name2
- if (addProjectionExprAndResultField(pCmd, pQueryInfo, pItem) != TSDB_CODE_SUCCESS) {
- return TSDB_CODE_TSC_INVALID_SQL;
- }
- } else if (pItem->pNode->nSQLOptr >= TK_COUNT && pItem->pNode->nSQLOptr <= TK_TBID) {
// sql function in selection clause, append sql function info in pSqlCmd structure sequentially
if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, pItem, true) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
-
- } else if (pItem->pNode->nSQLOptr >= TK_PLUS && pItem->pNode->nSQLOptr <= TK_REM) {
+ } else if (type == SQL_NODE_TABLE_COLUMN || type == SQL_NODE_VALUE) {
+ // use the dynamic array list to decide if the function is valid or not
+ // select table_name1.field_name1, table_name2.field_name2 from table_name1, table_name2
+ if (addProjectionExprAndResultField(pCmd, pQueryInfo, pItem) != TSDB_CODE_SUCCESS) {
+ return TSDB_CODE_TSC_INVALID_SQL;
+ }
+ } else if (type == SQL_NODE_EXPR) {
int32_t code = handleArithmeticExpr(pCmd, clauseIndex, i, pItem);
if (code != TSDB_CODE_SUCCESS) {
return code;
@@ -1636,11 +1704,11 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
// there is only one user-defined column in the final result field, add the timestamp column.
size_t numOfSrcCols = taosArrayGetSize(pQueryInfo->colList);
- if (numOfSrcCols <= 0 && !tscQueryTags(pQueryInfo)) {
+ if (numOfSrcCols <= 0 && !tscQueryTags(pQueryInfo) && !tscQueryBlockInfo(pQueryInfo)) {
addPrimaryTsColIntoResult(pQueryInfo);
}
- if (!functionCompatibleCheck(pQueryInfo, joinQuery, intervalQuery)) {
+ if (!functionCompatibleCheck(pQueryInfo, joinQuery, timeWindowQuery)) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
@@ -1751,7 +1819,7 @@ int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t
const char* msg1 = "tag for normal table query is not allowed";
int32_t startPos = (int32_t)tscSqlExprNumOfExprs(pQueryInfo);
- int32_t optr = pItem->pNode->nSQLOptr;
+ int32_t optr = pItem->pNode->tokenId;
if (optr == TK_ALL) { // project on all fields
TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_PROJECTION_QUERY);
@@ -1781,13 +1849,13 @@ int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t
index.columnIndex = (pQueryInfo->udColumnId--);
index.tableIndex = 0;
- SSchema colSchema = tGetUserSpecifiedColumnSchema(&pItem->pNode->val, &pItem->pNode->token, pItem->aliasName);
+ SSchema colSchema = tGetUserSpecifiedColumnSchema(&pItem->pNode->value, &pItem->pNode->token, pItem->aliasName);
SSqlExpr* pExpr =
tscAddFuncInSelectClause(pQueryInfo, startPos, TSDB_FUNC_PRJ, &index, &colSchema, TSDB_COL_UDC);
// NOTE: the first parameter is reserved for the tag column id during join query process.
pExpr->numOfParams = 2;
- tVariantAssign(&pExpr->param[1], &pItem->pNode->val);
+ tVariantAssign(&pExpr->param[1], &pItem->pNode->value);
} else if (optr == TK_ID) {
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
@@ -1896,9 +1964,25 @@ void setResultColName(char* name, tSqlExprItem* pItem, int32_t functionId, SStrT
}
}
+static void updateLastScanOrderIfNeeded(SQueryInfo* pQueryInfo) {
+ if (pQueryInfo->sessionWindow.gap > 0 || tscGroupbyColumn(pQueryInfo)) {
+ size_t numOfExpr = tscSqlExprNumOfExprs(pQueryInfo);
+ for (int32_t i = 0; i < numOfExpr; ++i) {
+ SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
+ if (pExpr->functionId != TSDB_FUNC_LAST && pExpr->functionId != TSDB_FUNC_LAST_DST) {
+ continue;
+ }
+
+ pExpr->numOfParams = 1;
+ pExpr->param->i64 = TSDB_ORDER_ASC;
+ pExpr->param->nType = TSDB_DATA_TYPE_INT;
+ }
+ }
+}
+
int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t colIndex, tSqlExprItem* pItem, bool finalResult) {
STableMetaInfo* pTableMetaInfo = NULL;
- int32_t optr = pItem->pNode->nSQLOptr;
+ int32_t functionId = pItem->pNode->functionId;
const char* msg1 = "not support column types";
const char* msg2 = "invalid parameters";
@@ -1908,28 +1992,22 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
const char* msg6 = "function applied to tags not allowed";
const char* msg7 = "normal table can not apply this function";
const char* msg8 = "multi-columns selection does not support alias column name";
- const char* msg9 = "invalid function";
- const char* msg10 = "diff can no be applied to unsigned numeric type";
+ const char* msg9 = "diff can no be applied to unsigned numeric type";
- switch (optr) {
- case TK_COUNT: {
+ switch (functionId) {
+ case TSDB_FUNC_COUNT: {
/* more than one parameter for count() function */
- if (pItem->pNode->pParam != NULL && pItem->pNode->pParam->nExpr != 1) {
+ if (pItem->pNode->pParam != NULL && taosArrayGetSize(pItem->pNode->pParam) != 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- int16_t functionID = 0;
- if (convertFunctionId(optr, &functionID) != TSDB_CODE_SUCCESS) {
- return TSDB_CODE_TSC_INVALID_SQL;
- }
-
SSqlExpr* pExpr = NULL;
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (pItem->pNode->pParam != NULL) {
- tSqlExprItem* pParamElem = &pItem->pNode->pParam->a[0];
+ tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->pParam, 0);
SStrToken* pToken = &pParamElem->pNode->colInfo;
- int16_t sqlOptr = pParamElem->pNode->nSQLOptr;
+ int16_t sqlOptr = pParamElem->pNode->tokenId;
if ((pToken->z == NULL || pToken->n == 0)
&& (TK_INTEGER != sqlOptr)) /*select count(1) from table*/ {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
@@ -1945,11 +2023,11 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
index = (SColumnIndex){0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
int32_t size = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
- pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false);
+ pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false);
} else if (sqlOptr == TK_INTEGER) { // select count(1) from table1
char buf[8] = {0};
int64_t val = -1;
- tVariant* pVariant = &pParamElem->pNode->val;
+ tVariant* pVariant = &pParamElem->pNode->value;
if (pVariant->nType == TSDB_DATA_TYPE_BIGINT) {
tVariantDump(pVariant, buf, TSDB_DATA_TYPE_BIGINT, true);
val = GET_INT64_VAL(buf);
@@ -1957,7 +2035,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
if (val == 1) {
index = (SColumnIndex){0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
int32_t size = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
- pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false);
+ pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false);
} else {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
@@ -1977,12 +2055,12 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
}
int32_t size = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
- pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, isTag);
+ pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, isTag);
}
} else { // count(*) is equalled to count(primary_timestamp_key)
index = (SColumnIndex){0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
int32_t size = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
- pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false);
+ pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, TSDB_DATA_TYPE_BIGINT, size, getNewResColId(pQueryInfo), size, false);
}
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
@@ -2007,29 +2085,29 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
return TSDB_CODE_SUCCESS;
}
- case TK_SUM:
- case TK_AVG:
- case TK_RATE:
- case TK_IRATE:
- case TK_SUM_RATE:
- case TK_SUM_IRATE:
- case TK_AVG_RATE:
- case TK_AVG_IRATE:
- case TK_TWA:
- case TK_MIN:
- case TK_MAX:
- case TK_DIFF:
- case TK_STDDEV:
- case TK_LEASTSQUARES: {
+ case TSDB_FUNC_SUM:
+ case TSDB_FUNC_AVG:
+ case TSDB_FUNC_RATE:
+ case TSDB_FUNC_IRATE:
+ case TSDB_FUNC_SUM_RATE:
+ case TSDB_FUNC_SUM_IRATE:
+ case TSDB_FUNC_AVG_RATE:
+ case TSDB_FUNC_AVG_IRATE:
+ case TSDB_FUNC_TWA:
+ case TSDB_FUNC_MIN:
+ case TSDB_FUNC_MAX:
+ case TSDB_FUNC_DIFF:
+ case TSDB_FUNC_STDDEV:
+ case TSDB_FUNC_LEASTSQR: {
// 1. valid the number of parameters
- if (pItem->pNode->pParam == NULL || (optr != TK_LEASTSQUARES && pItem->pNode->pParam->nExpr != 1) ||
- (optr == TK_LEASTSQUARES && pItem->pNode->pParam->nExpr != 3)) {
+ if (pItem->pNode->pParam == NULL || (functionId != TSDB_FUNC_LEASTSQR && taosArrayGetSize(pItem->pNode->pParam) != 1) ||
+ (functionId == TSDB_FUNC_LEASTSQR && taosArrayGetSize(pItem->pNode->pParam) != 3)) {
/* no parameters or more than one parameter for function */
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- tSqlExprItem* pParamElem = &(pItem->pNode->pParam->a[0]);
- if (pParamElem->pNode->nSQLOptr != TK_ALL && pParamElem->pNode->nSQLOptr != TK_ID) {
+ tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->pParam, 0);
+ if (pParamElem->pNode->tokenId != TK_ALL && pParamElem->pNode->tokenId != TK_ID) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
@@ -2049,26 +2127,21 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
if (!IS_NUMERIC_TYPE(colType)) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
- } else if (IS_UNSIGNED_NUMERIC_TYPE(colType) && optr == TK_DIFF) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg10);
+ } else if (IS_UNSIGNED_NUMERIC_TYPE(colType) && functionId == TSDB_FUNC_DIFF) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg9);
}
int16_t resultType = 0;
int16_t resultSize = 0;
int32_t intermediateResSize = 0;
- int16_t functionID = 0;
- if (convertFunctionId(optr, &functionID) != TSDB_CODE_SUCCESS) {
- return TSDB_CODE_TSC_INVALID_SQL;
- }
-
- if (getResultDataInfo(pSchema->type, pSchema->bytes, functionID, 0, &resultType, &resultSize,
+ if (getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &resultType, &resultSize,
&intermediateResSize, 0, false) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
// set the first column ts for diff query
- if (optr == TK_DIFF) {
+ if (functionId == TSDB_FUNC_DIFF) {
colIndex += 1;
SColumnIndex indexTS = {.tableIndex = index.tableIndex, .columnIndex = 0};
SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &indexTS, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE,
@@ -2083,19 +2156,19 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
- SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionID, &index, resultType, resultSize, getNewResColId(pQueryInfo), resultSize, false);
+ SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pQueryInfo), resultSize, false);
- if (optr == TK_LEASTSQUARES) {
+ if (functionId == TSDB_FUNC_LEASTSQR) {
/* set the leastsquares parameters */
char val[8] = {0};
- if (tVariantDump(&pParamElem[1].pNode->val, val, TSDB_DATA_TYPE_DOUBLE, true) < 0) {
+ if (tVariantDump(&pParamElem[1].pNode->value, val, TSDB_DATA_TYPE_DOUBLE, true) < 0) {
return TSDB_CODE_TSC_INVALID_SQL;
}
addExprParams(pExpr, val, TSDB_DATA_TYPE_DOUBLE, DOUBLE_BYTES);
memset(val, 0, tListLen(val));
- if (tVariantDump(&pParamElem[2].pNode->val, val, TSDB_DATA_TYPE_DOUBLE, true) < 0) {
+ if (tVariantDump(&pParamElem[2].pNode->value, val, TSDB_DATA_TYPE_DOUBLE, true) < 0) {
return TSDB_CODE_TSC_INVALID_SQL;
}
@@ -2121,43 +2194,38 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
tscInsertPrimaryTsSourceColumn(pQueryInfo, &index);
return TSDB_CODE_SUCCESS;
}
- case TK_FIRST:
- case TK_LAST:
- case TK_SPREAD:
- case TK_LAST_ROW:
- case TK_INTERP: {
+ case TSDB_FUNC_FIRST:
+ case TSDB_FUNC_LAST:
+ case TSDB_FUNC_SPREAD:
+ case TSDB_FUNC_LAST_ROW:
+ case TSDB_FUNC_INTERP: {
bool requireAllFields = (pItem->pNode->pParam == NULL);
- int16_t functionID = 0;
- if (convertFunctionId(optr, &functionID) != TSDB_CODE_SUCCESS) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg9);
- }
-
// NOTE: has time range condition or normal column filter condition, the last_row query will be transferred to last query
- SConvertFunc cvtFunc = {.originFuncId = functionID, .execFuncId = functionID};
- if (functionID == TSDB_FUNC_LAST_ROW && ((!TSWINDOW_IS_EQUAL(pQueryInfo->window, TSWINDOW_INITIALIZER)) || (hasNormalColumnFilter(pQueryInfo)))) {
+ SConvertFunc cvtFunc = {.originFuncId = functionId, .execFuncId = functionId};
+ if (functionId == TSDB_FUNC_LAST_ROW && ((!TSWINDOW_IS_EQUAL(pQueryInfo->window, TSWINDOW_INITIALIZER)) || (hasNormalColumnFilter(pQueryInfo)))) {
cvtFunc.execFuncId = TSDB_FUNC_LAST;
}
if (!requireAllFields) {
- if (pItem->pNode->pParam->nExpr < 1) {
+ if (taosArrayGetSize(pItem->pNode->pParam) < 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
- if (pItem->pNode->pParam->nExpr > 1 && (pItem->aliasName != NULL && strlen(pItem->aliasName) > 0)) {
+ if (taosArrayGetSize(pItem->pNode->pParam) > 1 && (pItem->aliasName != NULL && strlen(pItem->aliasName) > 0)) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg8);
}
/* in first/last function, multiple columns can be add to resultset */
- for (int32_t i = 0; i < pItem->pNode->pParam->nExpr; ++i) {
- tSqlExprItem* pParamElem = &(pItem->pNode->pParam->a[i]);
- if (pParamElem->pNode->nSQLOptr != TK_ALL && pParamElem->pNode->nSQLOptr != TK_ID) {
+ for (int32_t i = 0; i < taosArrayGetSize(pItem->pNode->pParam); ++i) {
+ tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->pParam, i);
+ if (pParamElem->pNode->tokenId != TK_ALL && pParamElem->pNode->tokenId != TK_ID) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
- if (pParamElem->pNode->nSQLOptr == TK_ALL) { // select table.*
+ if (pParamElem->pNode->tokenId == TK_ALL) { // select table.*
SStrToken tmpToken = pParamElem->pNode->colInfo;
if (getTableIndexByName(&tmpToken, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
@@ -2191,31 +2259,14 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
}
char name[TSDB_COL_NAME_LEN] = {0};
-
SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex);
- bool multiColOutput = pItem->pNode->pParam->nExpr > 1;
+ bool multiColOutput = taosArrayGetSize(pItem->pNode->pParam) > 1;
setResultColName(name, pItem, cvtFunc.originFuncId, &pParamElem->pNode->colInfo, multiColOutput);
- if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, name, colIndex + i, &index, finalResult) != 0) {
+ if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, name, colIndex++, &index, finalResult) != 0) {
return TSDB_CODE_TSC_INVALID_SQL;
}
-
- if (optr == TK_LAST) { // todo refactor
- SSqlGroupbyExpr* pGroupBy = &pQueryInfo->groupbyExpr;
- if (pGroupBy->numOfGroupCols > 0) {
- for(int32_t k = 0; k < pGroupBy->numOfGroupCols; ++k) {
- SColIndex* pIndex = taosArrayGet(pGroupBy->columnInfo, k);
- if (!TSDB_COL_IS_TAG(pIndex->flag) && pIndex->colIndex < tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) { // group by normal columns
- SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, colIndex + i);
- pExpr->numOfParams = 1;
- pExpr->param->i64 = TSDB_ORDER_ASC;
-
- break;
- }
- }
- }
- }
}
}
@@ -2242,29 +2293,28 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
if (setExprInfoForFunctions(pCmd, pQueryInfo, &pSchema[index.columnIndex], cvtFunc, name, colIndex, &index, finalResult) != 0) {
return TSDB_CODE_TSC_INVALID_SQL;
}
-
colIndex++;
}
numOfFields += tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
}
-
return TSDB_CODE_SUCCESS;
}
}
- case TK_TOP:
- case TK_BOTTOM:
- case TK_PERCENTILE:
- case TK_APERCENTILE: {
+
+ case TSDB_FUNC_TOP:
+ case TSDB_FUNC_BOTTOM:
+ case TSDB_FUNC_PERCT:
+ case TSDB_FUNC_APERCT: {
// 1. valid the number of parameters
- if (pItem->pNode->pParam == NULL || pItem->pNode->pParam->nExpr != 2) {
+ if (pItem->pNode->pParam == NULL || taosArrayGetSize(pItem->pNode->pParam) != 2) {
/* no parameters or more than one parameter for function */
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- tSqlExprItem* pParamElem = &(pItem->pNode->pParam->a[0]);
- if (pParamElem->pNode->nSQLOptr != TK_ID) {
+ tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->pParam, 0);
+ if (pParamElem->pNode->tokenId != TK_ID) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
@@ -2292,11 +2342,11 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
}
// 3. valid the parameters
- if (pParamElem[1].pNode->nSQLOptr == TK_ID) {
+ if (pParamElem[1].pNode->tokenId == TK_ID) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- tVariant* pVariant = &pParamElem[1].pNode->val;
+ tVariant* pVariant = &pParamElem[1].pNode->value;
int8_t resultType = pSchema[index.columnIndex].type;
int16_t resultSize = pSchema[index.columnIndex].bytes;
@@ -2304,7 +2354,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
char val[8] = {0};
SSqlExpr* pExpr = NULL;
- if (optr == TK_PERCENTILE || optr == TK_APERCENTILE) {
+ if (functionId == TSDB_FUNC_PERCT || functionId == TSDB_FUNC_APERCT) {
tVariantDump(pVariant, val, TSDB_DATA_TYPE_DOUBLE, true);
double dp = GET_DOUBLE_VAL(val);
@@ -2320,10 +2370,6 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
* for dp = 0, it is actually min,
* for dp = 100, it is max,
*/
- int16_t functionId = 0;
- if (convertFunctionId(optr, &functionId) != TSDB_CODE_SUCCESS) {
- return TSDB_CODE_TSC_INVALID_SQL;
- }
tscInsertPrimaryTsSourceColumn(pQueryInfo, &index);
colIndex += 1; // the first column is ts
@@ -2337,20 +2383,15 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
- int16_t functionId = 0;
- if (convertFunctionId(optr, &functionId) != TSDB_CODE_SUCCESS) {
- return TSDB_CODE_TSC_INVALID_SQL;
- }
-
// todo REFACTOR
// set the first column ts for top/bottom query
- SColumnIndex index1 = {0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
+ SColumnIndex index1 = {index.tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS, &index1, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, getNewResColId(pQueryInfo),
TSDB_KEYSIZE, false);
tstrncpy(pExpr->aliasName, aAggs[TSDB_FUNC_TS].name, sizeof(pExpr->aliasName));
const int32_t TS_COLUMN_INDEX = PRIMARYKEY_TIMESTAMP_COL_INDEX;
- SColumnList ids = getColumnList(1, 0, TS_COLUMN_INDEX);
+ SColumnList ids = getColumnList(1, index.tableIndex, TS_COLUMN_INDEX);
insertResultField(pQueryInfo, TS_COLUMN_INDEX, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP,
aAggs[TSDB_FUNC_TS].name, pExpr);
@@ -2363,7 +2404,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
memset(pExpr->aliasName, 0, tListLen(pExpr->aliasName));
getColumnName(pItem, pExpr->aliasName, sizeof(pExpr->aliasName) - 1);
- SColumnList ids = getColumnList(1, 0, index.columnIndex);
+ SColumnList ids = getColumnList(1, index.tableIndex, index.columnIndex);
if (finalResult) {
insertResultField(pQueryInfo, colIndex, &ids, resultSize, resultType, pExpr->aliasName, pExpr);
} else {
@@ -2375,19 +2416,20 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
return TSDB_CODE_SUCCESS;
};
- case TK_TBID: {
+ case TSDB_FUNC_TID_TAG: {
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7);
}
// no parameters or more than one parameter for function
- if (pItem->pNode->pParam == NULL || pItem->pNode->pParam->nExpr != 1) {
+ if (pItem->pNode->pParam == NULL || taosArrayGetSize(pItem->pNode->pParam) != 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- tSQLExpr* pParam = pItem->pNode->pParam->a[0].pNode;
-
+ tSqlExprItem* pParamItem = taosArrayGet(pItem->pNode->pParam, 0);
+ tSqlExpr* pParam = pParamItem->pNode;
+
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (getColumnIndexByName(pCmd, &pParam->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
@@ -2443,7 +2485,31 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
return TSDB_CODE_SUCCESS;
}
-
+ case TSDB_FUNC_BLKINFO: {
+ // no parameters or more than one parameter for function
+ if (pItem->pNode->pParam != NULL && taosArrayGetSize(pItem->pNode->pParam) != 0) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
+ }
+
+ SColumnIndex index = {.tableIndex = 0, .columnIndex = TSDB_BLOCK_DIST_COLUMN_INDEX,};
+ pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
+
+ SSchema s = {.name = "block_dist", .type = TSDB_DATA_TYPE_BINARY};
+ int32_t inter = 0;
+ int16_t resType = 0;
+ int16_t bytes = 0;
+ getResultDataInfo(TSDB_DATA_TYPE_INT, 4, TSDB_FUNC_BLKINFO, 0, &resType, &bytes, &inter, 0, 0);
+
+ s.bytes = bytes;
+ s.type = (uint8_t)resType;
+ SSqlExpr* pExpr = tscAddFuncInSelectClause(pQueryInfo, 0, TSDB_FUNC_BLKINFO, &index, &s, TSDB_COL_TAG);
+ pExpr->numOfParams = 1;
+ pExpr->param[0].i64 = pTableMetaInfo->pTableMeta->tableInfo.rowSize;
+ pExpr->param[0].nType = TSDB_DATA_TYPE_BIGINT;
+
+ return TSDB_CODE_SUCCESS;
+ }
+
default:
return TSDB_CODE_TSC_INVALID_SQL;
}
@@ -2468,8 +2534,8 @@ void getColumnName(tSqlExprItem* pItem, char* resultFieldName, int32_t nameLengt
if (pItem->aliasName != NULL) {
strncpy(resultFieldName, pItem->aliasName, nameLength);
} else {
- int32_t len = ((int32_t)pItem->pNode->operand.n < nameLength) ? (int32_t)pItem->pNode->operand.n : nameLength;
- strncpy(resultFieldName, pItem->pNode->operand.z, len);
+ int32_t len = ((int32_t)pItem->pNode->token.n < nameLength) ? (int32_t)pItem->pNode->token.n : nameLength;
+ strncpy(resultFieldName, pItem->pNode->token.z, len);
}
}
@@ -2609,87 +2675,6 @@ int32_t getColumnIndexByName(SSqlCmd* pCmd, const SStrToken* pToken, SQueryInfo*
return doGetColumnIndexByName(pCmd, &tmpToken, pQueryInfo, pIndex);
}
-int32_t convertFunctionId(int32_t optr, int16_t* functionId) {
- switch (optr) {
- case TK_COUNT:
- *functionId = TSDB_FUNC_COUNT;
- break;
- case TK_SUM:
- *functionId = TSDB_FUNC_SUM;
- break;
- case TK_AVG:
- *functionId = TSDB_FUNC_AVG;
- break;
- case TK_RATE:
- *functionId = TSDB_FUNC_RATE;
- break;
- case TK_IRATE:
- *functionId = TSDB_FUNC_IRATE;
- break;
- case TK_SUM_RATE:
- *functionId = TSDB_FUNC_SUM_RATE;
- break;
- case TK_SUM_IRATE:
- *functionId = TSDB_FUNC_SUM_IRATE;
- break;
- case TK_AVG_RATE:
- *functionId = TSDB_FUNC_AVG_RATE;
- break;
- case TK_AVG_IRATE:
- *functionId = TSDB_FUNC_AVG_IRATE;
- break;
- case TK_MIN:
- *functionId = TSDB_FUNC_MIN;
- break;
- case TK_MAX:
- *functionId = TSDB_FUNC_MAX;
- break;
- case TK_STDDEV:
- *functionId = TSDB_FUNC_STDDEV;
- break;
- case TK_PERCENTILE:
- *functionId = TSDB_FUNC_PERCT;
- break;
- case TK_APERCENTILE:
- *functionId = TSDB_FUNC_APERCT;
- break;
- case TK_FIRST:
- *functionId = TSDB_FUNC_FIRST;
- break;
- case TK_LAST:
- *functionId = TSDB_FUNC_LAST;
- break;
- case TK_LEASTSQUARES:
- *functionId = TSDB_FUNC_LEASTSQR;
- break;
- case TK_TOP:
- *functionId = TSDB_FUNC_TOP;
- break;
- case TK_BOTTOM:
- *functionId = TSDB_FUNC_BOTTOM;
- break;
- case TK_DIFF:
- *functionId = TSDB_FUNC_DIFF;
- break;
- case TK_SPREAD:
- *functionId = TSDB_FUNC_SPREAD;
- break;
- case TK_TWA:
- *functionId = TSDB_FUNC_TWA;
- break;
- case TK_INTERP:
- *functionId = TSDB_FUNC_INTERP;
- break;
- case TK_LAST_ROW:
- *functionId = TSDB_FUNC_LAST_ROW;
- break;
- default:
- return -1;
- }
-
- return TSDB_CODE_SUCCESS;
-}
-
int32_t setShowInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
SSqlCmd* pCmd = &pSql->cmd;
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
@@ -2943,23 +2928,23 @@ static bool groupbyTagsOrNull(SQueryInfo* pQueryInfo) {
return true;
}
-static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery, bool intervalQuery) {
+static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery, bool twQuery) {
int32_t startIdx = 0;
size_t numOfExpr = tscSqlExprNumOfExprs(pQueryInfo);
assert(numOfExpr > 0);
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, startIdx);
- int32_t functionID = pExpr->functionId;
// ts function can be simultaneously used with any other functions.
+ int32_t functionID = pExpr->functionId;
if (functionID == TSDB_FUNC_TS || functionID == TSDB_FUNC_TS_DUMMY) {
startIdx++;
}
int32_t factor = functionCompatList[tscSqlExprGet(pQueryInfo, startIdx)->functionId];
- if (tscSqlExprGet(pQueryInfo, 0)->functionId == TSDB_FUNC_LAST_ROW && (joinQuery || intervalQuery || !groupbyTagsOrNull(pQueryInfo))) {
+ if (tscSqlExprGet(pQueryInfo, 0)->functionId == TSDB_FUNC_LAST_ROW && (joinQuery || twQuery || !groupbyTagsOrNull(pQueryInfo))) {
return false;
}
@@ -2987,7 +2972,7 @@ static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery, bool
}
}
- if (functionId == TSDB_FUNC_LAST_ROW && (joinQuery || intervalQuery || !groupbyTagsOrNull(pQueryInfo))) {
+ if (functionId == TSDB_FUNC_LAST_ROW && (joinQuery || twQuery || !groupbyTagsOrNull(pQueryInfo))) {
return false;
}
}
@@ -3128,48 +3113,59 @@ static SColumnFilterInfo* addColumnFilterInfo(SColumn* pColumn) {
}
static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnFilterInfo* pColumnFilter,
- int16_t colType, tSQLExpr* pExpr) {
+ SColumnIndex* columnIndex, tSqlExpr* pExpr) {
const char* msg = "not supported filter condition";
- tSQLExpr* pRight = pExpr->pRight;
+ tSqlExpr* pRight = pExpr->pRight;
+ STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, columnIndex->tableIndex);
+
+ 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) {
colType = TSDB_DATA_TYPE_DOUBLE;
- } else if ((colType == TSDB_DATA_TYPE_TIMESTAMP) && (TSDB_DATA_TYPE_BINARY == pRight->val.nType)) {
- int retVal = setColumnFilterInfoForTimestamp(pCmd, pQueryInfo, &pRight->val);
+ } else if ((colType == TSDB_DATA_TYPE_TIMESTAMP) && (TSDB_DATA_TYPE_BINARY == pRight->value.nType)) {
+ int retVal = setColumnFilterInfoForTimestamp(pCmd, pQueryInfo, &pRight->value);
if (TSDB_CODE_SUCCESS != retVal) {
return retVal;
}
}
int32_t retVal = TSDB_CODE_SUCCESS;
- if (pExpr->nSQLOptr == TK_LE || pExpr->nSQLOptr == TK_LT) {
- retVal = tVariantDump(&pRight->val, (char*)&pColumnFilter->upperBndd, colType, false);
+
+ int32_t bufLen = 0;
+ if (IS_NUMERIC_TYPE(pRight->value.nType)) {
+ bufLen = 60;
+ } else {
+ bufLen = pRight->value.nLen + 1;
+ }
+
+ if (pExpr->tokenId == TK_LE || pExpr->tokenId == TK_LT) {
+ retVal = tVariantDump(&pRight->value, (char*)&pColumnFilter->upperBndd, colType, false);
// TK_GT,TK_GE,TK_EQ,TK_NE are based on the pColumn->lowerBndd
} else if (colType == TSDB_DATA_TYPE_BINARY) {
- pColumnFilter->pz = (int64_t)calloc(1, pRight->val.nLen + TSDB_NCHAR_SIZE);
- pColumnFilter->len = pRight->val.nLen;
- retVal = tVariantDump(&pRight->val, (char*)pColumnFilter->pz, colType, false);
+ pColumnFilter->pz = (int64_t)calloc(1, bufLen * TSDB_NCHAR_SIZE);
+ pColumnFilter->len = pRight->value.nLen;
+ retVal = tVariantDump(&pRight->value, (char*)pColumnFilter->pz, colType, false);
} else if (colType == TSDB_DATA_TYPE_NCHAR) {
- // pRight->val.nLen + 1 is larger than the actual nchar string length
- pColumnFilter->pz = (int64_t)calloc(1, (pRight->val.nLen + 1) * TSDB_NCHAR_SIZE);
- retVal = tVariantDump(&pRight->val, (char*)pColumnFilter->pz, colType, false);
+ // pRight->value.nLen + 1 is larger than the actual nchar string length
+ pColumnFilter->pz = (int64_t)calloc(1, bufLen * TSDB_NCHAR_SIZE);
+ retVal = tVariantDump(&pRight->value, (char*)pColumnFilter->pz, colType, false);
size_t len = twcslen((wchar_t*)pColumnFilter->pz);
pColumnFilter->len = len * TSDB_NCHAR_SIZE;
} else {
- retVal = tVariantDump(&pRight->val, (char*)&pColumnFilter->lowerBndd, colType, false);
+ retVal = tVariantDump(&pRight->value, (char*)&pColumnFilter->lowerBndd, colType, false);
}
if (retVal != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg);
}
- switch (pExpr->nSQLOptr) {
+ switch (pExpr->tokenId) {
case TK_LE:
pColumnFilter->upperRelOptr = TSDB_RELATION_LESS_EQUAL;
break;
@@ -3205,162 +3201,45 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
}
typedef struct SCondExpr {
- tSQLExpr* pTagCond;
- tSQLExpr* pTimewindow;
+ tSqlExpr* pTagCond;
+ tSqlExpr* pTimewindow;
- tSQLExpr* pColumnCond;
+ tSqlExpr* pColumnCond;
- tSQLExpr* pTableCond;
+ tSqlExpr* pTableCond;
int16_t relType; // relation between table name in expression and other tag
// filter condition expression, TK_AND or TK_OR
int16_t tableCondIndex;
- tSQLExpr* pJoinExpr; // join condition
+ tSqlExpr* pJoinExpr; // join condition
bool tsJoin;
} SCondExpr;
-static int32_t getTimeRange(STimeWindow* win, tSQLExpr* pRight, int32_t optr, int16_t timePrecision);
-
-static int32_t tSQLExprNodeToString(tSQLExpr* pExpr, char** str) {
- if (pExpr->nSQLOptr == TK_ID) { // column name
- strncpy(*str, pExpr->colInfo.z, pExpr->colInfo.n);
- *str += pExpr->colInfo.n;
-
- } else if (pExpr->nSQLOptr >= TK_BOOL && pExpr->nSQLOptr <= TK_STRING) { // value
- *str += tVariantToString(&pExpr->val, *str);
-
- } else if (pExpr->nSQLOptr >= TK_COUNT && pExpr->nSQLOptr <= TK_AVG_IRATE) {
- /*
- * arithmetic expression of aggregation, such as count(ts) + count(ts) *2
- */
- strncpy(*str, pExpr->operand.z, pExpr->operand.n);
- *str += pExpr->operand.n;
- } else { // not supported operation
- assert(false);
- }
-
- return TSDB_CODE_SUCCESS;
-}
-
-// pExpr->nSQLOptr == 0 while handling "is null" query
-static bool isExprLeafNode(tSQLExpr* pExpr) {
- return (pExpr->pRight == NULL && pExpr->pLeft == NULL) &&
- (pExpr->nSQLOptr == 0 || pExpr->nSQLOptr == TK_ID || (pExpr->nSQLOptr >= TK_BOOL && pExpr->nSQLOptr <= TK_NCHAR) || pExpr->nSQLOptr == TK_SET);
-}
-
-static bool isExprDirectParentOfLeafNode(tSQLExpr* pExpr) {
- return (pExpr->pLeft != NULL && pExpr->pRight != NULL) &&
- (isExprLeafNode(pExpr->pLeft) && isExprLeafNode(pExpr->pRight));
-}
-
-static int32_t tSQLExprLeafToString(tSQLExpr* pExpr, bool addParentheses, char** output) {
- if (!isExprDirectParentOfLeafNode(pExpr)) {
- return TSDB_CODE_TSC_INVALID_SQL;
- }
-
- tSQLExpr* pLeft = pExpr->pLeft;
- tSQLExpr* pRight = pExpr->pRight;
-
- if (addParentheses) {
- *(*output) = '(';
- *output += 1;
- }
-
- tSQLExprNodeToString(pLeft, output);
- if (optrToString(pExpr, output) != TSDB_CODE_SUCCESS) {
- return TSDB_CODE_TSC_INVALID_SQL;
- }
-
- tSQLExprNodeToString(pRight, output);
-
- if (addParentheses) {
- *(*output) = ')';
- *output += 1;
- }
+static int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t timePrecision);
- return TSDB_CODE_SUCCESS;
-}
-
-static int32_t optrToString(tSQLExpr* pExpr, char** exprString) {
- const char* le = "<=";
- const char* ge = ">=";
- const char* ne = "<>";
- const char* likeOptr = "LIKE";
-
- switch (pExpr->nSQLOptr) {
- case TK_LE: {
- *(int16_t*)(*exprString) = *(int16_t*)le;
- *exprString += 1;
- break;
- }
- case TK_GE: {
- *(int16_t*)(*exprString) = *(int16_t*)ge;
- *exprString += 1;
- break;
- }
- case TK_NE: {
- *(int16_t*)(*exprString) = *(int16_t*)ne;
- *exprString += 1;
- break;
- }
-
- case TK_LT:
- *(*exprString) = '<';
- break;
- case TK_GT:
- *(*exprString) = '>';
- break;
- case TK_EQ:
- *(*exprString) = '=';
- break;
- case TK_PLUS:
- *(*exprString) = '+';
- break;
- case TK_MINUS:
- *(*exprString) = '-';
- break;
- case TK_STAR:
- *(*exprString) = '*';
- break;
- case TK_DIVIDE:
- *(*exprString) = '/';
- break;
- case TK_REM:
- *(*exprString) = '%';
- break;
- case TK_LIKE: {
- int32_t len = sprintf(*exprString, " %s ", likeOptr);
- *exprString += (len - 1);
- break;
- }
- default:
- return TSDB_CODE_TSC_INVALID_SQL;
- }
-
- *exprString += 1;
-
- return TSDB_CODE_SUCCESS;
-}
+static int32_t tablenameListToString(tSqlExpr* pExpr, SStringBuilder* sb) {
+ SArray* pList = pExpr->pParam;
-static int32_t tablenameListToString(tSQLExpr* pExpr, SStringBuilder* sb) {
- tSQLExprList* pList = pExpr->pParam;
- if (pList->nExpr <= 0) {
+ int32_t size = (int32_t) taosArrayGetSize(pList);
+ if (size <= 0) {
return TSDB_CODE_TSC_INVALID_SQL;
}
- if (pList->nExpr > 0) {
+ if (size > 0) {
taosStringBuilderAppendStringLen(sb, QUERY_COND_REL_PREFIX_IN, QUERY_COND_REL_PREFIX_IN_LEN);
}
- for (int32_t i = 0; i < pList->nExpr; ++i) {
- tSQLExpr* pSub = pList->a[i].pNode;
- taosStringBuilderAppendStringLen(sb, pSub->val.pz, pSub->val.nLen);
+ for (int32_t i = 0; i < size; ++i) {
+ tSqlExprItem* pSub = taosArrayGet(pList, i);
+ tVariant* pVar = &pSub->pNode->value;
+
+ taosStringBuilderAppendStringLen(sb, pVar->pz, pVar->nLen);
- if (i < pList->nExpr - 1) {
+ if (i < size - 1) {
taosStringBuilderAppendString(sb, TBNAME_LIST_SEP);
}
- if (pSub->val.nLen <= 0 || !tscValidateTableNameLength(pSub->val.nLen)) {
+ if (pVar->nLen <= 0 || !tscValidateTableNameLength(pVar->nLen)) {
return TSDB_CODE_TSC_INVALID_SQL;
}
}
@@ -3368,9 +3247,9 @@ static int32_t tablenameListToString(tSQLExpr* pExpr, SStringBuilder* sb) {
return TSDB_CODE_SUCCESS;
}
-static int32_t tablenameCondToString(tSQLExpr* pExpr, SStringBuilder* sb) {
+static int32_t tablenameCondToString(tSqlExpr* pExpr, SStringBuilder* sb) {
taosStringBuilderAppendStringLen(sb, QUERY_COND_REL_PREFIX_LIKE, QUERY_COND_REL_PREFIX_LIKE_LEN);
- taosStringBuilderAppendString(sb, pExpr->val.pz);
+ taosStringBuilderAppendString(sb, pExpr->value.pz);
return TSDB_CODE_SUCCESS;
}
@@ -3382,7 +3261,7 @@ enum {
TSQL_EXPR_TBNAME = 3,
};
-static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnIndex* pIndex, tSQLExpr* pExpr, int32_t sqlOptr) {
+static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnIndex* pIndex, tSqlExpr* pExpr, int32_t sqlOptr) {
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, pIndex->tableIndex);
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
@@ -3424,78 +3303,34 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC
((pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) ? 1 : 0);
if (pColFilter->filterstr) {
- if (pExpr->nSQLOptr != TK_EQ
- && pExpr->nSQLOptr != TK_NE
- && pExpr->nSQLOptr != TK_ISNULL
- && pExpr->nSQLOptr != TK_NOTNULL
- && pExpr->nSQLOptr != TK_LIKE
+ 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->nSQLOptr == TK_LIKE) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
- }
-
- if (pSchema->type == TSDB_DATA_TYPE_BOOL) {
- if (pExpr->nSQLOptr != TK_EQ && pExpr->nSQLOptr != TK_NE) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
- }
- }
- }
-
- pColumn->colIndex = *pIndex;
-
- int16_t colType = pSchema->type;
-
- return doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, colType, pExpr);
-}
-
-static void relToString(tSQLExpr* pExpr, char** str) {
- assert(pExpr->nSQLOptr == TK_AND || pExpr->nSQLOptr == TK_OR);
-
- const char* or = "OR";
- const char*and = "AND";
-
- // if (pQueryInfo->tagCond.relType == TSQL_STABLE_QTYPE_COND) {
- if (pExpr->nSQLOptr == TK_AND) {
- strcpy(*str, and);
- *str += strlen(and);
- } else {
- strcpy(*str, or);
- *str += strlen(or);
- }
-}
-
-UNUSED_FUNC
-static int32_t getTagCondString(tSQLExpr* pExpr, char** str) {
- if (pExpr == NULL) {
- return TSDB_CODE_SUCCESS;
- }
-
- if (!isExprDirectParentOfLeafNode(pExpr)) {
- *(*str) = '(';
- *str += 1;
-
- int32_t ret = getTagCondString(pExpr->pLeft, str);
- if (ret != TSDB_CODE_SUCCESS) {
- return ret;
+ } else {
+ if (pExpr->tokenId == TK_LIKE) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
+ }
+
+ if (pSchema->type == TSDB_DATA_TYPE_BOOL) {
+ if (pExpr->tokenId != TK_EQ && pExpr->tokenId != TK_NE) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
+ }
}
-
- relToString(pExpr, str);
-
- ret = getTagCondString(pExpr->pRight, str);
-
- *(*str) = ')';
- *str += 1;
-
- return ret;
}
- return tSQLExprLeafToString(pExpr, true, str);
+ pColumn->colIndex = *pIndex;
+
+ int16_t colType = pSchema->type;
+
+ return doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, colType, pExpr);
}
-static int32_t getTablenameCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pTableCond, SStringBuilder* sb) {
+static int32_t getTablenameCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pTableCond, SStringBuilder* sb) {
const char* msg0 = "invalid table name list";
const char* msg1 = "not string following like";
@@ -3503,8 +3338,8 @@ static int32_t getTablenameCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr*
return TSDB_CODE_SUCCESS;
}
- tSQLExpr* pLeft = pTableCond->pLeft;
- tSQLExpr* pRight = pTableCond->pRight;
+ tSqlExpr* pLeft = pTableCond->pLeft;
+ tSqlExpr* pRight = pTableCond->pRight;
if (!isTablenameToken(&pLeft->colInfo)) {
return TSDB_CODE_TSC_INVALID_SQL;
@@ -3512,10 +3347,10 @@ static int32_t getTablenameCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr*
int32_t ret = TSDB_CODE_SUCCESS;
- if (pTableCond->nSQLOptr == TK_IN) {
+ if (pTableCond->tokenId == TK_IN) {
ret = tablenameListToString(pRight, sb);
- } else if (pTableCond->nSQLOptr == TK_LIKE) {
- if (pRight->nSQLOptr != TK_STRING) {
+ } else if (pTableCond->tokenId == TK_LIKE) {
+ if (pRight->tokenId != TK_STRING) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
@@ -3529,18 +3364,18 @@ static int32_t getTablenameCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr*
return ret;
}
-static int32_t getColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr, int32_t relOptr) {
+static int32_t getColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, int32_t relOptr) {
if (pExpr == NULL) {
return TSDB_CODE_SUCCESS;
}
- if (!isExprDirectParentOfLeafNode(pExpr)) { // internal node
- int32_t ret = getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pLeft, pExpr->nSQLOptr);
+ if (!tSqlExprIsParentOfLeaf(pExpr)) { // internal node
+ int32_t ret = getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pLeft, pExpr->tokenId);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
- return getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pRight, pExpr->nSQLOptr);
+ return getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pRight, pExpr->tokenId);
} else { // handle leaf node
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (getColumnIndexByName(pCmd, &pExpr->pLeft->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
@@ -3551,24 +3386,26 @@ static int32_t getColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQ
}
}
-static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr) {
- const char* msg1 = "invalid join query condition";
- const char* msg2 = "invalid table name in join query";
+static int32_t checkAndSetJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) {
+ int32_t code = 0;
+ const char* msg1 = "timestamp required for join tables";
const char* msg3 = "type of join columns must be identical";
const char* msg4 = "invalid column name in join condition";
+ const char* msg5 = "only support one join tag for each table";
if (pExpr == NULL) {
return TSDB_CODE_SUCCESS;
}
- if (!isExprDirectParentOfLeafNode(pExpr)) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
+ if (!tSqlExprIsParentOfLeaf(pExpr)) {
+ code = checkAndSetJoinCondInfo(pCmd, pQueryInfo, pExpr->pLeft);
+ if (code) {
+ return code;
+ }
+
+ return checkAndSetJoinCondInfo(pCmd, pQueryInfo, pExpr->pRight);
}
- STagCond* pTagCond = &pQueryInfo->tagCond;
- SJoinNode* pLeft = &pTagCond->joinInfo.left;
- SJoinNode* pRight = &pTagCond->joinInfo.right;
-
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (getColumnIndexByName(pCmd, &pExpr->pLeft->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
@@ -3577,14 +3414,29 @@ static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr*
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
SSchema* pTagSchema1 = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex);
- pLeft->uid = pTableMetaInfo->pTableMeta->id.uid;
- pLeft->tagColId = pTagSchema1->colId;
+ assert(index.tableIndex >= 0 && index.tableIndex < TSDB_MAX_JOIN_TABLE_NUM);
- int32_t code = tNameExtractFullName(&pTableMetaInfo->name, pLeft->tableName);
- if (code != TSDB_CODE_SUCCESS) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
+ SJoinNode **leftNode = &pQueryInfo->tagCond.joinInfo.joinTables[index.tableIndex];
+ if (*leftNode == NULL) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
+ }
+
+ (*leftNode)->uid = pTableMetaInfo->pTableMeta->id.uid;
+ (*leftNode)->tagColId = pTagSchema1->colId;
+
+ if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
+ index.columnIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
+ if (!tscColumnExists(pTableMetaInfo->tagColList, &index)) {
+ tscColumnListInsert(pTableMetaInfo->tagColList, &index);
+ if (taosArrayGetSize(pTableMetaInfo->tagColList) > 1) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
+ }
+ }
}
+ int16_t leftIdx = index.tableIndex;
+
+
index = (SColumnIndex)COLUMN_INDEX_INITIALIZER;
if (getColumnIndexByName(pCmd, &pExpr->pRight->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
@@ -3593,25 +3445,60 @@ static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr*
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
SSchema* pTagSchema2 = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex);
- pRight->uid = pTableMetaInfo->pTableMeta->id.uid;
- pRight->tagColId = pTagSchema2->colId;
+ assert(index.tableIndex >= 0 && index.tableIndex < TSDB_MAX_JOIN_TABLE_NUM);
- code = tNameExtractFullName(&pTableMetaInfo->name, pRight->tableName);
- if (code != TSDB_CODE_SUCCESS) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
+ SJoinNode **rightNode = &pQueryInfo->tagCond.joinInfo.joinTables[index.tableIndex];
+ if (*rightNode == NULL) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
+ }
+
+ (*rightNode)->uid = pTableMetaInfo->pTableMeta->id.uid;
+ (*rightNode)->tagColId = pTagSchema2->colId;
+
+ if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
+ index.columnIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
+ if (!tscColumnExists(pTableMetaInfo->tagColList, &index)) {
+ tscColumnListInsert(pTableMetaInfo->tagColList, &index);
+ if (taosArrayGetSize(pTableMetaInfo->tagColList) > 1) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
+ }
+ }
}
+ int16_t rightIdx = index.tableIndex;
+
if (pTagSchema1->type != pTagSchema2->type) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
- pTagCond->joinInfo.hasJoin = true;
+ if ((*leftNode)->tagJoin == NULL) {
+ (*leftNode)->tagJoin = taosArrayInit(2, sizeof(int16_t));
+ }
+
+ if ((*rightNode)->tagJoin == NULL) {
+ (*rightNode)->tagJoin = taosArrayInit(2, sizeof(int16_t));
+ }
+
+ taosArrayPush((*leftNode)->tagJoin, &rightIdx);
+ taosArrayPush((*rightNode)->tagJoin, &leftIdx);
+
+ pQueryInfo->tagCond.joinInfo.hasJoin = true;
+
return TSDB_CODE_SUCCESS;
+
+}
+
+static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) {
+ if (pExpr == NULL) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ return checkAndSetJoinCondInfo(pCmd, pQueryInfo, pExpr);
}
-static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList,
- int32_t* type, uint64_t* uid) {
- if (pExpr->nSQLOptr == TK_ID) {
+static int32_t validateSQLExpr(SSqlCmd* pCmd, tSqlExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList,
+ int32_t* type, uint64_t* uid) {
+ if (pExpr->type == SQL_NODE_TABLE_COLUMN) {
if (*type == NON_ARITHMEIC_EXPR) {
*type = NORMAL_ARITHMETIC;
} else if (*type == AGG_ARIGHTMEIC) {
@@ -3633,9 +3520,9 @@ static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQuer
}
pList->ids[pList->num++] = index;
- } else if (pExpr->nSQLOptr == TK_FLOAT && (isnan(pExpr->val.dKey) || isinf(pExpr->val.dKey))) {
+ } else if (pExpr->tokenId == TK_FLOAT && (isnan(pExpr->value.dKey) || isinf(pExpr->value.dKey))) {
return TSDB_CODE_TSC_INVALID_SQL;
- } else if (pExpr->nSQLOptr >= TK_COUNT && pExpr->nSQLOptr <= TK_AVG_IRATE) {
+ } else if (pExpr->type == SQL_NODE_SQLFUNCTION) {
if (*type == NON_ARITHMEIC_EXPR) {
*type = AGG_ARIGHTMEIC;
} else if (*type == NORMAL_ARITHMETIC) {
@@ -3648,6 +3535,11 @@ static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQuer
// sql function list in selection clause.
// Append the sqlExpr into exprList of pQueryInfo structure sequentially
+ pExpr->functionId = isValidFunction(pExpr->operand.z, pExpr->operand.n);
+ if (pExpr->functionId < 0) {
+ return TSDB_CODE_TSC_INVALID_SQL;
+ }
+
if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, &item, false) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
@@ -3680,16 +3572,16 @@ static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQuer
return TSDB_CODE_SUCCESS;
}
-static int32_t validateArithmeticSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, int32_t* type) {
+static int32_t validateArithmeticSQLExpr(SSqlCmd* pCmd, tSqlExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, int32_t* type) {
if (pExpr == NULL) {
return TSDB_CODE_SUCCESS;
}
- tSQLExpr* pLeft = pExpr->pLeft;
+ tSqlExpr* pLeft = pExpr->pLeft;
uint64_t uidLeft = 0;
uint64_t uidRight = 0;
- if (pLeft->nSQLOptr >= TK_PLUS && pLeft->nSQLOptr <= TK_REM) {
+ if (pLeft->type == SQL_NODE_EXPR) {
int32_t ret = validateArithmeticSQLExpr(pCmd, pLeft, pQueryInfo, pList, type);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
@@ -3701,8 +3593,8 @@ static int32_t validateArithmeticSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryI
}
}
- tSQLExpr* pRight = pExpr->pRight;
- if (pRight->nSQLOptr >= TK_PLUS && pRight->nSQLOptr <= TK_REM) {
+ tSqlExpr* pRight = pExpr->pRight;
+ if (pRight->type == SQL_NODE_EXPR) {
int32_t ret = validateArithmeticSQLExpr(pCmd, pRight, pQueryInfo, pList, type);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
@@ -3722,7 +3614,7 @@ static int32_t validateArithmeticSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryI
return TSDB_CODE_SUCCESS;
}
-static bool isValidExpr(tSQLExpr* pLeft, tSQLExpr* pRight, int32_t optr) {
+static bool isValidExpr(tSqlExpr* pLeft, tSqlExpr* pRight, int32_t optr) {
if (pLeft == NULL || (pRight == NULL && optr != TK_IN)) {
return false;
}
@@ -3735,44 +3627,70 @@ static bool isValidExpr(tSQLExpr* pLeft, tSQLExpr* pRight, int32_t optr) {
*
* However, columnA < 4+12 is valid
*/
- if (pLeft->nSQLOptr >= TK_COUNT && pLeft->nSQLOptr <= TK_AVG_IRATE) {
+ if (pLeft->type == SQL_NODE_SQLFUNCTION) {
return false;
}
if (pRight == NULL) {
return true;
}
-
- if (pRight->nSQLOptr >= TK_COUNT && pRight->nSQLOptr <= TK_AVG_IRATE) {
- return false;
- }
- if (pLeft->nSQLOptr >= TK_BOOL
- && pLeft->nSQLOptr <= TK_BINARY
- && pRight->nSQLOptr >= TK_BOOL
- && pRight->nSQLOptr <= TK_BINARY) {
+ if (pLeft->tokenId >= TK_BOOL && pLeft->tokenId <= TK_BINARY && pRight->tokenId >= TK_BOOL && pRight->tokenId <= TK_BINARY) {
return false;
}
return true;
}
+static void exchangeExpr(tSqlExpr* pExpr) {
+ tSqlExpr* pLeft = pExpr->pLeft;
+ tSqlExpr* pRight = pExpr->pRight;
+
+ if (pRight->tokenId == TK_ID && (pLeft->tokenId == TK_INTEGER || pLeft->tokenId == TK_FLOAT ||
+ pLeft->tokenId == TK_STRING || pLeft->tokenId == TK_BOOL)) {
+ /*
+ * exchange value of the left handside and the value of the right-handside
+ * to make sure that the value of filter expression always locates in
+ * right-handside and
+ * the column-id is at the left handside.
+ */
+ uint32_t optr = 0;
+ switch (pExpr->tokenId) {
+ case TK_LE:
+ optr = TK_GE;
+ break;
+ case TK_LT:
+ optr = TK_GT;
+ break;
+ case TK_GT:
+ optr = TK_LT;
+ break;
+ case TK_GE:
+ optr = TK_LE;
+ break;
+ default:
+ optr = pExpr->tokenId;
+ }
+ pExpr->tokenId = optr;
+ SWAP(pExpr->pLeft, pExpr->pRight, void*);
+ }
+}
-static bool validateJoinExprNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr, SColumnIndex* pLeftIndex) {
+static bool validateJoinExprNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, SColumnIndex* pLeftIndex) {
const char* msg1 = "illegal column name";
const char* msg2 = "= is expected in join expression";
const char* msg3 = "join column must have same type";
const char* msg4 = "self join is not allowed";
const char* msg5 = "join table must be the same type(table to table, super table to super table)";
- tSQLExpr* pRight = pExpr->pRight;
+ tSqlExpr* pRight = pExpr->pRight;
- if (pRight->nSQLOptr != TK_ID) {
+ if (pRight->tokenId != TK_ID) {
return true;
}
- if (pExpr->nSQLOptr != TK_EQ) {
+ if (pExpr->tokenId != TK_EQ) {
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
return false;
}
@@ -3810,11 +3728,11 @@ static bool validateJoinExprNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr
return true;
}
-static bool validTableNameOptr(tSQLExpr* pExpr) {
+static bool validTableNameOptr(tSqlExpr* pExpr) {
const char nameFilterOptr[] = {TK_IN, TK_LIKE};
for (int32_t i = 0; i < tListLen(nameFilterOptr); ++i) {
- if (pExpr->nSQLOptr == nameFilterOptr[i]) {
+ if (pExpr->tokenId == nameFilterOptr[i]) {
return true;
}
}
@@ -3822,7 +3740,7 @@ static bool validTableNameOptr(tSQLExpr* pExpr) {
return false;
}
-static int32_t setExprToCond(tSQLExpr** parent, tSQLExpr* pExpr, const char* msg, int32_t parentOptr, char* msgBuf) {
+static int32_t setExprToCond(tSqlExpr** parent, tSqlExpr* pExpr, const char* msg, int32_t parentOptr, char* msgBuf) {
if (*parent != NULL) {
if (parentOptr == TK_OR && msg != NULL) {
return invalidSqlErrMsg(msgBuf, msg);
@@ -3836,19 +3754,19 @@ static int32_t setExprToCond(tSQLExpr** parent, tSQLExpr* pExpr, const char* msg
return TSDB_CODE_SUCCESS;
}
-static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SCondExpr* pCondExpr,
+static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr,
int32_t* type, int32_t parentOptr) {
const char* msg1 = "table query cannot use tags filter";
const char* msg2 = "illegal column name";
const char* msg3 = "only one query time range allowed";
- const char* msg4 = "only one join condition allowed";
+ const char* msg4 = "too many join tables";
const char* msg5 = "not support ordinary column join";
const char* msg6 = "only one query condition on tbname allowed";
const char* msg7 = "only in/like allowed in filter table name";
const char* msg8 = "wildcard string should be less than 20 characters";
- tSQLExpr* pLeft = (*pExpr)->pLeft;
- tSQLExpr* pRight = (*pExpr)->pRight;
+ tSqlExpr* pLeft = (*pExpr)->pLeft;
+ tSqlExpr* pRight = (*pExpr)->pRight;
int32_t ret = TSDB_CODE_SUCCESS;
@@ -3857,7 +3775,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- assert(isExprDirectParentOfLeafNode(*pExpr));
+ assert(tSqlExprIsParentOfLeaf(*pExpr));
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
@@ -3868,10 +3786,51 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL
}
// set join query condition
- if (pRight->nSQLOptr == TK_ID) { // no need to keep the timestamp join condition
+ if (pRight->tokenId == TK_ID) { // no need to keep the timestamp join condition
TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_QUERY);
pCondExpr->tsJoin = true;
+ assert(index.tableIndex >= 0 && index.tableIndex < TSDB_MAX_JOIN_TABLE_NUM);
+ SJoinNode **leftNode = &pQueryInfo->tagCond.joinInfo.joinTables[index.tableIndex];
+ if (*leftNode == NULL) {
+ *leftNode = calloc(1, sizeof(SJoinNode));
+ if (*leftNode == NULL) {
+ return TSDB_CODE_TSC_OUT_OF_MEMORY;
+ }
+ }
+
+ int16_t leftIdx = index.tableIndex;
+
+ SColumnIndex index = COLUMN_INDEX_INITIALIZER;
+ if (getColumnIndexByName(pCmd, &pRight->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
+ }
+
+ if (index.tableIndex < 0 || index.tableIndex >= TSDB_MAX_JOIN_TABLE_NUM) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
+ }
+
+ SJoinNode **rightNode = &pQueryInfo->tagCond.joinInfo.joinTables[index.tableIndex];
+ if (*rightNode == NULL) {
+ *rightNode = calloc(1, sizeof(SJoinNode));
+ if (*rightNode == NULL) {
+ return TSDB_CODE_TSC_OUT_OF_MEMORY;
+ }
+ }
+
+ int16_t rightIdx = index.tableIndex;
+
+ if ((*leftNode)->tsJoin == NULL) {
+ (*leftNode)->tsJoin = taosArrayInit(2, sizeof(int16_t));
+ }
+
+ if ((*rightNode)->tsJoin == NULL) {
+ (*rightNode)->tsJoin = taosArrayInit(2, sizeof(int16_t));
+ }
+
+ taosArrayPush((*leftNode)->tsJoin, &rightIdx);
+ taosArrayPush((*rightNode)->tsJoin, &leftIdx);
+
/*
* to release expression, e.g., m1.ts = m2.ts,
* since this expression is used to set the join query type
@@ -3890,8 +3849,8 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL
}
// check for like expression
- if ((*pExpr)->nSQLOptr == TK_LIKE) {
- if (pRight->val.nLen > TSDB_PATTERN_STRING_MAX_LEN) {
+ if ((*pExpr)->tokenId == TK_LIKE) {
+ if (pRight->value.nLen > TSDB_PATTERN_STRING_MAX_LEN) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg8);
}
@@ -3924,15 +3883,11 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL
*type = TSQL_EXPR_TBNAME;
*pExpr = NULL;
} else {
- if (pRight != NULL && pRight->nSQLOptr == TK_ID) { // join on tag columns for stable query
+ if (pRight != NULL && pRight->tokenId == TK_ID) { // join on tag columns for stable query
if (!validateJoinExprNode(pCmd, pQueryInfo, *pExpr, &index)) {
return TSDB_CODE_TSC_INVALID_SQL;
}
- if (pCondExpr->pJoinExpr != NULL) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
- }
-
pQueryInfo->type |= TSDB_QUERY_TYPE_JOIN_QUERY;
ret = setExprToCond(&pCondExpr->pJoinExpr, *pExpr, NULL, parentOptr, pQueryInfo->msg);
*pExpr = NULL;
@@ -3948,7 +3903,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL
} else { // query on other columns
*type = TSQL_EXPR_COLUMN;
- if (pRight->nSQLOptr == TK_ID) { // other column cannot be served as the join column
+ if (pRight->tokenId == TK_ID) { // other column cannot be served as the join column
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
@@ -3959,7 +3914,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL
return ret;
}
-int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SCondExpr* pCondExpr,
+int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr,
int32_t* type, int32_t parentOptr) {
if (pExpr == NULL) {
return TSDB_CODE_SUCCESS;
@@ -3967,23 +3922,23 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr
const char* msg1 = "query condition between different columns must use 'AND'";
- tSQLExpr* pLeft = (*pExpr)->pLeft;
- tSQLExpr* pRight = (*pExpr)->pRight;
+ tSqlExpr* pLeft = (*pExpr)->pLeft;
+ tSqlExpr* pRight = (*pExpr)->pRight;
- if (!isValidExpr(pLeft, pRight, (*pExpr)->nSQLOptr)) {
+ if (!isValidExpr(pLeft, pRight, (*pExpr)->tokenId)) {
return TSDB_CODE_TSC_INVALID_SQL;
}
int32_t leftType = -1;
int32_t rightType = -1;
- if (!isExprDirectParentOfLeafNode(*pExpr)) {
- int32_t ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, &leftType, (*pExpr)->nSQLOptr);
+ if (!tSqlExprIsParentOfLeaf(*pExpr)) {
+ int32_t ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, &leftType, (*pExpr)->tokenId);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
- ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, pCondExpr, &rightType, (*pExpr)->nSQLOptr);
+ ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, pCondExpr, &rightType, (*pExpr)->tokenId);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
@@ -3993,7 +3948,7 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr
* expression is not valid for parent node, it must be TK_AND operator.
*/
if (leftType != rightType) {
- if ((*pExpr)->nSQLOptr == TK_OR && (leftType + rightType != TSQL_EXPR_TBNAME + TSQL_EXPR_TAG)) {
+ if ((*pExpr)->tokenId == TK_OR && (leftType + rightType != TSQL_EXPR_TBNAME + TSQL_EXPR_TAG)) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
}
@@ -4007,40 +3962,9 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr
return handleExprInQueryCond(pCmd, pQueryInfo, pExpr, pCondExpr, type, parentOptr);
}
-static void doCompactQueryExpr(tSQLExpr** pExpr) {
- if (*pExpr == NULL || isExprDirectParentOfLeafNode(*pExpr)) {
- return;
- }
-
- if ((*pExpr)->pLeft) {
- doCompactQueryExpr(&(*pExpr)->pLeft);
- }
-
- if ((*pExpr)->pRight) {
- doCompactQueryExpr(&(*pExpr)->pRight);
- }
-
- if ((*pExpr)->pLeft == NULL && (*pExpr)->pRight == NULL &&
- ((*pExpr)->nSQLOptr == TK_OR || (*pExpr)->nSQLOptr == TK_AND)) {
- tSqlExprNodeDestroy(*pExpr);
- *pExpr = NULL;
-
- } else if ((*pExpr)->pLeft == NULL && (*pExpr)->pRight != NULL) {
- tSQLExpr* tmpPtr = (*pExpr)->pRight;
- tSqlExprNodeDestroy(*pExpr);
-
- (*pExpr) = tmpPtr;
- } else if ((*pExpr)->pRight == NULL && (*pExpr)->pLeft != NULL) {
- tSQLExpr* tmpPtr = (*pExpr)->pLeft;
- tSqlExprNodeDestroy(*pExpr);
-
- (*pExpr) = tmpPtr;
- }
-}
-
-static void doExtractExprForSTable(SSqlCmd* pCmd, tSQLExpr** pExpr, SQueryInfo* pQueryInfo, tSQLExpr** pOut, int32_t tableIndex) {
- if (isExprDirectParentOfLeafNode(*pExpr)) {
- tSQLExpr* pLeft = (*pExpr)->pLeft;
+static void doExtractExprForSTable(SSqlCmd* pCmd, tSqlExpr** pExpr, SQueryInfo* pQueryInfo, tSqlExpr** pOut, int32_t tableIndex) {
+ if (tSqlExprIsParentOfLeaf(*pExpr)) {
+ tSqlExpr* pLeft = (*pExpr)->pLeft;
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (getColumnIndexByName(pCmd, &pLeft->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
@@ -4055,19 +3979,19 @@ static void doExtractExprForSTable(SSqlCmd* pCmd, tSQLExpr** pExpr, SQueryInfo*
(*pExpr) = NULL;
} else {
- *pOut = tSqlExprCreate(NULL, NULL, (*pExpr)->nSQLOptr);
+ *pOut = tSqlExprCreate(NULL, NULL, (*pExpr)->tokenId);
doExtractExprForSTable(pCmd, &(*pExpr)->pLeft, pQueryInfo, &((*pOut)->pLeft), tableIndex);
doExtractExprForSTable(pCmd, &(*pExpr)->pRight, pQueryInfo, &((*pOut)->pRight), tableIndex);
}
}
-static tSQLExpr* extractExprForSTable(SSqlCmd* pCmd, tSQLExpr** pExpr, SQueryInfo* pQueryInfo, int32_t tableIndex) {
- tSQLExpr* pResExpr = NULL;
+static tSqlExpr* extractExprForSTable(SSqlCmd* pCmd, tSqlExpr** pExpr, SQueryInfo* pQueryInfo, int32_t tableIndex) {
+ tSqlExpr* pResExpr = NULL;
if (*pExpr != NULL) {
doExtractExprForSTable(pCmd, pExpr, pQueryInfo, &pResExpr, tableIndex);
- doCompactQueryExpr(&pResExpr);
+ tSqlExprCompact(&pResExpr);
}
return pResExpr;
@@ -4087,7 +4011,7 @@ int tableNameCompar(const void* lhs, const void* rhs) {
}
static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, const char* account,
- tSQLExpr* pExpr, int16_t tableCondIndex, SStringBuilder* sb) {
+ tSqlExpr* pExpr, int16_t tableCondIndex, SStringBuilder* sb) {
const char* msg = "table name too long";
if (pExpr == NULL) {
@@ -4099,9 +4023,9 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
STagCond* pTagCond = &pQueryInfo->tagCond;
pTagCond->tbnameCond.uid = pTableMetaInfo->pTableMeta->id.uid;
- assert(pExpr->nSQLOptr == TK_LIKE || pExpr->nSQLOptr == TK_IN);
+ assert(pExpr->tokenId == TK_LIKE || pExpr->tokenId == TK_IN);
- if (pExpr->nSQLOptr == TK_LIKE) {
+ if (pExpr->tokenId == TK_LIKE) {
char* str = taosStringBuilderGetResult(sb, NULL);
pQueryInfo->tagCond.tbnameCond.cond = strdup(str);
pQueryInfo->tagCond.tbnameCond.len = (int32_t) strlen(str);
@@ -4188,21 +4112,25 @@ static bool validateFilterExpr(SQueryInfo* pQueryInfo) {
return true;
}
-static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr) {
+static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) {
const char* msg0 = "invalid timestamp";
const char* msg1 = "only one time stamp window allowed";
-
+ int32_t code = 0;
+
if (pExpr == NULL) {
return TSDB_CODE_SUCCESS;
}
- if (!isExprDirectParentOfLeafNode(pExpr)) {
- if (pExpr->nSQLOptr == TK_OR) {
+ if (!tSqlExprIsParentOfLeaf(pExpr)) {
+ if (pExpr->tokenId == TK_OR) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
- getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pLeft);
-
+ code = getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pLeft);
+ if (code) {
+ return code;
+ }
+
return getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pRight);
} else {
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
@@ -4213,10 +4141,10 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLE
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
- tSQLExpr* pRight = pExpr->pRight;
+ tSqlExpr* pRight = pExpr->pRight;
STimeWindow win = {.skey = INT64_MIN, .ekey = INT64_MAX};
- if (getTimeRange(&win, pRight, pExpr->nSQLOptr, tinfo.precision) != TSDB_CODE_SUCCESS) {
+ if (getTimeRange(&win, pRight, pExpr->tokenId, tinfo.precision) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg0);
}
@@ -4283,6 +4211,7 @@ static void cleanQueryExpr(SCondExpr* pCondExpr) {
}
}
+/*
static void doAddJoinTagsColumnsIntoTagList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondExpr* pCondExpr) {
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
if (QUERY_IS_JOIN_QUERY(pQueryInfo->type) && UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
@@ -4305,6 +4234,7 @@ static void doAddJoinTagsColumnsIntoTagList(SSqlCmd* pCmd, SQueryInfo* pQueryInf
tscColumnListInsert(pTableMetaInfo->tagColList, &index);
}
}
+*/
static int32_t validateTagCondExpr(SSqlCmd* pCmd, tExprNode *p) {
const char *msg1 = "invalid tag operator";
@@ -4355,13 +4285,21 @@ static int32_t validateTagCondExpr(SSqlCmd* pCmd, tExprNode *p) {
}
int32_t retVal = TSDB_CODE_SUCCESS;
+
+ int32_t bufLen = 0;
+ if (IS_NUMERIC_TYPE(vVariant->nType)) {
+ bufLen = 60; // The maximum length of string that a number is converted to.
+ } else {
+ bufLen = vVariant->nLen + 1;
+ }
+
if (schemaType == TSDB_DATA_TYPE_BINARY) {
- char *tmp = calloc(1, vVariant->nLen + TSDB_NCHAR_SIZE);
+ char *tmp = calloc(1, bufLen * TSDB_NCHAR_SIZE);
retVal = tVariantDump(vVariant, tmp, schemaType, false);
free(tmp);
} else if (schemaType == TSDB_DATA_TYPE_NCHAR) {
- // pRight->val.nLen + 1 is larger than the actual nchar string length
- char *tmp = calloc(1, (vVariant->nLen + 1) * TSDB_NCHAR_SIZE);
+ // pRight->value.nLen + 1 is larger than the actual nchar string length
+ char *tmp = calloc(1, bufLen * TSDB_NCHAR_SIZE);
retVal = tVariantDump(vVariant, tmp, schemaType, false);
free(tmp);
} else {
@@ -4372,12 +4310,12 @@ static int32_t validateTagCondExpr(SSqlCmd* pCmd, tExprNode *p) {
if (retVal != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- }while (0);
+ } while (0);
return TSDB_CODE_SUCCESS;
}
-static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondExpr* pCondExpr, tSQLExpr** pExpr) {
+static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondExpr* pCondExpr, tSqlExpr** pExpr) {
int32_t ret = TSDB_CODE_SUCCESS;
if (pCondExpr->pTagCond == NULL) {
@@ -4385,7 +4323,7 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE
}
for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
- tSQLExpr* p1 = extractExprForSTable(pCmd, pExpr, pQueryInfo, i);
+ tSqlExpr* p1 = extractExprForSTable(pCmd, pExpr, pQueryInfo, i);
if (p1 == NULL) { // no query condition on this table
continue;
}
@@ -4417,7 +4355,7 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE
}
tsSetSTableQueryCond(&pQueryInfo->tagCond, uid, &bw);
- doCompactQueryExpr(pExpr);
+ tSqlExprCompact(pExpr);
if (ret == TSDB_CODE_SUCCESS) {
ret = validateTagCondExpr(pCmd, p);
@@ -4440,7 +4378,103 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE
return ret;
}
-int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlObj* pSql) {
+int32_t validateJoinNodes(SQueryInfo* pQueryInfo, SSqlObj* pSql) {
+ const char* msg1 = "timestamp required for join tables";
+ const char* msg2 = "tag required for join stables";
+
+ for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
+ SJoinNode *node = pQueryInfo->tagCond.joinInfo.joinTables[i];
+
+ if (node == NULL || node->tsJoin == NULL || taosArrayGetSize(node->tsJoin) <= 0) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(&pSql->cmd), msg1);
+ }
+ }
+
+ STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+ if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
+ for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
+ SJoinNode *node = pQueryInfo->tagCond.joinInfo.joinTables[i];
+
+ if (node == NULL || node->tagJoin == NULL || taosArrayGetSize(node->tagJoin) <= 0) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(&pSql->cmd), msg2);
+ }
+ }
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
+void mergeJoinNodesImpl(int8_t* r, int8_t* p, int16_t* tidx, SJoinNode** nodes, int32_t type) {
+ SJoinNode *node = nodes[*tidx];
+ SArray* arr = (type == 0) ? node->tsJoin : node->tagJoin;
+ size_t size = taosArrayGetSize(arr);
+
+ p[*tidx] = 1;
+
+ for (int32_t j = 0; j < size; j++) {
+ int16_t* idx = taosArrayGet(arr, j);
+ r[*idx] = 1;
+ if (p[*idx] == 0) {
+ mergeJoinNodesImpl(r, p, idx, nodes, type);
+ }
+ }
+}
+
+int32_t mergeJoinNodes(SQueryInfo* pQueryInfo, SSqlObj* pSql) {
+ const char* msg1 = "not all join tables have same timestamp";
+ const char* msg2 = "not all join tables have same tag";
+
+ int8_t r[TSDB_MAX_JOIN_TABLE_NUM] = {0};
+ int8_t p[TSDB_MAX_JOIN_TABLE_NUM] = {0};
+
+ for (int16_t i = 0; i < pQueryInfo->numOfTables; ++i) {
+ mergeJoinNodesImpl(r, p, &i, pQueryInfo->tagCond.joinInfo.joinTables, 0);
+
+ taosArrayClear(pQueryInfo->tagCond.joinInfo.joinTables[i]->tsJoin);
+
+ for (int32_t j = 0; j < TSDB_MAX_JOIN_TABLE_NUM; ++j) {
+ if (r[j]) {
+ taosArrayPush(pQueryInfo->tagCond.joinInfo.joinTables[i]->tsJoin, &j);
+ }
+ }
+
+ memset(r, 0, sizeof(r));
+ memset(p, 0, sizeof(p));
+ }
+
+ if (taosArrayGetSize(pQueryInfo->tagCond.joinInfo.joinTables[0]->tsJoin) != pQueryInfo->numOfTables) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(&pSql->cmd), msg1);
+ }
+
+ STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+ if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
+ for (int16_t i = 0; i < pQueryInfo->numOfTables; ++i) {
+ mergeJoinNodesImpl(r, p, &i, pQueryInfo->tagCond.joinInfo.joinTables, 1);
+
+ taosArrayClear(pQueryInfo->tagCond.joinInfo.joinTables[i]->tagJoin);
+
+ for (int32_t j = 0; j < TSDB_MAX_JOIN_TABLE_NUM; ++j) {
+ if (r[j]) {
+ taosArrayPush(pQueryInfo->tagCond.joinInfo.joinTables[i]->tagJoin, &j);
+ }
+ }
+
+ memset(r, 0, sizeof(r));
+ memset(p, 0, sizeof(p));
+ }
+
+ if (taosArrayGetSize(pQueryInfo->tagCond.joinInfo.joinTables[0]->tagJoin) != pQueryInfo->numOfTables) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(&pSql->cmd), msg2);
+ }
+
+ }
+
+ return TSDB_CODE_SUCCESS;
+}
+
+
+int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql) {
if (pExpr == NULL) {
return TSDB_CODE_SUCCESS;
}
@@ -4459,11 +4493,11 @@ int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlObj* pSql
}
int32_t type = 0;
- if ((ret = getQueryCondExpr(&pSql->cmd, pQueryInfo, pExpr, &condExpr, &type, (*pExpr)->nSQLOptr)) != TSDB_CODE_SUCCESS) {
+ if ((ret = getQueryCondExpr(&pSql->cmd, pQueryInfo, pExpr, &condExpr, &type, (*pExpr)->tokenId)) != TSDB_CODE_SUCCESS) {
return ret;
}
- doCompactQueryExpr(pExpr);
+ tSqlExprCompact(pExpr);
// after expression compact, the expression tree is only include tag query condition
condExpr.pTagCond = (*pExpr);
@@ -4485,17 +4519,17 @@ int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlObj* pSql
// 4. get the table name query condition
if ((ret = getTablenameCond(&pSql->cmd, pQueryInfo, condExpr.pTableCond, &sb)) != TSDB_CODE_SUCCESS) {
- return ret;
+ goto PARSE_WHERE_EXIT;
}
// 5. other column query condition
if ((ret = getColumnQueryCondInfo(&pSql->cmd, pQueryInfo, condExpr.pColumnCond, TK_AND)) != TSDB_CODE_SUCCESS) {
- return ret;
+ goto PARSE_WHERE_EXIT;
}
// 6. join condition
if ((ret = getJoinCondInfo(&pSql->cmd, pQueryInfo, condExpr.pJoinExpr)) != TSDB_CODE_SUCCESS) {
- return ret;
+ goto PARSE_WHERE_EXIT;
}
// 7. query condition for table name
@@ -4503,20 +4537,37 @@ int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlObj* pSql
ret = setTableCondForSTableQuery(&pSql->cmd, pQueryInfo, getAccountId(pSql), condExpr.pTableCond, condExpr.tableCondIndex, &sb);
taosStringBuilderDestroy(&sb);
+ if (ret) {
+ goto PARSE_WHERE_EXIT;
+ }
if (!validateFilterExpr(pQueryInfo)) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(&pSql->cmd), msg2);
+ ret = invalidSqlErrMsg(tscGetErrorMsgPayload(&pSql->cmd), msg2);
+ goto PARSE_WHERE_EXIT;
+ }
+
+ //doAddJoinTagsColumnsIntoTagList(&pSql->cmd, pQueryInfo, &condExpr);
+ if (condExpr.tsJoin) {
+ ret = validateJoinNodes(pQueryInfo, pSql);
+ if (ret) {
+ goto PARSE_WHERE_EXIT;
+ }
+
+ ret = mergeJoinNodes(pQueryInfo, pSql);
+ if (ret) {
+ goto PARSE_WHERE_EXIT;
+ }
}
- doAddJoinTagsColumnsIntoTagList(&pSql->cmd, pQueryInfo, &condExpr);
+PARSE_WHERE_EXIT:
cleanQueryExpr(&condExpr);
return ret;
}
-int32_t getTimeRange(STimeWindow* win, tSQLExpr* pRight, int32_t optr, int16_t timePrecision) {
+int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t timePrecision) {
// this is join condition, do nothing
- if (pRight->nSQLOptr == TK_ID) {
+ if (pRight->tokenId == TK_ID) {
return TSDB_CODE_SUCCESS;
}
@@ -4524,42 +4575,42 @@ int32_t getTimeRange(STimeWindow* win, tSQLExpr* pRight, int32_t optr, int16_t t
* filter primary ts filter expression like:
* where ts in ('2015-12-12 4:8:12')
*/
- if (pRight->nSQLOptr == TK_SET || optr == TK_IN) {
+ if (pRight->tokenId == TK_SET || optr == TK_IN) {
return TSDB_CODE_TSC_INVALID_SQL;
}
int64_t val = 0;
bool parsed = false;
- if (pRight->val.nType == TSDB_DATA_TYPE_BINARY) {
- pRight->val.nLen = strdequote(pRight->val.pz);
+ if (pRight->value.nType == TSDB_DATA_TYPE_BINARY) {
+ pRight->value.nLen = strdequote(pRight->value.pz);
- char* seg = strnchr(pRight->val.pz, '-', pRight->val.nLen, false);
+ char* seg = strnchr(pRight->value.pz, '-', pRight->value.nLen, false);
if (seg != NULL) {
- if (taosParseTime(pRight->val.pz, &val, pRight->val.nLen, TSDB_TIME_PRECISION_MICRO, tsDaylight) == TSDB_CODE_SUCCESS) {
+ if (taosParseTime(pRight->value.pz, &val, pRight->value.nLen, TSDB_TIME_PRECISION_MICRO, tsDaylight) == TSDB_CODE_SUCCESS) {
parsed = true;
} else {
return TSDB_CODE_TSC_INVALID_SQL;
}
} else {
- SStrToken token = {.z = pRight->val.pz, .n = pRight->val.nLen, .type = TK_ID};
- int32_t len = tSQLGetToken(pRight->val.pz, &token.type);
+ SStrToken token = {.z = pRight->value.pz, .n = pRight->value.nLen, .type = TK_ID};
+ int32_t len = tSQLGetToken(pRight->value.pz, &token.type);
- if ((token.type != TK_INTEGER && token.type != TK_FLOAT) || len != pRight->val.nLen) {
+ if ((token.type != TK_INTEGER && token.type != TK_FLOAT) || len != pRight->value.nLen) {
return TSDB_CODE_TSC_INVALID_SQL;
}
}
- } else if (pRight->nSQLOptr == TK_INTEGER && timePrecision == TSDB_TIME_PRECISION_MILLI) {
+ } else if (pRight->tokenId == TK_INTEGER && timePrecision == TSDB_TIME_PRECISION_MILLI) {
/*
- * if the pRight->nSQLOptr == TK_INTEGER/TK_FLOAT, the value is adaptive, we
+ * if the pRight->tokenId == TK_INTEGER/TK_FLOAT, the value is adaptive, we
* need the time precision in metermeta to transfer the value in MICROSECOND
*
* Additional check to avoid data overflow
*/
- if (pRight->val.i64 <= INT64_MAX / 1000) {
- pRight->val.i64 *= 1000;
+ if (pRight->value.i64 <= INT64_MAX / 1000) {
+ pRight->value.i64 *= 1000;
}
- } else if (pRight->nSQLOptr == TK_FLOAT && timePrecision == TSDB_TIME_PRECISION_MILLI) {
- pRight->val.dKey *= 1000;
+ } else if (pRight->tokenId == TK_FLOAT && timePrecision == TSDB_TIME_PRECISION_MILLI) {
+ pRight->value.dKey *= 1000;
}
if (!parsed) {
@@ -4567,7 +4618,7 @@ int32_t getTimeRange(STimeWindow* win, tSQLExpr* pRight, int32_t optr, int16_t t
* failed to parse timestamp in regular formation, try next
* it may be a epoch time in string format
*/
- tVariantDump(&pRight->val, (char*)&val, TSDB_DATA_TYPE_BIGINT, true);
+ tVariantDump(&pRight->value, (char*)&val, TSDB_DATA_TYPE_BIGINT, true);
/*
* transfer it into MICROSECOND format if it is a string, since for
@@ -4575,7 +4626,7 @@ int32_t getTimeRange(STimeWindow* win, tSQLExpr* pRight, int32_t optr, int16_t t
*
* additional check to avoid data overflow
*/
- if (pRight->nSQLOptr == TK_STRING && timePrecision == TSDB_TIME_PRECISION_MILLI) {
+ if (pRight->tokenId == TK_STRING && timePrecision == TSDB_TIME_PRECISION_MILLI) {
if (val <= INT64_MAX / 1000) {
val *= 1000;
}
@@ -4634,7 +4685,7 @@ int32_t tsRewriteFieldNameIfNecessary(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
return TSDB_CODE_SUCCESS;
}
-int32_t parseFillClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySQL) {
+int32_t parseFillClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySqlNode* pQuerySQL) {
SArray* pFillToken = pQuerySQL->fillType;
tVariantListItem* pItem = taosArrayGet(pFillToken, 0);
@@ -4756,7 +4807,7 @@ static void setDefaultOrderInfo(SQueryInfo* pQueryInfo) {
}
}
-int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql, SSchema* pSchema) {
+int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySqlNode* pQuerySqlNode, SSchema* pSchema) {
const char* msg0 = "only support order by primary timestamp";
const char* msg1 = "invalid column name";
const char* msg2 = "order by primary timestamp or first tag in groupby clause allowed";
@@ -4771,11 +4822,11 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
pQueryInfo->order.orderColId = 0;
return TSDB_CODE_SUCCESS;
}
- if (pQuerySql->pSortOrder == NULL) {
+ if (pQuerySqlNode->pSortOrder == NULL) {
return TSDB_CODE_SUCCESS;
}
- SArray* pSortorder = pQuerySql->pSortOrder;
+ SArray* pSortorder = pQuerySqlNode->pSortOrder;
/*
* for table query, there is only one or none order option is allowed, which is the
@@ -4843,7 +4894,7 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
if (orderByTags) {
pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
- tVariantListItem* p1 = taosArrayGet(pQuerySql->pSortOrder, 0);
+ tVariantListItem* p1 = taosArrayGet(pQuerySqlNode->pSortOrder, 0);
pQueryInfo->groupbyExpr.orderType = p1->sortOrder;
} else if (isTopBottomQuery(pQueryInfo)) {
/* order of top/bottom query in interval is not valid */
@@ -4855,12 +4906,12 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- tVariantListItem* p1 = taosArrayGet(pQuerySql->pSortOrder, 0);
+ tVariantListItem* p1 = taosArrayGet(pQuerySqlNode->pSortOrder, 0);
pQueryInfo->order.order = p1->sortOrder;
pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId;
return TSDB_CODE_SUCCESS;
} else {
- tVariantListItem* p1 = taosArrayGet(pQuerySql->pSortOrder, 0);
+ tVariantListItem* p1 = taosArrayGet(pQuerySqlNode->pSortOrder, 0);
pQueryInfo->order.order = p1->sortOrder;
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
@@ -4873,7 +4924,7 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
}
if (s == 2) {
- tVariantListItem *pItem = taosArrayGet(pQuerySql->pSortOrder, 0);
+ tVariantListItem *pItem = taosArrayGet(pQuerySqlNode->pSortOrder, 0);
if (orderByTags) {
pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
pQueryInfo->groupbyExpr.orderType = pItem->sortOrder;
@@ -4882,7 +4933,7 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
}
- pItem = taosArrayGet(pQuerySql->pSortOrder, 1);
+ pItem = taosArrayGet(pQuerySqlNode->pSortOrder, 1);
tVariant* pVar2 = &pItem->pVar;
SStrToken cname = {pVar2->nLen, pVar2->nType, pVar2->pz};
if (getColumnIndexByName(pCmd, &cname, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
@@ -4917,13 +4968,13 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
- tVariantListItem* pItem = taosArrayGet(pQuerySql->pSortOrder, 0);
+ tVariantListItem* pItem = taosArrayGet(pQuerySqlNode->pSortOrder, 0);
pQueryInfo->order.order = pItem->sortOrder;
pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId;
return TSDB_CODE_SUCCESS;
}
- tVariantListItem* pItem = taosArrayGet(pQuerySql->pSortOrder, 0);
+ tVariantListItem* pItem = taosArrayGet(pQuerySqlNode->pSortOrder, 0);
pQueryInfo->order.order = pItem->sortOrder;
}
@@ -5386,7 +5437,7 @@ int32_t validateLocalConfig(SMiscInfo* pOptions) {
// reset log does not need value
for (int32_t i = 0; i < 1; ++i) {
SDNodeDynConfOption* pOption = &LOCAL_DYNAMIC_CFG_OPTIONS[i];
- if ((pOption->len == pOptionToken->n) &&
+ if ((pOption->len == pOptionToken->n) &&
(strncasecmp(pOption->name, pOptionToken->z, pOptionToken->n) == 0)) {
return TSDB_CODE_SUCCESS;
}
@@ -5401,7 +5452,7 @@ int32_t validateLocalConfig(SMiscInfo* pOptions) {
for (int32_t i = 1; i < tListLen(LOCAL_DYNAMIC_CFG_OPTIONS); ++i) {
SDNodeDynConfOption* pOption = &LOCAL_DYNAMIC_CFG_OPTIONS[i];
- if ((pOption->len == pOptionToken->n)
+ if ((pOption->len == pOptionToken->n)
&& (strncasecmp(pOption->name, pOptionToken->z, pOptionToken->n) == 0)) {
return TSDB_CODE_SUCCESS;
}
@@ -5451,7 +5502,7 @@ bool hasTimestampForPointInterpQuery(SQueryInfo* pQueryInfo) {
return (pQueryInfo->window.skey == pQueryInfo->window.ekey) && (pQueryInfo->window.skey != 0);
}
-int32_t parseLimitClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t clauseIndex, SQuerySQL* pQuerySql, SSqlObj* pSql) {
+int32_t parseLimitClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t clauseIndex, SQuerySqlNode* pQuerySqlNode, SSqlObj* pSql) {
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
const char* msg0 = "soffset/offset can not be less than 0";
@@ -5459,9 +5510,9 @@ int32_t parseLimitClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t clauseIn
const char* msg2 = "slimit/soffset can not apply to projection query";
// handle the limit offset value, validate the limit
- pQueryInfo->limit = pQuerySql->limit;
+ pQueryInfo->limit = pQuerySqlNode->limit;
pQueryInfo->clauseLimit = pQueryInfo->limit.limit;
- pQueryInfo->slimit = pQuerySql->slimit;
+ pQueryInfo->slimit = pQuerySqlNode->slimit;
tscDebug("%p limit:%" PRId64 ", offset:%" PRId64 " slimit:%" PRId64 ", soffset:%" PRId64, pSql, pQueryInfo->limit.limit,
pQueryInfo->limit.offset, pQueryInfo->slimit.limit, pQueryInfo->slimit.offset);
@@ -5622,6 +5673,8 @@ static void setCreateDBOption(SCreateDbMsg* pMsg, SCreateDbInfo* pCreateDb) {
pMsg->ignoreExist = pCreateDb->ignoreExists;
pMsg->update = pCreateDb->update;
pMsg->cacheLastRow = pCreateDb->cachelast;
+ pMsg->dbType = pCreateDb->dbType;
+ pMsg->partitions = htons(pCreateDb->partitions);
}
int32_t parseCreateDBOptions(SSqlCmd* pCmd, SCreateDbInfo* pCreateDbSql) {
@@ -5984,8 +6037,8 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo
SColumnList ids = getColumnList(1, 0, pColIndex->colIndex);
insertResultField(pQueryInfo, (int32_t)size - pQueryInfo->havingFieldNum, &ids, bytes, (int8_t)type, name, pExpr);
} else {
- // if this query is "group by" normal column, interval is not allowed
- if (pQueryInfo->interval.interval > 0) {
+ // if this query is "group by" normal column, time window query is not allowed
+ if (isTimeWindowQuery(pQueryInfo)) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
@@ -6047,7 +6100,7 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
- if (pQueryInfo->groupbyExpr.numOfGroupCols > 0 || pQueryInfo->interval.interval > 0) {
+ if (pQueryInfo->groupbyExpr.numOfGroupCols > 0 || isTimeWindowQuery(pQueryInfo)) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
} else {
return TSDB_CODE_SUCCESS;
@@ -6118,17 +6171,20 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
return checkUpdateTagPrjFunctions(pQueryInfo, pCmd);
}
}
-int32_t doLocalQueryProcess(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
+int32_t doLocalQueryProcess(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySqlNode* pQuerySqlNode) {
const char* msg1 = "only one expression allowed";
const char* msg2 = "invalid expression in select clause";
const char* msg3 = "invalid function";
- tSQLExprList* pExprList = pQuerySql->pSelection;
- if (pExprList->nExpr != 1) {
+ SArray* pExprList = pQuerySqlNode->pSelectList;
+ size_t size = taosArrayGetSize(pExprList);
+ if (size != 1) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
+
bool server_status = false;
- tSQLExpr* pExpr = pExprList->a[0].pNode;
+ tSqlExprItem* pExprItem = taosArrayGet(pExprList, 0);
+ tSqlExpr* pExpr = pExprItem->pNode;
if (pExpr->operand.z == NULL) {
//handle 'select 1'
if (pExpr->token.n == 1 && 0 == strncasecmp(pExpr->token.z, "1", 1)) {
@@ -6149,8 +6205,8 @@ int32_t doLocalQueryProcess(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ
index = 2;
} else {
for (int32_t i = 0; i < tListLen(functionsInfo); ++i) {
- if (strncasecmp(functionsInfo[i].name, pExpr->operand.z, functionsInfo[i].len) == 0 &&
- functionsInfo[i].len == pExpr->operand.n) {
+ if (strncasecmp(functionsInfo[i].name, pExpr->token.z, functionsInfo[i].len) == 0 &&
+ functionsInfo[i].len == pExpr->token.n) {
index = i;
break;
}
@@ -6174,8 +6230,9 @@ int32_t doLocalQueryProcess(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ
SColumnIndex ind = {0};
SSqlExpr* pExpr1 = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TAG_DUMMY, &ind, TSDB_DATA_TYPE_INT,
tDataTypes[TSDB_DATA_TYPE_INT].bytes, getNewResColId(pQueryInfo), tDataTypes[TSDB_DATA_TYPE_INT].bytes, false);
-
- const char* name = (pExprList->a[0].aliasName != NULL)? pExprList->a[0].aliasName:functionsInfo[index].name;
+
+ tSqlExprItem* item = taosArrayGet(pExprList, 0);
+ const char* name = (item->aliasName != NULL)? item->aliasName:functionsInfo[index].name;
tstrncpy(pExpr1->aliasName, name, tListLen(pExpr1->aliasName));
return TSDB_CODE_SUCCESS;
@@ -6252,6 +6309,15 @@ int32_t tscCheckCreateDbParams(SSqlCmd* pCmd, SCreateDbMsg* pCreate) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg);
}
+ val = (int16_t)htons(pCreate->partitions);
+ if (val != -1 &&
+ (val < TSDB_MIN_DB_PARTITON_OPTION || val > TSDB_MAX_DB_PARTITON_OPTION)) {
+ snprintf(msg, tListLen(msg), "invalid topic option partition: %d valid range: [%d, %d]", val,
+ TSDB_MIN_DB_PARTITON_OPTION, TSDB_MAX_DB_PARTITON_OPTION);
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg);
+ }
+
+
return TSDB_CODE_SUCCESS;
}
@@ -6301,7 +6367,7 @@ int32_t doCheckForCreateTable(SSqlObj* pSql, int32_t subClauseIndex, SSqlInfo* p
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, subClauseIndex);
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
- SCreateTableSQL* pCreateTable = pInfo->pCreateTableInfo;
+ SCreateTableSql* pCreateTable = pInfo->pCreateTableInfo;
SArray* pFieldList = pCreateTable->colInfo.pColumns;
SArray* pTagList = pCreateTable->colInfo.pTagColumns;
@@ -6356,7 +6422,7 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
SSqlCmd* pCmd = &pSql->cmd;
- SCreateTableSQL* pCreateTable = pInfo->pCreateTableInfo;
+ SCreateTableSql* pCreateTable = pInfo->pCreateTableInfo;
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
// two table: the first one is for current table, and the secondary is for the super table.
@@ -6436,12 +6502,12 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
tVariantListItem* pItem = taosArrayGet(pValList, i);
findColumnIndex = false;
-
+
// todo speedup by using hash list
for (int32_t t = 0; t < schemaSize; ++t) {
if (strncmp(sToken->z, pTagSchema[t].name, sToken->n) == 0 && strlen(pTagSchema[t].name) == sToken->n) {
SSchema* pSchema = &pTagSchema[t];
-
+
char tagVal[TSDB_MAX_TAGS_LEN];
if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) {
if (pItem->pVar.nLen > pSchema->bytes) {
@@ -6449,9 +6515,9 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
}
-
+
ret = tVariantDump(&(pItem->pVar), tagVal, pSchema->type, true);
-
+
// check again after the convert since it may be converted from binary to nchar.
if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) {
int16_t len = varDataTLen(tagVal);
@@ -6460,12 +6526,12 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
}
-
+
if (ret != TSDB_CODE_SUCCESS) {
tdDestroyKVRowBuilder(&kvRowBuilder);
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
}
-
+
tdAddColToKVRow(&kvRowBuilder, pSchema->colId, pSchema->type, tagVal);
findColumnIndex = true;
@@ -6476,7 +6542,7 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
if (!findColumnIndex) {
tdDestroyKVRowBuilder(&kvRowBuilder);
return tscInvalidSQLErrMsg(pCmd->payload, "invalid tag name", sToken->z);
- }
+ }
}
} else {
if (schemaSize != valSize) {
@@ -6487,7 +6553,7 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
for (int32_t i = 0; i < valSize; ++i) {
SSchema* pSchema = &pTagSchema[i];
tVariantListItem* pItem = taosArrayGet(pValList, i);
-
+
char tagVal[TSDB_MAX_TAGS_LEN];
if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) {
if (pItem->pVar.nLen > pSchema->bytes) {
@@ -6495,9 +6561,9 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
}
-
+
ret = tVariantDump(&(pItem->pVar), tagVal, pSchema->type, true);
-
+
// check again after the convert since it may be converted from binary to nchar.
if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) {
int16_t len = varDataTLen(tagVal);
@@ -6506,12 +6572,12 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
}
-
+
if (ret != TSDB_CODE_SUCCESS) {
tdDestroyKVRowBuilder(&kvRowBuilder);
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
}
-
+
tdAddColToKVRow(&kvRowBuilder, pSchema->colId, pSchema->type, tagVal);
}
}
@@ -6565,24 +6631,24 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
assert(pQueryInfo->numOfTables == 1);
- SCreateTableSQL* pCreateTable = pInfo->pCreateTableInfo;
+ SCreateTableSql* pCreateTable = pInfo->pCreateTableInfo;
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
// if sql specifies db, use it, otherwise use default db
SStrToken* pName = &(pCreateTable->name);
- SQuerySQL* pQuerySql = pCreateTable->pSelect;
+ SQuerySqlNode* pQuerySqlNode = pCreateTable->pSelect;
if (tscValidateName(pName) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
- SArray* pSrcMeterName = pInfo->pCreateTableInfo->pSelect->from;
- if (pSrcMeterName == NULL || taosArrayGetSize(pSrcMeterName) == 0) {
+ SFromInfo* pFromInfo = pInfo->pCreateTableInfo->pSelect->from;
+ if (pFromInfo == NULL || taosArrayGetSize(pFromInfo->tableList) == 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
- tVariantListItem* p1 = taosArrayGet(pSrcMeterName, 0);
- SStrToken srcToken = {.z = p1->pVar.pz, .n = p1->pVar.nLen, .type = TK_STRING};
+ STableNamePair* p1 = taosArrayGet(pFromInfo->tableList, 0);
+ SStrToken srcToken = {.z = p1->name.z, .n = p1->name.n, .type = TK_STRING};
if (tscValidateName(&srcToken) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
@@ -6598,23 +6664,22 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
}
bool isSTable = UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo);
- if (parseSelectClause(&pSql->cmd, 0, pQuerySql->pSelection, isSTable, false, false) != TSDB_CODE_SUCCESS) {
+ if (parseSelectClause(&pSql->cmd, 0, pQuerySqlNode->pSelectList, isSTable, false, false) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
- if (pQuerySql->pWhere != NULL) { // query condition in stream computing
- if (parseWhereClause(pQueryInfo, &pQuerySql->pWhere, pSql) != TSDB_CODE_SUCCESS) {
+ if (pQuerySqlNode->pWhere != NULL) { // query condition in stream computing
+ if (parseWhereClause(pQueryInfo, &pQuerySqlNode->pWhere, pSql) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
}
// set interval value
- if (parseIntervalClause(pSql, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
+ if (parseIntervalClause(pSql, pQueryInfo, pQuerySqlNode) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
- if ((pQueryInfo->interval.interval > 0) &&
- (validateFunctionsInIntervalOrGroupbyQuery(pCmd, pQueryInfo) != TSDB_CODE_SUCCESS)) {
+ if (isTimeWindowQuery(pQueryInfo) && (validateFunctionsInIntervalOrGroupbyQuery(pCmd, pQueryInfo) != TSDB_CODE_SUCCESS)) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
@@ -6628,7 +6693,7 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
return code;
}
- if (pQuerySql->selectToken.n > TSDB_MAX_SAVED_SQL_LEN) {
+ if (pQuerySqlNode->sqlstr.n > TSDB_MAX_SAVED_SQL_LEN) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
@@ -6646,12 +6711,12 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
* check if fill operation is available, the fill operation is parsed and executed during query execution,
* not here.
*/
- if (pQuerySql->fillType != NULL) {
+ if (pQuerySqlNode->fillType != NULL) {
if (pQueryInfo->interval.interval == 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
- tVariantListItem* pItem = taosArrayGet(pQuerySql->fillType, 0);
+ tVariantListItem* pItem = taosArrayGet(pQuerySqlNode->fillType, 0);
if (pItem->pVar.nType == TSDB_DATA_TYPE_BINARY) {
if (!((strncmp(pItem->pVar.pz, "none", 4) == 0 && pItem->pVar.nLen == 4) ||
(strncmp(pItem->pVar.pz, "null", 4) == 0 && pItem->pVar.nLen == 4))) {
@@ -7008,17 +7073,17 @@ int32_t parseHavingClause(SQueryInfo* pQueryInfo, tSQLExpr* pExpr, SSqlCmd* pCmd
-int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
- assert(pQuerySql != NULL && (pQuerySql->from == NULL || taosArrayGetSize(pQuerySql->from) > 0));
+int32_t doValidateSqlNode(SSqlObj* pSql, SQuerySqlNode* pQuerySqlNode, int32_t index) {
+ assert(pQuerySqlNode != NULL && (pQuerySqlNode->from == NULL || taosArrayGetSize(pQuerySqlNode->from->tableList) > 0));
- const char* msg0 = "invalid table name";
+ const char* msg0 = "invalid table name";
const char* msg1 = "point interpolation query needs timestamp";
const char* msg2 = "fill only available for interval query";
const char* msg3 = "start(end) time of query range required or time range too large";
- const char* msg4 = "illegal number of tables in from clause";
const char* msg5 = "too many columns in selection clause";
const char* msg6 = "too many tables in from clause";
const char* msg7 = "invalid table alias name";
+ const char* msg8 = "alias name too long";
int32_t code = TSDB_CODE_SUCCESS;
@@ -7033,7 +7098,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
assert(pCmd->clauseIndex == index);
// too many result columns not support order by in query
- if (pQuerySql->pSelection->nExpr > TSDB_MAX_COLUMNS) {
+ if (taosArrayGetSize(pQuerySqlNode->pSelectList) > TSDB_MAX_COLUMNS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
@@ -7044,77 +7109,74 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
* select client_version();
* select server_state();
*/
- if (pQuerySql->from == NULL) {
- assert(pQuerySql->fillType == NULL && pQuerySql->pGroupby == NULL && pQuerySql->pWhere == NULL &&
- pQuerySql->pSortOrder == NULL && pQuerySql->pHaving == NULL);
- return doLocalQueryProcess(pCmd, pQueryInfo, pQuerySql);
+ if (pQuerySqlNode->from == NULL) {
+ assert(pQuerySqlNode->fillType == NULL && pQuerySqlNode->pGroupby == NULL && pQuerySqlNode->pWhere == NULL &&
+ pQuerySqlNode->pSortOrder == NULL);
+ return doLocalQueryProcess(pCmd, pQueryInfo, pQuerySqlNode);
}
- size_t fromSize = taosArrayGetSize(pQuerySql->from);
+ size_t fromSize = taosArrayGetSize(pQuerySqlNode->from->tableList);
if (fromSize > TSDB_MAX_JOIN_TABLE_NUM * 2) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
pQueryInfo->command = TSDB_SQL_SELECT;
- if (fromSize > 4) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
- }
-
// set all query tables, which are maybe more than one.
- for (int32_t i = 0; i < fromSize; ) {
- tVariantListItem* item = taosArrayGet(pQuerySql->from, i);
- tVariant* pTableItem = &item->pVar;
+ for (int32_t i = 0; i < fromSize; ++i) {
+ STableNamePair* item = taosArrayGet(pQuerySqlNode->from->tableList, i);
+ SStrToken* pTableItem = &item->name;
- if (pTableItem->nType != TSDB_DATA_TYPE_BINARY) {
+ if (pTableItem->type != TSDB_DATA_TYPE_BINARY) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg0);
}
- pTableItem->nLen = strdequote(pTableItem->pz);
+ tscDequoteAndTrimToken(pTableItem);
- SStrToken tableName = {.z = pTableItem->pz, .n = pTableItem->nLen, .type = TK_STRING};
+ SStrToken tableName = {.z = pTableItem->z, .n = pTableItem->n, .type = TK_STRING};
if (tscValidateName(&tableName) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg0);
}
- if (pQueryInfo->numOfTables <= i/2) { // more than one table
+ if (pQueryInfo->numOfTables <= i) { // more than one table
tscAddEmptyMetaInfo(pQueryInfo);
}
- STableMetaInfo* pTableMetaInfo1 = tscGetMetaInfo(pQueryInfo, i/2);
-
- SStrToken t = {.type = TSDB_DATA_TYPE_BINARY, .n = pTableItem->nLen, .z = pTableItem->pz};
- code = tscSetTableFullName(pTableMetaInfo1, &t, pSql);
+ STableMetaInfo* pTableMetaInfo1 = tscGetMetaInfo(pQueryInfo, i);
+ code = tscSetTableFullName(pTableMetaInfo1, pTableItem, pSql);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
- tVariantListItem* p1 = taosArrayGet(pQuerySql->from, i + 1);
- if (p1->pVar.nType != TSDB_DATA_TYPE_BINARY) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7);
- }
+ SStrToken* aliasName = &item->aliasName;
+ if (TPARSER_HAS_TOKEN(*aliasName)) {
+ if (aliasName->type != TSDB_DATA_TYPE_BINARY) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7);
+ }
- SStrToken aliasName = {.z = p1->pVar.pz, .n = p1->pVar.nLen, .type = TK_STRING};
- if (tscValidateName(&aliasName) != TSDB_CODE_SUCCESS) {
- return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7);
- }
+ tscDequoteAndTrimToken(aliasName);
+
+ SStrToken aliasName1 = {.z = aliasName->z, .n = aliasName->n, .type = TK_STRING};
+ if (tscValidateName(&aliasName1) != TSDB_CODE_SUCCESS) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7);
+ }
+
+ if (aliasName1.n >= TSDB_TABLE_NAME_LEN) {
+ return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg8);
+ }
- // has no table alias name
- if (memcmp(pTableItem->pz, p1->pVar.pz, p1->pVar.nLen) == 0) {
- strncpy(pTableMetaInfo1->aliasName, tNameGetTableName(&pTableMetaInfo1->name), tListLen(pTableMetaInfo->aliasName));
+ strncpy(pTableMetaInfo1->aliasName, aliasName1.z, aliasName1.n);
} else {
- tstrncpy(pTableMetaInfo1->aliasName, p1->pVar.pz, sizeof(pTableMetaInfo1->aliasName));
+ strncpy(pTableMetaInfo1->aliasName, tNameGetTableName(&pTableMetaInfo1->name), tListLen(pTableMetaInfo1->aliasName));
}
code = tscGetTableMeta(pSql, pTableMetaInfo1);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
-
- i += 2;
}
- assert(pQueryInfo->numOfTables == taosArrayGetSize(pQuerySql->from) / 2);
+ assert(pQueryInfo->numOfTables == taosArrayGetSize(pQuerySqlNode->from->tableList));
bool isSTable = false;
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
@@ -7130,47 +7192,47 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
}
// parse the group by clause in the first place
- if (parseGroupbyClause(pQueryInfo, pQuerySql->pGroupby, pCmd) != TSDB_CODE_SUCCESS) {
+ if (parseGroupbyClause(pQueryInfo, pQuerySqlNode->pGroupby, pCmd) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
// set where info
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
- if (pQuerySql->pWhere != NULL) {
- if (parseWhereClause(pQueryInfo, &pQuerySql->pWhere, pSql) != TSDB_CODE_SUCCESS) {
+ if (pQuerySqlNode->pWhere != NULL) {
+ if (parseWhereClause(pQueryInfo, &pQuerySqlNode->pWhere, pSql) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
- pQuerySql->pWhere = NULL;
+ pQuerySqlNode->pWhere = NULL;
if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) {
pQueryInfo->window.skey = pQueryInfo->window.skey / 1000;
pQueryInfo->window.ekey = pQueryInfo->window.ekey / 1000;
}
} else { // set the time rang
- if (taosArrayGetSize(pQuerySql->from) > 2) { // it is a join query, no wher clause is not allowed.
+ if (taosArrayGetSize(pQuerySqlNode->from->tableList) > 1) { // it is a join query, no where clause is not allowed.
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), "condition missing for join query ");
}
}
- int32_t joinQuery = (pQuerySql->from != NULL && taosArrayGetSize(pQuerySql->from) > 2);
-
- int32_t intervalQuery = !(pQuerySql->interval.type == 0 || pQuerySql->interval.n == 0);
+ int32_t joinQuery = (pQuerySqlNode->from != NULL && taosArrayGetSize(pQuerySqlNode->from->tableList) > 1);
+ int32_t timeWindowQuery =
+ (TPARSER_HAS_TOKEN(pQuerySqlNode->interval.interval) || TPARSER_HAS_TOKEN(pQuerySqlNode->sessionVal.gap));
- if (parseSelectClause(pCmd, index, pQuerySql->pSelection, isSTable, joinQuery, intervalQuery) != TSDB_CODE_SUCCESS) {
+ if (parseSelectClause(pCmd, index, pQuerySqlNode->pSelectList, isSTable, joinQuery, timeWindowQuery) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
// set order by info
- if (parseOrderbyClause(pCmd, pQueryInfo, pQuerySql, tscGetTableSchema(pTableMetaInfo->pTableMeta)) != TSDB_CODE_SUCCESS) {
+ if (parseOrderbyClause(pCmd, pQueryInfo, pQuerySqlNode, tscGetTableSchema(pTableMetaInfo->pTableMeta)) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
// set interval value
- if (parseIntervalClause(pSql, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
+ if (parseIntervalClause(pSql, pQueryInfo, pQuerySqlNode) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
} else {
- if ((pQueryInfo->interval.interval > 0) &&
+ if (isTimeWindowQuery(pQueryInfo) &&
(validateFunctionsInIntervalOrGroupbyQuery(pCmd, pQueryInfo) != TSDB_CODE_SUCCESS)) {
return TSDB_CODE_TSC_INVALID_SQL;
}
@@ -7193,6 +7255,10 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
}
}
+ if (parseSessionClause(pCmd, pQueryInfo, pQuerySqlNode) != TSDB_CODE_SUCCESS) {
+ return TSDB_CODE_TSC_INVALID_SQL;
+ }
+
// no result due to invalid query time range
if (pQueryInfo->window.skey > pQueryInfo->window.ekey) {
pQueryInfo->command = TSDB_SQL_RETRIEVE_EMPTY_RESULT;
@@ -7206,13 +7272,12 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
// in case of join query, time range is required.
if (QUERY_IS_JOIN_QUERY(pQueryInfo->type)) {
int64_t timeRange = ABS(pQueryInfo->window.skey - pQueryInfo->window.ekey);
-
if (timeRange == 0 && pQueryInfo->window.skey == 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
}
- if ((code = parseLimitClause(pCmd, pQueryInfo, index, pQuerySql, pSql)) != TSDB_CODE_SUCCESS) {
+ if ((code = parseLimitClause(pCmd, pQueryInfo, index, pQuerySqlNode, pSql)) != TSDB_CODE_SUCCESS) {
return code;
}
@@ -7220,9 +7285,10 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
return code;
}
+ updateLastScanOrderIfNeeded(pQueryInfo);
tscFieldInfoUpdateOffset(pQueryInfo);
- if (pQuerySql->fillType != NULL) {
+ if (pQuerySqlNode->fillType != NULL) {
if (pQueryInfo->interval.interval == 0 && (!tscIsPointInterpQuery(pQueryInfo))) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
@@ -7235,7 +7301,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
return code;
}
- if ((code = parseFillClause(pCmd, pQueryInfo, pQuerySql)) != TSDB_CODE_SUCCESS) {
+ if ((code = parseFillClause(pCmd, pQueryInfo, pQuerySqlNode)) != TSDB_CODE_SUCCESS) {
return code;
}
}
@@ -7243,7 +7309,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
return TSDB_CODE_SUCCESS; // Does not build query message here
}
-int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pSqlExpr, SQueryInfo* pQueryInfo, SArray* pCols, int64_t *uid) {
+int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryInfo* pQueryInfo, SArray* pCols, int64_t *uid) {
tExprNode* pLeft = NULL;
tExprNode* pRight= NULL;
@@ -7261,25 +7327,25 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS
}
}
- if (pSqlExpr->pLeft == NULL && pSqlExpr->pRight == NULL && pSqlExpr->nSQLOptr == 0) {
+ if (pSqlExpr->pLeft == NULL && pSqlExpr->pRight == NULL && pSqlExpr->tokenId == 0) {
*pExpr = calloc(1, sizeof(tExprNode));
return TSDB_CODE_SUCCESS;
}
if (pSqlExpr->pLeft == NULL) {
- if (pSqlExpr->nSQLOptr >= TK_BOOL && pSqlExpr->nSQLOptr <= TK_STRING) {
+ if (pSqlExpr->type == SQL_NODE_VALUE) {
*pExpr = calloc(1, sizeof(tExprNode));
(*pExpr)->nodeType = TSQL_NODE_VALUE;
(*pExpr)->pVal = calloc(1, sizeof(tVariant));
- tVariantAssign((*pExpr)->pVal, &pSqlExpr->val);
+ tVariantAssign((*pExpr)->pVal, &pSqlExpr->value);
return TSDB_CODE_SUCCESS;
- } else if (pSqlExpr->nSQLOptr >= TK_COUNT && pSqlExpr->nSQLOptr <= TK_AVG_IRATE) {
+ } else if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) {
// arithmetic expression on the results of aggregation functions
*pExpr = calloc(1, sizeof(tExprNode));
(*pExpr)->nodeType = TSQL_NODE_COL;
(*pExpr)->pSchema = calloc(1, sizeof(SSchema));
- strncpy((*pExpr)->pSchema->name, pSqlExpr->operand.z, pSqlExpr->operand.n);
+ strncpy((*pExpr)->pSchema->name, pSqlExpr->token.z, pSqlExpr->token.n);
// set the input column data byte and type.
size_t size = taosArrayGetSize(pQueryInfo->exprList);
@@ -7299,7 +7365,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS
break;
}
}
- } else if (pSqlExpr->nSQLOptr == TK_ID) { // column name, normal column arithmetic expression
+ } else if (pSqlExpr->type == SQL_NODE_TABLE_COLUMN) { // column name, normal column arithmetic expression
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
int32_t ret = getColumnIndexByName(pCmd, &pSqlExpr->colInfo, pQueryInfo, &index);
if (ret != TSDB_CODE_SUCCESS) {
@@ -7339,7 +7405,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS
(*pExpr)->_node.pLeft = pLeft;
(*pExpr)->_node.pRight = pRight;
- SStrToken t = {.type = pSqlExpr->nSQLOptr};
+ SStrToken t = {.type = pSqlExpr->tokenId};
(*pExpr)->_node.optr = convertOptr(&t);
assert((*pExpr)->_node.optr != 0);
diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c
index 6f72f1a0791d070c8c56cb56a95f0b02c7fc2900..29274b36ead2be584a2d496eaeaf643ff17d68f6 100644
--- a/src/client/src/tscServer.c
+++ b/src/client/src/tscServer.c
@@ -350,8 +350,8 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
taosMsleep(duration);
}
+ pSql->retryReason = rpcMsg->code;
rpcMsg->code = tscRenewTableMeta(pSql, 0);
-
// if there is an error occurring, proceed to the following error handling procedure.
if (rpcMsg->code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
taosReleaseRef(tscObjRef, handle);
@@ -497,8 +497,6 @@ int tscProcessSql(SSqlObj *pSql) {
return pSql->res.code;
}
} else if (pCmd->command >= TSDB_SQL_LOCAL) {
- //pSql->epSet = tscMgmtEpSet;
-// } else { // local handler
return (*tscProcessMsgRsp[pCmd->command])(pSql);
}
@@ -510,7 +508,7 @@ int tscBuildFetchMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex);
pRetrieveMsg->free = htons(pQueryInfo->type);
- pRetrieveMsg->qhandle = htobe64(pSql->res.qhandle);
+ pRetrieveMsg->qId = htobe64(pSql->res.qId);
// todo valid the vgroupId at the client side
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
@@ -522,7 +520,7 @@ int tscBuildFetchMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
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", pSql, pVgroupInfo->vgroups[vgIndex].vgId, vgIndex);
+ tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d, qhandle:%" PRIX64, pSql, pVgroupInfo->vgroups[vgIndex].vgId, vgIndex, pSql->res.qId);
} else {
int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables);
assert(vgIndex >= 0 && vgIndex < numOfVgroups);
@@ -530,12 +528,12 @@ int tscBuildFetchMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SVgroupTableInfo* pTableIdList = taosArrayGet(pTableMetaInfo->pVgroupTables, vgIndex);
pRetrieveMsg->header.vgId = htonl(pTableIdList->vgInfo.vgId);
- tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d", pSql, pTableIdList->vgInfo.vgId, vgIndex);
+ tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d, qId:%" PRIu64, pSql, pTableIdList->vgInfo.vgId, vgIndex, pSql->res.qId);
}
} else {
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
pRetrieveMsg->header.vgId = htonl(pTableMeta->vgId);
- tscDebug("%p build fetch msg from only one vgroup, vgId:%d", pSql, pTableMeta->vgId);
+ tscDebug("%p build fetch msg from only one vgroup, vgId:%d, qId:%" PRIu64, pSql, pTableMeta->vgId, pSql->res.qId);
}
pSql->cmd.payloadLen = sizeof(SRetrieveTableMsg);
@@ -615,7 +613,7 @@ static int32_t tscEstimateQueryMsgSize(SSqlObj *pSql, int32_t clauseIndex) {
tableSerialize + sqlLen + 4096 + pQueryInfo->bufLen;
}
-static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char *pMsg) {
+static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char *pMsg, int32_t *succeed) {
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, pSql->cmd.clauseIndex, 0);
TSKEY dfltKey = htobe64(pQueryMsg->window.skey);
@@ -628,9 +626,14 @@ static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char
assert(index >= 0);
SVgroupInfo* pVgroupInfo = NULL;
- if (pTableMetaInfo->vgroupList->numOfVgroups > 0) {
+ if (pTableMetaInfo->vgroupList && pTableMetaInfo->vgroupList->numOfVgroups > 0) {
assert(index < pTableMetaInfo->vgroupList->numOfVgroups);
pVgroupInfo = &pTableMetaInfo->vgroupList->vgroups[index];
+ } else {
+ tscError("%p No vgroup info found", pSql);
+
+ *succeed = 0;
+ return pMsg;
}
vgId = pVgroupInfo->vgId;
@@ -645,7 +648,6 @@ static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char
}
pSql->epSet.inUse = rand()%pSql->epSet.numOfEps;
-
pQueryMsg->head.vgId = htonl(vgId);
STableIdInfo *pTableIdInfo = (STableIdInfo *)pMsg;
@@ -660,8 +662,6 @@ static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char
int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables);
assert(index >= 0 && index < numOfVgroups);
- tscDebug("%p query on stable, vgIndex:%d, numOfVgroups:%d", pSql, index, numOfVgroups);
-
SVgroupTableInfo* pTableIdList = taosArrayGet(pTableMetaInfo->pVgroupTables, index);
// set the vgroup info
@@ -670,7 +670,10 @@ static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char
int32_t numOfTables = (int32_t)taosArrayGetSize(pTableIdList->itemList);
pQueryMsg->numOfTables = htonl(numOfTables); // set the number of tables
-
+
+ tscDebug("%p query on stable, vgId:%d, numOfTables:%d, vgIndex:%d, numOfVgroups:%d", pSql,
+ pTableIdList->vgInfo.vgId, numOfTables, index, numOfVgroups);
+
// serialize each table id info
for(int32_t i = 0; i < numOfTables; ++i) {
STableIdInfo* pItem = taosArrayGet(pTableIdList->itemList, i);
@@ -705,7 +708,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
STableMeta * pTableMeta = pTableMetaInfo->pTableMeta;
size_t numOfSrcCols = taosArrayGetSize(pQueryInfo->colList);
- if (numOfSrcCols <= 0 && !tscQueryTags(pQueryInfo)) {
+ if (numOfSrcCols <= 0 && !tscQueryTags(pQueryInfo) && !tscQueryBlockInfo(pQueryInfo)) {
tscError("%p illegal value of numOfCols in query msg: %" PRIu64 ", table cols:%d", pSql, (uint64_t)numOfSrcCols,
tscGetNumOfColumns(pTableMeta));
@@ -756,6 +759,8 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
pQueryMsg->vgroupLimit = htobe64(pQueryInfo->vgroupLimit);
pQueryMsg->sqlstrLen = htonl(sqlLen);
pQueryMsg->prevResultLen = htonl(pQueryInfo->bufLen);
+ pQueryMsg->sw.gap = htobe64(pQueryInfo->sessionWindow.gap);
+ pQueryMsg->sw.primaryColId = htonl(PRIMARYKEY_TIMESTAMP_COL_INDEX);
size_t numOfOutput = tscSqlExprNumOfExprs(pQueryInfo);
pQueryMsg->numOfOutput = htons((int16_t)numOfOutput); // this is the stage one output column number
@@ -835,6 +840,25 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
pSqlFuncExpr->colInfo.colIndex = htons(pExpr->colInfo.colIndex);
pSqlFuncExpr->colInfo.flag = htons(pExpr->colInfo.flag);
+ if (TSDB_COL_IS_UD_COL(pExpr->colInfo.flag)) {
+ pSqlFuncExpr->colType = htons(pExpr->resType);
+ pSqlFuncExpr->colBytes = htons(pExpr->resBytes);
+ } else if (pExpr->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
+ SSchema *s = tGetTbnameColumnSchema();
+
+ pSqlFuncExpr->colType = htons(s->type);
+ pSqlFuncExpr->colBytes = htons(s->bytes);
+ } else if (pExpr->colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
+ SSchema s = tGetBlockDistColumnSchema();
+
+ pSqlFuncExpr->colType = htons(s.type);
+ pSqlFuncExpr->colBytes = htons(s.bytes);
+ } else {
+ SSchema* s = tscGetColumnSchemaById(pTableMeta, pExpr->colInfo.colId);
+ pSqlFuncExpr->colType = htons(s->type);
+ pSqlFuncExpr->colBytes = htons(s->bytes);
+ }
+
pSqlFuncExpr->functionId = htons(pExpr->functionId);
pSqlFuncExpr->numOfParams = htons(pExpr->numOfParams);
pSqlFuncExpr->resColId = htons(pExpr->resColId);
@@ -876,8 +900,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
}
- for (int32_t j = 0; j < pExpr->numOfParams; ++j) {
- // todo add log
+ 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);
@@ -902,6 +925,8 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
for (int32_t i = 0; i < output; ++i) {
SInternalField* pField = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i);
SSqlExpr *pExpr = pField->pSqlExpr;
+
+ // this should be switched to projection query
if (pExpr != NULL) {
// the queried table has been removed and a new table with the same name has already been created already
// return error msg
@@ -915,33 +940,31 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
return TSDB_CODE_TSC_INVALID_SQL;
}
- pSqlFuncExpr1->colInfo.colId = htons(pExpr->colInfo.colId);
- pSqlFuncExpr1->colInfo.colIndex = htons(pExpr->colInfo.colIndex);
- pSqlFuncExpr1->colInfo.flag = htons(pExpr->colInfo.flag);
-
- pSqlFuncExpr1->functionId = htons(pExpr->functionId);
- pSqlFuncExpr1->numOfParams = htons(pExpr->numOfParams);
- pMsg += sizeof(SSqlFuncMsg);
-
- for (int32_t j = 0; j < pExpr->numOfParams; ++j) {
- // todo add log
- pSqlFuncExpr1->arg[j].argType = htons((uint16_t)pExpr->param[j].nType);
- pSqlFuncExpr1->arg[j].argBytes = htons(pExpr->param[j].nLen);
-
- if (pExpr->param[j].nType == TSDB_DATA_TYPE_BINARY) {
- memcpy(pMsg, pExpr->param[j].pz, pExpr->param[j].nLen);
- pMsg += pExpr->param[j].nLen;
- } else {
- pSqlFuncExpr1->arg[j].argValue.i64 = htobe64(pExpr->param[j].i64);
+ pSqlFuncExpr1->numOfParams = 0; // no params for projection query
+ pSqlFuncExpr1->functionId = htons(TSDB_FUNC_PRJ);
+ pSqlFuncExpr1->colInfo.colId = htons(pExpr->resColId);
+ pSqlFuncExpr1->colInfo.flag = htons(TSDB_COL_NORMAL);
+
+ bool assign = false;
+ for (int32_t f = 0; f < tscSqlExprNumOfExprs(pQueryInfo); ++f) {
+ SSqlExpr *pe = tscSqlExprGet(pQueryInfo, f);
+ if (pe == pExpr) {
+ pSqlFuncExpr1->colInfo.colIndex = htons(f);
+ pSqlFuncExpr1->colType = htons(pe->resType);
+ pSqlFuncExpr1->colBytes = htons(pe->resBytes);
+ assign = true;
+ break;
}
}
+ assert(assign);
+ pMsg += sizeof(SSqlFuncMsg);
pSqlFuncExpr1 = (SSqlFuncMsg *)pMsg;
} else {
assert(pField->pArithExprInfo != NULL);
SExprInfo* pExprInfo = pField->pArithExprInfo;
- pSqlFuncExpr1->colInfo.colId = htons(pExprInfo->base.colInfo.colId);
+ pSqlFuncExpr1->colInfo.colId = htons(pExprInfo->base.colInfo.colId);
pSqlFuncExpr1->functionId = htons(pExprInfo->base.functionId);
pSqlFuncExpr1->numOfParams = htons(pExprInfo->base.numOfParams);
pMsg += sizeof(SSqlFuncMsg);
@@ -966,8 +989,13 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
pQueryMsg->secondStageOutput = 0;
}
+ int32_t succeed = 1;
+
// serialize the table info (sid, uid, tags)
- pMsg = doSerializeTableInfo(pQueryMsg, pSql, pMsg);
+ pMsg = doSerializeTableInfo(pQueryMsg, pSql, pMsg, &succeed);
+ if (succeed == 0) {
+ return TSDB_CODE_TSC_APP_ERROR;
+ }
SSqlGroupbyExpr *pGroupbyExpr = &pQueryInfo->groupbyExpr;
if (pGroupbyExpr->numOfGroupCols > 0) {
@@ -1091,7 +1119,8 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int32_t tscBuildCreateDbMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
pCmd->payloadLen = sizeof(SCreateDbMsg);
- pCmd->msgType = TSDB_MSG_TYPE_CM_CREATE_DB;
+
+ pCmd->msgType = (pInfo->pMiscInfo->dbOpt.dbType == TSDB_DB_TYPE_DEFAULT) ? TSDB_MSG_TYPE_CM_CREATE_DB : TSDB_MSG_TYPE_CM_CREATE_TP;
SCreateDbMsg *pCreateDbMsg = (SCreateDbMsg *)pCmd->payload;
@@ -1223,7 +1252,7 @@ int32_t tscBuildDropDbMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
pDropDbMsg->ignoreNotExists = pInfo->pMiscInfo->existsCheck ? 1 : 0;
- pCmd->msgType = TSDB_MSG_TYPE_CM_DROP_DB;
+ pCmd->msgType = (pInfo->pMiscInfo->dbType == TSDB_DB_TYPE_DEFAULT) ? TSDB_MSG_TYPE_CM_DROP_DB : TSDB_MSG_TYPE_CM_DROP_TP;
return TSDB_CODE_SUCCESS;
}
@@ -1301,6 +1330,23 @@ int32_t tscBuildUseDbMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
return TSDB_CODE_SUCCESS;
}
+int32_t tscBuildSyncDbReplicaMsg(SSqlObj* pSql, SSqlInfo *pInfo) {
+ SSqlCmd *pCmd = &pSql->cmd;
+ pCmd->payloadLen = sizeof(SSyncDbMsg);
+
+ if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, pCmd->payloadLen)) {
+ tscError("%p failed to malloc for query msg", pSql);
+ return TSDB_CODE_TSC_OUT_OF_MEMORY;
+ }
+
+ SSyncDbMsg *pSyncMsg = (SSyncDbMsg *)pCmd->payload;
+ STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
+ tNameExtractFullName(&pTableMetaInfo->name, pSyncMsg->db);
+ pCmd->msgType = TSDB_MSG_TYPE_CM_SYNC_DB;
+
+ return TSDB_CODE_SUCCESS;
+}
+
int32_t tscBuildShowMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
STscObj *pObj = pSql->pTscObj;
SSqlCmd *pCmd = &pSql->cmd;
@@ -1367,7 +1413,7 @@ int tscEstimateCreateTableMsgLength(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &(pSql->cmd);
int32_t size = minMsgSize() + sizeof(SCMCreateTableMsg) + sizeof(SCreateTableMsg);
- SCreateTableSQL *pCreateTableInfo = pInfo->pCreateTableInfo;
+ SCreateTableSql *pCreateTableInfo = pInfo->pCreateTableInfo;
if (pCreateTableInfo->type == TSQL_CREATE_TABLE_FROM_STABLE) {
int32_t numOfTables = (int32_t)taosArrayGetSize(pInfo->pCreateTableInfo->childTableInfo);
size += numOfTables * (sizeof(SCreateTableMsg) + TSDB_MAX_TAGS_LEN);
@@ -1376,7 +1422,7 @@ int tscEstimateCreateTableMsgLength(SSqlObj *pSql, SSqlInfo *pInfo) {
}
if (pCreateTableInfo->pSelect != NULL) {
- size += (pCreateTableInfo->pSelect->selectToken.n + 1);
+ size += (pCreateTableInfo->pSelect->sqlstr.n + 1);
}
return size + TSDB_EXTRA_PAYLOAD_SIZE;
@@ -1434,7 +1480,7 @@ int tscBuildCreateTableMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int32_t code = tNameExtractFullName(&pTableMetaInfo->name, pCreateMsg->tableName);
assert(code == 0);
- SCreateTableSQL *pCreateTable = pInfo->pCreateTableInfo;
+ SCreateTableSql *pCreateTable = pInfo->pCreateTableInfo;
pCreateMsg->igExists = pCreateTable->existCheck ? 1 : 0;
pCreateMsg->numOfColumns = htons(pCmd->numOfCols);
@@ -1457,11 +1503,11 @@ int tscBuildCreateTableMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
pMsg = (char *)pSchema;
if (type == TSQL_CREATE_STREAM) { // check if it is a stream sql
- SQuerySQL *pQuerySql = pInfo->pCreateTableInfo->pSelect;
+ SQuerySqlNode *pQuerySql = pInfo->pCreateTableInfo->pSelect;
- strncpy(pMsg, pQuerySql->selectToken.z, pQuerySql->selectToken.n + 1);
- pCreateMsg->sqlLen = htons(pQuerySql->selectToken.n + 1);
- pMsg += pQuerySql->selectToken.n + 1;
+ strncpy(pMsg, pQuerySql->sqlstr.z, pQuerySql->sqlstr.n + 1);
+ pCreateMsg->sqlLen = htons(pQuerySql->sqlstr.n + 1);
+ pMsg += pQuerySql->sqlstr.n + 1;
}
}
@@ -1550,9 +1596,11 @@ int tscBuildUpdateTagMsg(SSqlObj* pSql, SSqlInfo *pInfo) {
int tscAlterDbMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlCmd *pCmd = &pSql->cmd;
pCmd->payloadLen = sizeof(SAlterDbMsg);
- pCmd->msgType = TSDB_MSG_TYPE_CM_ALTER_DB;
+ pCmd->msgType = (pInfo->pMiscInfo->dbOpt.dbType == TSDB_DB_TYPE_DEFAULT) ? TSDB_MSG_TYPE_CM_ALTER_DB : TSDB_MSG_TYPE_CM_ALTER_TP;
SAlterDbMsg *pAlterDbMsg = (SAlterDbMsg* )pCmd->payload;
+ pAlterDbMsg->dbType = -1;
+
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
tNameExtractFullName(&pTableMetaInfo->name, pAlterDbMsg->db);
@@ -1571,7 +1619,7 @@ int tscBuildRetrieveFromMgmtMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
SRetrieveTableMsg *pRetrieveMsg = (SRetrieveTableMsg*)pCmd->payload;
- pRetrieveMsg->qhandle = htobe64(pSql->res.qhandle);
+ pRetrieveMsg->qId = htobe64(pSql->res.qId);
pRetrieveMsg->free = htons(pQueryInfo->type);
return TSDB_CODE_SUCCESS;
@@ -2079,19 +2127,24 @@ int tscProcessSTableVgroupRsp(SSqlObj *pSql) {
assert(pInfo->vgroupList != NULL);
pInfo->vgroupList->numOfVgroups = pVgroupMsg->numOfVgroups;
- for (int32_t j = 0; j < pInfo->vgroupList->numOfVgroups; ++j) {
- //just init, no need to lock
- SVgroupInfo *pVgroups = &pInfo->vgroupList->vgroups[j];
+ if (pInfo->vgroupList->numOfVgroups <= 0) {
+ //tfree(pInfo->vgroupList);
+ 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];
- SVgroupMsg *vmsg = &pVgroupMsg->vgroups[j];
- pVgroups->vgId = htonl(vmsg->vgId);
- pVgroups->numOfEps = vmsg->numOfEps;
+ SVgroupMsg *vmsg = &pVgroupMsg->vgroups[j];
+ pVgroups->vgId = htonl(vmsg->vgId);
+ pVgroups->numOfEps = vmsg->numOfEps;
- assert(pVgroups->numOfEps >= 1 && pVgroups->vgId >= 1);
+ assert(pVgroups->numOfEps >= 1 && pVgroups->vgId >= 1);
- 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));
+ 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));
+ }
}
}
@@ -2117,7 +2170,7 @@ int tscProcessShowRsp(SSqlObj *pSql) {
pShow = (SShowRsp *)pRes->pRsp;
pShow->qhandle = htobe64(pShow->qhandle);
- pRes->qhandle = pShow->qhandle;
+ pRes->qId = pShow->qhandle;
tscResetForNextRetrieve(pRes);
pMetaMsg = &(pShow->tableMeta);
@@ -2299,11 +2352,12 @@ int tscProcessQueryRsp(SSqlObj *pSql) {
SSqlRes *pRes = &pSql->res;
SQueryTableRsp *pQuery = (SQueryTableRsp *)pRes->pRsp;
- pQuery->qhandle = htobe64(pQuery->qhandle);
- pRes->qhandle = pQuery->qhandle;
+ pQuery->qId = htobe64(pQuery->qId);
+ pRes->qId = pQuery->qId;
pRes->data = NULL;
tscResetForNextRetrieve(pRes);
+ tscDebug("%p query rsp received, qId:%"PRIu64, pSql, pRes->qId);
return 0;
}
@@ -2361,7 +2415,8 @@ int tscProcessRetrieveRspFromNode(SSqlObj *pSql) {
}
pRes->row = 0;
- tscDebug("%p numOfRows:%d, offset:%" PRId64 ", complete:%d", pSql, pRes->numOfRows, pRes->offset, pRes->completed);
+ tscDebug("%p numOfRows:%d, offset:%" PRId64 ", complete:%d, qId:%"PRIu64, pSql, pRes->numOfRows, pRes->offset,
+ pRes->completed, pRes->qId);
return 0;
}
@@ -2574,6 +2629,7 @@ void tscInitMsgsFp() {
tscBuildMsg[TSDB_SQL_DROP_USER] = tscBuildDropUserAcctMsg;
tscBuildMsg[TSDB_SQL_DROP_ACCT] = tscBuildDropUserAcctMsg;
tscBuildMsg[TSDB_SQL_DROP_DB] = tscBuildDropDbMsg;
+ tscBuildMsg[TSDB_SQL_SYNC_DB_REPLICA] = tscBuildSyncDbReplicaMsg;
tscBuildMsg[TSDB_SQL_DROP_TABLE] = tscBuildDropTableMsg;
tscBuildMsg[TSDB_SQL_ALTER_USER] = tscBuildUserMsg;
tscBuildMsg[TSDB_SQL_CREATE_DNODE] = tscBuildCreateDnodeMsg;
diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c
index 13539a9b197875210d76c86bd93ec986190c0c37..93d0e9fd092b7e91fc8028e30f73a13bdb02627d 100644
--- a/src/client/src/tscSql.c
+++ b/src/client/src/tscSql.c
@@ -476,7 +476,7 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) {
SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res;
- if (pRes->qhandle == 0 ||
+ if (pRes->qId == 0 ||
pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED ||
pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
pCmd->command == TSDB_SQL_INSERT) {
@@ -508,7 +508,7 @@ int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res;
- if (pRes->qhandle == 0 ||
+ if (pRes->qId == 0 ||
pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED ||
pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
pCmd->command == TSDB_SQL_INSERT) {
@@ -554,7 +554,7 @@ static bool tscKillQueryInDnode(SSqlObj* pSql) {
SSqlCmd* pCmd = &pSql->cmd;
SSqlRes* pRes = &pSql->res;
- if (pRes == NULL || pRes->qhandle == 0) {
+ if (pRes == NULL || pRes->qId == 0) {
return true;
}
@@ -1050,7 +1050,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
* If qhandle is NOT set 0, the function of taos_free_result() will send message to server by calling tscProcessSql()
* to free connection, which may cause segment fault, when the parse phrase is not even successfully executed.
*/
- pRes->qhandle = 0;
+ pRes->qId = 0;
free(str);
if (code != TSDB_CODE_SUCCESS) {
diff --git a/src/client/src/tscSub.c b/src/client/src/tscSub.c
index f3d7ef28c05fc3128622f8217341d52327d79ec0..1277a436a14c926b756ff99b0cd2e045f5dfed1f 100644
--- a/src/client/src/tscSub.c
+++ b/src/client/src/tscSub.c
@@ -149,7 +149,7 @@ static SSub* tscCreateSubscription(STscObj* pObj, const char* topic, const char*
}
strtolower(pSql->sqlstr, pSql->sqlstr);
- pRes->qhandle = 0;
+ pRes->qId = 0;
pRes->numOfRows = 1;
code = tscAllocPayload(pCmd, TSDB_DEFAULT_PAYLOAD_SIZE);
@@ -448,7 +448,7 @@ SSqlObj* recreateSqlObj(SSub* pSub) {
return NULL;
}
- pRes->qhandle = 0;
+ pRes->qId = 0;
pRes->numOfRows = 1;
int code = tscAllocPayload(pCmd, TSDB_DEFAULT_PAYLOAD_SIZE);
@@ -503,9 +503,19 @@ TAOS_RES *taos_consume(TAOS_SUB *tsub) {
SSqlCmd *pCmd = &pSql->cmd;
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
- if (taosArrayGetSize(pSub->progress) > 0) { // fix crash in single tabel subscription
- pQueryInfo->window.skey = ((SSubscriptionProgress*)taosArrayGet(pSub->progress, 0))->key;
- tscDebug("subscribe:%s set subscribe skey:%"PRId64, pSub->topic, pQueryInfo->window.skey);
+ if (taosArrayGetSize(pSub->progress) > 0) { // fix crash in single table subscription
+
+ size_t size = taosArrayGetSize(pSub->progress);
+ TSKEY s = INT64_MAX;
+ for(int32_t i = 0; i < size; ++i) {
+ TSKEY k = ((SSubscriptionProgress*)taosArrayGet(pSub->progress, i))->key;
+ if (s > k) {
+ s = k;
+ }
+ }
+
+ pQueryInfo->window.skey = s;
+ tscDebug("subscribe:%s set next round subscribe skey:%"PRId64, pSub->topic, pQueryInfo->window.skey);
}
if (pSub->pTimer == NULL) {
@@ -536,7 +546,7 @@ TAOS_RES *taos_consume(TAOS_SUB *tsub) {
uint32_t type = pQueryInfo->type;
tscFreeSqlResult(pSql);
pRes->numOfRows = 1;
- pRes->qhandle = 0;
+ pRes->qId = 0;
pSql->cmd.command = TSDB_SQL_SELECT;
pQueryInfo->type = type;
diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c
index 6dca3f9059338057efc59a787839c1d287a42f8c..299cf038057bf5ce80c449be41faa484e0a8ef93 100644
--- a/src/client/src/tscSubquery.c
+++ b/src/client/src/tscSubquery.c
@@ -46,6 +46,13 @@ static int32_t tsCompare(int32_t order, int64_t left, int64_t right) {
}
static void skipRemainValue(STSBuf* pTSBuf, tVariant* tag1) {
+ STSElem el1 = tsBufGetElem(pTSBuf);
+
+ int32_t res = tVariantCompare(el1.tag, tag1);
+ if (res != 0) { // it is a record with new tag
+ return;
+ }
+
while (tsBufNextPos(pTSBuf)) {
STSElem el1 = tsBufGetElem(pTSBuf);
@@ -74,14 +81,14 @@ static bool allSubqueryDone(SSqlObj *pParentSql) {
SSubqueryState *subState = &pParentSql->subState;
//lock in caller
-
+ tscDebug("%p total subqueries: %d", pParentSql, subState->numOfSub);
for (int i = 0; i < subState->numOfSub; i++) {
if (0 == subState->states[i]) {
- tscDebug("%p subquery:%p,%d is NOT finished, total:%d", pParentSql, pParentSql->pSubs[i], i, subState->numOfSub);
+ tscDebug("%p subquery:%p, index: %d NOT finished, abort query completion check", pParentSql, pParentSql->pSubs[i], i);
done = false;
break;
} else {
- tscDebug("%p subquery:%p,%d is finished, total:%d", pParentSql, pParentSql->pSubs[i], i, subState->numOfSub);
+ tscDebug("%p subquery:%p, index: %d finished", pParentSql, pParentSql->pSubs[i], i);
}
}
@@ -118,123 +125,233 @@ static bool subAndCheckDone(SSqlObj *pSql, SSqlObj *pParentSql, int idx) {
-static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJoinSupporter* pSupporter2, STimeWindow * win) {
+static int64_t doTSBlockIntersect(SSqlObj* pSql, STimeWindow * win) {
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex);
- STSBuf* output1 = tsBufCreate(true, pQueryInfo->order.order);
- STSBuf* output2 = tsBufCreate(true, pQueryInfo->order.order);
-
win->skey = INT64_MAX;
win->ekey = INT64_MIN;
SLimitVal* pLimit = &pQueryInfo->limit;
int32_t order = pQueryInfo->order.order;
+ int32_t joinNum = pSql->subState.numOfSub;
+ SMergeTsCtx ctxlist[TSDB_MAX_JOIN_TABLE_NUM] = {{0}};
+ SMergeTsCtx* ctxStack[TSDB_MAX_JOIN_TABLE_NUM] = {0};
+ int32_t slot = 0;
+ size_t tableNum = 0;
+ int16_t* tableMIdx = 0;
+ int32_t equalNum = 0;
+ int32_t stackidx = 0;
+ SMergeTsCtx* ctx = NULL;
+ SMergeTsCtx* pctx = NULL;
+ SMergeTsCtx* mainCtx = NULL;
+ STSElem cur;
+ STSElem prev;
+ SArray* tsCond = NULL;
+ int32_t mergeDone = 0;
+
+ for (int32_t i = 0; i < joinNum; ++i) {
+ STSBuf* output = tsBufCreate(true, pQueryInfo->order.order);
+ SQueryInfo* pSubQueryInfo = tscGetQueryInfoDetail(&pSql->pSubs[i]->cmd, 0);
+
+ pSubQueryInfo->tsBuf = output;
+
+ SJoinSupporter* pSupporter = pSql->pSubs[i]->param;
- SQueryInfo* pSubQueryInfo1 = tscGetQueryInfoDetail(&pSql->pSubs[0]->cmd, 0);
- SQueryInfo* pSubQueryInfo2 = tscGetQueryInfoDetail(&pSql->pSubs[1]->cmd, 0);
+ if (pSupporter->pTSBuf == NULL) {
+ tscDebug("%p at least one ts-comp is empty, 0 for secondary query after ts blocks intersecting", pSql);
+ return 0;
+ }
- pSubQueryInfo1->tsBuf = output1;
- pSubQueryInfo2->tsBuf = output2;
+ tsBufResetPos(pSupporter->pTSBuf);
- TSKEY st = taosGetTimestampUs();
+ if (!tsBufNextPos(pSupporter->pTSBuf)) {
+ tscDebug("%p input1 is empty, 0 for secondary query after ts blocks intersecting", pSql);
+ return 0;
+ }
- // no result generated, return directly
- if (pSupporter1->pTSBuf == NULL || pSupporter2->pTSBuf == NULL) {
- tscDebug("%p at least one ts-comp is empty, 0 for secondary query after ts blocks intersecting", pSql);
- return 0;
+ tscDebug("%p sub:%p table idx:%d, input group number:%d", pSql, pSql->pSubs[i], i, pSupporter->pTSBuf->numOfGroups);
+
+ ctxlist[i].p = pSupporter;
+ ctxlist[i].res = output;
}
- tsBufResetPos(pSupporter1->pTSBuf);
- tsBufResetPos(pSupporter2->pTSBuf);
+ TSKEY st = taosGetTimestampUs();
- if (!tsBufNextPos(pSupporter1->pTSBuf)) {
- tsBufFlush(output1);
- tsBufFlush(output2);
+ for (int16_t tidx = 0; tidx < joinNum; tidx++) {
+ pctx = &ctxlist[tidx];
+ if (pctx->compared) {
+ continue;
+ }
- tscDebug("%p input1 is empty, 0 for secondary query after ts blocks intersecting", pSql);
- return 0;
- }
+ assert(pctx->numOfInput == 0);
- if (!tsBufNextPos(pSupporter2->pTSBuf)) {
- tsBufFlush(output1);
- tsBufFlush(output2);
+ tsCond = pQueryInfo->tagCond.joinInfo.joinTables[tidx]->tsJoin;
- tscDebug("%p input2 is empty, 0 for secondary query after ts blocks intersecting", pSql);
- return 0;
- }
+ tableNum = taosArrayGetSize(tsCond);
+ assert(tableNum >= 2);
- int64_t numOfInput1 = 1;
- int64_t numOfInput2 = 1;
+ for (int32_t i = 0; i < tableNum; ++i) {
+ tableMIdx = taosArrayGet(tsCond, i);
+ SMergeTsCtx* tctx = &ctxlist[*tableMIdx];
+ tctx->compared = 1;
+ }
- while(1) {
- STSElem elem = tsBufGetElem(pSupporter1->pTSBuf);
+ tableMIdx = taosArrayGet(tsCond, 0);
+ pctx = &ctxlist[*tableMIdx];
- // no data in pSupporter1 anymore, jump out of loop
- if (!tsBufIsValidElem(&elem)) {
- break;
- }
+ mainCtx = pctx;
- // find the data in supporter2 with the same tag value
- STSElem e2 = tsBufFindElemStartPosByTag(pSupporter2->pTSBuf, elem.tag);
+ while (1) {
+ pctx = mainCtx;
- /**
- * there are elements in pSupporter2 with the same tag, continue
- */
- tVariant tag1 = {0};
- tVariantAssign(&tag1, elem.tag);
+ prev = tsBufGetElem(pctx->p->pTSBuf);
+
+ ctxStack[stackidx++] = pctx;
+
+ if (!tsBufIsValidElem(&prev)) {
+ break;
+ }
+
+ tVariant tag = {0};
+ tVariantAssign(&tag, prev.tag);
+
+ int32_t skipped = 0;
+
+ for (int32_t i = 1; i < tableNum; ++i) {
+ SMergeTsCtx* tctx = &ctxlist[i];
+
+ // find the data in supporter2 with the same tag value
+ STSElem e2 = tsBufFindElemStartPosByTag(tctx->p->pTSBuf, &tag);
+
+ if (!tsBufIsValidElem(&e2)) {
+ skipRemainValue(pctx->p->pTSBuf, &tag);
+ skipped = 1;
+ break;
+ }
+ }
+
+ if (skipped) {
+ slot = 0;
+ stackidx = 0;
+ continue;
+ }
+
+ tableMIdx = taosArrayGet(tsCond, ++slot);
+ equalNum = 1;
- if (tsBufIsValidElem(&e2)) {
while (1) {
- STSElem elem1 = tsBufGetElem(pSupporter1->pTSBuf);
- STSElem elem2 = tsBufGetElem(pSupporter2->pTSBuf);
+ ctx = &ctxlist[*tableMIdx];
+
+ prev = tsBufGetElem(pctx->p->pTSBuf);
+ cur = tsBufGetElem(ctx->p->pTSBuf);
// data with current are exhausted
- if (!tsBufIsValidElem(&elem1) || tVariantCompare(elem1.tag, &tag1) != 0) {
+ if (!tsBufIsValidElem(&prev) || tVariantCompare(prev.tag, &tag) != 0) {
break;
}
- if (!tsBufIsValidElem(&elem2) || tVariantCompare(elem2.tag, &tag1) != 0) { // ignore all records with the same tag
- skipRemainValue(pSupporter1->pTSBuf, &tag1);
+ if (!tsBufIsValidElem(&cur) || tVariantCompare(cur.tag, &tag) != 0) { // ignore all records with the same tag
break;
}
- /*
- * in case of stable query, limit/offset is not applied here. the limit/offset is applied to the
- * final results which is acquired after the secondary merge of in the client.
- */
- int32_t re = tsCompare(order, elem1.ts, elem2.ts);
- if (re < 0) {
- tsBufNextPos(pSupporter1->pTSBuf);
- numOfInput1++;
- } else if (re > 0) {
- tsBufNextPos(pSupporter2->pTSBuf);
- numOfInput2++;
- } else {
- if (pLimit->offset == 0 || pQueryInfo->interval.interval > 0 || QUERY_IS_STABLE_QUERY(pQueryInfo->type)) {
- if (win->skey > elem1.ts) {
- win->skey = elem1.ts;
+ ctxStack[stackidx++] = ctx;
+
+ int32_t ret = tsCompare(order, prev.ts, cur.ts);
+ if (ret == 0) {
+ if (++equalNum < tableNum) {
+ pctx = ctx;
+
+ if (++slot >= tableNum) {
+ slot = 0;
}
- if (win->ekey < elem1.ts) {
- win->ekey = elem1.ts;
+ tableMIdx = taosArrayGet(tsCond, slot);
+ continue;
+ }
+
+ assert(stackidx == tableNum);
+
+ if (pLimit->offset == 0 || pQueryInfo->interval.interval > 0 || QUERY_IS_STABLE_QUERY(pQueryInfo->type)) {
+ if (win->skey > prev.ts) {
+ win->skey = prev.ts;
+ }
+
+ if (win->ekey < prev.ts) {
+ win->ekey = prev.ts;
}
- tsBufAppend(output1, elem1.id, elem1.tag, (const char*)&elem1.ts, sizeof(elem1.ts));
- tsBufAppend(output2, elem2.id, elem2.tag, (const char*)&elem2.ts, sizeof(elem2.ts));
+ for (int32_t i = 0; i < stackidx; ++i) {
+ SMergeTsCtx* tctx = ctxStack[i];
+ prev = tsBufGetElem(tctx->p->pTSBuf);
+
+ tsBufAppend(tctx->res, prev.id, prev.tag, (const char*)&prev.ts, sizeof(prev.ts));
+ }
} else {
pLimit->offset -= 1;//offset apply to projection?
}
- tsBufNextPos(pSupporter1->pTSBuf);
- numOfInput1++;
+ for (int32_t i = 0; i < stackidx; ++i) {
+ SMergeTsCtx* tctx = ctxStack[i];
+
+ if (!tsBufNextPos(tctx->p->pTSBuf) && tctx == mainCtx) {
+ mergeDone = 1;
+ }
+ tctx->numOfInput++;
+ }
+
+ if (mergeDone) {
+ break;
+ }
+
+ stackidx = 0;
+ equalNum = 1;
+
+ ctxStack[stackidx++] = pctx;
+ } else if (ret > 0) {
+ if (!tsBufNextPos(ctx->p->pTSBuf) && ctx == mainCtx) {
+ mergeDone = 1;
+ break;
+ }
+
+ ctx->numOfInput++;
+ stackidx--;
+ } else {
+ stackidx--;
+
+ for (int32_t i = 0; i < stackidx; ++i) {
+ SMergeTsCtx* tctx = ctxStack[i];
+
+ if (!tsBufNextPos(tctx->p->pTSBuf) && tctx == mainCtx) {
+ mergeDone = 1;
+ }
+ tctx->numOfInput++;
+ }
- tsBufNextPos(pSupporter2->pTSBuf);
- numOfInput2++;
+ if (mergeDone) {
+ break;
+ }
+
+ stackidx = 0;
+ equalNum = 1;
+
+ ctxStack[stackidx++] = pctx;
}
+
}
- } else { // no data in pSupporter2, ignore current data in pSupporter2
- skipRemainValue(pSupporter1->pTSBuf, &tag1);
+
+ if (mergeDone) {
+ break;
+ }
+
+ slot = 0;
+ stackidx = 0;
+
+ skipRemainValue(mainCtx->p->pTSBuf, &tag);
}
+
+ stackidx = 0;
+ slot = 0;
+ mergeDone = 0;
}
/*
@@ -242,28 +359,32 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJ
* 1. only one element
* 2. only one element for each tag.
*/
- if (output1->tsOrder == -1) {
- output1->tsOrder = TSDB_ORDER_ASC;
- output2->tsOrder = TSDB_ORDER_ASC;
+ if (ctxlist[0].res->tsOrder == -1) {
+ for (int32_t i = 0; i < joinNum; ++i) {
+ ctxlist[i].res->tsOrder = TSDB_ORDER_ASC;
+ }
}
- tsBufFlush(output1);
- tsBufFlush(output2);
-
- tsBufDestroy(pSupporter1->pTSBuf);
- pSupporter1->pTSBuf = NULL;
- tsBufDestroy(pSupporter2->pTSBuf);
- pSupporter2->pTSBuf = NULL;
+ for (int32_t i = 0; i < joinNum; ++i) {
+ tsBufFlush(ctxlist[i].res);
+
+ tsBufDestroy(ctxlist[i].p->pTSBuf);
+ ctxlist[i].p->pTSBuf = NULL;
+ }
TSKEY et = taosGetTimestampUs();
- tscDebug("%p input1:%" PRId64 ", input2:%" PRId64 ", final:%" PRId64 " in %d vnodes for secondary query after ts blocks "
- "intersecting, skey:%" PRId64 ", ekey:%" PRId64 ", numOfVnode:%d, elapsed time:%" PRId64 " us",
- pSql, numOfInput1, numOfInput2, output1->numOfTotal, output1->numOfGroups, win->skey, win->ekey,
- tsBufGetNumOfGroup(output1), et - st);
- return output1->numOfTotal;
+ for (int32_t i = 0; i < joinNum; ++i) {
+ tscDebug("%p sub:%p tblidx:%d, input:%" PRId64 ", final:%" PRId64 " in %d vnodes for secondary query after ts blocks "
+ "intersecting, skey:%" PRId64 ", ekey:%" PRId64 ", numOfVnode:%d, elapsed time:%" PRId64 " us",
+ pSql, pSql->pSubs[i], i, ctxlist[i].numOfInput, ctxlist[i].res->numOfTotal, ctxlist[i].res->numOfGroups, win->skey, win->ekey,
+ tsBufGetNumOfGroup(ctxlist[i].res), et - st);
+ }
+
+ return ctxlist[0].res->numOfTotal;
}
+
// todo handle failed to create sub query
SJoinSupporter* tscCreateJoinSupporter(SSqlObj* pSql, int32_t index) {
SJoinSupporter* pSupporter = calloc(1, sizeof(SJoinSupporter));
@@ -453,7 +574,7 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) {
pSubQueryInfo->tsBuf = NULL;
// free result for async object will also free sqlObj
- assert(tscSqlExprNumOfExprs(pSubQueryInfo) == 1); // ts_comp query only requires one resutl columns
+ assert(tscSqlExprNumOfExprs(pSubQueryInfo) == 1); // ts_comp query only requires one result columns
taos_free_result(pPrevSub);
SSqlObj *pNew = createSubqueryObj(pSql, (int16_t) i, tscJoinQueryCallback, pSupporter, TSDB_SQL_SELECT, NULL);
@@ -507,6 +628,7 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, 0);
int16_t funcId = pExpr->functionId;
+ // add the invisible timestamp column
if ((pExpr->colInfo.colId != PRIMARYKEY_TIMESTAMP_COL_INDEX) ||
(funcId != TSDB_FUNC_TS && funcId != TSDB_FUNC_TS_DUMMY && funcId != TSDB_FUNC_PRJ)) {
@@ -767,76 +889,218 @@ static bool checkForDuplicateTagVal(SSchema* pColSchema, SJoinSupporter* p1, SSq
return true;
}
-static int32_t getIntersectionOfTableTuple(SQueryInfo* pQueryInfo, SSqlObj* pParentSql, SArray** s1, SArray** s2) {
- SJoinSupporter* p1 = pParentSql->pSubs[0]->param;
- SJoinSupporter* p2 = pParentSql->pSubs[1]->param;
-
- tscDebug("%p all subquery retrieve complete, do tags match, %d, %d", pParentSql, p1->num, p2->num);
-
- // sort according to the tag value
- qsort(p1->pIdTagList, p1->num, p1->tagSize, tagValCompar);
- qsort(p2->pIdTagList, p2->num, p2->tagSize, tagValCompar);
+static int32_t getIntersectionOfTableTuple(SQueryInfo* pQueryInfo, SSqlObj* pParentSql, SArray* resList) {
+ int16_t joinNum = pParentSql->subState.numOfSub;
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
int16_t tagColId = tscGetJoinTagColIdByUid(&pQueryInfo->tagCond, pTableMetaInfo->pTableMeta->id.uid);
+ SJoinSupporter* p0 = pParentSql->pSubs[0]->param;
+ SMergeCtx ctxlist[TSDB_MAX_JOIN_TABLE_NUM] = {{0}};
+ SMergeCtx* ctxStack[TSDB_MAX_JOIN_TABLE_NUM] = {0};
+
+ // int16_t for padding
+ int32_t size = p0->tagSize - sizeof(int16_t);
SSchema* pColSchema = tscGetColumnSchemaById(pTableMetaInfo->pTableMeta, tagColId);
+
+ tscDebug("%p all subquery retrieve complete, do tags match", pParentSql);
- // int16_t for padding
- int32_t size = p1->tagSize - sizeof(int16_t);
- *s1 = taosArrayInit(p1->num, size);
- *s2 = taosArrayInit(p2->num, size);
-
- if (!(checkForDuplicateTagVal(pColSchema, p1, pParentSql) && checkForDuplicateTagVal(pColSchema, p2, pParentSql))) {
- return TSDB_CODE_QRY_DUP_JOIN_KEY;
- }
-
- int32_t i = 0, j = 0;
- while(i < p1->num && j < p2->num) {
- STidTags* pp1 = (STidTags*) varDataVal(p1->pIdTagList + i * p1->tagSize);
- STidTags* pp2 = (STidTags*) varDataVal(p2->pIdTagList + j * p2->tagSize);
- assert(pp1->tid != 0 && pp2->tid != 0);
-
- int32_t ret = doCompare(pp1->tag, pp2->tag, pColSchema->type, pColSchema->bytes);
- if (ret == 0) {
- tscDebug("%p tag matched, vgId:%d, val:%d, tid:%d, uid:%"PRIu64", tid:%d, uid:%"PRIu64, pParentSql, pp1->vgId,
- *(int*) pp1->tag, pp1->tid, pp1->uid, pp2->tid, pp2->uid);
-
- taosArrayPush(*s1, pp1);
- taosArrayPush(*s2, pp2);
- j++;
- i++;
- } else if (ret > 0) {
- j++;
- } else {
- i++;
+ for (int32_t i = 0; i < joinNum; i++) {
+ SJoinSupporter* p = pParentSql->pSubs[i]->param;
+
+ ctxlist[i].p = p;
+ ctxlist[i].res = taosArrayInit(p->num, size);
+
+ tscDebug("Join %d - num:%d", i, p->num);
+
+ // sort according to the tag valu
+ qsort(p->pIdTagList, p->num, p->tagSize, tagValCompar);
+
+ if (!checkForDuplicateTagVal(pColSchema, p, pParentSql)) {
+ for (int32_t j = 0; j <= i; j++) {
+ taosArrayDestroy(ctxlist[j].res);
+ }
+ return TSDB_CODE_QRY_DUP_JOIN_KEY;
}
}
- // reorganize the tid-tag value according to both the vgroup id and tag values
- // sort according to the tag value
- size_t t1 = taosArrayGetSize(*s1);
- size_t t2 = taosArrayGetSize(*s2);
+ int32_t slot = 0;
+ size_t tableNum = 0;
+ int16_t* tableMIdx = 0;
+ int32_t equalNum = 0;
+ int32_t stackidx = 0;
+ int32_t mergeDone = 0;
+ SMergeCtx* ctx = NULL;
+ SMergeCtx* pctx = NULL;
+ STidTags* cur = NULL;
+ STidTags* prev = NULL;
+ SArray* tagCond = NULL;
+
+ for (int16_t tidx = 0; tidx < joinNum; tidx++) {
+ pctx = &ctxlist[tidx];
+ if (pctx->compared) {
+ continue;
+ }
- qsort((*s1)->pData, t1, size, tidTagsCompar);
- qsort((*s2)->pData, t2, size, tidTagsCompar);
+ assert(pctx->idx == 0 && taosArrayGetSize(pctx->res) == 0);
-#if 0
- for(int32_t k = 0; k < t1; ++k) {
- STidTags* p = (*s1)->pData + size * k;
- printf("%d, tag:%s\n", p->vgId, ((tstr*)(p->tag))->data);
- }
+ tagCond = pQueryInfo->tagCond.joinInfo.joinTables[tidx]->tagJoin;
+
+ tableNum = taosArrayGetSize(tagCond);
+ assert(tableNum >= 2);
+
+ for (int32_t i = 0; i < tableNum; ++i) {
+ tableMIdx = taosArrayGet(tagCond, i);
+ SMergeCtx* tctx = &ctxlist[*tableMIdx];
+ tctx->compared = 1;
+ }
+
+ for (int32_t i = 0; i < tableNum; ++i) {
+ tableMIdx = taosArrayGet(tagCond, i);
+ SMergeCtx* tctx = &ctxlist[*tableMIdx];
+ if (tctx->p->num <= 0 || tctx->p->pIdTagList == NULL) {
+ mergeDone = 1;
+ break;
+ }
+ }
+
+ if (mergeDone) {
+ mergeDone = 0;
+ continue;
+ }
+
+ tableMIdx = taosArrayGet(tagCond, slot);
+
+ pctx = &ctxlist[*tableMIdx];
+
+ prev = (STidTags*) varDataVal(pctx->p->pIdTagList + pctx->idx * pctx->p->tagSize);
+
+ ctxStack[stackidx++] = pctx;
+
+ tableMIdx = taosArrayGet(tagCond, ++slot);
+
+ equalNum = 1;
+
+ while (1) {
+ ctx = &ctxlist[*tableMIdx];
+
+ cur = (STidTags*) varDataVal(ctx->p->pIdTagList + ctx->idx * ctx->p->tagSize);
+
+ assert(cur->tid != 0 && prev->tid != 0);
+
+ ctxStack[stackidx++] = ctx;
+
+ int32_t ret = doCompare(prev->tag, cur->tag, pColSchema->type, pColSchema->bytes);
+ if (ret == 0) {
+ if (++equalNum < tableNum) {
+ prev = cur;
+ pctx = ctx;
+
+ if (++slot >= tableNum) {
+ slot = 0;
+ }
+
+ tableMIdx = taosArrayGet(tagCond, slot);
+ continue;
+ }
+
+ tscDebug("%p tag matched, vgId:%d, val:%d, tid:%d, uid:%"PRIu64", tid:%d, uid:%"PRIu64, pParentSql, prev->vgId,
+ *(int*) prev->tag, prev->tid, prev->uid, cur->tid, cur->uid);
+
+ assert(stackidx == tableNum);
+
+ for (int32_t i = 0; i < stackidx; ++i) {
+ SMergeCtx* tctx = ctxStack[i];
+ prev = (STidTags*) varDataVal(tctx->p->pIdTagList + tctx->idx * tctx->p->tagSize);
+
+ taosArrayPush(tctx->res, prev);
+ }
+
+ for (int32_t i = 0; i < stackidx; ++i) {
+ SMergeCtx* tctx = ctxStack[i];
+
+ if (++tctx->idx >= tctx->p->num) {
+ mergeDone = 1;
+ break;
+ }
+ }
+
+ if (mergeDone) {
+ break;
+ }
+
+ stackidx = 0;
+ equalNum = 1;
+
+ prev = (STidTags*) varDataVal(pctx->p->pIdTagList + pctx->idx * pctx->p->tagSize);
+
+ ctxStack[stackidx++] = pctx;
+ } else if (ret > 0) {
+ stackidx--;
+
+ if (++ctx->idx >= ctx->p->num) {
+ break;
+ }
+ } else {
+ stackidx--;
+
+ for (int32_t i = 0; i < stackidx; ++i) {
+ SMergeCtx* tctx = ctxStack[i];
+ if (++tctx->idx >= tctx->p->num) {
+ mergeDone = 1;
+ break;
+ }
+ }
+
+ if (mergeDone) {
+ break;
+ }
+
+ stackidx = 0;
+ equalNum = 1;
+
+ prev = (STidTags*) varDataVal(pctx->p->pIdTagList + pctx->idx * pctx->p->tagSize);
+ ctxStack[stackidx++] = pctx;
+ }
+
+ }
- for(int32_t k = 0; k < t1; ++k) {
- STidTags* p = (*s2)->pData + size * k;
- printf("%d, tag:%s\n", p->vgId, ((tstr*)(p->tag))->data);
+ slot = 0;
+ mergeDone = 0;
+ stackidx = 0;
}
-#endif
- tscDebug("%p tags match complete, result: %"PRIzu", %"PRIzu, pParentSql, t1, t2);
+ for (int32_t i = 0; i < joinNum; ++i) {
+ // reorganize the tid-tag value according to both the vgroup id and tag values
+ // sort according to the tag value
+ size_t num = taosArrayGetSize(ctxlist[i].res);
+
+ qsort((ctxlist[i].res)->pData, num, size, tidTagsCompar);
+
+ taosArrayPush(resList, &ctxlist[i].res);
+
+ tscDebug("%p tags match complete, result num: %"PRIzu, pParentSql, num);
+ }
+
return TSDB_CODE_SUCCESS;
}
+bool emptyTagList(SArray* resList, int32_t size) {
+ size_t rsize = taosArrayGetSize(resList);
+ if (rsize != size) {
+ return true;
+ }
+
+ for (int32_t i = 0; i < size; ++i) {
+ SArray** s = taosArrayGet(resList, i);
+ if (taosArrayGetSize(*s) <= 0) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRows) {
SJoinSupporter* pSupporter = (SJoinSupporter*)param;
@@ -847,6 +1111,8 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
SSqlRes* pRes = &pSql->res;
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+
+ // todo, the type may not include TSDB_QUERY_TYPE_TAG_FILTER_QUERY
assert(TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY));
if (pParentSql->res.code != TSDB_CODE_SUCCESS) {
@@ -936,19 +1202,19 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
return;
}
- SArray *s1 = NULL, *s2 = NULL;
- int32_t code = getIntersectionOfTableTuple(pQueryInfo, pParentSql, &s1, &s2);
+ SArray* resList = taosArrayInit(pParentSql->subState.numOfSub, sizeof(SArray *));
+
+ int32_t code = getIntersectionOfTableTuple(pQueryInfo, pParentSql, resList);
if (code != TSDB_CODE_SUCCESS) {
freeJoinSubqueryObj(pParentSql);
pParentSql->res.code = code;
tscAsyncResultOnError(pParentSql);
- taosArrayDestroy(s1);
- taosArrayDestroy(s2);
+ taosArrayDestroy(resList);
return;
}
- if (taosArrayGetSize(s1) == 0 || taosArrayGetSize(s2) == 0) { // no results,return.
+ if (emptyTagList(resList, pParentSql->subState.numOfSub)) { // no results,return.
assert(pParentSql->fp != tscJoinQueryCallback);
tscDebug("%p tag intersect does not generated qualified tables for join, free all sub SqlObj and quit", pParentSql);
@@ -960,37 +1226,34 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
(*pParentSql->fp)(pParentSql->param, pParentSql, 0);
} else {
- // proceed to for ts_comp query
- SSqlCmd* pSubCmd1 = &pParentSql->pSubs[0]->cmd;
- SSqlCmd* pSubCmd2 = &pParentSql->pSubs[1]->cmd;
-
- SQueryInfo* pQueryInfo1 = tscGetQueryInfoDetail(pSubCmd1, 0);
- STableMetaInfo* pTableMetaInfo1 = tscGetMetaInfo(pQueryInfo1, 0);
- tscBuildVgroupTableInfo(pParentSql, pTableMetaInfo1, s1);
-
- SQueryInfo* pQueryInfo2 = tscGetQueryInfoDetail(pSubCmd2, 0);
- STableMetaInfo* pTableMetaInfo2 = tscGetMetaInfo(pQueryInfo2, 0);
- tscBuildVgroupTableInfo(pParentSql, pTableMetaInfo2, s2);
-
- SSqlObj* psub1 = pParentSql->pSubs[0];
- ((SJoinSupporter*)psub1->param)->pVgroupTables = tscVgroupTableInfoDup(pTableMetaInfo1->pVgroupTables);
-
- SSqlObj* psub2 = pParentSql->pSubs[1];
- ((SJoinSupporter*)psub2->param)->pVgroupTables = tscVgroupTableInfoDup(pTableMetaInfo2->pVgroupTables);
-
- pParentSql->subState.numOfSub = 2;
-
- memset(pParentSql->subState.states, 0, sizeof(pParentSql->subState.states[0]) * pParentSql->subState.numOfSub);
- tscDebug("%p reset all sub states to 0", pParentSql);
-
for (int32_t m = 0; m < pParentSql->subState.numOfSub; ++m) {
- SSqlObj* sub = pParentSql->pSubs[m];
- issueTsCompQuery(sub, sub->param, pParentSql);
+ // proceed to for ts_comp query
+ SSqlCmd* pSubCmd = &pParentSql->pSubs[m]->cmd;
+ SArray** s = taosArrayGet(resList, m);
+
+ SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pSubCmd, 0);
+ STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+ tscBuildVgroupTableInfo(pParentSql, pTableMetaInfo, *s);
+
+ SSqlObj* psub = pParentSql->pSubs[m];
+ ((SJoinSupporter*)psub->param)->pVgroupTables = tscVgroupTableInfoDup(pTableMetaInfo->pVgroupTables);
+
+ memset(pParentSql->subState.states, 0, sizeof(pParentSql->subState.states[0]) * pParentSql->subState.numOfSub);
+ tscDebug("%p reset all sub states to 0", pParentSql);
+
+ issueTsCompQuery(psub, psub->param, pParentSql);
+ }
+ }
+
+ size_t rsize = taosArrayGetSize(resList);
+ for (int32_t i = 0; i < rsize; ++i) {
+ SArray** s = taosArrayGet(resList, i);
+ if (*s) {
+ taosArrayDestroy(*s);
}
}
- taosArrayDestroy(s1);
- taosArrayDestroy(s2);
+ taosArrayDestroy(resList);
}
static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRows) {
@@ -1059,7 +1322,6 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
tscError("%p invalid ts comp file from vnode, abort subquery, file size:%d", pSql, numOfRows);
pParentSql->res.code = TAOS_SYSTEM_ERROR(errno);
-
if (quitAllSubquery(pSql, pParentSql, pSupporter)){
return;
}
@@ -1122,12 +1384,8 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
tscDebug("%p all subquery retrieve ts complete, do ts block intersect", pParentSql);
- // proceeds to launched secondary query to retrieve final data
- SJoinSupporter* p1 = pParentSql->pSubs[0]->param;
- SJoinSupporter* p2 = pParentSql->pSubs[1]->param;
-
STimeWindow win = TSWINDOW_INITIALIZER;
- int64_t num = doTSBlockIntersect(pParentSql, p1, p2, &win);
+ int64_t num = doTSBlockIntersect(pParentSql, &win);
if (num <= 0) { // no result during ts intersect
tscDebug("%p no results generated in ts intersection, free all sub SqlObj and quit", pParentSql);
freeJoinSubqueryObj(pParentSql);
@@ -1582,7 +1840,7 @@ int32_t tscCreateJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter
SSqlCmd * pCmd = &pSql->cmd;
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
- pSql->res.qhandle = 0x1;
+ pSql->res.qId = 0x1;
assert(pSql->res.numOfRows == 0);
if (pSql->pSubs == NULL) {
@@ -1637,6 +1895,8 @@ int32_t tscCreateJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter
pNewQueryInfo->limit.limit = -1;
pNewQueryInfo->limit.offset = 0;
+ pNewQueryInfo->order.orderColId = INT32_MIN;
+
// backup the data and clear it in the sqlcmd object
memset(&pNewQueryInfo->groupbyExpr, 0, sizeof(SSqlGroupbyExpr));
@@ -1948,7 +2208,11 @@ void tscFirstRoundRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
// tag or group by column
if (TSDB_COL_IS_TAG(pExpr->colInfo.flag) || pExpr->functionId == TSDB_FUNC_PRJ) {
- memcpy(p + offset, row[i], length[i]);
+ if (row[i] == NULL) {
+ setNull(p + offset, pExpr->resType, pExpr->resBytes);
+ } else {
+ memcpy(p + offset, row[i], length[i]);
+ }
offset += pExpr->resBytes;
}
}
@@ -2176,7 +2440,7 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
SColumnModel *pModel = NULL;
SColumnModel *pFinalModel = NULL;
- pRes->qhandle = 0x1; // hack the qhandle check
+ pRes->qId = 0x1; // hack the qhandle check
const uint32_t nBufferSize = (1u << 16u); // 64KB
@@ -2646,12 +2910,17 @@ static SSqlObj *tscCreateSTableSubquery(SSqlObj *pSql, SRetrieveSupport *trsuppo
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pNew->cmd, 0);
pQueryInfo->type |= TSDB_QUERY_TYPE_STABLE_SUBQUERY;
+
+ // clear the limit/offset info, since it should not be sent to vnode to be executed.
+ pQueryInfo->limit.limit = -1;
+ pQueryInfo->limit.offset = 0;
+
assert(pQueryInfo->numOfTables == 1 && pNew->cmd.numOfClause == 1 && trsupport->subqueryIndex < pSql->subState.numOfSub);
// launch subquery for each vnode, so the subquery index equals to the vgroupIndex.
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, table_index);
pTableMetaInfo->vgroupIndex = trsupport->subqueryIndex;
-
+
pSql->pSubs[trsupport->subqueryIndex] = pNew;
}
@@ -2719,7 +2988,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);
- if (pSql->res.qhandle == 0) { // qhandle is NULL, code is TSDB_CODE_SUCCESS means no results generated from this vnode
+ if (pSql->res.qId == 0) { // qhandle is NULL, code is TSDB_CODE_SUCCESS means no results generated from this vnode
tscRetrieveFromDnodeCallBack(param, pSql, 0);
} else {
taos_fetch_rows_a(tres, tscRetrieveFromDnodeCallBack, param);
@@ -3105,30 +3374,6 @@ void tscBuildResFromSubqueries(SSqlObj *pSql) {
}
}
-static UNUSED_FUNC void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pField) {
- SSqlRes *pRes = &pSql->res;
-
- if (pRes->tsrow[columnIndex] != NULL && pField->type == TSDB_DATA_TYPE_NCHAR) {
- // convert unicode to native code in a temporary buffer extra one byte for terminated symbol
- if (pRes->buffer[columnIndex] == NULL) {
- pRes->buffer[columnIndex] = malloc(pField->bytes + TSDB_NCHAR_SIZE);
- }
-
- /* string terminated char for binary data*/
- memset(pRes->buffer[columnIndex], 0, pField->bytes + TSDB_NCHAR_SIZE);
-
- int32_t length = taosUcs4ToMbs(pRes->tsrow[columnIndex], pRes->length[columnIndex], pRes->buffer[columnIndex]);
- if ( length >= 0 ) {
- pRes->tsrow[columnIndex] = (unsigned char*)pRes->buffer[columnIndex];
- pRes->length[columnIndex] = length;
- } else {
- tscError("%p charset:%s to %s. val:%s convert failed.", pSql, DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)pRes->tsrow[columnIndex]);
- pRes->tsrow[columnIndex] = NULL;
- pRes->length[columnIndex] = 0;
- }
- }
-}
-
char *getArithmeticInputSrc(void *param, const char *name, int32_t colId) {
SArithmeticSupport *pSupport = (SArithmeticSupport *) param;
diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c
index 2abd7efb1f7991f39fd770351da211aabec4dd53..59f193d596b3d4bffde55a2ddf52d09cc4e28411 100644
--- a/src/client/src/tscUtil.c
+++ b/src/client/src/tscUtil.c
@@ -97,6 +97,22 @@ bool tscQueryTags(SQueryInfo* pQueryInfo) {
return true;
}
+bool tscQueryBlockInfo(SQueryInfo* pQueryInfo) {
+ int32_t numOfCols = (int32_t) tscSqlExprNumOfExprs(pQueryInfo);
+
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
+ int32_t functId = pExpr->functionId;
+
+ // "select count(tbname)" query
+ if (functId == TSDB_FUNC_BLKINFO) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool tscIsTwoStageSTableQuery(SQueryInfo* pQueryInfo, int32_t tableIndex) {
if (pQueryInfo == NULL) {
return false;
@@ -223,6 +239,21 @@ bool tscIsSecondStageQuery(SQueryInfo* pQueryInfo) {
return false;
}
+bool tscGroupbyColumn(SQueryInfo* pQueryInfo) {
+ STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
+ int32_t numOfCols = tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
+
+ SSqlGroupbyExpr* pGroupbyExpr = &pQueryInfo->groupbyExpr;
+ for (int32_t k = 0; k < pGroupbyExpr->numOfGroupCols; ++k) {
+ SColIndex* pIndex = taosArrayGet(pGroupbyExpr->columnInfo, k);
+ if (!TSDB_COL_IS_TAG(pIndex->flag) && pIndex->colIndex < numOfCols) { // group by normal columns
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool tscIsTWAQuery(SQueryInfo* pQueryInfo) {
size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo);
for (int32_t i = 0; i < numOfExprs; ++i) {
@@ -1151,7 +1182,7 @@ SSqlExpr* tscSqlExprInsert(SQueryInfo* pQueryInfo, int32_t index, int16_t functi
}
SSqlExpr* tscSqlExprAppend(SQueryInfo* pQueryInfo, int16_t functionId, SColumnIndex* pColIndex, int16_t type,
- int16_t size, int16_t resColId, int16_t interSize, bool isTagCol) {
+ int16_t size, int16_t resColId, int16_t interSize, bool isTagCol) {
SSqlExpr* pExpr = doCreateSqlExpr(pQueryInfo, functionId, pColIndex, type, size, resColId, interSize, isTagCol);
taosArrayPush(pQueryInfo->exprList, &pExpr);
return pExpr;
@@ -1271,6 +1302,34 @@ int32_t tscSqlExprCopy(SArray* dst, const SArray* src, uint64_t uid, bool deepco
return 0;
}
+bool tscColumnExists(SArray* pColumnList, SColumnIndex* pColIndex) {
+ // ignore the tbname columnIndex to be inserted into source list
+ if (pColIndex->columnIndex < 0) {
+ return false;
+ }
+
+ size_t numOfCols = taosArrayGetSize(pColumnList);
+ int16_t col = pColIndex->columnIndex;
+
+ int32_t i = 0;
+ while (i < numOfCols) {
+ SColumn* pCol = taosArrayGetP(pColumnList, i);
+ if ((pCol->colIndex.columnIndex != col) || (pCol->colIndex.tableIndex != pColIndex->tableIndex)) {
+ ++i;
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ if (i >= numOfCols || numOfCols == 0) {
+ return false;
+ }
+
+ return true;
+}
+
+
SColumn* tscColumnListInsert(SArray* pColumnList, SColumnIndex* pColIndex) {
// ignore the tbname columnIndex to be inserted into source list
if (pColIndex->columnIndex < 0) {
@@ -1563,7 +1622,25 @@ int32_t tscTagCondCopy(STagCond* dest, const STagCond* src) {
dest->tbnameCond.uid = src->tbnameCond.uid;
dest->tbnameCond.len = src->tbnameCond.len;
- memcpy(&dest->joinInfo, &src->joinInfo, sizeof(SJoinInfo));
+ dest->joinInfo.hasJoin = src->joinInfo.hasJoin;
+
+ for (int32_t i = 0; i < TSDB_MAX_JOIN_TABLE_NUM; ++i) {
+ if (src->joinInfo.joinTables[i]) {
+ dest->joinInfo.joinTables[i] = calloc(1, sizeof(SJoinNode));
+
+ memcpy(dest->joinInfo.joinTables[i], src->joinInfo.joinTables[i], sizeof(SJoinNode));
+
+ if (src->joinInfo.joinTables[i]->tsJoin) {
+ dest->joinInfo.joinTables[i]->tsJoin = taosArrayDup(src->joinInfo.joinTables[i]->tsJoin);
+ }
+
+ if (src->joinInfo.joinTables[i]->tagJoin) {
+ dest->joinInfo.joinTables[i]->tagJoin = taosArrayDup(src->joinInfo.joinTables[i]->tagJoin);
+ }
+ }
+ }
+
+
dest->relType = src->relType;
if (src->pCond == NULL) {
@@ -1609,6 +1686,23 @@ void tscTagCondRelease(STagCond* pTagCond) {
taosArrayDestroy(pTagCond->pCond);
}
+ for (int32_t i = 0; i < TSDB_MAX_JOIN_TABLE_NUM; ++i) {
+ SJoinNode *node = pTagCond->joinInfo.joinTables[i];
+ if (node == NULL) {
+ continue;
+ }
+
+ if (node->tsJoin != NULL) {
+ taosArrayDestroy(node->tsJoin);
+ }
+
+ if (node->tagJoin != NULL) {
+ taosArrayDestroy(node->tagJoin);
+ }
+
+ tfree(node);
+ }
+
memset(pTagCond, 0, sizeof(STagCond));
}
@@ -1733,10 +1827,15 @@ void tscInitQueryInfo(SQueryInfo* pQueryInfo) {
pQueryInfo->fieldsInfo.internalField = taosArrayInit(4, sizeof(SInternalField));
assert(pQueryInfo->exprList == NULL);
- pQueryInfo->exprList = taosArrayInit(4, POINTER_BYTES);
- pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES);
- pQueryInfo->udColumnId = TSDB_UD_COLUMN_INDEX;
- pQueryInfo->resColumnId= -1000;
+ pQueryInfo->exprList = taosArrayInit(4, POINTER_BYTES);
+ pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES);
+ pQueryInfo->udColumnId = TSDB_UD_COLUMN_INDEX;
+ pQueryInfo->resColumnId = -1000;
+ pQueryInfo->limit.limit = -1;
+ pQueryInfo->limit.offset = 0;
+
+ pQueryInfo->slimit.limit = -1;
+ pQueryInfo->slimit.offset = 0;
}
int32_t tscAddSubqueryInfo(SSqlCmd* pCmd) {
@@ -2293,16 +2392,21 @@ void tscDoQuery(SSqlObj* pSql) {
}
int16_t tscGetJoinTagColIdByUid(STagCond* pTagCond, uint64_t uid) {
- if (pTagCond->joinInfo.left.uid == uid) {
- return pTagCond->joinInfo.left.tagColId;
- } else if (pTagCond->joinInfo.right.uid == uid) {
- return pTagCond->joinInfo.right.tagColId;
- } else {
- assert(0);
- return -1;
+ int32_t i = 0;
+ while (i < TSDB_MAX_JOIN_TABLE_NUM) {
+ SJoinNode* node = pTagCond->joinInfo.joinTables[i];
+ if (node && node->uid == uid) {
+ return node->tagColId;
+ }
+
+ i++;
}
+
+ assert(0);
+ return -1;
}
+
int16_t tscGetTagColIndexById(STableMeta* pTableMeta, int16_t colId) {
int32_t numOfTags = tscGetNumOfTags(pTableMeta);
diff --git a/src/common/inc/tcmdtype.h b/src/common/inc/tcmdtype.h
index bec85905369b5a1ea4274a9d799c664ce7aee544..be16e80124358012a079ada5f7cd689afa0f7b75 100644
--- a/src/common/inc/tcmdtype.h
+++ b/src/common/inc/tcmdtype.h
@@ -51,6 +51,7 @@ enum {
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_ALTER_ACCT, "alter-acct" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_ALTER_TABLE, "alter-table" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_ALTER_DB, "alter-db" )
+ TSDB_DEFINE_SQL_TYPE(TSDB_SQL_SYNC_DB_REPLICA, "sync db-replica")
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CREATE_MNODE, "create-mnode" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_DROP_MNODE, "drop-mnode" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CREATE_DNODE, "create-dnode" )
@@ -87,13 +88,13 @@ enum {
*/
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_RETRIEVE_EMPTY_RESULT, "retrieve-empty-result" )
- TSDB_DEFINE_SQL_TYPE( TSDB_SQL_RESET_CACHE, "reset-cache" )
- TSDB_DEFINE_SQL_TYPE( TSDB_SQL_SERV_STATUS, "serv-status" )
- TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CURRENT_DB, "current-db" )
+ TSDB_DEFINE_SQL_TYPE( TSDB_SQL_RESET_CACHE, "reset-cache" )
+ TSDB_DEFINE_SQL_TYPE( TSDB_SQL_SERV_STATUS, "serv-status" )
+ TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CURRENT_DB, "current-db" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_SERV_VERSION, "serv-version" )
- TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CLI_VERSION, "cli-version" )
+ TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CLI_VERSION, "cli-version" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CURRENT_USER, "current-user ")
- TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CFG_LOCAL, "cfg-local" )
+ TSDB_DEFINE_SQL_TYPE( TSDB_SQL_CFG_LOCAL, "cfg-local" )
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_MAX, "max" )
};
diff --git a/src/common/inc/tdataformat.h b/src/common/inc/tdataformat.h
index 959654d1585b13c31e96ab7972d0aa2782a51901..e8c076099759ffe683c78b55a54848cf765daada 100644
--- a/src/common/inc/tdataformat.h
+++ b/src/common/inc/tdataformat.h
@@ -283,12 +283,37 @@ typedef struct {
#define keyCol(pCols) (&((pCols)->cols[0])) // Key column
#define dataColsTKeyAt(pCols, idx) ((TKEY *)(keyCol(pCols)->pData))[(idx)]
#define dataColsKeyAt(pCols, idx) tdGetKey(dataColsTKeyAt(pCols, idx))
-#define dataColsTKeyFirst(pCols) (((pCols)->numOfRows == 0) ? TKEY_INVALID : dataColsTKeyAt(pCols, 0))
-#define dataColsKeyFirst(pCols) (((pCols)->numOfRows == 0) ? TSDB_DATA_TIMESTAMP_NULL : dataColsKeyAt(pCols, 0))
-#define dataColsTKeyLast(pCols) \
- (((pCols)->numOfRows == 0) ? TKEY_INVALID : dataColsTKeyAt(pCols, (pCols)->numOfRows - 1))
-#define dataColsKeyLast(pCols) \
- (((pCols)->numOfRows == 0) ? TSDB_DATA_TIMESTAMP_NULL : dataColsKeyAt(pCols, (pCols)->numOfRows - 1))
+static FORCE_INLINE TKEY dataColsTKeyFirst(SDataCols *pCols) {
+ if (pCols->numOfRows) {
+ return dataColsTKeyAt(pCols, 0);
+ } else {
+ return TKEY_INVALID;
+ }
+}
+
+static FORCE_INLINE TSKEY dataColsKeyFirst(SDataCols *pCols) {
+ if (pCols->numOfRows) {
+ return dataColsKeyAt(pCols, 0);
+ } else {
+ return TSDB_DATA_TIMESTAMP_NULL;
+ }
+}
+
+static FORCE_INLINE TKEY dataColsTKeyLast(SDataCols *pCols) {
+ if (pCols->numOfRows) {
+ return dataColsTKeyAt(pCols, pCols->numOfRows - 1);
+ } else {
+ return TKEY_INVALID;
+ }
+}
+
+static FORCE_INLINE TSKEY dataColsKeyLast(SDataCols *pCols) {
+ if (pCols->numOfRows) {
+ return dataColsKeyAt(pCols, pCols->numOfRows - 1);
+ } else {
+ return TSDB_DATA_TIMESTAMP_NULL;
+ }
+}
SDataCols *tdNewDataCols(int maxRowSize, int maxCols, int maxRows);
void tdResetDataCols(SDataCols *pCols);
diff --git a/src/common/inc/tglobal.h b/src/common/inc/tglobal.h
index c6d0226244b9b64d21fcc6c7939d61fa27a55525..3f96466cc00fc3250860e79bc3dd85e6fd0368d7 100644
--- a/src/common/inc/tglobal.h
+++ b/src/common/inc/tglobal.h
@@ -95,6 +95,7 @@ extern int8_t tsCompression;
extern int8_t tsWAL;
extern int32_t tsFsyncPeriod;
extern int32_t tsReplications;
+extern int16_t tsPartitons;
extern int32_t tsQuorum;
extern int8_t tsUpdate;
extern int8_t tsCacheLastRow;
@@ -162,6 +163,7 @@ extern float tsTotalDataDirGB;
extern float tsAvailLogDirGB;
extern float tsAvailTmpDirectorySpace;
extern float tsAvailDataDirGB;
+extern float tsUsedDataDirGB;
extern float tsMinimalLogDirGB;
extern float tsReservedTmpDirectorySpace;
extern float tsMinimalDataDirGB;
diff --git a/src/common/inc/tname.h b/src/common/inc/tname.h
index b651913d7384bac75eea7c9644b501b781c47e33..465b298973cbccdf380150bdce46a09b56594801 100644
--- a/src/common/inc/tname.h
+++ b/src/common/inc/tname.h
@@ -33,7 +33,7 @@ typedef struct SDataStatis {
typedef struct SColumnInfoData {
SColumnInfo info;
- void* pData; // the corresponding block data in memory
+ char* pData; // the corresponding block data in memory
} SColumnInfoData;
typedef struct SResPair {
diff --git a/src/common/src/texpr.c b/src/common/src/texpr.c
index f50b829baa7c6dadea99bd81874cef57140f4fc0..1008c4cf8f77ca77f59a57aea189cdebef9c9129 100644
--- a/src/common/src/texpr.c
+++ b/src/common/src/texpr.c
@@ -41,41 +41,46 @@ static uint8_t UNUSED_FUNC isQueryOnPrimaryKey(const char *primaryColumnName, co
static void reverseCopy(char* dest, const char* src, int16_t type, int32_t numOfRows) {
switch(type) {
- case TSDB_DATA_TYPE_TINYINT: {
+ case TSDB_DATA_TYPE_TINYINT:
+ case TSDB_DATA_TYPE_UTINYINT:{
int8_t* p = (int8_t*) dest;
int8_t* pSrc = (int8_t*) src;
for(int32_t i = 0; i < numOfRows; ++i) {
p[i] = pSrc[numOfRows - i - 1];
}
- break;
+ return;
}
- case TSDB_DATA_TYPE_SMALLINT: {
+
+ case TSDB_DATA_TYPE_SMALLINT:
+ case TSDB_DATA_TYPE_USMALLINT:{
int16_t* p = (int16_t*) dest;
int16_t* pSrc = (int16_t*) src;
for(int32_t i = 0; i < numOfRows; ++i) {
p[i] = pSrc[numOfRows - i - 1];
}
- break;
+ return;
}
- case TSDB_DATA_TYPE_INT: {
+ case TSDB_DATA_TYPE_INT:
+ case TSDB_DATA_TYPE_UINT: {
int32_t* p = (int32_t*) dest;
int32_t* pSrc = (int32_t*) src;
for(int32_t i = 0; i < numOfRows; ++i) {
p[i] = pSrc[numOfRows - i - 1];
}
- break;
+ return;
}
- case TSDB_DATA_TYPE_BIGINT: {
+ case TSDB_DATA_TYPE_BIGINT:
+ case TSDB_DATA_TYPE_UBIGINT: {
int64_t* p = (int64_t*) dest;
int64_t* pSrc = (int64_t*) src;
for(int32_t i = 0; i < numOfRows; ++i) {
p[i] = pSrc[numOfRows - i - 1];
}
- break;
+ return;
}
case TSDB_DATA_TYPE_FLOAT: {
float* p = (float*) dest;
@@ -84,7 +89,7 @@ static void reverseCopy(char* dest, const char* src, int16_t type, int32_t numOf
for(int32_t i = 0; i < numOfRows; ++i) {
p[i] = pSrc[numOfRows - i - 1];
}
- break;
+ return;
}
case TSDB_DATA_TYPE_DOUBLE: {
double* p = (double*) dest;
@@ -93,7 +98,7 @@ static void reverseCopy(char* dest, const char* src, int16_t type, int32_t numOf
for(int32_t i = 0; i < numOfRows; ++i) {
p[i] = pSrc[numOfRows - i - 1];
}
- break;
+ return;
}
default: assert(0);
}
diff --git a/src/common/src/tglobal.c b/src/common/src/tglobal.c
index 4ed4e0473bdf3c11c2838842b24c15d886a02f2e..4fef3844c4f6ed93bb893d2e920f176ff4a1e9fa 100644
--- a/src/common/src/tglobal.c
+++ b/src/common/src/tglobal.c
@@ -71,7 +71,7 @@ int32_t tsMaxBinaryDisplayWidth = 30;
int32_t tsCompressMsgSize = -1;
// client
-int32_t tsMaxSQLStringLen = TSDB_MAX_SQL_LEN;
+int32_t tsMaxSQLStringLen = TSDB_MAX_ALLOWED_SQL_LEN;
int8_t tsTscEnableRecordSql = 0;
// the maximum number of results for projection query on super table that are returned from
@@ -126,8 +126,9 @@ int8_t tsWAL = TSDB_DEFAULT_WAL_LEVEL;
int32_t tsFsyncPeriod = TSDB_DEFAULT_FSYNC_PERIOD;
int32_t tsReplications = TSDB_DEFAULT_DB_REPLICA_OPTION;
int32_t tsQuorum = TSDB_DEFAULT_DB_QUORUM_OPTION;
+int16_t tsPartitons = TSDB_DEFAULT_DB_PARTITON_OPTION;
int8_t tsUpdate = TSDB_DEFAULT_DB_UPDATE_OPTION;
-int8_t tsCacheLastRow = TSDB_DEFAULT_CACHE_BLOCK_SIZE;
+int8_t tsCacheLastRow = TSDB_DEFAULT_CACHE_LAST_ROW;
int32_t tsMaxVgroupsPerDb = 0;
int32_t tsMinTablePerVnode = TSDB_TABLES_STEP;
int32_t tsMaxTablePerVnode = TSDB_DEFAULT_TABLES;
@@ -209,6 +210,7 @@ float tsTotalTmpDirGB = 0;
float tsTotalDataDirGB = 0;
float tsAvailTmpDirectorySpace = 0;
float tsAvailDataDirGB = 0;
+float tsUsedDataDirGB = 0;
float tsReservedTmpDirectorySpace = 1.0f;
float tsMinimalDataDirGB = 1.0f;
int32_t tsTotalMemoryMB = 0;
@@ -853,6 +855,16 @@ static void doInitGlobalConfig(void) {
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
+ cfg.option = "partitions";
+ cfg.ptr = &tsPartitons;
+ cfg.valType = TAOS_CFG_VTYPE_INT16;
+ cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_SHOW;
+ cfg.minValue = TSDB_MIN_DB_PARTITON_OPTION;
+ cfg.maxValue = TSDB_MAX_DB_PARTITON_OPTION;
+ cfg.ptrLength = 0;
+ cfg.unitType = TAOS_CFG_UTYPE_NONE;
+ taosInitConfigOption(cfg);
+
cfg.option = "quorum";
cfg.ptr = &tsQuorum;
cfg.valType = TAOS_CFG_VTYPE_INT32;
diff --git a/src/connector/jdbc/CMakeLists.txt b/src/connector/jdbc/CMakeLists.txt
index 3c50ac566b5fe49a619a50c9eac446285a2b431c..86ddfcb022f4467f7378b85dda5760b66366bbbc 100644
--- a/src/connector/jdbc/CMakeLists.txt
+++ b/src/connector/jdbc/CMakeLists.txt
@@ -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.21-dist.jar ${LIBRARY_OUTPUT_PATH}
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.22-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})
diff --git a/src/connector/jdbc/deploy-pom.xml b/src/connector/jdbc/deploy-pom.xml
index 1c24b621efe52e152ac8ea70ef3c2afdbc72d5b0..fe93e54c69e969cd8f54b41b6275423157f56197 100755
--- a/src/connector/jdbc/deploy-pom.xml
+++ b/src/connector/jdbc/deploy-pom.xml
@@ -5,7 +5,7 @@
com.taosdata.jdbctaos-jdbcdriver
- 2.0.21
+ 2.0.22jarJDBCDriver
diff --git a/src/connector/jdbc/pom.xml b/src/connector/jdbc/pom.xml
index f1e013e864f4617e04be0c8c5b892c4396c66e79..51cb0b380822c81137c1a5514c898b51ae0d85be 100755
--- a/src/connector/jdbc/pom.xml
+++ b/src/connector/jdbc/pom.xml
@@ -3,7 +3,7 @@
4.0.0com.taosdata.jdbctaos-jdbcdriver
- 2.0.21
+ 2.0.22jarJDBCDriverhttps://github.com/taosdata/TDengine/tree/master/src/connector/jdbc
@@ -102,6 +102,8 @@
**/*Test.java
+ **/TSDBJNIConnectorTest.java
+ **/UnsignedNumberJniTest.java**/DatetimeBefore1970Test.java**/AppMemoryLeakTest.java**/AuthenticationTest.java
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractDriver.java
index c4785127fdbfaad3b67c2aa513bc874d7dd3fd9a..5eaac1cd3ba7283b019a1d294c1a33334a3d9fa7 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractDriver.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractDriver.java
@@ -1,80 +1,18 @@
package com.taosdata.jdbc;
-import java.io.*;
import java.sql.Driver;
import java.sql.DriverPropertyInfo;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
public abstract class AbstractDriver implements Driver {
- private static final String TAOS_CFG_FILENAME = "taos.cfg";
-
- /**
- * @param cfgDirPath
- * @return return the config dir
- **/
- protected File loadConfigDir(String cfgDirPath) {
- if (cfgDirPath == null)
- return loadDefaultConfigDir();
- File cfgDir = new File(cfgDirPath);
- if (!cfgDir.exists())
- return loadDefaultConfigDir();
- return cfgDir;
- }
-
- /**
- * @return search the default config dir, if the config dir is not exist will return null
- */
- protected File loadDefaultConfigDir() {
- File cfgDir;
- File cfgDir_linux = new File("/etc/taos");
- cfgDir = cfgDir_linux.exists() ? cfgDir_linux : null;
- File cfgDir_windows = new File("C:\\TDengine\\cfg");
- cfgDir = (cfgDir == null && cfgDir_windows.exists()) ? cfgDir_windows : cfgDir;
- return cfgDir;
- }
-
- protected List loadConfigEndpoints(File cfgFile) {
- List endpoints = new ArrayList<>();
- try (BufferedReader reader = new BufferedReader(new FileReader(cfgFile))) {
- String line = null;
- while ((line = reader.readLine()) != null) {
- if (line.trim().startsWith("firstEp") || line.trim().startsWith("secondEp")) {
- endpoints.add(line.substring(line.indexOf('p') + 1).trim());
- }
- if (endpoints.size() > 1)
- break;
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return endpoints;
- }
-
- protected void loadTaosConfig(Properties info) {
- if ((info.getProperty(TSDBDriver.PROPERTY_KEY_HOST) == null || info.getProperty(TSDBDriver.PROPERTY_KEY_HOST).isEmpty()) && (
- info.getProperty(TSDBDriver.PROPERTY_KEY_PORT) == null || info.getProperty(TSDBDriver.PROPERTY_KEY_PORT).isEmpty())) {
- File cfgDir = loadConfigDir(info.getProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR));
- File cfgFile = cfgDir.listFiles((dir, name) -> TAOS_CFG_FILENAME.equalsIgnoreCase(name))[0];
- List endpoints = loadConfigEndpoints(cfgFile);
- if (!endpoints.isEmpty()) {
- info.setProperty(TSDBDriver.PROPERTY_KEY_HOST, endpoints.get(0).split(":")[0]);
- info.setProperty(TSDBDriver.PROPERTY_KEY_PORT, endpoints.get(0).split(":")[1]);
- }
- }
- }
-
protected DriverPropertyInfo[] getPropertyInfo(Properties info) {
DriverPropertyInfo hostProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_HOST, info.getProperty(TSDBDriver.PROPERTY_KEY_HOST));
hostProp.required = false;
hostProp.description = "Hostname";
- DriverPropertyInfo portProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_PORT, info.getProperty(TSDBDriver.PROPERTY_KEY_PORT, TSDBConstants.DEFAULT_PORT));
+ DriverPropertyInfo portProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_PORT, info.getProperty(TSDBDriver.PROPERTY_KEY_PORT));
portProp.required = false;
portProp.description = "Port";
@@ -102,11 +40,11 @@ public abstract class AbstractDriver implements Driver {
protected Properties parseURL(String url, Properties defaults) {
Properties urlProps = (defaults != null) ? defaults : new Properties();
- // parse properties
+ // parse properties in url
int beginningOfSlashes = url.indexOf("//");
int index = url.indexOf("?");
if (index != -1) {
- String paramString = url.substring(index + 1, url.length());
+ String paramString = url.substring(index + 1);
url = url.substring(0, index);
StringTokenizer queryParams = new StringTokenizer(paramString, "&");
while (queryParams.hasMoreElements()) {
@@ -130,6 +68,7 @@ public abstract class AbstractDriver implements Driver {
String dbProductName = url.substring(0, beginningOfSlashes);
dbProductName = dbProductName.substring(dbProductName.indexOf(":") + 1);
dbProductName = dbProductName.substring(0, dbProductName.indexOf(":"));
+ urlProps.setProperty(TSDBDriver.PROPERTY_KEY_PRODUCT_NAME,dbProductName);
// parse dbname
url = url.substring(beginningOfSlashes + 2);
int indexOfSlash = url.indexOf("/");
@@ -154,6 +93,4 @@ public abstract class AbstractDriver implements Driver {
return urlProps;
}
-
-
}
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractResultSet.java
index 14bd2929f17e344381510897528bc479c50a4d36..238d18039de8ca6bf2f178263827bc4f1d6634f2 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractResultSet.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractResultSet.java
@@ -29,12 +29,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet
public abstract boolean getBoolean(int columnIndex) throws SQLException;
@Override
- public byte getByte(int columnIndex) throws SQLException {
- if (isClosed())
- throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED);
-
- throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
- }
+ public abstract byte getByte(int columnIndex) throws SQLException;
@Override
public abstract short getShort(int columnIndex) throws SQLException;
@@ -1205,6 +1200,7 @@ public abstract class AbstractResultSet extends WrapperImpl implements ResultSet
public T getObject(String columnLabel, Class type) throws SQLException {
if (isClosed())
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
- throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD); }
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_METHOD);
+ }
}
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java
index fe16aa653546f4033bd944f0b6c72aec1863ab8a..14e75f0e09e3403e703658fb503019fefbb6156d 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java
@@ -52,4 +52,14 @@ public class ColumnMetaData {
public void setColIndex(int colIndex) {
this.colIndex = colIndex;
}
+
+ @Override
+ public String toString() {
+ return "ColumnMetaData{" +
+ "colType=" + colType +
+ ", colName='" + colName + '\'' +
+ ", colSize=" + colSize +
+ ", colIndex=" + colIndex +
+ '}';
+ }
}
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/SavedPreparedStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/SavedPreparedStatement.java
index a0aa7ec584ee351185d10b023e5142d00d60d66b..512fcd26b8ce01b9e673fd7ed9a266ed0372ba52 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/SavedPreparedStatement.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/SavedPreparedStatement.java
@@ -122,8 +122,7 @@ public class SavedPreparedStatement {
initPreparedParam = initDefaultParam(tableName, middleParamSize, valueListSize);
} else {
- // not match
- throw new SQLException(TSDBConstants.WrapErrMsg("the sql is not complete!"));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_SQL);
}
}
@@ -189,7 +188,7 @@ public class SavedPreparedStatement {
String errorMsg = String.format("the parameterIndex %s out of the range [1, %s]", parameterIndex, paramSize);
if (parameterIndex < 1 || parameterIndex > paramSize) {
- throw new SQLException(TSDBConstants.WrapErrMsg(errorMsg));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE,errorMsg);
}
this.isAddBatch = false; //set isAddBatch to false
@@ -212,7 +211,7 @@ public class SavedPreparedStatement {
return;
}
- throw new SQLException(TSDBConstants.WrapErrMsg(errorMsg));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE,errorMsg);
}
public void addBatch() {
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java
index 8d947b9411eb91eded49b3c7b1f12586682346ff..a8653eb1729dffa83fb556e1f7a1772257018699 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java
@@ -87,11 +87,10 @@ public class TSDBConnection extends AbstractConnection {
}
public void close() throws SQLException {
- if (isClosed()) {
- throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED);
- }
- this.isClosed = true;
+ if (isClosed)
+ return;
this.connector.closeConnection();
+ this.isClosed = true;
}
public boolean isClosed() throws SQLException {
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConstants.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConstants.java
index 6179b47da1041a3461f1be43625f8c7d4e284e64..37073e243fef99176c6d3d16d87d7cdaabb0e1b4 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConstants.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConstants.java
@@ -16,16 +16,11 @@ package com.taosdata.jdbc;
import java.sql.SQLException;
import java.sql.Types;
-import java.util.HashMap;
-import java.util.Map;
public abstract class TSDBConstants {
- public static final String DEFAULT_PORT = "6200";
- public static Map DATATYPE_MAP = null;
-
public static final long JNI_NULL_POINTER = 0L;
-
+ // JNI_ERROR_NUMBER
public static final int JNI_SUCCESS = 0;
public static final int JNI_TDENGINE_ERROR = -1;
public static final int JNI_CONNECTION_NULL = -2;
@@ -34,8 +29,7 @@ public abstract class TSDBConstants {
public static final int JNI_SQL_NULL = -5;
public static final int JNI_FETCH_END = -6;
public static final int JNI_OUT_OF_MEMORY = -7;
-
- public static final int TSDB_DATA_TYPE_NULL = 0;
+ // TSDB Data Types
public static final int TSDB_DATA_TYPE_BOOL = 1;
public static final int TSDB_DATA_TYPE_TINYINT = 2;
public static final int TSDB_DATA_TYPE_SMALLINT = 3;
@@ -46,46 +40,36 @@ public abstract class TSDBConstants {
public static final int TSDB_DATA_TYPE_BINARY = 8;
public static final int TSDB_DATA_TYPE_TIMESTAMP = 9;
public static final int TSDB_DATA_TYPE_NCHAR = 10;
-
- // nchar field's max length
+ /*
+ 系统增加新的无符号数据类型,分别是:
+ unsigned tinyint, 数值范围:0-254, NULL 为255
+ unsigned smallint,数值范围: 0-65534, NULL 为65535
+ unsigned int,数值范围:0-4294967294,NULL 为4294967295u
+ unsigned bigint,数值范围:0-18446744073709551614u,NULL 为18446744073709551615u。
+ example:
+ create table tb(ts timestamp, a tinyint unsigned, b smallint unsigned, c int unsigned, d bigint unsigned);
+ */
+ public static final int TSDB_DATA_TYPE_UTINYINT = 11; //unsigned tinyint
+ public static final int TSDB_DATA_TYPE_USMALLINT = 12; //unsigned smallint
+ public static final int TSDB_DATA_TYPE_UINT = 13; //unsigned int
+ public static final int TSDB_DATA_TYPE_UBIGINT = 14; //unsigned bigint
+ // nchar column max length
public static final int maxFieldSize = 16 * 1024;
- public static String WrapErrMsg(String msg) {
- return "TDengine Error: " + msg;
- }
-
- public static String FixErrMsg(int code) {
- switch (code) {
- case JNI_TDENGINE_ERROR:
- return WrapErrMsg("internal error of database!");
- case JNI_CONNECTION_NULL:
- return WrapErrMsg("invalid tdengine connection!");
- case JNI_RESULT_SET_NULL:
- return WrapErrMsg("invalid resultset pointer!");
- case JNI_NUM_OF_FIELDS_0:
- return WrapErrMsg("invalid num of fields!");
- case JNI_SQL_NULL:
- return WrapErrMsg("can't execute empty sql!");
- case JNI_FETCH_END:
- return WrapErrMsg("fetch to the end of resultset");
- default:
- break;
- }
- return WrapErrMsg("unkown error!");
- }
-
public static int taosType2JdbcType(int taosType) throws SQLException {
switch (taosType) {
- case TSDBConstants.TSDB_DATA_TYPE_NULL:
- return Types.NULL;
case TSDBConstants.TSDB_DATA_TYPE_BOOL:
return Types.BOOLEAN;
case TSDBConstants.TSDB_DATA_TYPE_TINYINT:
+ case TSDBConstants.TSDB_DATA_TYPE_UTINYINT:
return Types.TINYINT;
+ case TSDBConstants.TSDB_DATA_TYPE_USMALLINT:
case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:
return Types.SMALLINT;
+ case TSDBConstants.TSDB_DATA_TYPE_UINT:
case TSDBConstants.TSDB_DATA_TYPE_INT:
return Types.INTEGER;
+ case TSDBConstants.TSDB_DATA_TYPE_UBIGINT:
case TSDBConstants.TSDB_DATA_TYPE_BIGINT:
return Types.BIGINT;
case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
@@ -99,13 +83,42 @@ public abstract class TSDBConstants {
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
return Types.NCHAR;
}
- throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_SQL_TYPE_IN_TDENGINE);
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE);
+ }
+
+ public static String taosType2JdbcTypeName(int taosType) throws SQLException {
+ switch (taosType){
+ case TSDBConstants.TSDB_DATA_TYPE_BOOL:
+ return "BOOL";
+ case TSDBConstants.TSDB_DATA_TYPE_UTINYINT:
+ case TSDBConstants.TSDB_DATA_TYPE_TINYINT:
+ return "TINYINT";
+ case TSDBConstants.TSDB_DATA_TYPE_USMALLINT:
+ case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:
+ return "SMALLINT";
+ case TSDBConstants.TSDB_DATA_TYPE_UINT:
+ case TSDBConstants.TSDB_DATA_TYPE_INT:
+ return "INT";
+ case TSDBConstants.TSDB_DATA_TYPE_UBIGINT:
+ case TSDBConstants.TSDB_DATA_TYPE_BIGINT:
+ return "BIGINT";
+ case TSDBConstants.TSDB_DATA_TYPE_FLOAT:
+ return "FLOAT";
+ case TSDBConstants.TSDB_DATA_TYPE_DOUBLE:
+ return "DOUBLE";
+ case TSDBConstants.TSDB_DATA_TYPE_BINARY:
+ return "BINARY";
+ case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP:
+ return "TIMESTAMP";
+ case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
+ return "NCHAR";
+ default:
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE);
+ }
}
public static int jdbcType2TaosType(int jdbcType) throws SQLException {
switch (jdbcType){
- case Types.NULL:
- return TSDBConstants.TSDB_DATA_TYPE_NULL;
case Types.BOOLEAN:
return TSDBConstants.TSDB_DATA_TYPE_BOOL;
case Types.TINYINT:
@@ -130,22 +143,31 @@ public abstract class TSDBConstants {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_SQL_TYPE_IN_TDENGINE);
}
- static {
- DATATYPE_MAP = new HashMap<>();
- DATATYPE_MAP.put(0, "NULL");
- DATATYPE_MAP.put(1, "BOOL");
- DATATYPE_MAP.put(2, "TINYINT");
- DATATYPE_MAP.put(3, "SMALLINT");
- DATATYPE_MAP.put(4, "INT");
- DATATYPE_MAP.put(5, "BIGINT");
- DATATYPE_MAP.put(6, "FLOAT");
- DATATYPE_MAP.put(7, "DOUBLE");
- DATATYPE_MAP.put(8, "BINARY");
- DATATYPE_MAP.put(9, "TIMESTAMP");
- DATATYPE_MAP.put(10, "NCHAR");
+ public static String jdbcType2TaosTypeName(int jdbcType) throws SQLException {
+ switch (jdbcType){
+ case Types.BOOLEAN:
+ return "BOOL";
+ case Types.TINYINT:
+ return "TINYINT";
+ case Types.SMALLINT:
+ return "SMALLINT";
+ case Types.INTEGER:
+ return "INT";
+ case Types.BIGINT:
+ return "BIGINT";
+ case Types.FLOAT:
+ return "FLOAT";
+ case Types.DOUBLE:
+ return "DOUBLE";
+ case Types.BINARY:
+ return "BINARY";
+ case Types.TIMESTAMP:
+ return "TIMESTAMP";
+ case Types.NCHAR:
+ return "NCHAR";
+ default:
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_SQL_TYPE_IN_TDENGINE);
+ }
}
- public static String jdbcType2TaosTypeName(int type) throws SQLException {
- return DATATYPE_MAP.get(jdbcType2TaosType(type));
- }
}
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java
index 2b87b72fef0f2b621536c5a11aba69975aa86434..5f599df1300b3d6959e9a7b58c00a720d722e07b 100755
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java
@@ -44,6 +44,10 @@ public class TSDBDriver extends AbstractDriver {
private static final String URL_PREFIX = "jdbc:TAOS://";
+ /**
+ * PRODUCT_NAME
+ */
+ public static final String PROPERTY_KEY_PRODUCT_NAME = "productName";
/**
* Key used to retrieve the host value from the properties instance passed to
* the driver.
@@ -96,40 +100,34 @@ public class TSDBDriver extends AbstractDriver {
static {
try {
java.sql.DriverManager.registerDriver(new TSDBDriver());
- } catch (SQLException E) {
- throw new RuntimeException(TSDBConstants.WrapErrMsg("can't register tdengine jdbc driver!"));
+ } catch (SQLException e) {
+ throw TSDBError.createRuntimeException(TSDBErrorNumbers.ERROR_CANNOT_REGISTER_JNI_DRIVER, e);
}
}
public Connection connect(String url, Properties info) throws SQLException {
if (url == null)
- throw new SQLException(TSDBConstants.WrapErrMsg("url is not set!"));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_URL_NOT_SET);
if (!acceptsURL(url))
return null;
- Properties props = null;
- if ((props = parseURL(url, info)) == null) {
+ Properties props = parseURL(url, info);
+ if (props == null) {
return null;
}
- //load taos.cfg start
- loadTaosConfig(info);
try {
TSDBJNIConnector.init((String) props.get(PROPERTY_KEY_CONFIG_DIR), (String) props.get(PROPERTY_KEY_LOCALE),
(String) props.get(PROPERTY_KEY_CHARSET), (String) props.get(PROPERTY_KEY_TIME_ZONE));
- Connection newConn = new TSDBConnection(props, this.dbMetaData);
- return newConn;
+ return new TSDBConnection(props, this.dbMetaData);
} catch (SQLWarning sqlWarning) {
sqlWarning.printStackTrace();
- Connection newConn = new TSDBConnection(props, this.dbMetaData);
- return newConn;
+ return new TSDBConnection(props, this.dbMetaData);
} catch (SQLException sqlEx) {
throw sqlEx;
} catch (Exception ex) {
- SQLException sqlEx = new SQLException("SQLException:" + ex.toString());
- sqlEx.initCause(ex);
- throw sqlEx;
+ throw new SQLException("SQLException:" + ex.toString(), ex);
}
}
@@ -141,8 +139,8 @@ public class TSDBDriver extends AbstractDriver {
*/
public boolean acceptsURL(String url) throws SQLException {
if (url == null)
- throw new SQLException(TSDBConstants.WrapErrMsg("url is null"));
- return (url != null && url.length() > 0 && url.trim().length() > 0) && (url.startsWith(URL_PREFIX) || url.startsWith(URL_PREFIX1));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_URL_NOT_SET);
+ return url.length() > 0 && url.trim().length() > 0 && (url.startsWith(URL_PREFIX) || url.startsWith(URL_PREFIX1));
}
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBError.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBError.java
index c7717e331b39247542d1a022cafd1cab2ac65627..90967b3620fdaccf69f253c8f8927c067b6221fd 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBError.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBError.java
@@ -3,6 +3,7 @@ package com.taosdata.jdbc;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLWarning;
import java.util.HashMap;
import java.util.Map;
@@ -18,18 +19,25 @@ public class TSDBError {
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_BATCH_IS_EMPTY, "Batch is empty!");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY, "Can not issue data manipulation statements with executeQuery()");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEUPDATE, "Can not issue SELECT via executeUpdate()");
- TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: (?)");
+ TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "invalid sql for executeQuery: (?)");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_DATABASE_NOT_SPECIFIED_OR_AVAILABLE, "Database not specified or available");
- TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_UPDATE, "not a valid sql for executeUpdate: (?)");
- TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE, "not a valid sql for execute: (?)");
+ TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_UPDATE, "invalid sql for executeUpdate: (?)");
+ TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE, "invalid sql for execute: (?)");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "parameter index out of range");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED, "connection already closed");
+ TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_SQL_TYPE_IN_TDENGINE, "unknown sql type in tdengine");
+ TSDBErrorMap.put(TSDBErrorNumbers.ERROR_CANNOT_REGISTER_JNI_DRIVER, "can't register JDBC-JNI driver");
+ TSDBErrorMap.put(TSDBErrorNumbers.ERROR_CANNOT_REGISTER_RESTFUL_DRIVER, "can't register JDBC-RESTful driver");
+ TSDBErrorMap.put(TSDBErrorNumbers.ERROR_URL_NOT_SET, "url is not set");
+ TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_SQL, "invalid sql");
+ TSDBErrorMap.put(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE, "numeric value out of range");
+ TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE, "unknown taos type in tdengine");
+
/**************************************************/
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error");
/**************************************************/
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_SUBSCRIBE_FAILED, "failed to create subscription");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNSUPPORTED_ENCODING, "Unsupported encoding");
-
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_TDENGINE_ERROR, "internal error of database");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL, "JNI connection is NULL");
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL, "JNI result set is NULL");
@@ -65,4 +73,12 @@ public class TSDBError {
return new SQLException("TDengine ERROR (" + Integer.toHexString(errorCode) + "): " + message, "", errorCode);
}
-}
+ public static RuntimeException createRuntimeException(int errorCode, Throwable t) {
+ String message = TSDBErrorMap.get(errorCode);
+ return new RuntimeException("ERROR (" + Integer.toHexString(errorCode) + "): " + message, t);
+ }
+
+ public static SQLWarning createSQLWarning(String message) {
+ return new SQLWarning(message);
+ }
+}
\ No newline at end of file
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java
index 78e7aec79c252a2e6b2eeafcba37ab1c66f8674d..c978bb3a2e4a1b9dbd264268f057f2b6c735250a 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java
@@ -16,15 +16,20 @@ public class TSDBErrorNumbers {
public static final int ERROR_DATABASE_NOT_SPECIFIED_OR_AVAILABLE = 0x230a; //Database not specified or available
public static final int ERROR_INVALID_FOR_EXECUTE_UPDATE = 0x230b; //not a valid sql for executeUpdate: (SQL)
public static final int ERROR_INVALID_FOR_EXECUTE = 0x230c; //not a valid sql for execute: (SQL)
- public static final int ERROR_PARAMETER_INDEX_OUT_RANGE = 0x230d; // parameter index out of range
+ public static final int ERROR_PARAMETER_INDEX_OUT_RANGE = 0x230d; // parameter index out of range
public static final int ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED = 0x230e; // connection already closed
public static final int ERROR_UNKNOWN_SQL_TYPE_IN_TDENGINE = 0x230f; //unknown sql type in tdengine
+ public static final int ERROR_CANNOT_REGISTER_JNI_DRIVER = 0x2310; // can't register JDBC-JNI driver
+ public static final int ERROR_CANNOT_REGISTER_RESTFUL_DRIVER = 0x2311; // can't register JDBC-RESTful driver
+ public static final int ERROR_URL_NOT_SET = 0x2312; // url is not set
+ public static final int ERROR_INVALID_SQL = 0x2313; // invalid sql
+ public static final int ERROR_NUMERIC_VALUE_OUT_OF_RANGE = 0x2314; // numeric value out of range
+ public static final int ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE = 0x2315; //unknown taos type in tdengine
public static final int ERROR_UNKNOWN = 0x2350; //unknown error
public static final int ERROR_SUBSCRIBE_FAILED = 0x2351; // failed to create subscription
public static final int ERROR_UNSUPPORTED_ENCODING = 0x2352; // Unsupported encoding
-
public static final int ERROR_JNI_TDENGINE_ERROR = 0x2353; // internal error of database
public static final int ERROR_JNI_CONNECTION_NULL = 0x2354; // JNI connection is NULL
public static final int ERROR_JNI_RESULT_SET_NULL = 0x2355; // invalid JNI result set
@@ -51,11 +56,16 @@ public class TSDBErrorNumbers {
errorNumbers.add(ERROR_PARAMETER_INDEX_OUT_RANGE);
errorNumbers.add(ERROR_SQLCLIENT_EXCEPTION_ON_CONNECTION_CLOSED);
errorNumbers.add(ERROR_UNKNOWN_SQL_TYPE_IN_TDENGINE);
+ errorNumbers.add(ERROR_CANNOT_REGISTER_JNI_DRIVER);
+ errorNumbers.add(ERROR_CANNOT_REGISTER_RESTFUL_DRIVER);
+ errorNumbers.add(ERROR_URL_NOT_SET);
+ errorNumbers.add(ERROR_INVALID_SQL);
+ errorNumbers.add(ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
+ errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE);
/*****************************************************/
errorNumbers.add(ERROR_SUBSCRIBE_FAILED);
errorNumbers.add(ERROR_UNSUPPORTED_ENCODING);
-
errorNumbers.add(ERROR_JNI_TDENGINE_ERROR);
errorNumbers.add(ERROR_JNI_CONNECTION_NULL);
errorNumbers.add(ERROR_JNI_RESULT_SET_NULL);
@@ -63,7 +73,6 @@ public class TSDBErrorNumbers {
errorNumbers.add(ERROR_JNI_SQL_NULL);
errorNumbers.add(ERROR_JNI_FETCH_END);
errorNumbers.add(ERROR_JNI_OUT_OF_MEMORY);
-
}
private TSDBErrorNumbers() {
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java
index f3c4e025798e8e3fd8db0e5c1a1b25aa6fea3dc7..7d3741917cb9166a5b29e69ad2b4d3f5023bd43d 100755
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java
@@ -1,17 +1,19 @@
-/***************************************************************************
+/**
+ * *************************************************************************
* Copyright (c) 2019 TAOS Data, Inc.
- *
+ *
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
- *
+ *
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
- *****************************************************************************/
+ * ***************************************************************************
+ */
package com.taosdata.jdbc;
import com.taosdata.jdbc.utils.TaosInfo;
@@ -20,6 +22,9 @@ import java.sql.SQLException;
import java.sql.SQLWarning;
import java.util.List;
+/**
+ * JNI connector
+ */
public class TSDBJNIConnector {
private static volatile Boolean isInitialized = false;
@@ -68,13 +73,13 @@ public class TSDBJNIConnector {
if (!isInitialized) {
initImp(configDir);
if (setOptions(0, locale) < 0) {
- throw new SQLWarning(TSDBConstants.WrapErrMsg("Failed to set locale: " + locale + ". System default will be used."));
+ throw TSDBError.createSQLWarning("Failed to set locale: " + locale + ". System default will be used.");
}
if (setOptions(1, charset) < 0) {
- throw new SQLWarning(TSDBConstants.WrapErrMsg("Failed to set charset: " + charset + ". System default will be used."));
+ throw TSDBError.createSQLWarning("Failed to set charset: " + charset + ". System default will be used.");
}
if (setOptions(2, timezone) < 0) {
- throw new SQLWarning(TSDBConstants.WrapErrMsg("Failed to set timezone: " + timezone + ". System default will be used."));
+ throw TSDBError.createSQLWarning("Failed to set timezone: " + timezone + ". System default will be used.");
}
isInitialized = true;
TaosGlobalConfig.setCharset(getTsCharset());
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java
index 80ff49253016c632b6bf85f4756fe2d702a9bffc..7c2940fdc2c1a0cb15a5a0f1557598cb5b062e61 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java
@@ -20,18 +20,16 @@ import java.util.ArrayList;
import java.util.List;
public class TSDBResultSet extends AbstractResultSet implements ResultSet {
- private TSDBJNIConnector jniConnector;
-
+ private final TSDBJNIConnector jniConnector;
private final TSDBStatement statement;
- private long resultSetPointer = 0L;
+ private final long resultSetPointer;
private List columnMetaDataList = new ArrayList<>();
+ private final TSDBResultSetRowData rowData;
+ private final TSDBResultSetBlockData blockData;
- private TSDBResultSetRowData rowData;
- private TSDBResultSetBlockData blockData;
-
- private boolean batchFetch = false;
- private boolean lastWasNull = false;
- private final int COLUMN_INDEX_START_VALUE = 1;
+ private boolean batchFetch;
+ private boolean lastWasNull;
+ private boolean isClosed;
public void setBatchFetch(boolean batchFetch) {
this.batchFetch = batchFetch;
@@ -56,13 +54,13 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
int code = this.jniConnector.getSchemaMetaData(this.resultSetPointer, this.columnMetaDataList);
if (code == TSDBConstants.JNI_CONNECTION_NULL) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL);
}
if (code == TSDBConstants.JNI_RESULT_SET_NULL) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL);
}
if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_NUM_OF_FIELDS_0));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0);
}
this.rowData = new TSDBResultSetRowData(this.columnMetaDataList.size());
this.blockData = new TSDBResultSetBlockData(this.columnMetaDataList, this.columnMetaDataList.size());
@@ -78,28 +76,23 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
this.blockData.reset();
if (code == TSDBConstants.JNI_CONNECTION_NULL) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL);
} else if (code == TSDBConstants.JNI_RESULT_SET_NULL) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL);
} else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_NUM_OF_FIELDS_0));
- } else if (code == TSDBConstants.JNI_FETCH_END) {
- return false;
- }
-
- return true;
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0);
+ } else return code != TSDBConstants.JNI_FETCH_END;
} else {
if (rowData != null) {
this.rowData.clear();
}
-
int code = this.jniConnector.fetchRow(this.resultSetPointer, this.rowData);
if (code == TSDBConstants.JNI_CONNECTION_NULL) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL);
} else if (code == TSDBConstants.JNI_RESULT_SET_NULL) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL);
} else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_NUM_OF_FIELDS_0));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0);
} else if (code == TSDBConstants.JNI_FETCH_END) {
return false;
} else {
@@ -109,14 +102,17 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
}
public void close() throws SQLException {
+ if (isClosed)
+ return;
if (this.jniConnector != null) {
int code = this.jniConnector.freeResultSet(this.resultSetPointer);
if (code == TSDBConstants.JNI_CONNECTION_NULL) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL);
} else if (code == TSDBConstants.JNI_RESULT_SET_NULL) {
- throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL));
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL);
}
}
+ isClosed = true;
}
public boolean wasNull() throws SQLException {
@@ -127,30 +123,27 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
String res = null;
int colIndex = getTrueColumnIndex(columnIndex);
- if (!this.getBatchFetch()) {
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType());
- }
- return res;
- } else {
+ if (this.getBatchFetch())
return this.blockData.getString(colIndex);
+
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType());
}
+ return res;
}
public boolean getBoolean(int columnIndex) throws SQLException {
boolean res = false;
int colIndex = getTrueColumnIndex(columnIndex);
- if (!this.getBatchFetch()) {
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getBoolean(colIndex, this.columnMetaDataList.get(colIndex).getColType());
- }
- } else {
+ if (this.getBatchFetch())
return this.blockData.getBoolean(colIndex);
- }
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getBoolean(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ }
return res;
}
@@ -158,91 +151,84 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
byte res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
- if (!this.getBatchFetch()) {
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = (byte) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType());
- }
- return res;
- } else {
+ if (this.getBatchFetch())
return (byte) this.blockData.getInt(colIndex);
+
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = (byte) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType());
}
+ return res;
}
public short getShort(int columnIndex) throws SQLException {
short res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
- if (!this.getBatchFetch()) {
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = (short) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType());
- }
- return res;
- } else {
+ if (this.getBatchFetch())
return (short) this.blockData.getInt(colIndex);
+
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = (short) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType());
}
+ return res;
}
public int getInt(int columnIndex) throws SQLException {
int res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
- if (!this.getBatchFetch()) {
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType());
- }
- return res;
- } else {
+ if (this.getBatchFetch())
return this.blockData.getInt(colIndex);
- }
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+ }
+ return res;
}
public long getLong(int columnIndex) throws SQLException {
long res = 0L;
int colIndex = getTrueColumnIndex(columnIndex);
- if (!this.getBatchFetch()) {
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType());
- }
- return res;
- } else {
+ if (this.getBatchFetch())
return this.blockData.getLong(colIndex);
+
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType());
}
+ return res;
}
public float getFloat(int columnIndex) throws SQLException {
float res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
- if (!this.getBatchFetch()) {
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getFloat(colIndex, this.columnMetaDataList.get(colIndex).getColType());
- }
- return res;
- } else {
+ if (this.getBatchFetch())
return (float) this.blockData.getDouble(colIndex);
- }
+
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull)
+ res = this.rowData.getFloat(colIndex, this.columnMetaDataList.get(colIndex).getColType());
+
+ return res;
}
public double getDouble(int columnIndex) throws SQLException {
double res = 0;
int colIndex = getTrueColumnIndex(columnIndex);
- if (!this.getBatchFetch()) {
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getDouble(colIndex, this.columnMetaDataList.get(colIndex).getColType());
- }
- return res;
- } else {
+ if (this.getBatchFetch())
return this.blockData.getDouble(colIndex);
+
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getDouble(colIndex, this.columnMetaDataList.get(colIndex).getColType());
}
+ return res;
}
@Deprecated
@@ -258,15 +244,14 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
Timestamp res = null;
int colIndex = getTrueColumnIndex(columnIndex);
- if (!this.getBatchFetch()) {
- this.lastWasNull = this.rowData.wasNull(colIndex);
- if (!lastWasNull) {
- res = this.rowData.getTimestamp(colIndex);
- }
- return res;
- } else {
+ if (this.getBatchFetch())
return this.blockData.getTimestamp(columnIndex);
+
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ if (!lastWasNull) {
+ res = this.rowData.getTimestamp(colIndex);
}
+ return res;
}
public ResultSetMetaData getMetaData() throws SQLException {
@@ -277,12 +262,11 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
public Object getObject(int columnIndex) throws SQLException {
int colIndex = getTrueColumnIndex(columnIndex);
- if (!this.getBatchFetch()) {
- this.lastWasNull = this.rowData.wasNull(colIndex);
- return this.rowData.get(colIndex);
- } else {
+ if (this.getBatchFetch())
return this.blockData.get(colIndex);
- }
+
+ this.lastWasNull = this.rowData.wasNull(colIndex);
+ return this.rowData.get(colIndex);
}
@Override
@@ -415,8 +399,8 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
}
public boolean isClosed() throws SQLException {
- //TODO: check if need release resources
- boolean isClosed = true;
+ if (isClosed)
+ return true;
if (jniConnector != null) {
isClosed = jniConnector.isResultsetClosed();
}
@@ -429,14 +413,12 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
}
private int getTrueColumnIndex(int columnIndex) throws SQLException {
- if (columnIndex < this.COLUMN_INDEX_START_VALUE) {
- throw new SQLException("Column Index out of range, " + columnIndex + " < " + this.COLUMN_INDEX_START_VALUE);
- }
+ if (columnIndex < 1)
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "columnIndex(" + columnIndex + "): < 1");
int numOfCols = this.columnMetaDataList.size();
- if (columnIndex > numOfCols) {
- throw new SQLException("Column Index out of range, " + columnIndex + " > " + numOfCols);
- }
+ if (columnIndex > numOfCols)
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "columnIndex: " + columnIndex);
return columnIndex - 1;
}
}
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java
index 9352cf525350ff57525680f405d61c6b00c0cf55..ce5290de6616dfcc367434cc2e24899e992ddd63 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java
@@ -30,468 +30,472 @@ import java.util.Collections;
import java.util.List;
public class TSDBResultSetBlockData {
- private int numOfRows = 0;
- private int rowIndex = 0;
-
- private List columnMetaDataList;
- private ArrayList