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/Jenkinsfile b/Jenkinsfile index e7603b578bf2c7718e67fbd9fda1674db49c07c0..d96eeaa724b975f7b22ed4351d86e98648cf1473 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -32,25 +32,24 @@ def abort_previous(){ milestone(buildNumber) } def pre_test(){ - catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { - sh ''' - sudo rmtaos - ''' - } + + sh ''' + sudo rmtaos || echo "taosd has not installed" + ''' sh ''' 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 + git --no-pager diff --name-only FETCH_HEAD $(git merge-base FETCH_HEAD develop)|grep -v -E '.*md|//src//connector|Jenkinsfile' 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 diff --git a/README-CN.md b/README-CN.md new file mode 100644 index 0000000000000000000000000000000000000000..9601cde3af526800a407c8bf9af8694e01e5641e --- /dev/null +++ b/README-CN.md @@ -0,0 +1,267 @@ +[![Build Status](https://travis-ci.org/taosdata/TDengine.svg?branch=master)](https://travis-ci.org/taosdata/TDengine) +[![Build status](https://ci.appveyor.com/api/projects/status/kf3pwh2or5afsgl9/branch/master?svg=true)](https://ci.appveyor.com/project/sangshuduo/tdengine-2n8ge/branch/master) +[![Coverage Status](https://coveralls.io/repos/github/taosdata/TDengine/badge.svg?branch=develop)](https://coveralls.io/github/taosdata/TDengine?branch=develop) +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/4201/badge)](https://bestpractices.coreinfrastructure.org/projects/4201) +[![tdengine](https://snapcraft.io//tdengine/badge.svg)](https://snapcraft.io/tdengine) + +[![TDengine](TDenginelogo.png)](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为好友,即可入群。 diff --git a/README.md b/README.md index 489b6d0a4e12db06c9f2c1274e7a87f22cf76655..79c140c741c1164633e5a2953db9c2d86569e01f 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ [![TDengine](TDenginelogo.png)](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 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/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/11.administrator/docs.md b/documentation20/cn/11.administrator/docs.md index 52a0da6551a332b9b578d3830d1bb8135eb30692..027828d9033c138a727d5f0e9056118681484b10 100644 --- a/documentation20/cn/11.administrator/docs.md +++ b/documentation20/cn/11.administrator/docs.md @@ -14,6 +14,8 @@ Memory Size = maxVgroupsPerDb * (blocks * cache + 10MB) + numOfTables * (tagSize 示例:假设是 4 核机器,cache 是缺省大小 16M, blocks 是缺省值 6,假设有 10 万张表,标签总长度是 256 字节,则总的内存需求为:4 \* (16 \* 6 + 10) + 100000 \* (0.25 + 0.5) / 1000 = 499M。 +注意:从这个公式计算得到的内存容量,应理解为系统的“必要需求”,而不是“内存总数”。在实际运行的生产系统中,由于操作系统缓存、资源管理调度等方面的需要,内存规划应当在计算结果的基础上保留一定冗余,以维持系统状态和系统性能的稳定性。 + 实际运行的系统往往会根据数据特点的不同,将数据存放在不同的 DB 里。因此做规划时,也需要考虑。 如果内存充裕,可以加大 Blocks 的配置,这样更多数据将保存在内存里,提高查询速度。 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/tsclient.h b/src/client/inc/tsclient.h index 7a38141b53cf855070768da7e82d4053ab6aec74..013733bfe36950d9e74cd883d3fed488b2698add 100644 --- a/src/client/inc/tsclient.h +++ b/src/client/inc/tsclient.h @@ -47,9 +47,6 @@ enum { DATA_FROM_DATA_FILE = 2, }; -#define TSDB_UDF_TYPE_SCALAR 1 -#define TSDB_UDF_TYPE_AGGREGATE 2 - typedef void (*__async_cb_func_t)(void *param, TAOS_RES *tres, int32_t numOfRows); typedef struct STableComInfo { 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..87f6058cecefbfc1bb45fd4ccff584d8d0c10aba 100644 --- a/src/client/src/tscAsync.c +++ b/src/client/src/tscAsync.c @@ -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,23 +292,26 @@ 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); void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) { diff --git a/src/client/src/tscParseInsert.c b/src/client/src/tscParseInsert.c index d071520b88b2d961e062766233295530fe48fd0f..2b962333d588117ba54f363b7da586b6f04e3d47 100644 --- a/src/client/src/tscParseInsert.c +++ b/src/client/src/tscParseInsert.c @@ -394,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) { @@ -1360,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..0669d6aeb095e2410e48b86b10c724a38a5728fa 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; @@ -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/tscSQLParser.c b/src/client/src/tscSQLParser.c index caace8251f2e129bc286614a65a5d4ab9604b16c..03c202327a678782120baa3a5a96a19314057279 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -77,29 +77,29 @@ static int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SC static uint8_t convertOptr(SStrToken *pToken); -static int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery, bool timeWindowQuery); +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 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); @@ -110,15 +110,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); @@ -126,8 +125,8 @@ 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 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) { @@ -335,6 +334,8 @@ int32_t handleUserDefinedFunc(SSqlObj* pSql, struct SSqlInfo* pInfo) { strcpy(pMsg->name, createInfo->name.z); strcpy(pMsg->path, createInfo->path.z); + pMsg->funcType = htonl(createInfo->type); + pMsg->outputType = createInfo->output.type; pMsg->outputLen = htons(createInfo->output.bytes); @@ -727,7 +728,7 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) { } 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) { @@ -762,9 +763,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; } @@ -906,7 +907,7 @@ static int32_t checkInvalidExprForTimeWindow(SSqlCmd* pCmd, SQueryInfo* pQueryIn return addPrimaryTsColumnForTimeWindowQuery(pQueryInfo); } -int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) { +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"; @@ -915,8 +916,8 @@ int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQ STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta); - if (pQuerySql->interval.interval.type == 0 || pQuerySql->interval.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); } @@ -929,7 +930,7 @@ int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQ } // interval is not null - SStrToken* t = &pQuerySql->interval.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; } @@ -946,11 +947,11 @@ int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQ } } - if (parseIntervalOffset(pCmd, pQueryInfo, &pQuerySql->interval.offset) != TSDB_CODE_SUCCESS) { + if (parseIntervalOffset(pCmd, pQueryInfo, &pQuerySqlNode->interval.offset) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_SQL; } - if (parseSlidingClause(pCmd, pQueryInfo, &pQuerySql->sliding) != TSDB_CODE_SUCCESS) { + if (parseSlidingClause(pCmd, pQueryInfo, &pQuerySqlNode->sliding) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_SQL; } @@ -958,19 +959,19 @@ int32_t parseIntervalClause(SSqlObj* pSql, SQueryInfo* pQueryInfo, SQuerySQL* pQ return checkInvalidExprForTimeWindow(pCmd, pQueryInfo); } -int32_t parseSessionClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL * pQuerySql) { +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 (pQuerySql->sessionVal.gap.n == 0 || pQuerySql->sessionVal.col.n == 0) { + if (!TPARSER_HAS_TOKEN(pQuerySqlNode->sessionVal.gap)) { return TSDB_CODE_SUCCESS; } - SStrToken* col = &pQuerySql->sessionVal.col; - SStrToken* gap = &pQuerySql->sessionVal.gap; + 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) { @@ -1723,7 +1724,7 @@ bool isValidDistinctSql(SQueryInfo* pQueryInfo) { return false; } -void genUdfList(SArray* pUdfInfo, tSQLExpr *pNode) { +void genUdfList(SArray* pUdfInfo, tSqlExpr *pNode) { if (pNode == NULL) { return; } @@ -1744,15 +1745,18 @@ void genUdfList(SArray* pUdfInfo, tSQLExpr *pNode) { } } -static int32_t checkForUdf(SSqlObj* pSql, tSQLExprList* pSelection) { +static int32_t checkForUdf(SSqlObj* pSql, SArray* pSelection) { SSqlCmd* pCmd = &pSql->cmd; if (pCmd->pUdfInfo != NULL) { return TSDB_CODE_SUCCESS; } pCmd->pUdfInfo = taosArrayInit(4, sizeof(struct SUdfInfo)); - for (int32_t i = 0; i < pSelection->nExpr; ++i) { - tSqlExprItem* pItem = &pSelection->a[i]; + + size_t nExpr = taosArrayGetSize(pSelection); + + for (int32_t i = 0; i < nExpr; ++i) { + tSqlExprItem* pItem = taosArrayGet(pSelection, i); int32_t type = pItem->pNode->type; if (type == SQL_NODE_EXPR || type == SQL_NODE_SQLFUNCTION) { @@ -1779,8 +1783,8 @@ static SUdfInfo* isValidUdf(SArray* pUdfInfo, const char* name, int32_t len) { return NULL; } -int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery, bool timeWindowQuery) { - 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"; @@ -1794,9 +1798,10 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel } 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); @@ -2151,7 +2156,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col 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); } @@ -2159,7 +2164,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col 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->tokenId; if ((pToken->z == NULL || pToken->n == 0) @@ -2254,13 +2259,13 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col case TSDB_FUNC_STDDEV: case TSDB_FUNC_LEASTSQR: { // 1. valid the number of parameters - if (pItem->pNode->pParam == NULL || (functionId != TSDB_FUNC_LEASTSQR && pItem->pNode->pParam->nExpr != 1) || - (functionId == TSDB_FUNC_LEASTSQR && 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]); + tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->pParam, 0); if (pParamElem->pNode->tokenId != TK_ALL && pParamElem->pNode->tokenId != TK_ID) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); } @@ -2362,17 +2367,17 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col } 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]); + 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); } @@ -2415,10 +2420,10 @@ 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; } } @@ -2462,12 +2467,12 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col 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]); + tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->pParam, 0); if (pParamElem->pNode->tokenId != TK_ID) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); } @@ -2539,13 +2544,13 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col // 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); @@ -2558,7 +2563,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 { @@ -2577,12 +2582,13 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col } // 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); @@ -2640,7 +2646,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col } case TSDB_FUNC_BLKINFO: { // no parameters or more than one parameter for function - if (pItem->pNode->pParam != NULL && pItem->pNode->pParam->nExpr != 0) { + if (pItem->pNode->pParam != NULL && taosArrayGetSize(pItem->pNode->pParam) != 0) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); } @@ -2669,7 +2675,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg9); } - tSqlExprItem* pParamElem = &(pItem->pNode->pParam->a[0]); + tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->pParam, 0);; if (pParamElem->pNode->tokenId != TK_ID) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); } @@ -3309,10 +3315,10 @@ static SColumnFilterInfo* addColumnFilterInfo(SColumn* pColumn) { } static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnFilterInfo* pColumnFilter, - SColumnIndex* columnIndex, 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); SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, columnIndex->columnIndex); @@ -3330,18 +3336,26 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, } int32_t retVal = TSDB_CODE_SUCCESS; + + 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->value.nLen + TSDB_NCHAR_SIZE); + 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->value.nLen + 1 is larger than the actual nchar string length - pColumnFilter->pz = (int64_t)calloc(1, (pRight->value.nLen + 1) * TSDB_NCHAR_SIZE); + 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; @@ -3390,162 +3404,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->tokenId == TK_ID) { // column name - strncpy(*str, pExpr->colInfo.z, pExpr->colInfo.n); - *str += pExpr->colInfo.n; - - } else if (pExpr->tokenId >= TK_BOOL && pExpr->tokenId <= TK_STRING) { // value - *str += tVariantToString(&pExpr->value, *str); - - } else if (pExpr->tokenId >= TSDB_FUNC_COUNT && pExpr->tokenId <= TSDB_FUNC_BLKINFO) { - /* - * 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->tokenId == 0 while handling "is null" query -static bool isExprLeafNode(tSQLExpr* pExpr) { - return (pExpr->pRight == NULL && pExpr->pLeft == NULL) && - (pExpr->tokenId == 0 || pExpr->tokenId == TK_ID || (pExpr->tokenId >= TK_BOOL && pExpr->tokenId <= TK_NCHAR) || pExpr->tokenId == 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; - } - - 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->tokenId) { - 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; +static int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t timePrecision); - 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->value.pz, pSub->value.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->value.nLen <= 0 || !tscValidateTableNameLength(pSub->value.nLen)) { + if (pVar->nLen <= 0 || !tscValidateTableNameLength(pVar->nLen)) { return TSDB_CODE_TSC_INVALID_SQL; } } @@ -3553,7 +3450,7 @@ 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->value.pz); @@ -3567,7 +3464,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; @@ -3633,51 +3530,7 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC return doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, pIndex, pExpr); } -static void relToString(tSQLExpr* pExpr, char** str) { - assert(pExpr->tokenId == TK_AND || pExpr->tokenId == TK_OR); - - const char* or = "OR"; - const char*and = "AND"; - - // if (pQueryInfo->tagCond.relType == TSQL_STABLE_QTYPE_COND) { - if (pExpr->tokenId == 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; - } - - relToString(pExpr, str); - - ret = getTagCondString(pExpr->pRight, str); - - *(*str) = ')'; - *str += 1; - - return ret; - } - - return tSQLExprLeafToString(pExpr, true, str); -} - -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"; @@ -3685,8 +3538,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; @@ -3711,12 +3564,12 @@ 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 + if (!tSqlExprIsParentOfLeaf(pExpr)) { // internal node int32_t ret = getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pLeft, pExpr->tokenId); if (ret != TSDB_CODE_SUCCESS) { return ret; @@ -3733,7 +3586,7 @@ static int32_t getColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQ } } -static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr) { +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"; const char* msg3 = "type of join columns must be identical"; @@ -3743,7 +3596,7 @@ static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* return TSDB_CODE_SUCCESS; } - if (!isExprDirectParentOfLeafNode(pExpr)) { + if (!tSqlExprIsParentOfLeaf(pExpr)) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); } @@ -3791,7 +3644,7 @@ static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* return TSDB_CODE_SUCCESS; } -static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, +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) { @@ -3865,12 +3718,12 @@ 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; @@ -3886,7 +3739,7 @@ static int32_t validateArithmeticSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryI } } - tSQLExpr* pRight = pExpr->pRight; + tSqlExpr* pRight = pExpr->pRight; if (pRight->type == SQL_NODE_EXPR) { int32_t ret = validateArithmeticSQLExpr(pCmd, pRight, pQueryInfo, pList, type); if (ret != TSDB_CODE_SUCCESS) { @@ -3907,7 +3760,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; } @@ -3935,9 +3788,9 @@ static bool isValidExpr(tSQLExpr* pLeft, tSQLExpr* pRight, int32_t optr) { return true; } -static void exchangeExpr(tSQLExpr* pExpr) { - tSQLExpr* pLeft = pExpr->pLeft; - tSQLExpr* pRight = pExpr->pRight; +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)) { @@ -3970,14 +3823,14 @@ static void exchangeExpr(tSQLExpr* pExpr) { } } -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->tokenId != TK_ID) { return true; @@ -4021,7 +3874,7 @@ 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) { @@ -4033,7 +3886,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); @@ -4047,7 +3900,7 @@ 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"; @@ -4058,8 +3911,8 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL 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; @@ -4068,7 +3921,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; @@ -4170,7 +4023,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; @@ -4178,8 +4031,8 @@ 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)->tokenId)) { return TSDB_CODE_TSC_INVALID_SQL; @@ -4188,7 +4041,7 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr int32_t leftType = -1; int32_t rightType = -1; - if (!isExprDirectParentOfLeafNode(*pExpr)) { + if (!tSqlExprIsParentOfLeaf(*pExpr)) { int32_t ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, &leftType, (*pExpr)->tokenId); if (ret != TSDB_CODE_SUCCESS) { return ret; @@ -4218,40 +4071,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)->tokenId == TK_OR || (*pExpr)->tokenId == 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) { @@ -4273,12 +4095,12 @@ static void doExtractExprForSTable(SSqlCmd* pCmd, tSQLExpr** pExpr, SQueryInfo* } } -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; @@ -4298,7 +4120,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) { @@ -4399,7 +4221,7 @@ 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"; @@ -4407,7 +4229,7 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLE return TSDB_CODE_SUCCESS; } - if (!isExprDirectParentOfLeafNode(pExpr)) { + if (!tSqlExprIsParentOfLeaf(pExpr)) { if (pExpr->tokenId == TK_OR) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); } @@ -4424,7 +4246,7 @@ 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->tokenId, tinfo.precision) != TSDB_CODE_SUCCESS) { @@ -4566,13 +4388,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->value.nLen + 1 is larger than the actual nchar string length - char *tmp = calloc(1, (vVariant->nLen + 1) * TSDB_NCHAR_SIZE); + char *tmp = calloc(1, bufLen * TSDB_NCHAR_SIZE); retVal = tVariantDump(vVariant, tmp, schemaType, false); free(tmp); } else { @@ -4583,12 +4413,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) { @@ -4596,7 +4426,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; } @@ -4628,7 +4458,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); @@ -4651,7 +4481,7 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE return ret; } -int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlObj* pSql) { +int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql) { if (pExpr == NULL) { return TSDB_CODE_SUCCESS; } @@ -4674,7 +4504,7 @@ int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlObj* pSql return ret; } - doCompactQueryExpr(pExpr); + tSqlExprCompact(pExpr); // after expression compact, the expression tree is only include tag query condition condExpr.pTagCond = (*pExpr); @@ -4725,7 +4555,7 @@ int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlObj* pSql 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->tokenId == TK_ID) { return TSDB_CODE_SUCCESS; @@ -4845,7 +4675,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); @@ -4967,7 +4797,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"; @@ -4982,11 +4812,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 @@ -5054,7 +4884,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 */ @@ -5066,12 +4896,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; @@ -5084,7 +4914,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; @@ -5093,7 +4923,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) { @@ -5128,13 +4958,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; } @@ -5662,7 +5492,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"; @@ -5670,9 +5500,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); @@ -6331,17 +6161,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)) { @@ -6387,8 +6220,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; @@ -6523,7 +6357,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; @@ -6578,7 +6412,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. @@ -6787,24 +6621,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); } @@ -6819,24 +6653,24 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) { return code; } - code = checkForUdf(pSql, pQuerySql->pSelection); + code = checkForUdf(pSql, pQuerySqlNode->pSelectList); if (code != TSDB_CODE_SUCCESS) { return code; } 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; } @@ -6854,7 +6688,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); } @@ -6872,12 +6706,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))) { @@ -6926,10 +6760,10 @@ static int32_t checkQueryRangeForFill(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) { return TSDB_CODE_SUCCESS; } -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"; @@ -6937,6 +6771,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) { 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; @@ -6951,7 +6786,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); } @@ -6962,77 +6797,77 @@ 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); - 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); - if (fromSize > TSDB_MAX_JOIN_TABLE_NUM * 2) { + size_t fromSize = taosArrayGetSize(pQuerySqlNode->from->tableList); + if (fromSize > TSDB_MAX_JOIN_TABLE_NUM) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4); } pQueryInfo->command = TSDB_SQL_SELECT; - - if (fromSize > 4) { + if (fromSize > 2) { 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); + } - // 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)); + if (aliasName1.n >= TSDB_TABLE_NAME_LEN) { + return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg8); + } + + 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)) { @@ -7048,50 +6883,50 @@ 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 timeWindowQuery = !(pQuerySql->interval.interval.type == 0 || pQuerySql->interval.interval.n == 0 || - pQuerySql->sessionVal.gap.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)); - code = checkForUdf(pSql, pQuerySql->pSelection); + code = checkForUdf(pSql, pQuerySqlNode->pSelectList); if (code != TSDB_CODE_SUCCESS) { return code; } - if (parseSelectClause(pCmd, index, pQuerySql->pSelection, isSTable, joinQuery, timeWindowQuery) != 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 (isTimeWindowQuery(pQueryInfo) && @@ -7100,7 +6935,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) { } } - if (parseSessionClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) { + if (parseSessionClause(pCmd, pQueryInfo, pQuerySqlNode) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_SQL; } @@ -7122,7 +6957,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) { } } - if ((code = parseLimitClause(pCmd, pQueryInfo, index, pQuerySql, pSql)) != TSDB_CODE_SUCCESS) { + if ((code = parseLimitClause(pCmd, pQueryInfo, index, pQuerySqlNode, pSql)) != TSDB_CODE_SUCCESS) { return code; } @@ -7133,7 +6968,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) { updateLastScanOrderIfNeeded(pQueryInfo); tscFieldInfoUpdateOffset(pQueryInfo); - if (pQuerySql->fillType != NULL) { + if (pQuerySqlNode->fillType != NULL) { if (pQueryInfo->interval.interval == 0 && (!tscIsPointInterpQuery(pQueryInfo))) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2); } @@ -7146,7 +6981,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; } } @@ -7154,7 +6989,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; diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index c9440cfb020477f4962517cf7b198dce51211adb..e695fd04d6b380e5a2282a4c20e81eec8ee5faa9 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -1409,7 +1409,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); @@ -1418,7 +1418,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; @@ -1476,7 +1476,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); @@ -1499,11 +1499,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; } } @@ -2790,3 +2790,4 @@ void tscInitMsgsFp() { tscKeepConn[TSDB_SQL_FETCH] = 1; tscKeepConn[TSDB_SQL_HB] = 1; } + \ No newline at end of file diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 2d5e8382a430f144a09697b709748f605ce2625a..e8994502610653c01b9a6f93247f9ab4b42792af 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -1159,7 +1159,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; diff --git a/src/common/inc/tglobal.h b/src/common/inc/tglobal.h index df1a622101afa032001ed499495656186b40754f..3f96466cc00fc3250860e79bc3dd85e6fd0368d7 100644 --- a/src/common/inc/tglobal.h +++ b/src/common/inc/tglobal.h @@ -163,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/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 9e405fdfe115e36cf0a1d64143a30ea9f19b1373..4a5df9361b7a9bb8d6fe852db273f53cab6bf879 100644 --- a/src/common/src/tglobal.c +++ b/src/common/src/tglobal.c @@ -210,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; 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.jdbc taos-jdbcdriver - 2.0.21 + 2.0.22 jar JDBCDriver 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.0 com.taosdata.jdbc taos-jdbcdriver - 2.0.21 + 2.0.22 jar JDBCDriver https://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 28b7bd6a5ff0eef90dee8d97767f71a44ed1552d..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 @@ -12,7 +12,7 @@ public abstract class AbstractDriver implements Driver { 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"; @@ -40,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()) { @@ -68,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("/"); 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/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/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 530ece6bcb6d1e75609ceee0a333dcd1aeb39bde..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,38 +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; } 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); } } @@ -139,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 b27bc63db17e2f7268ee9f1c8ae3c074db15c0e5..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,18 +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; @@ -23,7 +24,7 @@ import java.util.List; /** * JNI connector - * */ + */ public class TSDBJNIConnector { private static volatile Boolean isInitialized = false; @@ -72,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 5d68ffad6c35697bdc96d4b1919f23be5aa88e4a..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 @@ -27,8 +27,8 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { private final TSDBResultSetRowData rowData; private final TSDBResultSetBlockData blockData; - private boolean batchFetch = false; - private boolean lastWasNull = false; + private boolean batchFetch; + private boolean lastWasNull; private boolean isClosed; public void setBatchFetch(boolean batchFetch) { @@ -86,7 +86,6 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet { if (rowData != null) { this.rowData.clear(); } - int code = this.jniConnector.fetchRow(this.resultSetPointer, this.rowData); if (code == TSDBConstants.JNI_CONNECTION_NULL) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL); @@ -124,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; } @@ -155,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 @@ -255,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 { @@ -274,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 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 colData = null; - - public TSDBResultSetBlockData(List colMeta, int numOfCols) { - this.columnMetaDataList = colMeta; - this.colData = new ArrayList(numOfCols); - } - - public TSDBResultSetBlockData() { - this.colData = new ArrayList(); - } - - public void clear() { - int size = this.colData.size(); - if (this.colData != null) { - this.colData.clear(); - } - - setNumOfCols(size); - } - - public int getNumOfRows() { - return this.numOfRows; - } - - public void setNumOfRows(int numOfRows) { - this.numOfRows = numOfRows; - } - - public int getNumOfCols() { - return this.colData.size(); - } - - public void setNumOfCols(int numOfCols) { - this.colData = new ArrayList(numOfCols); - this.colData.addAll(Collections.nCopies(numOfCols, null)); - } - - public boolean hasMore() { - return this.rowIndex < this.numOfRows; - } - - public boolean forward() { - if (this.rowIndex > this.numOfRows) { - return false; - } - - return ((++this.rowIndex) < this.numOfRows); - } - - public void reset() { - this.rowIndex = 0; - } - - public void setBoolean(int col, boolean value) { - colData.set(col, value); - } - - public void setByteArray(int col, int length, byte[] value) { - try { - switch (this.columnMetaDataList.get(col).getColType()) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: { - ByteBuffer buf = ByteBuffer.wrap(value, 0, length); - buf.order(ByteOrder.LITTLE_ENDIAN).asCharBuffer(); - this.colData.set(col, buf); - break; - } - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { - ByteBuffer buf = ByteBuffer.wrap(value, 0, length); - buf.order(ByteOrder.LITTLE_ENDIAN); - this.colData.set(col, buf); - break; - } - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { - ByteBuffer buf = ByteBuffer.wrap(value, 0, length); - ShortBuffer sb = buf.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer(); - this.colData.set(col, sb); - break; - } - case TSDBConstants.TSDB_DATA_TYPE_INT: { - ByteBuffer buf = ByteBuffer.wrap(value, 0, length); - IntBuffer ib = buf.order(ByteOrder.LITTLE_ENDIAN).asIntBuffer(); - this.colData.set(col, ib); - break; - } - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { - ByteBuffer buf = ByteBuffer.wrap(value, 0, length); - LongBuffer lb = buf.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer(); - this.colData.set(col, lb); - break; - } - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { - ByteBuffer buf = ByteBuffer.wrap(value, 0, length); - FloatBuffer fb = buf.order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer(); - this.colData.set(col, fb); - break; - } - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { - ByteBuffer buf = ByteBuffer.wrap(value, 0, length); - DoubleBuffer db = buf.order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer(); - this.colData.set(col, db); - break; - } - case TSDBConstants.TSDB_DATA_TYPE_BINARY: { - ByteBuffer buf = ByteBuffer.wrap(value, 0, length); - buf.order(ByteOrder.LITTLE_ENDIAN); - this.colData.set(col, buf); - break; - } - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { - ByteBuffer buf = ByteBuffer.wrap(value, 0, length); - LongBuffer lb = buf.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer(); - this.colData.set(col, lb); - break; - } - case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { - ByteBuffer buf = ByteBuffer.wrap(value, 0, length); - buf.order(ByteOrder.LITTLE_ENDIAN); - this.colData.set(col, buf); - break; - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - private static class NullType { - private static final byte NULL_BOOL_VAL = 0x2; - private static final String NULL_STR = "null"; - - public String toString() { - return NullType.NULL_STR; - } - - public static boolean isBooleanNull(byte val) { - return val == NullType.NULL_BOOL_VAL; - } - - private static boolean isTinyIntNull(byte val) { - return val == Byte.MIN_VALUE; - } - - private static boolean isSmallIntNull(short val) { - return val == Short.MIN_VALUE; - } - - private static boolean isIntNull(int val) { - return val == Integer.MIN_VALUE; - } - - private static boolean isBigIntNull(long val) { - return val == Long.MIN_VALUE; - } - - private static boolean isFloatNull(float val) { - return Float.isNaN(val); - } - - private static boolean isDoubleNull(double val) { - return Double.isNaN(val); - } - - private static boolean isBinaryNull(byte[] val, int length) { - if (length != Byte.BYTES) { - return false; - } - - return val[0] == 0xFF; - } - - private static boolean isNcharNull(byte[] val, int length) { - if (length != Integer.BYTES) { - return false; - } - - return (val[0] & val[1] & val[2] & val[3]) == 0xFF; - } - - } - - /** - * The original type may not be a string type, but will be converted to by - * calling this method - * - * @param col column index - * @return - * @throws SQLException - */ - public String getString(int col) throws SQLException { - Object obj = get(col); - if (obj == null) { - return new NullType().toString(); - } - - return obj.toString(); - } - - public int getInt(int col) { - Object obj = get(col); - if (obj == null) { - return 0; - } - - int type = this.columnMetaDataList.get(col).getColType(); - switch (type) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: - case TSDBConstants.TSDB_DATA_TYPE_INT: { - return (int) obj; - } - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { - return ((Long) obj).intValue(); - } - - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { - return ((Double) obj).intValue(); - } - - case TSDBConstants.TSDB_DATA_TYPE_NCHAR: - case TSDBConstants.TSDB_DATA_TYPE_BINARY: { - return Integer.parseInt((String) obj); - } - } - - return 0; - } - - public boolean getBoolean(int col) throws SQLException { - Object obj = get(col); - if (obj == null) { - return Boolean.FALSE; - } - - int type = this.columnMetaDataList.get(col).getColType(); - switch (type) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: - case TSDBConstants.TSDB_DATA_TYPE_INT: { - return ((int) obj == 0L) ? Boolean.FALSE : Boolean.TRUE; - } - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { - return (((Long) obj) == 0L) ? Boolean.FALSE : Boolean.TRUE; - } - - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { - return (((Double) obj) == 0) ? Boolean.FALSE : Boolean.TRUE; - } - - case TSDBConstants.TSDB_DATA_TYPE_NCHAR: - case TSDBConstants.TSDB_DATA_TYPE_BINARY: { - if ("TRUE".compareToIgnoreCase((String) obj) == 0) { - return Boolean.TRUE; - } else if ("FALSE".compareToIgnoreCase((String) obj) == 0) { - return Boolean.TRUE; - } else { - throw new SQLDataException(); - } - } - } - - return Boolean.FALSE; - } - - public long getLong(int col) throws SQLException { - Object obj = get(col); - if (obj == null) { - return 0; - } - - int type = this.columnMetaDataList.get(col).getColType(); - switch (type) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: - case TSDBConstants.TSDB_DATA_TYPE_INT: { - return (int) obj; - } - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { - return (long) obj; - } - - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { - return ((Double) obj).longValue(); - } - - case TSDBConstants.TSDB_DATA_TYPE_NCHAR: - case TSDBConstants.TSDB_DATA_TYPE_BINARY: { - return Long.parseLong((String) obj); - } - } - - return 0; - } - - public Timestamp getTimestamp(int col) { - try { - return new Timestamp(getLong(col)); - } catch (SQLException e) { - e.printStackTrace(); - } - - return null; - } - - public double getDouble(int col) { - Object obj = get(col); - if (obj == null) { - return 0; - } - - int type = this.columnMetaDataList.get(col).getColType(); - switch (type) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: - case TSDBConstants.TSDB_DATA_TYPE_INT: { - return (int) obj; - } - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { - return (long) obj; - } - - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { - return (double) obj; - } - - case TSDBConstants.TSDB_DATA_TYPE_NCHAR: - case TSDBConstants.TSDB_DATA_TYPE_BINARY: { - return Double.parseDouble((String) obj); - } - } - - return 0; - } - - public Object get(int col) { - int fieldSize = this.columnMetaDataList.get(col).getColSize(); - - switch (this.columnMetaDataList.get(col).getColType()) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: { - ByteBuffer bb = (ByteBuffer) this.colData.get(col); - - byte val = bb.get(this.rowIndex); - if (NullType.isBooleanNull(val)) { - return null; - } - - return (val == 0x0) ? Boolean.FALSE : Boolean.TRUE; - } - - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { - ByteBuffer bb = (ByteBuffer) this.colData.get(col); - - byte val = bb.get(this.rowIndex); - if (NullType.isTinyIntNull(val)) { - return null; - } - - return val; - } - - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { - ShortBuffer sb = (ShortBuffer) this.colData.get(col); - short val = sb.get(this.rowIndex); - if (NullType.isSmallIntNull(val)) { - return null; - } - - return val; - } - - case TSDBConstants.TSDB_DATA_TYPE_INT: { - IntBuffer ib = (IntBuffer) this.colData.get(col); - int val = ib.get(this.rowIndex); - if (NullType.isIntNull(val)) { - return null; - } - - return val; - } - - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { - LongBuffer lb = (LongBuffer) this.colData.get(col); - long val = lb.get(this.rowIndex); - if (NullType.isBigIntNull(val)) { - return null; - } - - return (long) val; - } - - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { - FloatBuffer fb = (FloatBuffer) this.colData.get(col); - float val = fb.get(this.rowIndex); - if (NullType.isFloatNull(val)) { - return null; - } - - return val; - } - - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { - DoubleBuffer lb = (DoubleBuffer) this.colData.get(col); - double val = lb.get(this.rowIndex); - if (NullType.isDoubleNull(val)) { - return null; - } - - return val; - } - - case TSDBConstants.TSDB_DATA_TYPE_BINARY: { - ByteBuffer bb = (ByteBuffer) this.colData.get(col); - bb.position(fieldSize * this.rowIndex); - - int length = bb.getShort(); - - byte[] dest = new byte[length]; - bb.get(dest, 0, length); - if (NullType.isBinaryNull(dest, length)) { - return null; - } - - return new String(dest); - } - - case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { - ByteBuffer bb = (ByteBuffer) this.colData.get(col); - bb.position(fieldSize * this.rowIndex); - - int length = bb.getShort(); - - byte[] dest = new byte[length]; - bb.get(dest, 0, length); - if (NullType.isNcharNull(dest, length)) { - return null; - } - - try { - String ss = TaosGlobalConfig.getCharset(); - return new String(dest, ss); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - } - } - - return 0; - } + private int numOfRows = 0; + private int rowIndex = 0; + + private List columnMetaDataList; + private ArrayList colData = null; + + public TSDBResultSetBlockData(List colMeta, int numOfCols) { + this.columnMetaDataList = colMeta; + this.colData = new ArrayList(numOfCols); + } + + public TSDBResultSetBlockData() { + this.colData = new ArrayList(); + } + + public void clear() { + int size = this.colData.size(); + if (this.colData != null) { + this.colData.clear(); + } + + setNumOfCols(size); + } + + public int getNumOfRows() { + return this.numOfRows; + } + + public void setNumOfRows(int numOfRows) { + this.numOfRows = numOfRows; + } + + public int getNumOfCols() { + return this.colData.size(); + } + + public void setNumOfCols(int numOfCols) { + this.colData = new ArrayList(numOfCols); + this.colData.addAll(Collections.nCopies(numOfCols, null)); + } + + public boolean hasMore() { + return this.rowIndex < this.numOfRows; + } + + public boolean forward() { + if (this.rowIndex > this.numOfRows) { + return false; + } + + return ((++this.rowIndex) < this.numOfRows); + } + + public void reset() { + this.rowIndex = 0; + } + + public void setBoolean(int col, boolean value) { + colData.set(col, value); + } + + public void setByteArray(int col, int length, byte[] value) { + try { + switch (this.columnMetaDataList.get(col).getColType()) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + buf.order(ByteOrder.LITTLE_ENDIAN).asCharBuffer(); + this.colData.set(col, buf); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + buf.order(ByteOrder.LITTLE_ENDIAN); + this.colData.set(col, buf); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + ShortBuffer sb = buf.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer(); + this.colData.set(col, sb); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_UINT: + case TSDBConstants.TSDB_DATA_TYPE_INT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + IntBuffer ib = buf.order(ByteOrder.LITTLE_ENDIAN).asIntBuffer(); + this.colData.set(col, ib); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + LongBuffer lb = buf.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer(); + this.colData.set(col, lb); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + FloatBuffer fb = buf.order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer(); + this.colData.set(col, fb); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + DoubleBuffer db = buf.order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer(); + this.colData.set(col, db); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + buf.order(ByteOrder.LITTLE_ENDIAN); + this.colData.set(col, buf); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + LongBuffer lb = buf.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer(); + this.colData.set(col, lb); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + buf.order(ByteOrder.LITTLE_ENDIAN); + this.colData.set(col, buf); + break; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static class NullType { + private static final byte NULL_BOOL_VAL = 0x2; + private static final String NULL_STR = "null"; + + public String toString() { + return NullType.NULL_STR; + } + + public static boolean isBooleanNull(byte val) { + return val == NullType.NULL_BOOL_VAL; + } + + private static boolean isTinyIntNull(byte val) { + return val == Byte.MIN_VALUE; + } + + private static boolean isSmallIntNull(short val) { + return val == Short.MIN_VALUE; + } + + private static boolean isIntNull(int val) { + return val == Integer.MIN_VALUE; + } + + private static boolean isBigIntNull(long val) { + return val == Long.MIN_VALUE; + } + + private static boolean isFloatNull(float val) { + return Float.isNaN(val); + } + + private static boolean isDoubleNull(double val) { + return Double.isNaN(val); + } + + private static boolean isBinaryNull(byte[] val, int length) { + if (length != Byte.BYTES) { + return false; + } + + return val[0] == 0xFF; + } + + private static boolean isNcharNull(byte[] val, int length) { + if (length != Integer.BYTES) { + return false; + } + + return (val[0] & val[1] & val[2] & val[3]) == 0xFF; + } + + } + + /** + * The original type may not be a string type, but will be converted to by + * calling this method + * + * @param col column index + * @return + * @throws SQLException + */ + public String getString(int col) throws SQLException { + Object obj = get(col); + if (obj == null) { + return new NullType().toString(); + } + + return obj.toString(); + } + + public int getInt(int col) { + Object obj = get(col); + if (obj == null) { + return 0; + } + + int type = this.columnMetaDataList.get(col).getColType(); + switch (type) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_INT: { + return (int) obj; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + return ((Long) obj).intValue(); + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + return ((Double) obj).intValue(); + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + return Integer.parseInt((String) obj); + } + } + + return 0; + } + + public boolean getBoolean(int col) throws SQLException { + Object obj = get(col); + if (obj == null) { + return Boolean.FALSE; + } + + int type = this.columnMetaDataList.get(col).getColType(); + switch (type) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_INT: { + return ((int) obj == 0L) ? Boolean.FALSE : Boolean.TRUE; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + return (((Long) obj) == 0L) ? Boolean.FALSE : Boolean.TRUE; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + return (((Double) obj) == 0) ? Boolean.FALSE : Boolean.TRUE; + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + if ("TRUE".compareToIgnoreCase((String) obj) == 0) { + return Boolean.TRUE; + } else if ("FALSE".compareToIgnoreCase((String) obj) == 0) { + return Boolean.TRUE; + } else { + throw new SQLDataException(); + } + } + } + + return Boolean.FALSE; + } + + public long getLong(int col) throws SQLException { + Object obj = get(col); + if (obj == null) { + return 0; + } + + int type = this.columnMetaDataList.get(col).getColType(); + switch (type) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_INT: { + return (int) obj; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + return (long) obj; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + return ((Double) obj).longValue(); + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + return Long.parseLong((String) obj); + } + } + + return 0; + } + + public Timestamp getTimestamp(int col) { + try { + return new Timestamp(getLong(col)); + } catch (SQLException e) { + e.printStackTrace(); + } + + return null; + } + + public double getDouble(int col) { + Object obj = get(col); + if (obj == null) { + return 0; + } + + int type = this.columnMetaDataList.get(col).getColType(); + switch (type) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_INT: { + return (int) obj; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + return (long) obj; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + return (double) obj; + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + return Double.parseDouble((String) obj); + } + } + + return 0; + } + + public Object get(int col) { + int fieldSize = this.columnMetaDataList.get(col).getColSize(); + + switch (this.columnMetaDataList.get(col).getColType()) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: { + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + + byte val = bb.get(this.rowIndex); + if (NullType.isBooleanNull(val)) { + return null; + } + + return (val == 0x0) ? Boolean.FALSE : Boolean.TRUE; + } + + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + + byte val = bb.get(this.rowIndex); + if (NullType.isTinyIntNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { + ShortBuffer sb = (ShortBuffer) this.colData.get(col); + short val = sb.get(this.rowIndex); + if (NullType.isSmallIntNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_INT: { + IntBuffer ib = (IntBuffer) this.colData.get(col); + int val = ib.get(this.rowIndex); + if (NullType.isIntNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { + LongBuffer lb = (LongBuffer) this.colData.get(col); + long val = lb.get(this.rowIndex); + if (NullType.isBigIntNull(val)) { + return null; + } + + return (long) val; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { + FloatBuffer fb = (FloatBuffer) this.colData.get(col); + float val = fb.get(this.rowIndex); + if (NullType.isFloatNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + DoubleBuffer lb = (DoubleBuffer) this.colData.get(col); + double val = lb.get(this.rowIndex); + if (NullType.isDoubleNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + bb.position(fieldSize * this.rowIndex); + + int length = bb.getShort(); + + byte[] dest = new byte[length]; + bb.get(dest, 0, length); + if (NullType.isBinaryNull(dest, length)) { + return null; + } + + return new String(dest); + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + bb.position(fieldSize * this.rowIndex); + + int length = bb.getShort(); + + byte[] dest = new byte[length]; + bb.get(dest, 0, length); + if (NullType.isNcharNull(dest, length)) { + return null; + } + + try { + String ss = TaosGlobalConfig.getCharset(); + return new String(dest, ss); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + } + + return 0; + } } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetMetaData.java index e0b1c246cbea246f885ab4c56c7ece0be212ff66..7abd997459fd8478a0a3bd06aa3eb0f51d1584ae 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetMetaData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetMetaData.java @@ -126,34 +126,12 @@ public class TSDBResultSetMetaData extends WrapperImpl implements ResultSetMetaD public int getColumnType(int column) throws SQLException { ColumnMetaData meta = this.colMetaDataList.get(column - 1); - switch (meta.getColType()) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: - return Types.BOOLEAN; - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: - return java.sql.Types.TINYINT; - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: - return java.sql.Types.SMALLINT; - case TSDBConstants.TSDB_DATA_TYPE_INT: - return java.sql.Types.INTEGER; - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: - return java.sql.Types.BIGINT; - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: - return java.sql.Types.FLOAT; - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: - return java.sql.Types.DOUBLE; - case TSDBConstants.TSDB_DATA_TYPE_BINARY: - return Types.BINARY; - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: - return java.sql.Types.TIMESTAMP; - case TSDBConstants.TSDB_DATA_TYPE_NCHAR: - return Types.NCHAR; - } - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE); + return TSDBConstants.taosType2JdbcType(meta.getColType()); } public String getColumnTypeName(int column) throws SQLException { ColumnMetaData meta = this.colMetaDataList.get(column - 1); - return TSDBConstants.DATATYPE_MAP.get(meta.getColType()); + return TSDBConstants.taosType2JdbcTypeName(meta.getColType()); } public boolean isReadOnly(int column) throws SQLException { diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java index 6518bf10e444a05073206e1ef72b8f21a87e26b1..44d760897b2cdac20c510e0c3f98910f25ac40d8 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java @@ -14,208 +14,322 @@ *****************************************************************************/ package com.taosdata.jdbc; +import java.math.BigDecimal; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Collections; public class TSDBResultSetRowData { - private ArrayList data = null; - private int colSize = 0; - - public TSDBResultSetRowData(int colSize) { - this.setColSize(colSize); - } - - public TSDBResultSetRowData() { - this.data = new ArrayList<>(); - this.setColSize(0); - } - - public void clear() { - if(this.data != null) { - this.data.clear(); - } - if (this.colSize == 0) { - return; - } - this.data = new ArrayList<>(colSize); - this.data.addAll(Collections.nCopies(this.colSize, null)); - } - - public boolean wasNull(int col) { - return data.get(col) == null; - } - - public void setBoolean(int col, boolean value) { - data.set(col, value); - } - - public boolean getBoolean(int col, int srcType) throws SQLException { - Object obj = data.get(col); - - switch(srcType) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: return (Boolean) obj; - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return ((Float) obj) == 1.0? Boolean.TRUE:Boolean.FALSE; - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: return ((Double) obj) == 1.0? Boolean.TRUE:Boolean.FALSE; - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: return ((Byte) obj) == 1? Boolean.TRUE:Boolean.FALSE; - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:return ((Short)obj) == 1? Boolean.TRUE:Boolean.FALSE; - case TSDBConstants.TSDB_DATA_TYPE_INT: return ((Integer)obj) == 1? Boolean.TRUE:Boolean.FALSE; - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return ((Long) obj) == 1L? Boolean.TRUE:Boolean.FALSE; - } - - return Boolean.TRUE; - } - - public void setByte(int col, byte value) { - data.set(col, value); - } - - public void setShort(int col, short value) { - data.set(col, value); - } - - public void setInt(int col, int value) { - data.set(col, value); - } - - public int getInt(int col, int srcType) throws SQLException { - Object obj = data.get(col); - - switch(srcType) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0; - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return ((Float) obj).intValue(); - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: return ((Double)obj).intValue(); - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: return (Byte) obj; - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:return (Short) obj; - case TSDBConstants.TSDB_DATA_TYPE_INT: return (Integer) obj; - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return ((Long) obj).intValue(); - case TSDBConstants.TSDB_DATA_TYPE_NCHAR: - case TSDBConstants.TSDB_DATA_TYPE_BINARY: return Integer.parseInt((String) obj); - } - - return 0; - } - - public void setLong(int col, long value) { - data.set(col, value); - } - - public long getLong(int col, int srcType) throws SQLException { - Object obj = data.get(col); - - switch(srcType) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0; - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return ((Float) obj).longValue(); - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: return ((Double) obj).longValue(); - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: return (Byte) obj; - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:return (Short) obj; - case TSDBConstants.TSDB_DATA_TYPE_INT: return (Integer) obj; - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return (Long) obj; - case TSDBConstants.TSDB_DATA_TYPE_NCHAR: - case TSDBConstants.TSDB_DATA_TYPE_BINARY: return Long.parseLong((String) obj); - } - - return 0; - } - - public void setFloat(int col, float value) { - data.set(col, value); - } - - public float getFloat(int col, int srcType) throws SQLException { - Object obj = data.get(col); - - switch(srcType) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0; - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return (Float) obj; - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: return ((Double) obj).floatValue(); - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: return (Byte) obj; - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: return (Short) obj; - case TSDBConstants.TSDB_DATA_TYPE_INT: return (Integer) obj; - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return (Long) obj; - } - - return 0; - } - - public void setDouble(int col, double value) { - data.set(col, value); - } - - public double getDouble(int col, int srcType) throws SQLException { - Object obj = data.get(col); - - switch(srcType) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: return Boolean.TRUE.equals(obj)? 1:0; - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return (Float) obj; - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: return (Double) obj; - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: return (Byte) obj; - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT:return (Short) obj; - case TSDBConstants.TSDB_DATA_TYPE_INT: return (Integer) obj; - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return (Long) obj; - } - - return 0; - } - - public void setString(int col, String value) { - data.set(col, value); - } - - public void setByteArray(int col, byte[] value) { + private ArrayList data = null; + private int colSize = 0; + + public TSDBResultSetRowData(int colSize) { + this.setColSize(colSize); + } + + public TSDBResultSetRowData() { + this.data = new ArrayList<>(); + this.setColSize(0); + } + + public void clear() { + if (this.data != null) { + this.data.clear(); + } + if (this.colSize == 0) { + return; + } + this.data = new ArrayList<>(colSize); + this.data.addAll(Collections.nCopies(this.colSize, null)); + } + + public boolean wasNull(int col) { + return data.get(col) == null; + } + + public void setBoolean(int col, boolean value) { + data.set(col, value); + } + + public boolean getBoolean(int col, int srcType) throws SQLException { + Object obj = data.get(col); + + switch (srcType) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + return (Boolean) obj; + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + return ((Float) obj) == 1.0 ? Boolean.TRUE : Boolean.FALSE; + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: + return ((Double) obj) == 1.0 ? Boolean.TRUE : Boolean.FALSE; + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + return ((Byte) obj) == 1 ? Boolean.TRUE : Boolean.FALSE; + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + return ((Short) obj) == 1 ? Boolean.TRUE : Boolean.FALSE; + case TSDBConstants.TSDB_DATA_TYPE_INT: + return ((Integer) obj) == 1 ? Boolean.TRUE : Boolean.FALSE; + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + return ((Long) obj) == 1L ? Boolean.TRUE : Boolean.FALSE; + } + + return Boolean.TRUE; + } + + public void setByte(int col, byte value) { + data.set(col, value); + } + + public void setShort(int col, short value) { + data.set(col, value); + } + + public void setInt(int col, int value) { + data.set(col, value); + } + + public int getInt(int col, int srcType) throws SQLException { + Object obj = data.get(col); + + switch (srcType) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + return Boolean.TRUE.equals(obj) ? 1 : 0; + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + return ((Float) obj).intValue(); + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: + return ((Double) obj).intValue(); + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + return (Byte) obj; + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + return (Short) obj; + case TSDBConstants.TSDB_DATA_TYPE_INT: + return (Integer) obj; + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + return ((Long) obj).intValue(); + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: + return Integer.parseInt((String) obj); + case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: { + Byte value = (byte) obj; + if (value < 0) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); + return value; + } + case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: { + short value = (short) obj; + if (value < 0) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); + return value; + } + case TSDBConstants.TSDB_DATA_TYPE_UINT: { + int value = (int) obj; + if (value < 0) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); + return value; + } + case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: { + long value = (long) obj; + if (value < 0) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); + return new Long(value).intValue(); + } + } + + return 0; + } + + public void setLong(int col, long value) { + data.set(col, value); + } + + public long getLong(int col, int srcType) throws SQLException { + Object obj = data.get(col); + + switch (srcType) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + return Boolean.TRUE.equals(obj) ? 1 : 0; + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + return ((Float) obj).longValue(); + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: + return ((Double) obj).longValue(); + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + return (Byte) obj; + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + return (Short) obj; + case TSDBConstants.TSDB_DATA_TYPE_INT: + return (Integer) obj; + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + return (Long) obj; + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: + return Long.parseLong((String) obj); + case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: { + Byte value = (byte) obj; + if (value < 0) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); + return value; + } + case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: { + short value = (short) obj; + if (value < 0) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); + return value; + } + case TSDBConstants.TSDB_DATA_TYPE_UINT: { + int value = (int) obj; + if (value < 0) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); + return value; + } + case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: { + long value = (long) obj; + if (value < 0) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE); + return value; + } + } + + return 0; + } + + public void setFloat(int col, float value) { + data.set(col, value); + } + + public float getFloat(int col, int srcType) throws SQLException { + Object obj = data.get(col); + + switch (srcType) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + return Boolean.TRUE.equals(obj) ? 1 : 0; + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + return (Float) obj; + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: + return ((Double) obj).floatValue(); + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + return (Byte) obj; + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + return (Short) obj; + case TSDBConstants.TSDB_DATA_TYPE_INT: + return (Integer) obj; + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + return (Long) obj; + } + + return 0; + } + + public void setDouble(int col, double value) { + data.set(col, value); + } + + public double getDouble(int col, int srcType) throws SQLException { + Object obj = data.get(col); + + switch (srcType) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + return Boolean.TRUE.equals(obj) ? 1 : 0; + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + return (Float) obj; + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: + return (Double) obj; + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + return (Byte) obj; + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + return (Short) obj; + case TSDBConstants.TSDB_DATA_TYPE_INT: + return (Integer) obj; + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + return (Long) obj; + } + + return 0; + } + + public void setString(int col, String value) { + data.set(col, value); + } + + public void setByteArray(int col, byte[] value) { try { data.set(col, new String(value, TaosGlobalConfig.getCharset())); } catch (Exception e) { e.printStackTrace(); } - } - - /** - * The original type may not be a string type, but will be converted to by calling this method - * @param col column index - * @return - * @throws SQLException - */ - public String getString(int col, int srcType) throws SQLException { - if (srcType == TSDBConstants.TSDB_DATA_TYPE_BINARY || srcType == TSDBConstants.TSDB_DATA_TYPE_NCHAR) { - return (String) data.get(col); - } else { - return String.valueOf(data.get(col)); - } - } - - public void setTimestamp(int col, long ts) { - data.set(col, ts); - } - - public Timestamp getTimestamp(int col) { - return new Timestamp((Long) data.get(col)); - } - - public Object get(int col) { - return data.get(col); - } - - public int getColSize() { - return colSize; - } - - public void setColSize(int colSize) { - this.colSize = colSize; - this.clear(); - } - - public ArrayList getData() { - return data; - } - - public void setData(ArrayList data) { - this.data = (ArrayList) data.clone(); - } + } + + /** + * The original type may not be a string type, but will be converted to by calling this method + * + * @param col column index + * @return + * @throws SQLException + */ + public String getString(int col, int srcType) throws SQLException { + switch (srcType) { + case TSDBConstants.TSDB_DATA_TYPE_BINARY: + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + return (String) data.get(col); + case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: { + Byte value = new Byte(String.valueOf(data.get(col))); + if (value >= 0) + return value.toString(); + return Integer.toString(value & 0xff); + } + case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: { + Short value = new Short(String.valueOf(data.get(col))); + if (value >= 0) + return value.toString(); + return Integer.toString(value & 0xffff); + } + case TSDBConstants.TSDB_DATA_TYPE_UINT: { + Integer value = new Integer(String.valueOf(data.get(col))); + if (value >= 0) + return value.toString(); + return Long.toString(value & 0xffffffffl); + } + case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: { + Long value = new Long(String.valueOf(data.get(col))); + if (value >= 0) + return value.toString(); + long lowValue = value & 0x7fffffffffffffffL; + return BigDecimal.valueOf(lowValue).add(BigDecimal.valueOf(Long.MAX_VALUE)).add(BigDecimal.valueOf(1)).toString(); + } + default: + return String.valueOf(data.get(col)); + } + } + + public void setTimestamp(int col, long ts) { + data.set(col, ts); + } + + public Timestamp getTimestamp(int col) { + return new Timestamp((Long) data.get(col)); + } + + public Object get(int col) { + return data.get(col); + } + + public int getColSize() { + return colSize; + } + + public void setColSize(int colSize) { + this.colSize = colSize; + this.clear(); + } + + public ArrayList getData() { + return data; + } + + public void setData(ArrayList data) { + this.data = (ArrayList) data.clone(); + } } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java index 29e849049e8ec0206ca3fe906f86534ecf7fd53a..fb20a621b0f11413e13e4234be357f6456a2a4fa 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java @@ -51,7 +51,6 @@ public class TSDBStatement extends AbstractStatement { this.connector.freeResultSet(pSql); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY); } - TSDBResultSet res = new TSDBResultSet(this, this.connector, pSql); res.setBatchFetch(this.connection.getBatchFetch()); return res; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBSubscribe.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBSubscribe.java index dd0d0d5b7b2744e0e6d28a3d73ec2b29fab37743..c5fd497ca3dfed8bc8555110660ff70a9fd23447 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBSubscribe.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBSubscribe.java @@ -21,27 +21,23 @@ public class TSDBSubscribe { private final long id; TSDBSubscribe(TSDBJNIConnector connecter, long id) throws SQLException { - if (null != connecter) { - this.connecter = connecter; - this.id = id; - } else { - throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); - } + if (connecter == null) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL); + + this.connecter = connecter; + this.id = id; } /** * consume - * */ public TSDBResultSet consume() throws SQLException { - if (this.connecter.isClosed()) { - throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); - } + if (this.connecter.isClosed()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL); long resultSetPointer = this.connecter.consume(this.id); - if (resultSetPointer == TSDBConstants.JNI_CONNECTION_NULL) { - throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL); } else if (resultSetPointer == TSDBConstants.JNI_NULL_POINTER) { return null; } else { @@ -56,9 +52,9 @@ public class TSDBSubscribe { * @throws SQLException */ public void close(boolean keepProgress) throws SQLException { - if (this.connecter.isClosed()) { - throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); - } + if (this.connecter.isClosed()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL); + this.connecter.unsubscribe(this.id, keepProgress); } } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java index 0484701f68f317dab2a1415b321d093d488c5b6a..c1834a7b804428ab3875b8e6937223b651cd217f 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java @@ -27,7 +27,6 @@ public class RestfulConnection extends AbstractConnection { public Statement createStatement() throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_CONNECTION_CLOSED); - ; return new RestfulStatement(this, database); } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java index d45ca0c3a0bc4ea596b9e9577db33e8aa1bee696..a94cfa6e07c62ee9b163823aaad03bcc402bbffc 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java @@ -2,9 +2,7 @@ package com.taosdata.jdbc.rs; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; -import com.taosdata.jdbc.AbstractDriver; -import com.taosdata.jdbc.TSDBConstants; -import com.taosdata.jdbc.TSDBDriver; +import com.taosdata.jdbc.*; import com.taosdata.jdbc.utils.HttpClientPoolUtil; import java.io.UnsupportedEncodingException; @@ -21,15 +19,16 @@ public class RestfulDriver extends AbstractDriver { try { DriverManager.registerDriver(new RestfulDriver()); } catch (SQLException e) { - throw new RuntimeException(TSDBConstants.WrapErrMsg("can not register Restful JDBC driver"), e); + throw TSDBError.createRuntimeException(TSDBErrorNumbers.ERROR_URL_NOT_SET, e); } } @Override public Connection connect(String url, Properties info) throws SQLException { // throw SQLException if url is null - if (url == null) - throw new SQLException(TSDBConstants.WrapErrMsg("url is not set!")); + if (url == null || url.trim().isEmpty() || url.trim().replaceAll("\\s", "").isEmpty()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_URL_NOT_SET); + // return null if url is not be accepted if (!acceptsURL(url)) return null; @@ -61,14 +60,20 @@ public class RestfulDriver extends AbstractDriver { throw new SQLException(jsonResult.getString("desc")); } - return new RestfulConnection(host, port, props, database, url); + RestfulConnection conn = new RestfulConnection(host, port, props, database, url); + if (database != null && !database.trim().replaceAll("\\s", "").isEmpty()) { + Statement stmt = conn.createStatement(); + stmt.execute("use " + database); + stmt.close(); + } + return conn; } @Override 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); + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_URL_NOT_SET); + return url.length() > 0 && url.trim().length() > 0 && url.startsWith(URL_PREFIX); } @Override diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java index 9d394b8b038917d637ab43826d57e4d79b1746c7..0cbb40dbb69f9e3b6b8fb2cc5bfd6ddac6ea4aef 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java @@ -9,7 +9,6 @@ import com.taosdata.jdbc.TSDBErrorNumbers; import java.sql.*; import java.util.ArrayList; -import java.util.List; public class RestfulResultSet extends AbstractResultSet implements ResultSet { private volatile boolean isClosed; @@ -17,8 +16,9 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { private final String database; private final Statement statement; +// private final JSONObject resultJson; // data - private ArrayList> resultSet; + private final ArrayList> resultSet; // meta private ArrayList columnNames; private ArrayList columns; @@ -32,6 +32,8 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { public RestfulResultSet(String database, Statement statement, JSONObject resultJson) throws SQLException { this.database = database; this.statement = statement; +// this.resultJson = resultJson; + // column metadata JSONArray columnMeta = resultJson.getJSONArray("column_meta"); columnNames = new ArrayList<>(); @@ -39,10 +41,11 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { for (int colIndex = 0; colIndex < columnMeta.size(); colIndex++) { JSONArray col = columnMeta.getJSONArray(colIndex); String col_name = col.getString(0); - int col_type = TSDBConstants.taosType2JdbcType(col.getInteger(1)); + int taos_type = col.getInteger(1); + int col_type = TSDBConstants.taosType2JdbcType(taos_type); int col_length = col.getInteger(2); columnNames.add(col_name); - columns.add(new Field(col_name, col_type, col_length, "")); + columns.add(new Field(col_name, col_type, col_length, "", taos_type)); } this.metaData = new RestfulResultSetMetaData(this.database, columns, this); @@ -53,105 +56,50 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { ArrayList row = new ArrayList(); JSONArray jsonRow = data.getJSONArray(rowIndex); for (int colIndex = 0; colIndex < jsonRow.size(); colIndex++) { - row.add(parseColumnData(jsonRow, colIndex, columns.get(colIndex).type)); + row.add(parseColumnData(jsonRow, colIndex, columns.get(colIndex).taos_type)); } resultSet.add(row); } - - /* - int columnIndex = 0; - for (; columnIndex < data.size(); columnIndex++) { - ArrayList oneRow = new ArrayList<>(); - JSONArray one = data.getJSONArray(columnIndex); - for (int j = 0; j < one.size(); j++) { - oneRow.add(one.getString(j)); - } - resultSet.add(oneRow); - } - - // column only names - JSONArray head = resultJson.getJSONArray("head"); - for (int i = 0; i < head.size(); i++) { - String name = head.getString(i); - columnNames.add(name); - columns.add(new Field(name, "", 0, "")); - } - this.metaData = new RestfulResultSetMetaData(this.database, columns, this); - */ } - private Object parseColumnData(JSONArray row, int colIndex, int sqlType) { - switch (sqlType) { - case Types.NULL: - return null; - case Types.BOOLEAN: + private Object parseColumnData(JSONArray row, int colIndex, int taosType) { + switch (taosType) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: return row.getBoolean(colIndex); - case Types.TINYINT: - case Types.SMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + return row.getByte(colIndex); + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: return row.getShort(colIndex); - case Types.INTEGER: + case TSDBConstants.TSDB_DATA_TYPE_INT: return row.getInteger(colIndex); - case Types.BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: return row.getBigInteger(colIndex); - case Types.FLOAT: + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: return row.getFloat(colIndex); - case Types.DOUBLE: + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: return row.getDouble(colIndex); - case Types.TIMESTAMP: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: return new Timestamp(row.getDate(colIndex).getTime()); - case Types.BINARY: - case Types.NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: default: return row.getString(colIndex); } } -// /** -// * 由多个resultSet的JSON构造结果集 -// * -// * @param resultJson: 包含data信息的结果集,有sql返回的结果集 -// * @param fieldJson: 包含多个(最多2个)meta信息的结果集,有describe xxx -// **/ -// public RestfulResultSet(String database, Statement statement, JSONObject resultJson, List fieldJson) throws SQLException { -// this(database, statement, resultJson); -// ArrayList newColumns = new ArrayList<>(); -// -// for (Field column : columns) { -// Field field = findField(column.name, fieldJson); -// if (field != null) { -// newColumns.add(field); -// } else { -// newColumns.add(column); -// } -// } -// this.columns = newColumns; -// this.metaData = new RestfulResultSetMetaData(this.database, this.columns, this); -// } - -// public Field findField(String columnName, List fieldJsonList) { -// for (JSONObject fieldJSON : fieldJsonList) { -// JSONArray fieldDataJson = fieldJSON.getJSONArray("data"); -// for (int i = 0; i < fieldDataJson.size(); i++) { -// JSONArray field = fieldDataJson.getJSONArray(i); -// if (columnName.equalsIgnoreCase(field.getString(0))) { -// return new Field(field.getString(0), field.getString(1), field.getInteger(2), field.getString(3)); -// } -// } -// } -// return null; -// } - public class Field { String name; int type; int length; String note; + int taos_type; - public Field(String name, int type, int length, String note) { + public Field(String name, int type, int length, String note, int taos_type) { this.name = name; this.type = type; this.length = length; this.note = note; + this.taos_type = taos_type; } } @@ -184,53 +132,119 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { public String getString(int columnIndex) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); - - if (columnIndex > resultSet.get(pos).size()) { - throw new SQLException(TSDBConstants.WrapErrMsg("Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size())); - } + if (columnIndex > resultSet.get(pos).size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size()); columnIndex = getTrueColumnIndex(columnIndex); - return resultSet.get(pos).get(columnIndex).toString(); + Object value = resultSet.get(pos).get(columnIndex); + return value == null ? null : value.toString(); } @Override public boolean getBoolean(int columnIndex) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); + if (columnIndex > resultSet.get(pos).size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size()); columnIndex = getTrueColumnIndex(columnIndex); int result = getInt(columnIndex); return result == 0 ? false : true; } + @Override + public byte getByte(int columnIndex) throws SQLException { + if (isClosed()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); + if (columnIndex > resultSet.get(pos).size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size()); + + columnIndex = getTrueColumnIndex(columnIndex); + Object value = resultSet.get(pos).get(columnIndex); + if (value == null) + return 0; + long valueAsLong = Long.parseLong(value.toString()); + if (valueAsLong == Byte.MIN_VALUE) + return 0; + if (valueAsLong < Byte.MIN_VALUE || valueAsLong > Byte.MAX_VALUE) + throwRangeException(value.toString(), columnIndex, Types.TINYINT); + + return (byte) valueAsLong; + } + + private void throwRangeException(String valueAsString, int columnIndex, int jdbcType) throws SQLException { + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE, + "'" + valueAsString + "' in column '" + columnIndex + "' is outside valid range for the jdbcType " + TSDBConstants.jdbcType2TaosTypeName(jdbcType)); + } + @Override public short getShort(int columnIndex) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); + if (columnIndex > resultSet.get(pos).size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size()); + columnIndex = getTrueColumnIndex(columnIndex); - return Short.parseShort(resultSet.get(pos).get(columnIndex).toString()); + Object value = resultSet.get(pos).get(columnIndex); + if (value == null) + return 0; + long valueAsLong = Long.parseLong(value.toString()); + if (valueAsLong == Short.MIN_VALUE) + return 0; + if (valueAsLong < Short.MIN_VALUE || valueAsLong > Short.MAX_VALUE) + throwRangeException(value.toString(), columnIndex, Types.SMALLINT); + return (short) valueAsLong; } @Override public int getInt(int columnIndex) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); + if (columnIndex > resultSet.get(pos).size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size()); + columnIndex = getTrueColumnIndex(columnIndex); - return Integer.parseInt(resultSet.get(pos).get(columnIndex).toString()); + Object value = resultSet.get(pos).get(columnIndex); + if (value == null) + return 0; + long valueAsLong = Long.parseLong(value.toString()); + if (valueAsLong == Integer.MIN_VALUE) + return 0; + if (valueAsLong < Integer.MIN_VALUE || valueAsLong > Integer.MAX_VALUE) + throwRangeException(value.toString(), columnIndex, Types.INTEGER); + return (int) valueAsLong; } @Override public long getLong(int columnIndex) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); + if (columnIndex > resultSet.get(pos).size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size()); + columnIndex = getTrueColumnIndex(columnIndex); - return Long.parseLong(resultSet.get(pos).get(columnIndex).toString()); + Object value = resultSet.get(pos).get(columnIndex); + if (value == null) + return 0; + + long valueAsLong = 0; + try { + valueAsLong = Long.parseLong(value.toString()); + if (valueAsLong == Long.MIN_VALUE) + return 0; + } catch (NumberFormatException e) { + throwRangeException(value.toString(), columnIndex, Types.BIGINT); + } + return valueAsLong; } @Override public float getFloat(int columnIndex) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); + if (columnIndex > resultSet.get(pos).size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size()); + columnIndex = getTrueColumnIndex(columnIndex); return Float.parseFloat(resultSet.get(pos).get(columnIndex).toString()); } @@ -239,6 +253,8 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { public double getDouble(int columnIndex) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESULTSET_CLOSED); + if (columnIndex > resultSet.get(pos).size()) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE, "Column Index out of range, " + columnIndex + " > " + resultSet.get(pos).size()); columnIndex = getTrueColumnIndex(columnIndex); return Double.parseDouble(resultSet.get(pos).get(columnIndex).toString()); @@ -246,12 +262,14 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet { private int getTrueColumnIndex(int columnIndex) throws SQLException { if (columnIndex < 1) { - throw new SQLException("Column Index out of range, " + columnIndex + " < 1"); + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE + , "Column Index out of range, " + columnIndex + " < 1"); } int numOfCols = resultSet.get(pos).size(); if (columnIndex > numOfCols) { - throw new SQLException("Column Index out of range, " + columnIndex + " > " + numOfCols); + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PARAMETER_INDEX_OUT_RANGE + , "Column Index out of range, " + columnIndex + " > " + numOfCols); } return columnIndex - 1; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSetMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSetMetaData.java index 29ba13bec107be4564a95d27e800fce53b114f96..7ead8bd1bbaeeb8fe1f24c951656888f6bba6b6f 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSetMetaData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSetMetaData.java @@ -1,6 +1,7 @@ package com.taosdata.jdbc.rs; import com.taosdata.jdbc.TSDBConstants; +import com.taosdata.jdbc.WrapperImpl; import java.sql.ResultSetMetaData; import java.sql.SQLException; @@ -8,7 +9,7 @@ import java.sql.Timestamp; import java.sql.Types; import java.util.ArrayList; -public class RestfulResultSetMetaData implements ResultSetMetaData { +public class RestfulResultSetMetaData extends WrapperImpl implements ResultSetMetaData { private final String database; private ArrayList fields; @@ -20,6 +21,10 @@ public class RestfulResultSetMetaData implements ResultSetMetaData { this.resultSet = resultSet; } + public ArrayList getFields() { + return fields; + } + @Override public int getColumnCount() throws SQLException { return fields.size(); @@ -134,8 +139,8 @@ public class RestfulResultSetMetaData implements ResultSetMetaData { @Override public String getColumnTypeName(int column) throws SQLException { - int type = fields.get(column - 1).type; - return TSDBConstants.jdbcType2TaosTypeName(type); + int taos_type = fields.get(column - 1).taos_type; + return TSDBConstants.taosType2JdbcTypeName(taos_type); } @Override @@ -180,18 +185,4 @@ public class RestfulResultSetMetaData implements ResultSetMetaData { return columnClassName; } - @Override - public T unwrap(Class iface) throws SQLException { - try { - return iface.cast(this); - } catch (ClassCastException cce) { - throw new SQLException("Unable to unwrap to " + iface.toString()); - } - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - return iface.isInstance(this); - } - } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java index d60940d87762340203e54fb7df23579c2f93d510..9071c046726a0ef7df3f712ac3ddbb10d3afafba 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java @@ -4,17 +4,14 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.taosdata.jdbc.AbstractStatement; -import com.taosdata.jdbc.TSDBConstants; import com.taosdata.jdbc.TSDBError; import com.taosdata.jdbc.TSDBErrorNumbers; import com.taosdata.jdbc.utils.HttpClientPoolUtil; import com.taosdata.jdbc.utils.SqlSyntaxValidator; -import java.sql.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; public class RestfulStatement extends AbstractStatement { @@ -30,39 +27,6 @@ public class RestfulStatement extends AbstractStatement { this.database = database; } - protected String[] parseTableIdentifier(String sql) { - sql = sql.trim().toLowerCase(); - String[] ret = null; - if (sql.contains("where")) - sql = sql.substring(0, sql.indexOf("where")); - if (sql.contains("interval")) - sql = sql.substring(0, sql.indexOf("interval")); - if (sql.contains("fill")) - sql = sql.substring(0, sql.indexOf("fill")); - if (sql.contains("sliding")) - sql = sql.substring(0, sql.indexOf("sliding")); - if (sql.contains("group by")) - sql = sql.substring(0, sql.indexOf("group by")); - if (sql.contains("order by")) - sql = sql.substring(0, sql.indexOf("order by")); - if (sql.contains("slimit")) - sql = sql.substring(0, sql.indexOf("slimit")); - if (sql.contains("limit")) - sql = sql.substring(0, sql.indexOf("limit")); - // parse - if (sql.contains("from")) { - sql = sql.substring(sql.indexOf("from") + 4).trim(); - return Arrays.asList(sql.split(",")).stream() - .map(tableIdentifier -> { - tableIdentifier = tableIdentifier.trim(); - if (tableIdentifier.contains(" ")) - tableIdentifier = tableIdentifier.substring(0, tableIdentifier.indexOf(" ")); - return tableIdentifier; - }).collect(Collectors.joining(",")).split(","); - } - return ret; - } - @Override public ResultSet executeQuery(String sql) throws SQLException { if (isClosed()) @@ -75,9 +39,8 @@ public class RestfulStatement extends AbstractStatement { return executeOneQuery(url, sql); } -// if (this.database == null || this.database.isEmpty()) -// throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_DATABASE_NOT_SPECIFIED_OR_AVAILABLE); - HttpClientPoolUtil.execute(url, "use " + this.database); +// if (this.database != null && !this.database.trim().replaceAll("\\s","").isEmpty()) +// HttpClientPoolUtil.execute(url, "use " + this.database); return executeOneQuery(url, sql); } @@ -93,10 +56,8 @@ public class RestfulStatement extends AbstractStatement { return executeOneUpdate(url, sql); } -// if (this.database == null || this.database.isEmpty()) -// throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_DATABASE_NOT_SPECIFIED_OR_AVAILABLE); - - HttpClientPoolUtil.execute(url, "use " + this.database); +// if (this.database != null && !this.database.trim().replaceAll("\\s", "").isEmpty()) +// HttpClientPoolUtil.execute(url, "use " + this.database); return executeOneUpdate(url, sql); } @@ -148,24 +109,9 @@ public class RestfulStatement extends AbstractStatement { String result = HttpClientPoolUtil.execute(url, sql); JSONObject resultJson = JSON.parseObject(result); if (resultJson.getString("status").equals("error")) { - throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " + resultJson.getString("desc") + "\n" + "error code: " + resultJson.getString("code"))); + throw TSDBError.createSQLException(resultJson.getInteger("code"), resultJson.getString("desc")); } - // parse table name from sql -// String[] tableIdentifiers = parseTableIdentifier(sql); -// if (tableIdentifiers != null) { -// List fieldJsonList = new ArrayList<>(); -// for (String tableIdentifier : tableIdentifiers) { -// String fields = HttpClientPoolUtil.execute(url, "DESCRIBE " + tableIdentifier); -// JSONObject fieldJson = JSON.parseObject(fields); -// if (fieldJson.getString("status").equals("error")) { -// throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " + fieldJson.getString("desc") + "\n" + "error code: " + fieldJson.getString("code"))); -// } -// fieldJsonList.add(fieldJson); -// } -// this.resultSet = new RestfulResultSet(database, this, resultJson, fieldJsonList); -// } else { this.resultSet = new RestfulResultSet(database, this, resultJson); -// } this.affectedRows = 0; return resultSet; } @@ -177,7 +123,7 @@ public class RestfulStatement extends AbstractStatement { String result = HttpClientPoolUtil.execute(url, sql); JSONObject jsonObject = JSON.parseObject(result); if (jsonObject.getString("status").equals("error")) { - throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " + jsonObject.getString("desc") + "\n" + "error code: " + jsonObject.getString("code"))); + throw TSDBError.createSQLException(jsonObject.getInteger("code"), jsonObject.getString("desc")); } this.resultSet = null; this.affectedRows = checkJsonResultSet(jsonObject); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBJNIConnectorTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBJNIConnectorTest.java index aba95f65b7d618d8f008cad986dd879f5113724c..161539962da5e26e928a669083954cc0817483a2 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBJNIConnectorTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBJNIConnectorTest.java @@ -15,12 +15,12 @@ public class TSDBJNIConnectorTest { public void test() { try { // init - TSDBJNIConnector.init(null, null, null, null); + TSDBJNIConnector.init("/etc/taos/taos.cfg", null, null, null); // connect TSDBJNIConnector connector = new TSDBJNIConnector(); - connector.connect("127.0.0.1", 6030, null, "root", "taosdata"); + connector.connect("127.0.0.1", 6030, "unsign_jni", "root", "taosdata"); // executeQuery - long pSql = connector.executeQuery("show variables"); + long pSql = connector.executeQuery("select * from unsign_jni.us_table"); if (connector.isUpdateQuery(pSql)) { connector.freeResultSet(pSql); throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY); @@ -29,13 +29,13 @@ public class TSDBJNIConnectorTest { List columnMetaDataList = new ArrayList<>(); int code = connector.getSchemaMetaData(pSql, 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); } int columnSize = columnMetaDataList.size(); // print metadata diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertDbwithoutUseDbTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertDbwithoutUseDbTest.java new file mode 100644 index 0000000000000000000000000000000000000000..54ee8fd6ebafbb18dfcfbab99503c1c30f148dc8 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertDbwithoutUseDbTest.java @@ -0,0 +1,92 @@ +package com.taosdata.jdbc.cases; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import java.sql.*; +import java.util.Properties; +import java.util.Random; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class InsertDbwithoutUseDbTest { + + private static String host = "127.0.0.1"; + // private static String host = "master"; + private static Properties properties; + private static Random random = new Random(System.currentTimeMillis()); + + @Test + public void case001() throws ClassNotFoundException, SQLException { + // prepare schema + Class.forName("com.taosdata.jdbc.TSDBDriver"); + String url = "jdbc:TAOS://127.0.0.1:6030/?user=root&password=taosdata"; + Connection conn = DriverManager.getConnection(url, properties); + try (Statement stmt = conn.createStatement()) { + stmt.execute("drop database if exists inWithoutDb"); + stmt.execute("create database if not exists inWithoutDb"); + stmt.execute("create table inWithoutDb.weather(ts timestamp, f1 int)"); + } + conn.close(); + + // execute insert + url = "jdbc:TAOS://127.0.0.1:6030/inWithoutDb?user=root&password=taosdata"; + conn = DriverManager.getConnection(url, properties); + try (Statement stmt = conn.createStatement()) { + int affectedRow = stmt.executeUpdate("insert into weather(ts, f1) values(now," + random.nextInt(100) + ")"); + Assert.assertEquals(1, affectedRow); + boolean flag = stmt.execute("insert into weather(ts, f1) values(now + 10s," + random.nextInt(100) + ")"); + Assert.assertEquals(false, flag); + ResultSet rs = stmt.executeQuery("select count(*) from weather"); + rs.next(); + int count = rs.getInt("count(*)"); + Assert.assertEquals(2, count); + + } catch (SQLException e) { + e.printStackTrace(); + } + + conn.close(); + } + + @Test + public void case002() throws ClassNotFoundException, SQLException { + // prepare the schema + Class.forName("com.taosdata.jdbc.rs.RestfulDriver"); + final String url = "jdbc:TAOS-RS://" + host + ":6041/inWithoutDb?user=root&password=taosdata"; + Connection conn = DriverManager.getConnection(url, properties); + try (Statement stmt = conn.createStatement()) { + stmt.execute("drop database if exists inWithoutDb"); + stmt.execute("create database if not exists inWithoutDb"); + stmt.execute("create table inWithoutDb.weather(ts timestamp, f1 int)"); + } + conn.close(); + + // execute + conn = DriverManager.getConnection(url, properties); + try (Statement stmt = conn.createStatement()) { + int affectedRow = stmt.executeUpdate("insert into weather(ts, f1) values(now," + random.nextInt(100) + ")"); + Assert.assertEquals(1, affectedRow); + boolean flag = stmt.execute("insert into weather(ts, f1) values(now + 10s," + random.nextInt(100) + ")"); + Assert.assertEquals(false, flag); + ResultSet rs = stmt.executeQuery("select count(*) from weather"); + rs.next(); + int count = rs.getInt("count(*)"); + Assert.assertEquals(2, count); + + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @BeforeClass + public static void beforeClass() { + properties = new Properties(); + properties.setProperty("charset", "UTF-8"); + properties.setProperty("locale", "en_US.UTF-8"); + properties.setProperty("timezone", "UTC-8"); + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberJniTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberJniTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d1816a3e7c84703e76a28e6b0e5db842de9c0ac4 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberJniTest.java @@ -0,0 +1,191 @@ +package com.taosdata.jdbc.cases; + +import com.taosdata.jdbc.TSDBDriver; +import org.junit.*; +import org.junit.runners.MethodSorters; + +import java.sql.*; +import java.util.Properties; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class UnsignedNumberJniTest { + private static final String host = "127.0.0.1"; + private static Connection conn; + + @Test + public void testCase001() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select * from us_table"); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + for (int i = 1; i <= meta.getColumnCount(); i++) { + System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); + } + System.out.println(); + Assert.assertEquals("127", rs.getString(2)); + Assert.assertEquals("32767", rs.getString(3)); + Assert.assertEquals("2147483647", rs.getString(4)); + Assert.assertEquals("9223372036854775807", rs.getString(5)); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void testCase002() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select * from us_table"); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + System.out.print(meta.getColumnLabel(1) + ": " + rs.getTimestamp(1) + "\t"); + System.out.print(meta.getColumnLabel(2) + ": " + rs.getByte(2) + "\t"); + System.out.print(meta.getColumnLabel(3) + ": " + rs.getShort(3) + "\t"); + System.out.print(meta.getColumnLabel(4) + ": " + rs.getInt(4) + "\t"); + System.out.print(meta.getColumnLabel(5) + ": " + rs.getLong(5) + "\t"); + System.out.println(); + Assert.assertEquals(127, rs.getByte(2)); + Assert.assertEquals(32767, rs.getShort(3)); + Assert.assertEquals(2147483647, rs.getInt(4)); + Assert.assertEquals(9223372036854775807l, rs.getLong(5)); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test(expected = SQLException.class) + public void testCase003() throws SQLException { + try (Statement stmt = conn.createStatement()) { + long now = System.currentTimeMillis(); + stmt.executeUpdate("insert into us_table(ts,f1,f2,f3,f4) values(" + now + ", 127, 32767,2147483647, 18446744073709551614)"); + ResultSet rs = stmt.executeQuery("select * from us_table where ts = " + now); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + System.out.print(meta.getColumnLabel(1) + ": " + rs.getTimestamp(1) + "\t"); + System.out.print(meta.getColumnLabel(2) + ": " + rs.getByte(2) + "\t"); + System.out.print(meta.getColumnLabel(3) + ": " + rs.getShort(3) + "\t"); + System.out.print(meta.getColumnLabel(4) + ": " + rs.getInt(4) + "\t"); + System.out.print(meta.getColumnLabel(5) + ": " + rs.getLong(5) + "\t"); + System.out.println(); + Assert.assertEquals(127, rs.getByte(2)); + Assert.assertEquals(32767, rs.getShort(3)); + Assert.assertEquals(2147483647, rs.getInt(4)); + } + } + } + + @Test(expected = SQLException.class) + public void testCase004() throws SQLException { + try (Statement stmt = conn.createStatement()) { + long now = System.currentTimeMillis(); + stmt.executeUpdate("insert into us_table(ts,f1,f2,f3,f4) values(" + now + ", 127, 32767,4294967294, 18446744073709551614)"); + ResultSet rs = stmt.executeQuery("select * from us_table where ts = " + now); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + System.out.print(meta.getColumnLabel(1) + ": " + rs.getTimestamp(1) + "\t"); + System.out.print(meta.getColumnLabel(2) + ": " + rs.getByte(2) + "\t"); + System.out.print(meta.getColumnLabel(3) + ": " + rs.getShort(3) + "\t"); + System.out.print(meta.getColumnLabel(4) + ": " + rs.getInt(4) + "\t"); + System.out.print(meta.getColumnLabel(5) + ": " + rs.getLong(5) + "\t"); + System.out.println(); + Assert.assertEquals(127, rs.getByte(2)); + Assert.assertEquals(32767, rs.getShort(3)); + } + } + } + + @Test(expected = SQLException.class) + public void testCase005() throws SQLException { + try (Statement stmt = conn.createStatement()) { + long now = System.currentTimeMillis(); + stmt.executeUpdate("insert into us_table(ts,f1,f2,f3,f4) values(" + now + ", 127, 65534,4294967294, 18446744073709551614)"); + ResultSet rs = stmt.executeQuery("select * from us_table where ts = " + now); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + System.out.print(meta.getColumnLabel(1) + ": " + rs.getTimestamp(1) + "\t"); + System.out.print(meta.getColumnLabel(2) + ": " + rs.getByte(2) + "\t"); + System.out.print(meta.getColumnLabel(3) + ": " + rs.getShort(3) + "\t"); + System.out.print(meta.getColumnLabel(4) + ": " + rs.getInt(4) + "\t"); + System.out.print(meta.getColumnLabel(5) + ": " + rs.getLong(5) + "\t"); + System.out.println(); + + Assert.assertEquals(127, rs.getByte(2)); + } + } + } + + @Test(expected = SQLException.class) + public void testCase006() throws SQLException { + try (Statement stmt = conn.createStatement()) { + long now = System.currentTimeMillis(); + stmt.executeUpdate("insert into us_table(ts,f1,f2,f3,f4) values(" + now + ", 254, 65534,4294967294, 18446744073709551614)"); + ResultSet rs = stmt.executeQuery("select * from us_table where ts = " + now); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + System.out.print(meta.getColumnLabel(1) + ": " + rs.getTimestamp(1) + "\t"); + System.out.print(meta.getColumnLabel(2) + ": " + rs.getByte(2) + "\t"); + System.out.print(meta.getColumnLabel(3) + ": " + rs.getShort(3) + "\t"); + System.out.print(meta.getColumnLabel(4) + ": " + rs.getInt(4) + "\t"); + System.out.print(meta.getColumnLabel(5) + ": " + rs.getLong(5) + "\t"); + System.out.println(); + } + } + } + + @Test + public void testCase007() throws SQLException { + try (Statement stmt = conn.createStatement()) { + long now = System.currentTimeMillis(); + stmt.executeUpdate("insert into us_table(ts,f1,f2,f3,f4) values(" + now + ", 254, 65534,4294967294, 18446744073709551614)"); + ResultSet rs = stmt.executeQuery("select * from us_table where ts = " + now); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + for (int i = 1; i <= meta.getColumnCount(); i++) { + System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); + } + System.out.println(); + Assert.assertEquals("254", rs.getString(2)); + Assert.assertEquals("65534", rs.getString(3)); + Assert.assertEquals("4294967294", rs.getString(4)); + Assert.assertEquals("18446744073709551614", rs.getString(5)); + } + } + } + + + @BeforeClass + public static void beforeClass() { + Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); + + try { + Class.forName("com.taosdata.jdbc.TSDBDriver"); + final String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"; + conn = DriverManager.getConnection(url, properties); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists unsign_jni"); + stmt.execute("create database if not exists unsign_jni"); + stmt.execute("use unsign_jni"); + stmt.execute("create table us_table(ts timestamp, f1 tinyint unsigned, f2 smallint unsigned, f3 int unsigned, f4 bigint unsigned)"); + stmt.executeUpdate("insert into us_table(ts,f1,f2,f3,f4) values(now, 127, 32767,2147483647, 9223372036854775807)"); + stmt.close(); + } catch (ClassNotFoundException | SQLException e) { + e.printStackTrace(); + } + } + + @AfterClass + public static void afterClass() { + try { + if (conn != null) + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberRestfulTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberRestfulTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d0e63067049d0cf739b4e9764af5d352f64f409c --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UnsignedNumberRestfulTest.java @@ -0,0 +1,177 @@ +package com.taosdata.jdbc.cases; + +import com.taosdata.jdbc.TSDBDriver; +import org.junit.*; +import org.junit.runners.MethodSorters; + +import java.sql.*; +import java.util.Properties; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class UnsignedNumberRestfulTest { + private static final String host = "127.0.0.1"; +// private static final String host = "master"; + private static Connection conn; + + @Test + public void testCase001() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select * from us_table"); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + for (int i = 1; i <= meta.getColumnCount(); i++) { + System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); + } + System.out.println(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void testCase002() { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select * from us_table"); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + System.out.print(meta.getColumnLabel(1) + ": " + rs.getTimestamp(1) + "\t"); + System.out.print(meta.getColumnLabel(2) + ": " + rs.getByte(2) + "\t"); + System.out.print(meta.getColumnLabel(3) + ": " + rs.getShort(3) + "\t"); + System.out.print(meta.getColumnLabel(4) + ": " + rs.getInt(4) + "\t"); + System.out.print(meta.getColumnLabel(5) + ": " + rs.getLong(5) + "\t"); + System.out.println(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test(expected = SQLException.class) + public void testCase003() throws SQLException { + try (Statement stmt = conn.createStatement()) { + long now = System.currentTimeMillis(); + stmt.executeUpdate("insert into us_table(ts,f1,f2,f3,f4) values(" + now + ", 127, 32767,2147483647, 18446744073709551614)"); + ResultSet rs = stmt.executeQuery("select * from us_table where ts = " + now); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + System.out.print(meta.getColumnLabel(1) + ": " + rs.getTimestamp(1) + "\t"); + System.out.print(meta.getColumnLabel(2) + ": " + rs.getByte(2) + "\t"); + System.out.print(meta.getColumnLabel(3) + ": " + rs.getShort(3) + "\t"); + System.out.print(meta.getColumnLabel(4) + ": " + rs.getInt(4) + "\t"); + System.out.print(meta.getColumnLabel(5) + ": " + rs.getLong(5) + "\t"); + System.out.println(); + } + } + } + + @Test(expected = SQLException.class) + public void testCase004() throws SQLException { + try (Statement stmt = conn.createStatement()) { + long now = System.currentTimeMillis(); + stmt.executeUpdate("insert into us_table(ts,f1,f2,f3,f4) values(" + now + ", 127, 32767,4294967294, 18446744073709551614)"); + ResultSet rs = stmt.executeQuery("select * from us_table where ts = " + now); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + System.out.print(meta.getColumnLabel(1) + ": " + rs.getTimestamp(1) + "\t"); + System.out.print(meta.getColumnLabel(2) + ": " + rs.getByte(2) + "\t"); + System.out.print(meta.getColumnLabel(3) + ": " + rs.getShort(3) + "\t"); + System.out.print(meta.getColumnLabel(4) + ": " + rs.getInt(4) + "\t"); + System.out.print(meta.getColumnLabel(5) + ": " + rs.getLong(5) + "\t"); + System.out.println(); + } + } + } + + @Test(expected = SQLException.class) + public void testCase005() throws SQLException { + try (Statement stmt = conn.createStatement()) { + long now = System.currentTimeMillis(); + stmt.executeUpdate("insert into us_table(ts,f1,f2,f3,f4) values(" + now + ", 127, 65534,4294967294, 18446744073709551614)"); + ResultSet rs = stmt.executeQuery("select * from us_table where ts = " + now); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + System.out.print(meta.getColumnLabel(1) + ": " + rs.getTimestamp(1) + "\t"); + System.out.print(meta.getColumnLabel(2) + ": " + rs.getByte(2) + "\t"); + System.out.print(meta.getColumnLabel(3) + ": " + rs.getShort(3) + "\t"); + System.out.print(meta.getColumnLabel(4) + ": " + rs.getInt(4) + "\t"); + System.out.print(meta.getColumnLabel(5) + ": " + rs.getLong(5) + "\t"); + System.out.println(); + } + } + } + + @Test(expected = SQLException.class) + public void testCase006() throws SQLException { + try (Statement stmt = conn.createStatement()) { + long now = System.currentTimeMillis(); + stmt.executeUpdate("insert into us_table(ts,f1,f2,f3,f4) values(" + now + ", 254, 65534,4294967294, 18446744073709551614)"); + ResultSet rs = stmt.executeQuery("select * from us_table where ts = " + now); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + System.out.print(meta.getColumnLabel(1) + ": " + rs.getTimestamp(1) + "\t"); + System.out.print(meta.getColumnLabel(2) + ": " + rs.getByte(2) + "\t"); + System.out.print(meta.getColumnLabel(3) + ": " + rs.getShort(3) + "\t"); + System.out.print(meta.getColumnLabel(4) + ": " + rs.getInt(4) + "\t"); + System.out.print(meta.getColumnLabel(5) + ": " + rs.getLong(5) + "\t"); + System.out.println(); + } + } + } + + @Test + public void testCase007() throws SQLException { + try (Statement stmt = conn.createStatement()) { + long now = System.currentTimeMillis(); + stmt.executeUpdate("insert into us_table(ts,f1,f2,f3,f4) values(" + now + ", 254, 65534,4294967294, 18446744073709551614)"); + ResultSet rs = stmt.executeQuery("select * from us_table where ts = " + now); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + for (int i = 1; i <= meta.getColumnCount(); i++) { + System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); + } + System.out.println(); + Assert.assertEquals("254", rs.getString(2)); + Assert.assertEquals("65534", rs.getString(3)); + Assert.assertEquals("4294967294", rs.getString(4)); + Assert.assertEquals("18446744073709551614", rs.getString(5)); + } + } + } + + @BeforeClass + public static void beforeClass() { + Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); + + try { + Class.forName("com.taosdata.jdbc.rs.RestfulDriver"); + final String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata"; + conn = DriverManager.getConnection(url, properties); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists unsign_restful"); + stmt.execute("create database if not exists unsign_restful"); + stmt.execute("use unsign_restful"); + stmt.execute("create table us_table(ts timestamp, f1 tinyint unsigned, f2 smallint unsigned, f3 int unsigned, f4 bigint unsigned)"); + stmt.executeUpdate("insert into us_table(ts,f1,f2,f3,f4) values(now, 127, 32767,2147483647, 9223372036854775807)"); + stmt.close(); + } catch (ClassNotFoundException | SQLException e) { + e.printStackTrace(); + } + } + + @AfterClass + public static void afterClass() { + try { + if (conn != null) + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetTest.java index b199eff1baab53d9c4a8c65f7e0bb58157657d33..a15b1964ea8301b5153a548b53c9fc8763cd65f5 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulResultSetTest.java @@ -40,9 +40,12 @@ public class RestfulResultSetTest { Assert.assertEquals(true, f9); } - @Test(expected = SQLFeatureNotSupportedException.class) + @Test public void getByte() throws SQLException { - rs.getByte(1); + byte f8 = rs.getByte("f8"); + Assert.assertEquals(10, f8); + f8 = rs.getByte(8); + Assert.assertEquals(10, f8); } @Test diff --git a/src/connector/odbc/.gitignore b/src/connector/odbc/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..bfef9b2efaaf8cf6071c42687a1c4c02688a9eee --- /dev/null +++ b/src/connector/odbc/.gitignore @@ -0,0 +1,3 @@ +!c/ +node_modules/ +package-lock.json diff --git a/src/connector/odbc/CMakeLists.txt b/src/connector/odbc/CMakeLists.txt index 0d8c07041aa741793b7a1b8db20c3a3b470cf193..5a93ac3f7e2934fd8383c5a18f22c24845793f1a 100644 --- a/src/connector/odbc/CMakeLists.txt +++ b/src/connector/odbc/CMakeLists.txt @@ -15,7 +15,7 @@ IF (TD_LINUX_64) message(STATUS "unixodbc/unixodbc-dev are installed, and odbc connector will be built") find_package(FLEX) if(NOT FLEX_FOUND) - message(FATAL_ERROR "you need to install flex first") + message(WARNING "you need to install flex first") else () if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0.0) message(WARNING "gcc 4.8.0 will complain too much about flex-generated code, we just bypass building ODBC driver in such case") @@ -24,7 +24,7 @@ IF (TD_LINUX_64) SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wconversion") ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(tools) - ADD_SUBDIRECTORY(tests) + ADD_SUBDIRECTORY(examples) endif () endif() endif() @@ -33,10 +33,44 @@ IF (TD_LINUX_64) ENDIF () ENDIF () +IF (TD_DARWIN) + find_program(HAVE_ODBCINST NAMES odbcinst) + IF (HAVE_ODBCINST) + include(CheckSymbolExists) + # shall we revert CMAKE_REQUIRED_LIBRARIES and how? + set(CMAKE_REQUIRED_LIBRARIES odbc) + set(CMAKE_REQUIRED_INCLUDES /usr/local/include) + set(CMAKE_REQUIRED_LINK_OPTIONS -L/usr/local/lib) + check_symbol_exists(SQLExecute "sql.h" HAVE_ODBC_DEV) + if(NOT (HAVE_ODBC_DEV)) + unset(HAVE_ODBC_DEV CACHE) + message(WARNING "unixodbc-dev is not installed yet, you may install it with homebrew by typing: brew install unixodbc") + else () + message(STATUS "unixodbc/unixodbc-dev are installed, and odbc connector will be built") + find_package(FLEX) + if(NOT FLEX_FOUND) + message(WARNING "you need to install flex first") + else () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0.0) + message(WARNING "gcc 4.8.0 will complain too much about flex-generated code, we just bypass building ODBC driver in such case") + else () + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wconversion") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wconversion") + ADD_SUBDIRECTORY(src) + ADD_SUBDIRECTORY(tools) + ADD_SUBDIRECTORY(examples) + endif () + endif() + endif() + ELSE () + message(WARNING "unixodbc is not installed yet, you may install it under ubuntu by typing: brew install unixodbc") + ENDIF () +ENDIF () + IF (TD_WINDOWS_64) find_package(ODBC) if (NOT ODBC_FOUND) - message(FATAL_ERROR "you need to install ODBC first") + message(WARNING "you need to install ODBC first") else () message(STATUS "ODBC_INCLUDE_DIRS: ${ODBC_INCLUDE_DIRS}") message(STATUS "ODBC_LIBRARIES: ${ODBC_LIBRARIES}") @@ -50,6 +84,7 @@ IF (TD_WINDOWS_64) else () ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(tools) - ADD_SUBDIRECTORY(tests) + ADD_SUBDIRECTORY(examples) endif() ENDIF () + diff --git a/src/connector/odbc/README.cn.md b/src/connector/odbc/README.cn.md new file mode 100644 index 0000000000000000000000000000000000000000..bf114356a6329a6299599734e81b2cafc8769132 --- /dev/null +++ b/src/connector/odbc/README.cn.md @@ -0,0 +1,169 @@ + +# ODBC 驱动 # + +- **TAOS ODBC驱动持续更新中** + +- **目前导出的ODBC函数包括(注: 有些不常用的函数只是导出,但并未实现)**: +SQLAllocEnv +SQLFreeEnv +SQLAllocConnect +SQLFreeConnect +SQLGetEnvAttr +SQLSetEnvAttr +SQLGetConnectAttr +SQLGetConnectOption +SQLGetInfo +SQLConnect +SQLDisconnect +SQLAllocStmt +SQLAllocHandle +SQLFreeHandle +SQLFreeStmt +SQLExecDirect +SQLNumResultCols +SQLRowCount +SQLColAttribute +SQLGetData +SQLFetch +SQLPrepare +SQLExecute +SQLParamData +SQLPutData +SQLGetDiagRec +SQLBindParameter +SQLDescribeParam +SQLDriverConnect +SQLSetConnectAttr +SQLDescribeCol +SQLBindCol +SQLNumParams +SQLSetStmtAttr +SQLBindParam +SQLCancel +SQLCancelHandle +SQLCloseCursor +SQLColumns +SQLCopyDesc +SQLDataSources +SQLEndTran +SQLFetchScroll +SQLGetCursorName +SQLGetDescField +SQLGetDescRec +SQLGetStmtAttr +SQLGetStmtOption +SQLGetTypeInfo +SQLSetConnectOption +SQLSetCursorName +SQLSetDescField +SQLSetDescRec +SQLSetParam +SQLSetStmtOption +SQLSpecialColumns +SQLStatistics +SQLTables +SQLTransact + +` + +- **国际化。可以通过在ODBC连接串中指定针对SQLCHAR/SQLWCHAR/taos_charset/system-locale的字符集来解决常见的环境匹配问题**. + +- **现有的ODBC客户端工具可以籍此驱动同TAOS数据源互联,包括主流linux/macosx/windows平台** + +- **现有的支持ODBC的编程语言可以籍此驱动同TAOS数据源互联, 例如: c/nodejs/python/rust/go已经在上述三个主流平台测试通过, 熟悉其他语言的同学可以发现这基本上是开箱即用** + +- **持续更新中**... + +# 编译和测试使用 +**Note**: 下述所有步骤都在TDengine项目的根目录下进行 +**Note**: 请先确保src/connector/odbc如下所示,被包含在src/CMakeLists.txt源文件中 +``` +... +ADD_SUBDIRECTORY(dnode) +ADD_SUBDIRECTORY(connector/odbc) +ADD_SUBDIRECTORY(connector/jdbc) +``` + +# Linux下的编译, 以Ubuntu为例 +``` +sudo apt install unixodbc unixodbc-dev flex +rm -rf debug && cmake -B debug && cmake --build debug && cmake --install debug && echo yes +``` +# MacOSX下的编译, 以Catalina为例,依赖homebrew进行第三方工具安装[https://brew.sh/] +``` +brew install unixodbc +rm -rf debug && cmake -B debug && cmake --build debug && cmake --install debug && echo yes +``` +# Windows下的编译, 以Windows 10为例 +- 安装windows的`flex`工具. 目前我们使用[https://github.com/lexxmark/winflexbison](url). 安装完成后请确保win_flex.exe所在目录记录于`PATH`环境变量中. +- 安装Microsoft Visual Studio工具, 以VS2019为例 +- `"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"` +- `rmdir /s /q debug` +- `cmake -G "NMake Makefiles" -B debug` +- `cmake --build debug` +- `cmake --install debug` +- 以管理员身份打开`命令提示符` +- 安装ODBC驱动: 在上述打开的提示符下执行 `odbcconf /A {INSTALLDRIVER "TAOS | Driver=C:/TDengine/driver/todbc.dll | ConnectFunctions=YYN | DriverODBCVer=03.00"}` +- 新增一个数据源DSN: 执行 `odbcconf /A {CONFIGDSN "TAOS" "DSN=TAOS_DSN | Server=:"}` +上述步骤出现失败的话,可以参看这些链接: +1. win flex的安装: https://github.com/lexxmark/winflexbison/releases +2. PATH环境变量: https://jingyan.baidu.com/article/8ebacdf02d3c2949f65cd5d0.html +3. 管理员身份: https://blog.csdn.net/weixin_41083002/article/details/81019893 +4. 安装odbc驱动/数据源: https://docs.microsoft.com/en-us/sql/odbc/odbcconf-exe?view=sql-server-ver15 + +# 测试使用 +强烈建议您在linux上编译运行taosd服务端,因为当前TAOS还没有windows侧的服务端移植. +**Note1**: <>符号所括起的内容请按您当前的系统填写 +**Note2**: `.stmts` 文件存放的是测试用sql语句, 注意其格式为`UTF-8`(不带BOM导引头) +## 按官方文档在linux侧启动taosd,确保选用'UTF-8'作为其字符集 +## 在linux下创建数据 +``` +./debug/build/bin/tcodbc --dsn TAOS_DSN --uid --pwd --sts ./src/connector/odbc/samples/create_data.stmts +--<或指定特殊的ODBC连接字符串 --> +./debug/build/bin/tcodbc -C 'DSN=TAOS_DSN;UID=;PWD=;Server=:' --sts ./src/connector/odbc/samples/create_data.stmts +``` +## 在windows下检索数据 +``` +.\debug\build\bin\tcodbc -C "DSN=TAOS_DSN;UID=;PWD=;Server=:;enc_char=UTF-8" --sts .\src\connector\odbc\samples\query_data.stmts +``` +## 在MacOSX下检索数据 +``` +./debug/build/bin/tcodbc -C "DSN=TAOS_DSN;UID=;PWD=;Server=:" --sts ./src/connector/odbc/samples/query_data.stmts +``` + +## 代码示例 +- src/connector/odbc/examples/c +- src/connector/odbc/examples/js +- src/connector/odbc/examples/py +- src/connector/odbc/examples/rust +- src/connector/odbc/examples/go + +在linux或MacOSX上, 可以通过修改运行如下脚本来尝试各种测试: +**Note**: 不要忘记替换: +**Note**: 你需要在你的平台上安装nodejs/python/rust/go +**Note**: 你还需要安装对应语言的ODBC包: +-- node-odbc for nodejs: https://www.npmjs.com/package/odbc +-- pyodbc for python: https://pypi.org/project/pyodbc/ +-- rust-odbc for rust: https://docs.rs/odbc/0.17.0/odbc/ +-- go-odbc for go: https://github.com/alexbrainman/odbc + +``` +echo c && +./debug/build/bin/tcodbc -C "DSN=TAOS_DSN;Server=:" --sts src/connector/odbc/samples/create_data.stmts && +echo nodejs && +./src/connector/odbc/examples/js/odbc.js -C 'DSN=TAOS_DSN;Server=:' && +echo python && +python3 src/connector/odbc/examples/py/odbc.py -C 'DSN=TAOS_DSN;Server=:' && +echo rust && +pushd src/connector/odbc/examples/rust/main && DSN='DSN=TAOS_DSN;Server=:' cargo run && popd && +echo go && +DSN='DSN=TAOS_DSN;Server=:' go run src/connector/odbc/examples/go/odbc.go && +``` + +## 您可以对比测试一下prepared-batch-insert是否会带来速度的提升: +**注** src/connector/odbc/examples/c/main.c是tcodbc的源代码 +``` +./debug/build/bin/tcodbc -C "DSN=TAOS_DSN;Server=:" --insert --batch_size 200 --batchs 10000 +``` + + diff --git a/src/connector/odbc/README.md b/src/connector/odbc/README.md index e026884a0766772ac315acd3d0cac6535fb77557..670c7b9d9572ae066c51b2b43f593bed161fae40 100644 --- a/src/connector/odbc/README.md +++ b/src/connector/odbc/README.md @@ -1,20 +1,25 @@ # ODBC Driver # -- **very initial implementation of ODBC driver for TAOS +- **on-going implementation of ODBC driver for TAOS** -- **currently partially supported ODBC functions are: ` +- **currently exported ODBC functions are**: SQLAllocEnv SQLFreeEnv SQLAllocConnect SQLFreeConnect +SQLGetEnvAttr +SQLSetEnvAttr +SQLGetConnectAttr +SQLGetConnectOption +SQLGetInfo SQLConnect SQLDisconnect SQLAllocStmt SQLAllocHandle +SQLFreeHandle SQLFreeStmt SQLExecDirect -SQLExecDirectW SQLNumResultCols SQLRowCount SQLColAttribute @@ -22,29 +27,62 @@ SQLGetData SQLFetch SQLPrepare SQLExecute -SQLGetDiagField +SQLParamData +SQLPutData SQLGetDiagRec SQLBindParameter +SQLDescribeParam SQLDriverConnect SQLSetConnectAttr SQLDescribeCol +SQLBindCol SQLNumParams SQLSetStmtAttr -ConfigDSN +SQLBindParam +SQLCancel +SQLCancelHandle +SQLCloseCursor +SQLColumns +SQLCopyDesc +SQLDataSources +SQLEndTran +SQLFetchScroll +SQLGetCursorName +SQLGetDescField +SQLGetDescRec +SQLGetStmtAttr +SQLGetStmtOption +SQLGetTypeInfo +SQLSetConnectOption +SQLSetCursorName +SQLSetDescField +SQLSetDescRec +SQLSetParam +SQLSetStmtOption +SQLSpecialColumns +SQLStatistics +SQLTables +SQLTransact + ` -- **internationalized, you can specify different charset/code page for easy going. eg.: insert `utf-8.zh_cn` characters into database located in linux machine, while query them out in `gb2312/gb18030/...` code page in your chinese windows machine, or vice-versa. and much fun, insert `gb2312/gb18030/...` characters into database located in linux box from -your japanese windows box, and query them out in your local chinese windows machine. +- **internationalized, you can specify charset for SQLCHAR/SQLWCHAR/taos_charset/system-locale to coordinate with the environment**. -- **enable ODBC-aware software to communicate with TAOS. +- **enable ODBC-aware software to communicate with TAOS, no matter what platform it's running on, currently we support linux/macosx/windows** -- **enable any language with ODBC-bindings/ODBC-plugings to communicate with TAOS +- **enable any language with ODBC-bindings/ODBC-plugings to communicate with TAOS, currently c/nodejs/python/rust/go are all passed in our test environment, we believe other languages with ODBC-bindings/plugins are available-out-of-box** -- **still going on... +- **still going on**... # Building and Testing **Note**: all `work` is done in TDengine's project directory - +**Note**: please make sure src/connector/odbc is included in src/CMakeLists.txt +``` +... +ADD_SUBDIRECTORY(dnode) +ADD_SUBDIRECTORY(connector/odbc) +ADD_SUBDIRECTORY(connector/jdbc) +``` # Building under Linux, use Ubuntu as example ``` @@ -53,36 +91,68 @@ rm -rf debug && cmake -B debug && cmake --build debug && cmake --install debug & ``` # Building under Windows, use Windows 10 as example - install windows `flex` port. We use [https://github.com/lexxmark/winflexbison](url) at the moment. Please be noted to append `` to your `PATH`. -- install Microsoft Visual Studio, take VS2015 as example here -- `"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64` +- install Microsoft Visual Studio, take VS2019 as example here +- `"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"` - `rmdir /s /q debug` - `cmake -G "NMake Makefiles" -B debug` - `cmake --build debug` - `cmake --install debug` - open your `Command Prompt` with Administrator's priviledge -- remove previously installed TAOS ODBC driver: run `C:\TDengine\todbcinst -u -f -n TAOS` -- install TAOS ODBC driver that was just built: run `C:\TDengine\todbcinst -i -n TAOS -p C:\TDengine\driver` -- add a new user dsn: run `odbcconf CONFIGDSN TAOS "DSN=TAOS_DSN|Server=:` +- install TAOS ODBC driver that was just built: run `odbcconf /A {INSTALLDRIVER "TAOS | Driver=C:/TDengine/driver/todbc.dll | ConnectFunctions=YYN | DriverODBCVer=03.00"}` +- add a new user dsn: run `odbcconf /A {CONFIGDSN "TAOS" "DSN=TAOS_DSN | Server=host:port"}` # Test -we highly suggest that you build both in linux(ubuntu) and windows(windows 10) platform, because currently TAOS only has it's server-side port on linux platform. +we highly suggest that you build both in linux(ubuntu) and windows(windows 10) platform, because currently TAOS has not server-side port on windows platform. **Note1**: content within <> shall be modified to match your environment **Note2**: `.stmts` source files are all encoded in `UTF-8` -## start taosd in linux, suppose charset is `UTF-8` as default -``` -taosd -c ./debug/test/cfg -``` +## start taosd in linux, suppose charset is `UTF-8` as default, please follow TAOS doc for starting up ## create data in linux ``` -./debug/build/bin/tcodbc --dsn TAOS_DSN --uid --pwd --sts ./src/connector/odbc/tests/create_data.stmts +./debug/build/bin/tcodbc --dsn TAOS_DSN --uid --pwd --sts ./src/connector/odbc/samples/create_data.stmts -- -./debug/build/bin/tcodbc --dcs 'Driver=TAOS;UID=;PWD=;Server=:;client_enc=UTF-8' ./src/connector/odbc/tests/create_data.stmts +./debug/build/bin/tcodbc -C 'DSN=TAOS_DSN;UID=;PWD=;Server=:' --sts ./src/connector/odbc/samples/create_data.stmts ``` ## query data in windows ``` -.\debug\build\bin\tcodbc --dsn TAOS_DSN --uid --pwd --sts .\src\connector\odbc\tests\query_data.stmts --- -.\debug\build\bin\tcodbc --dcs "Driver=TAOS;UID=;PWD=;Server=:;client_enc=UTF-8" .\src\connector\odbc\tests\query_data.stmts +.\debug\build\bin\tcodbc -C "DSN=TAOS_DSN;UID=;PWD=;Server=:;enc_char=UTF-8" --sts .\src\connector\odbc\samples\query_data.stmts +``` +## query data in MacOSX +``` +./debug/build/bin/tcodbc -C "DSN=TAOS_DSN;UID=;PWD=;Server=:" --sts ./src/connector/odbc/samples/query_data.stmts +``` + +## code examples +- src/connector/odbc/examples/c +- src/connector/odbc/examples/js +- src/connector/odbc/examples/py +- src/connector/odbc/examples/rust +- src/connector/odbc/examples/go + +on linux/MacOSX, here after are script-snippet for you to play with: +**Note**: don't forget to replace : with whatever on your environment +**Note**: you need to install node/python3/rust/go on you machine +**Note**: you also need to install odbc-bindings/odbc-pluggins on those language platform, such as: +-- node-odbc for nodejs: https://www.npmjs.com/package/odbc +-- pyodbc for python: https://pypi.org/project/pyodbc/ +-- rust-odbc for rust: https://docs.rs/odbc/0.17.0/odbc/ +-- go-odbc for go: https://github.com/alexbrainman/odbc + +``` +echo c && +./debug/build/bin/tcodbc -C "DSN=TAOS_DSN;Server=:" --sts src/connector/odbc/samples/create_data.stmts && +echo nodejs && +./src/connector/odbc/examples/js/odbc.js -C 'DSN=TAOS_DSN;Server=:' && +echo python && +python3 src/connector/odbc/examples/py/odbc.py -C 'DSN=TAOS_DSN;Server=:' && +echo rust && +pushd src/connector/odbc/examples/rust/main && DSN='DSN=TAOS_DSN;Server=:' cargo run && popd && +echo go && +DSN='DSN=TAOS_DSN;Server=:' go run src/connector/odbc/examples/go/odbc.go && +``` + +## see how fast prepared-statment could bring up with: +``` +./debug/build/bin/tcodbc -C "DSN=TAOS_DSN;Server=:" --insert --batch_size 200 --batchs 10000 ``` diff --git a/src/connector/odbc/examples/CMakeLists.txt b/src/connector/odbc/examples/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..71f00a04e3013bc35137629555bdaa037850f0b1 --- /dev/null +++ b/src/connector/odbc/examples/CMakeLists.txt @@ -0,0 +1,4 @@ +PROJECT(TDengine) + +ADD_SUBDIRECTORY(c) + diff --git a/src/connector/odbc/examples/c/CMakeLists.txt b/src/connector/odbc/examples/c/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7821f894d072e129be563805a10901e403e3cf2a --- /dev/null +++ b/src/connector/odbc/examples/c/CMakeLists.txt @@ -0,0 +1,22 @@ +PROJECT(TDengine) + +ADD_EXECUTABLE(tcodbc main.c ../../src/todbc_log.c) + +IF (TD_LINUX OR TD_DARWIN) + TARGET_LINK_LIBRARIES(tcodbc taos odbc) +ENDIF () + +IF (TD_DARWIN) + target_include_directories(tcodbc PRIVATE /usr/local/include) + target_link_directories(tcodbc PUBLIC /usr/local/lib) +ENDIF () + +IF (TD_WINDOWS_64) + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /GL") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") + TARGET_LINK_LIBRARIES(tcodbc taos_static odbc32 odbccp32 user32 legacy_stdio_definitions os) + + ADD_EXECUTABLE(tms main.cpp) + TARGET_LINK_LIBRARIES(tms odbc32) +ENDIF () + diff --git a/src/connector/odbc/examples/c/main.c b/src/connector/odbc/examples/c/main.c new file mode 100644 index 0000000000000000000000000000000000000000..e36c75688e3440a62b66fa5fc2f8b13b83f55237 --- /dev/null +++ b/src/connector/odbc/examples/c/main.c @@ -0,0 +1,1060 @@ +#include "../../src/todbc_log.h" + +#ifdef _MSC_VER +#include +#include +#include "os.h" +#endif +#include +#include +#include + +#include "taos.h" +#include "taoserror.h" + +#include +#include + +#define CHK_TEST(statement) \ +do { \ + D("testing: %s", #statement); \ + int r = (statement); \ + if (r) { \ + D("testing failed: %s", #statement); \ + return 1; \ + } \ +} while (0); + +typedef struct { + int batch_size; + int batchs; + int keep_stmt_among_batchs; + int use_odbc; + int use_taos_query; + int use_taos_stmt; +} insert_arg_t; + +typedef struct db_column_s db_column_t; +struct db_column_s { + SQLSMALLINT nameLength; + char name[4096]; // seems enough + SQLSMALLINT dataType; + SQLULEN columnSize; + SQLSMALLINT decimalDigits; + SQLSMALLINT nullable; +}; + +static db_column_t *columns = NULL; + +typedef struct data_s data_t; +struct data_s { + int64_t ts; + int8_t b; + int8_t v1; + int16_t v2; + int32_t v4; + int64_t v8; + float f4; + double f8; + char bin[40+1]; + char blob[40+1]; // why 80? ref: tests/examples/c/apitest.c +}; + +#define CHK_RESULT(r, ht, h, fmt, ...) \ +do { \ + if (r==0) break; \ + SQLSMALLINT i_0381 = 1; \ + while (1) { \ + SQLCHAR ss[10]; \ + SQLINTEGER ne = 0; \ + SQLCHAR es[4096]; \ + SQLSMALLINT n = 0; \ + ss[0] = '\0'; \ + es[0] = '\0'; \ + SQLRETURN ret = SQLGetDiagRec(ht, h, i_0381, ss, &ne, es, sizeof(es), &n); \ + if (ret) break; \ + D("[%s]%s: " fmt "", ss, es, ##__VA_ARGS__); \ + ++i_0381; \ + } \ +} while (0) + +static int open_connect(const char *dsn, const char *uid, const char *pwd, SQLHENV *pEnv, SQLHDBC *pConn) { + SQLRETURN r; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + r = SQLAllocEnv(&env); + if (r!=SQL_SUCCESS) return 1; + do { + r = SQLAllocConnect(env, &conn); + CHK_RESULT(r, SQL_HANDLE_ENV, env, ""); + if (r!=SQL_SUCCESS) break; + do { + r = SQLConnect(conn, (SQLCHAR*)dsn, (SQLSMALLINT)(dsn ? strlen(dsn) : 0), + (SQLCHAR*)uid, (SQLSMALLINT)(uid ? strlen(uid) : 0), + (SQLCHAR*)pwd, (SQLSMALLINT)(pwd ? strlen(pwd) : 0)); + CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); + if (r==SQL_SUCCESS) { + *pEnv = env; + *pConn = conn; + return 0; + } + } while (0); + SQLFreeConnect(conn); + } while (0); + SQLFreeEnv(env); + + return 1; +} + +static int open_driver_connect(const char *connstr, SQLHENV *pEnv, SQLHDBC *pConn) { + SQLRETURN r; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + r = SQLAllocEnv(&env); + if (r!=SQL_SUCCESS) return 1; + do { + r = SQLAllocConnect(env, &conn); + CHK_RESULT(r, SQL_HANDLE_ENV, env, ""); + if (r!=SQL_SUCCESS) break; + do { + SQLCHAR buf[4096]; + SQLSMALLINT blen = 0; + SQLHDBC ConnectionHandle = conn; + SQLHWND WindowHandle = NULL; + SQLCHAR * InConnectionString = (SQLCHAR*)connstr; + SQLSMALLINT StringLength1 = (SQLSMALLINT)(connstr ? strlen(connstr) : 0); + SQLCHAR * OutConnectionString = buf; + SQLSMALLINT BufferLength = sizeof(buf); + SQLSMALLINT * StringLength2Ptr = &blen; + SQLUSMALLINT DriverCompletion = SQL_DRIVER_NOPROMPT; + r = SQLDriverConnect(ConnectionHandle, WindowHandle, InConnectionString, + StringLength1, OutConnectionString, BufferLength, + StringLength2Ptr, DriverCompletion); + CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); + if (r==SQL_SUCCESS) { + *pEnv = env; + *pConn = conn; + return 0; + } + } while (0); + SQLFreeConnect(conn); + } while (0); + SQLFreeEnv(env); + + return 1; +} + +static SQLRETURN traverse_cols(SQLHSTMT stmt, SQLSMALLINT cols) { + SQLRETURN r = SQL_ERROR; + for (SQLSMALLINT i=0; i0) fprintf(stdout, "\n"); + return r; + } + } + if (soi==SQL_NULL_DATA) { + fprintf(stdout, "%snull", i==0?"":","); + } else { + fprintf(stdout, "%s\"%s\"", i==0?"":",", buf); + } + } + fprintf(stdout, "\n"); + } + } while (0); + return r; +} + +int test_statements(const char *dsn, const char *uid, const char *pwd, const char **statements) { + SQLRETURN r = SQL_SUCCESS; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + int n = open_connect(dsn, uid, pwd, &env, &conn); + if (n) return 1; + do { + SQLHSTMT stmt = {0}; + r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt); + if (r!=SQL_SUCCESS) break; + const char **p = statements; + while (*p) { + if (do_statement(stmt, *p)) { + r = SQL_ERROR; + break; + } + ++p; + } + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + } while (0); + SQLDisconnect(conn); + SQLFreeConnect(conn); + SQLFreeEnv(env); + return r ? 1 : 0; +} + +int test_driver_connect(const char *connstr) { + SQLRETURN r = SQL_SUCCESS; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + int n = open_driver_connect(connstr, &env, &conn); + if (n) return 1; + SQLDisconnect(conn); + SQLFreeConnect(conn); + SQLFreeEnv(env); + return r ? 1 : 0; +} + +int create_statement(SQLHENV env, SQLHDBC conn, SQLHSTMT *pStmt) { + SQLHSTMT stmt = {0}; + SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt); + CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); + if (r==SQL_SUCCESS) { + *pStmt = stmt; + return 0; + } + if (r==SQL_SUCCESS_WITH_INFO) { + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + } + return 1; +} + +int do_statements(SQLHSTMT stmt, const char **statements) { + const char **p = statements; + while (p && *p) { + CHK_TEST(do_statement(stmt, *p)); + ++p; + } + return 0; +} + +int tests_stmt(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt) { + const char *statements[] = { + "drop database if exists m", + "create database m", + "use m", + // "create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(1), name nchar(1))", + "create table t (ts timestamp, b bool)", + "insert into t values('2020-10-10 00:00:00', 0)", + "insert into t values('2020-10-10 00:00:00.001', 1)", + NULL + }; + CHK_TEST(do_statements(stmt, statements)); + return 0; +} + +int tests(SQLHENV env, SQLHDBC conn) { + SQLHSTMT stmt = {0}; + CHK_TEST(create_statement(env, conn, &stmt)); + int r = tests_stmt(env, conn, stmt); + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + return r ? 1 : 0; +} + +int test_env(void) { + SQLRETURN r; + SQLHENV env = {0}; + r = SQLAllocEnv(&env); + if (r!=SQL_SUCCESS) return 1; + SQLFreeEnv(env); + return 0; +} + +static int test_sqls_in_stmt(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt, const char *sqls) { + FILE *f = fopen(sqls, "rb"); + if (!f) { + D("failed to open file [%s]", sqls); + return -1; + } + + int r = 0; + while (!feof(f)) { + char *line = NULL; + size_t len = 0; + + ssize_t n = 0; +#ifdef _MSC_VER + n = taosGetlineImp(&line, &len, f); +#else + n = getline(&line, &len, f); +#endif + if (n==-1) break; + + const char *p = NULL; + do { + if (line[0] == '#') break; + if (n>0 && line[n-1] == '\n') line[n-1]='\0'; + if (n>0 && line[n-1] == '\r') line[n-1]='\0'; + if (n>1 && line[n-2] == '\r') line[n-2]='\0'; + p = line; + while (isspace(*p)) ++p; + + if (*p==0) break; + + int positive = 1; + if (strncmp(p, "N:", 2)==0) { + // negative sample + positive = 0; + p += 2; + } else if (strncmp(p, "P:", 2)==0) { + // positive sample + p += 2; + } + + D("statement: [%s]", p); + r = do_statement(stmt, p); + + if (positive && r==0) break; + if (!positive && r) { r = 0; break; } + if (positive) return r; + D("expecting negative result, but got positive"); + return -1; + } while (0); + + free(line); + + if (r) break; + } + + fclose(f); + return r ? 1 : 0; +} + +static int test_sqls_in_conn(SQLHENV env, SQLHDBC conn, const char *sqls) { + SQLHSTMT stmt = {0}; + CHK_TEST(create_statement(env, conn, &stmt)); + int r = test_sqls_in_stmt(env, conn, stmt, sqls); + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + return r ? 1 : 0; +} + +static int test_sqls(const char *dsn, const char *uid, const char *pwd, const char *connstr, const char *sqls) { + int r = 0; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + if (dsn) { + CHK_TEST(open_connect(dsn, uid, pwd, &env, &conn)); + } else { + CHK_TEST(open_driver_connect(connstr, &env, &conn)); + } + + if (sqls) { + r = test_sqls_in_conn(env, conn, sqls); + } + SQLDisconnect(conn); + SQLFreeConnect(conn); + SQLFreeEnv(env); + return r ? 1 : 0; +} + +typedef struct record_s record_t; +struct record_s { + int dummy; + char ts[64]; + SQLLEN ts_len; + int32_t v1; + SQLLEN v1_len; + char ts2[64]; + SQLLEN ts2_len; +}; + +static int do_prepare_in_stmt(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt) { + SQLRETURN r = SQL_SUCCESS; + do { + const char *sql = "insert into m.v (ts, v1, ts2) values (?, ?, ?)"; + r = SQLPrepare(stmt, (SQLCHAR*)sql, SQL_NTS); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + + record_t records[] = { + {0, "2020-01-03 11:22:33.345", SQL_NTS, 1, sizeof(int32_t), "2020-01-02 11:22:33.455", SQL_NTS}, + {0, "2020-01-03 11:22:34.346", SQL_NTS, 2, sizeof(int32_t), "2020-01-02 11:22:34.445", SQL_NTS}, + {0, "2020-01-04 11:22:34.345", SQL_NTS, 2, sizeof(int32_t), "2020-01-02 11:22:34.445", SQL_NTS}, + {0, "2020-01-05 11:22:34.345", SQL_NTS, 2, sizeof(int32_t), "2020-01-02 11:22:34.445", SQL_NTS}, + }; + + record_t *base = (record_t*)0; + + r = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(base->ts)-1, 0, base->ts, sizeof(base->ts), &(base->ts_len)); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + r = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &base->v1, 0, &(base->v1_len)); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + r = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(base->ts2)-1, 0, base->ts2, sizeof(base->ts2), &(base->ts2_len)); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + + SQLSetStmtAttr(stmt, SQL_ATTR_PARAM_BIND_TYPE, (SQLPOINTER)sizeof(*base), 0); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + + SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)(sizeof(records)/sizeof(records[0])), 0); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + + record_t *record = NULL; + + SQLSetStmtAttr(stmt, SQL_ATTR_PARAM_BIND_OFFSET_PTR, &record, 0); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + + record = records; + + r = SQLExecute(stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + } while (0); + + return r ? -1 : 0; +} + +static int do_prepare_in_conn(SQLHENV env, SQLHDBC conn) { + SQLHSTMT stmt = {0}; + CHK_TEST(create_statement(env, conn, &stmt)); + int r = do_prepare_in_stmt(env, conn, stmt); + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + return r ? 1 : 0; +} + +static int do_prepare(const char *dsn, const char *uid, const char *pwd, const char *connstr) { + int r = 0; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + if (dsn) { + CHK_TEST(open_connect(dsn, uid, pwd, &env, &conn)); + } else { + CHK_TEST(open_driver_connect(connstr, &env, &conn)); + } + + r = do_prepare_in_conn(env, conn); + + SQLDisconnect(conn); + SQLFreeConnect(conn); + SQLFreeEnv(env); + return r ? 1 : 0; +} + +typedef struct { + int dummy; + int64_t ts; + SQLLEN ts_len; + int8_t v1; + SQLLEN v1_len; + int16_t v2; + SQLLEN v2_len; + int32_t v4; + SQLLEN v4_len; + int64_t v8; + SQLLEN v8_len; +} test_v_t; + +static int do_insert_in_stmt(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt, int64_t *ts, insert_arg_t *arg) { + SQLRETURN r = SQL_SUCCESS; + int batch_size = arg->batch_size; + test_v_t *recs = NULL; + do { + const char *sql = "insert into test.v (ts, v1, v2, v4, v8) values (?, ?, ?, ?, ?)"; + r = SQLPrepare(stmt, (SQLCHAR*)sql, SQL_NTS); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + + test_v_t *base = NULL; + + r = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, &base->ts, 0, &base->ts_len); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + r = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_TINYINT, 0, 0, &base->v1, 0, &base->v1_len); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + r = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_SMALLINT, 0, 0, &base->v2, 0, &base->v2_len); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + r = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &base->v4, 0, &base->v4_len); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + r = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, &base->v8, 0, &base->v8_len); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + + SQLSetStmtAttr(stmt, SQL_ATTR_PARAM_BIND_TYPE, (SQLPOINTER)sizeof(*base), 0); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + + base = NULL; + + SQLSetStmtAttr(stmt, SQL_ATTR_PARAM_BIND_OFFSET_PTR, &base, 0); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + + size_t n_recs = (size_t)batch_size; + recs = (test_v_t*)calloc(n_recs, sizeof(*recs)); + OILE(recs, ""); + + SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)n_recs, 0); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + + base = recs; + + for (int batch=0; batchbatchs; ++batch) { + for (int i=0; idummy = 0; + rec->ts = *ts + i; + rec->ts_len = sizeof(rec->ts); + rec->v1 = (int8_t)rand(); + rec->v1_len = sizeof(rec->v1); + rec->v2 = (int16_t)rand(); + rec->v2_len = sizeof(rec->v2); + rec->v4 = rand(); + rec->v4_len = sizeof(rec->v4); + rec->v8 = rand(); + rec->v8_len = sizeof(rec->v8); + } + + *ts += (int64_t)n_recs; + + r = SQLExecute(stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + if (r) break; + } + } while (0); + + free(recs); + return r ? -1 : 0; +} + +static int do_insert_in_conn(SQLHENV env, SQLHDBC conn, insert_arg_t *arg) { + SQLHSTMT stmt = {0}; + int64_t ts = 1502535178128; + int r = 0; + CHK_TEST(create_statement(env, conn, &stmt)); + for (int i=0; i<1 && ibatchs; ++i) { + r = do_insert_in_stmt(env, conn, stmt, &ts, arg); + if (r) break; + if (!arg->keep_stmt_among_batchs) { + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + r = create_statement(env, conn, &stmt); + if (r) break; + } + } + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + return r ? 1 : 0; +} + +static int do_insert_batch(const char *dsn, const char *uid, const char *pwd, const char *connstr, insert_arg_t *arg, const char *sqls[]) { + int r = 0; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + if (dsn) { + CHK_TEST(open_connect(dsn, uid, pwd, &env, &conn)); + } else { + CHK_TEST(open_driver_connect(connstr, &env, &conn)); + } + + SQLHSTMT stmt = {0}; + CHK_TEST(create_statement(env, conn, &stmt)); + CHK_TEST(do_statements(stmt, sqls)); + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + + OD("................"); + r = do_insert_in_conn(env, conn, arg); + OD("................"); + + SQLDisconnect(conn); + SQLFreeConnect(conn); + SQLFreeEnv(env); + return r ? 1 : 0; +} + +static int inited = 0; +static void init_once(void) { + if (inited) return; + + int r = taos_init(); + if (r) OILE(0, ""); + inited = 1; +} + +static int do_sqls(TAOS *taos, const char *sqls[]) { + for (int i=0; sqls[i]; ++i) { + OD("[%s]", sqls[i]); + TAOS_RES *res = taos_query(taos, sqls[i]); + if (!res) { + int e = terrno; + OD("taos_query [%s] failed: [%d]%s", sqls[i], e, tstrerror(e)); + return -1; + } + int e = taos_errno(res); + if (e) { + OD("taos_query [%s] failed: [%d]%s", sqls[i], e, tstrerror(e)); + } + taos_stop_query(res); + if (e) return -1; + } + return 0; +} + +static int do_taos_query(TAOS *taos, insert_arg_t *arg) { + char **sqls = (char**)calloc((size_t)arg->batchs, sizeof(*sqls)); + if (!sqls) { + OILE(0, "out of memory"); + } + + int64_t ts = 1502535178128; + for (int i=0; ibatchs; ++i) { + size_t bytes = 100 * (size_t)arg->batch_size; + sqls[i] = (char*)malloc(bytes); + OILE(sqls[i], ""); + char *p = sqls[i]; + size_t count = 0; + + while (1) { + int n = 0; + n = snprintf(p, bytes, "insert into test.v values"); + OILE(n>0, ""); + if (p) p += n; + OILE(bytes>n, ""); + if (bytes>=n) bytes -= (size_t)n; + else bytes = 0; + count += (size_t)n; + + for (int j=0; jbatch_size; ++j) { + int8_t v1 = (int8_t)rand(); if (v1==INT8_MIN) v1++; + int16_t v2 = (int16_t)rand(); if (v2==INT16_MIN) v2++; + int32_t v4 = (int32_t)rand(); if (v4==INT32_MIN) v4++; + int64_t v8 = (int64_t)rand(); if (v8==INT64_MIN) v8++; + n = snprintf(p, bytes, " (%" PRId64 ", %d, %d, %d, %" PRId64 ")", ts + i*arg->batch_size + j, (int)v1, (int)v2, v4, v8); + OILE(n>0, ""); + if (p) p += n; + OILE(bytes>n, ""); + if (bytes>=n) bytes -= (size_t)n; + else bytes = 0; + count += (size_t)n; + } + + if (p) break; + OILE(0, ""); + } + } + + OD(".............."); + for (int i=0; ibatchs; ++i) { + TAOS_RES *res = taos_query(taos, sqls[i]); + if (!res) { + int e = terrno; + OD("taos_query [%s] failed: [%d]%s", sqls[i], e, tstrerror(e)); + return -1; + } + int e = taos_errno(res); + if (e) { + OD("taos_query [%s] failed: [%d]%s", sqls[i], e, tstrerror(e)); + } + taos_stop_query(res); + if (e) return -1; + } + OD(".............."); + + for (int i=0; ibatchs; ++i) { + free(sqls[i]); + } + free(sqls); + + return 0; +} + +static int do_taos_stmt(TAOS *taos, insert_arg_t *arg) { + TAOS_STMT *stmt = taos_stmt_init(taos); + OILE(stmt, ""); + const char *sql = "insert into test.v values (?,?,?,?,?)"; + int r = 0; + do { + r = taos_stmt_prepare(stmt, sql, (unsigned long)strlen(sql)); + if (r) { + OD("taos_stmt_prepare [%s] failed: [%d]%s", sql, r, tstrerror(r)); + break; + } + int64_t ts = 1502535178128; + TAOS_BIND *bindings = (TAOS_BIND*)calloc(5, sizeof(*bindings)); + TAOS_BIND *b_ts = bindings + 0; + TAOS_BIND *b_v1 = bindings + 1; + TAOS_BIND *b_v2 = bindings + 2; + TAOS_BIND *b_v4 = bindings + 3; + TAOS_BIND *b_v8 = bindings + 4; + b_ts->buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + b_ts->buffer_length = sizeof(b_ts->u.ts); + b_ts->length = &b_ts->buffer_length; + b_ts->buffer = &b_ts->u.ts; + b_ts->is_null = NULL; + + b_v1->buffer_type = TSDB_DATA_TYPE_TINYINT; + b_v1->buffer_length = sizeof(b_v1->u.v1); + b_v1->length = &b_v1->buffer_length; + b_v1->buffer = &b_v1->u.v1; + b_v1->is_null = NULL; + + b_v2->buffer_type = TSDB_DATA_TYPE_SMALLINT; + b_v2->buffer_length = sizeof(b_v2->u.v2); + b_v2->length = &b_v2->buffer_length; + b_v2->buffer = &b_v2->u.v2; + b_v2->is_null = NULL; + + b_v4->buffer_type = TSDB_DATA_TYPE_INT; + b_v4->buffer_length = sizeof(b_v4->u.v4); + b_v4->length = &b_v4->buffer_length; + b_v4->buffer = &b_v4->u.v4; + b_v4->is_null = NULL; + + b_v8->buffer_type = TSDB_DATA_TYPE_BIGINT; + b_v8->buffer_length = sizeof(b_v8->u.v8); + b_v8->length = &b_v8->buffer_length; + b_v8->buffer = &b_v8->u.v8; + b_v8->is_null = NULL; + + OILE(bindings, ""); + OD("................"); + for (int i=0; ibatchs; ++i) { + for (int j=0; jbatch_size; ++j) { + b_ts->u.ts = ts + i*arg->batch_size + j; + b_v1->u.v1 = (int8_t)rand(); + b_v2->u.v2 = (int16_t)rand(); + b_v4->u.v4 = (int32_t)rand(); + b_v8->u.v8 = (int64_t)rand(); + r = taos_stmt_bind_param(stmt, bindings); + if (r) { + OD("taos_stmt_bind_param failed: [%d]%s", r, tstrerror(r)); + break; + } + r = taos_stmt_add_batch(stmt); + if (r) { + OD("taos_stmt_add_batch failed: [%d]%s", r, tstrerror(r)); + break; + } + } + + if (r) break; + + r = taos_stmt_execute(stmt); + if (r) { + OD("taos_stmt_execute failed: [%d]%s", r, tstrerror(r)); + break; + } + } + OD("................"); + + free(bindings); + + if (r) break; + } while (0); + taos_stmt_close(stmt); + return r ? -1 : 0; +} + +static int do_insert_batch_taos(const char *dsn, const char *uid, const char *pwd, const char *connstr, insert_arg_t *arg, const char *sqls[]) { + int r = 0; + + init_once(); + + int port = 0; + char *ip = NULL; + const char *p = strchr(connstr, ':'); + if (p) { + ip = strndup(connstr, (size_t)(p-connstr)); + ++p; + sscanf(p, "%d", &port); + } else { + ip = strdup(connstr); + port = 6030; + } + if (!ip) { + OD("bad ip/port:[%s]", connstr); + return -1; + } + + TAOS *taos = NULL; + do { + taos = taos_connect(ip, uid, pwd, NULL, (uint16_t)port); + if (!taos) { + int e = terrno; + OD("taos_connect [%s/%d] failed:[%d]%s", ip, port, e, tstrerror(e)); + break; + } + r = do_sqls(taos, sqls); + if (r) break; + if (arg->use_taos_query) { + r = do_taos_query(taos, arg); + } else if (arg->use_taos_stmt) { + r = do_taos_stmt(taos, arg); + } else { + OILE(0, ""); + } + } while (0); + + if (taos) taos_close(taos); + free(ip); + + return r ? 1 : 0; +} + +static int do_debug_col_name_max_len(const char *dsn, const char *uid, const char *pwd, const char *connstr) { + SQLRETURN r; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + r = SQLAllocEnv(&env); + if (r!=SQL_SUCCESS) { + D("SQLAllocEnv failed"); + return 1; + }; + do { + r = SQLAllocConnect(env, &conn); + CHK_RESULT(r, SQL_HANDLE_ENV, env, ""); + if (r!=SQL_SUCCESS) break; + do { + if (dsn) { + r = SQLConnect(conn, (SQLCHAR*)dsn, (SQLSMALLINT)(dsn ? strlen(dsn) : 0), + (SQLCHAR*)uid, (SQLSMALLINT)(uid ? strlen(uid) : 0), + (SQLCHAR*)pwd, (SQLSMALLINT)(pwd ? strlen(pwd) : 0)); + } else { + SQLCHAR buf[4096]; + SQLSMALLINT blen = 0; + SQLHDBC ConnectionHandle = conn; + SQLHWND WindowHandle = NULL; + SQLCHAR * InConnectionString = (SQLCHAR*)connstr; + SQLSMALLINT StringLength1 = (SQLSMALLINT)(connstr ? strlen(connstr) : 0); + SQLCHAR * OutConnectionString = buf; + SQLSMALLINT BufferLength = sizeof(buf); + SQLSMALLINT * StringLength2Ptr = &blen; + SQLUSMALLINT DriverCompletion = SQL_DRIVER_NOPROMPT; + r = SQLDriverConnect(ConnectionHandle, WindowHandle, InConnectionString, + StringLength1, OutConnectionString, BufferLength, + StringLength2Ptr, DriverCompletion); + } + CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); + if (r!=SQL_SUCCESS) break; + D("connected"); + if (1) { + SQLSMALLINT maxColumnNameLength = 0; + SQLSMALLINT len = 0; + r = SQLGetInfo(conn, SQL_MAX_COLUMN_NAME_LEN, &maxColumnNameLength, sizeof(SQLSMALLINT), &len); + CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); + if (r!=SQL_SUCCESS) break; + D("maxColumnNameLength: %d", maxColumnNameLength); + } + } while (0); + SQLFreeConnect(conn); + conn = NULL; + } while (0); + SQLFreeEnv(env); + env = NULL; + + return (r==SQL_SUCCESS) ? 0 : 1; +} + +void usage(const char *arg0) { + fprintf(stdout, "%s usage:\n", arg0); + fprintf(stdout, "%s [--dsn ] [--uid ] [--pwd ] [-C ] [--sts ]\n", arg0); + fprintf(stdout, " --dsn : DSN\n"); + fprintf(stdout, " --uid : UID\n"); + fprintf(stdout, " --pwd : PWD\n"); + fprintf(stdout, " -C : driver connection string\n"); + fprintf(stdout, " --sts : file where statements store\n"); +} + +int main(int argc, char *argv[]) { + srand((unsigned)time(0)); + const char *conn_str = NULL; + const char *dsn = NULL; + const char *uid = NULL; + const char *pwd = NULL; + const char *sts = NULL; // statements file + int debug_col_name_max_len = 0; + int prepare = 0; + int insert = 0; + insert_arg_t insert_arg = { + .batch_size = 100, + .batchs = 100, + .keep_stmt_among_batchs = 0 + }; + for (size_t i=1; i=argc) { + D(" expected but got nothing"); + return 1; + } + sscanf(argv[i], "%d", &insert_arg.batch_size); + if (insert_arg.batch_size<=0) { + D(" invalid"); + return 1; + } + continue; + } + if (strcmp(arg, "--batchs")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + sscanf(argv[i], "%d", &insert_arg.batchs); + if (insert_arg.batchs<=0) { + D(" invalid"); + return 1; + } + continue; + } + if (strcmp(arg, "--keep_stmt_among_batchs")==0) { + insert_arg.keep_stmt_among_batchs = 1; + continue; + } + if (strcmp(arg, "--dsn")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + if (conn_str) { + D("-C has already been specified"); + return 1; + } + dsn = argv[i]; + continue; + } + if (strcmp(arg, "--uid")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + uid = argv[i]; + continue; + } + if (strcmp(arg, "--pwd")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + pwd = argv[i]; + continue; + } + if (strcmp(arg, "-C")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + if (dsn || uid || pwd) { + D("either of --dsn/--uid/--pwd has already been specified"); + return 1; + } + conn_str = argv[i]; + continue; + } + if (strcmp(arg, "--sts")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + sts = argv[i]; + continue; + } + if (strcmp(arg, "-p")==0) { + prepare = 1; + continue; + } + } + if (debug_col_name_max_len) { + int r = do_debug_col_name_max_len(dsn, uid, pwd, conn_str); + if (r) return 1; + } + if (insert) { + const char *sqls[] = { + "drop database if exists test", + "create database test", + "create table test.v (ts timestamp, v1 tinyint, v2 smallint, v4 int, v8 bigint)", + NULL + }; + int r = 0; + if (insert_arg.use_odbc) { + r = do_insert_batch(dsn, uid, pwd, conn_str, &insert_arg, sqls); + } else { + r = do_insert_batch_taos(dsn, uid, pwd, conn_str, &insert_arg, sqls); + } + if (r) return 1; + } + if (sts) { + int r = test_sqls(dsn, uid, pwd, conn_str, sts); + if (r) return 1; + } + if (prepare) { + int r = do_prepare(dsn, uid, pwd, conn_str); + if (r) return 1; + } + D("Done!"); + return 0; +} + diff --git a/src/connector/odbc/examples/c/main.cpp b/src/connector/odbc/examples/c/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b719534f986fd0076de7dc3351ce273a2847f919 --- /dev/null +++ b/src/connector/odbc/examples/c/main.cpp @@ -0,0 +1,654 @@ +/******************************************************************************* +/* ODBCSQL: a sample program that implements an ODBC command line interpreter. +/* +/* USAGE: ODBCSQL DSN= or +/* ODBCSQL FILEDSN= or +/* ODBCSQL DRIVER={driver name} +/* +/* +/* Copyright(c) Microsoft Corporation. This is a WDAC sample program and +/* is not suitable for use in production environments. +/* +/******************************************************************************/ +/* Modules: +/* Main Main driver loop, executes queries. +/* DisplayResults Display the results of the query if any +/* AllocateBindings Bind column data +/* DisplayTitles Print column titles +/* SetConsole Set console display mode +/* HandleError Show ODBC error messages +/******************************************************************************/ + +#define _UNICODE +#define UNICODE + +#include +#include +#include +#include +#include +#include +#include +#include + + +/*******************************************/ +/* Macro to call ODBC functions and */ +/* report an error on failure. */ +/* Takes handle, handle type, and stmt */ +/*******************************************/ + +#define TRYODBC(h, ht, x) { RETCODE rc = x;\ + if (rc != SQL_SUCCESS) \ + { \ + HandleDiagnosticRecord (h, ht, rc); \ + } \ + if (rc == SQL_ERROR) \ + { \ + fwprintf(stderr, L"Error in " L#x L"\n"); \ + goto Exit; \ + } \ + } +/******************************************/ +/* Structure to store information about */ +/* a column. +/******************************************/ + +typedef struct STR_BINDING { + SQLSMALLINT cDisplaySize; /* size to display */ + WCHAR *wszBuffer; /* display buffer */ + SQLLEN indPtr; /* size or null */ + BOOL fChar; /* character col? */ + struct STR_BINDING *sNext; /* linked list */ +} BINDING; + + + +/******************************************/ +/* Forward references */ +/******************************************/ + +void HandleDiagnosticRecord (SQLHANDLE hHandle, + SQLSMALLINT hType, + RETCODE RetCode); + +void DisplayResults(HSTMT hStmt, + SQLSMALLINT cCols); + +void AllocateBindings(HSTMT hStmt, + SQLSMALLINT cCols, + BINDING** ppBinding, + SQLSMALLINT* pDisplay); + + +void DisplayTitles(HSTMT hStmt, + DWORD cDisplaySize, + BINDING* pBinding); + +void SetConsole(DWORD cDisplaySize, + BOOL fInvert); + +/*****************************************/ +/* Some constants */ +/*****************************************/ + + +#define DISPLAY_MAX 50 // Arbitrary limit on column width to display +#define DISPLAY_FORMAT_EXTRA 3 // Per column extra display bytes (| ) +#define DISPLAY_FORMAT L"%c %*.*s " +#define DISPLAY_FORMAT_C L"%c %-*.*s " +#define NULL_SIZE 6 // +#define SQL_QUERY_SIZE 1000 // Max. Num characters for SQL Query passed in. + +#define PIPE L'|' + +SHORT gHeight = 80; // Users screen height + +int __cdecl wmain(int argc, _In_reads_(argc) WCHAR **argv) +{ + SQLHENV hEnv = NULL; + SQLHDBC hDbc = NULL; + SQLHSTMT hStmt = NULL; + WCHAR* pwszConnStr; + WCHAR wszInput[SQL_QUERY_SIZE]; + + // Allocate an environment + + if (SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv) == SQL_ERROR) + { + fwprintf(stderr, L"Unable to allocate an environment handle\n"); + exit(-1); + } + + // Register this as an application that expects 3.x behavior, + // you must register something if you use AllocHandle + + TRYODBC(hEnv, + SQL_HANDLE_ENV, + SQLSetEnvAttr(hEnv, + SQL_ATTR_ODBC_VERSION, + (SQLPOINTER)SQL_OV_ODBC3, + 0)); + + // Allocate a connection + TRYODBC(hEnv, + SQL_HANDLE_ENV, + SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc)); + + if (argc > 1) + { + pwszConnStr = *++argv; + } + else + { + pwszConnStr = L""; + } + + // Connect to the driver. Use the connection string if supplied + // on the input, otherwise let the driver manager prompt for input. + + TRYODBC(hDbc, + SQL_HANDLE_DBC, + SQLDriverConnect(hDbc, + GetDesktopWindow(), + pwszConnStr, + SQL_NTS, + NULL, + 0, + NULL, + SQL_DRIVER_COMPLETE)); + + fwprintf(stderr, L"Connected!\n"); + + TRYODBC(hDbc, + SQL_HANDLE_DBC, + SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt)); + + wprintf(L"Enter SQL commands, type (control)Z to exit\nSQL COMMAND>"); + + // Loop to get input and execute queries + + while(_fgetts(wszInput, SQL_QUERY_SIZE-1, stdin)) + { + RETCODE RetCode; + SQLSMALLINT sNumResults; + + // Execute the query + + if (!(*wszInput)) + { + wprintf(L"SQL COMMAND>"); + continue; + } + RetCode = SQLExecDirect(hStmt,wszInput, SQL_NTS); + + switch(RetCode) + { + case SQL_SUCCESS_WITH_INFO: + { + HandleDiagnosticRecord(hStmt, SQL_HANDLE_STMT, RetCode); + // fall through + } + case SQL_SUCCESS: + { + // If this is a row-returning query, display + // results + TRYODBC(hStmt, + SQL_HANDLE_STMT, + SQLNumResultCols(hStmt,&sNumResults)); + + if (sNumResults > 0) + { + DisplayResults(hStmt,sNumResults); + } + else + { + SQLLEN cRowCount; + + TRYODBC(hStmt, + SQL_HANDLE_STMT, + SQLRowCount(hStmt,&cRowCount)); + + if (cRowCount >= 0) + { + wprintf(L"%Id %s affected\n", + cRowCount, + cRowCount == 1 ? L"row" : L"rows"); + } + } + break; + } + + case SQL_ERROR: + { + HandleDiagnosticRecord(hStmt, SQL_HANDLE_STMT, RetCode); + break; + } + + default: + fwprintf(stderr, L"Unexpected return code %hd!\n", RetCode); + + } + TRYODBC(hStmt, + SQL_HANDLE_STMT, + SQLFreeStmt(hStmt, SQL_CLOSE)); + + wprintf(L"SQL COMMAND>"); + } + +Exit: + + // Free ODBC handles and exit + + if (hStmt) + { + SQLFreeHandle(SQL_HANDLE_STMT, hStmt); + } + + if (hDbc) + { + SQLDisconnect(hDbc); + SQLFreeHandle(SQL_HANDLE_DBC, hDbc); + } + + if (hEnv) + { + SQLFreeHandle(SQL_HANDLE_ENV, hEnv); + } + + wprintf(L"\nDisconnected."); + + return 0; + +} + +/************************************************************************ +/* DisplayResults: display results of a select query +/* +/* Parameters: +/* hStmt ODBC statement handle +/* cCols Count of columns +/************************************************************************/ + +void DisplayResults(HSTMT hStmt, + SQLSMALLINT cCols) +{ + BINDING *pFirstBinding, *pThisBinding; + SQLSMALLINT cDisplaySize; + RETCODE RetCode = SQL_SUCCESS; + int iCount = 0; + + // Allocate memory for each column + + AllocateBindings(hStmt, cCols, &pFirstBinding, &cDisplaySize); + + // Set the display mode and write the titles + + DisplayTitles(hStmt, cDisplaySize+1, pFirstBinding); + + + // Fetch and display the data + + bool fNoData = false; + + do { + // Fetch a row + + if (iCount++ >= gHeight - 2) + { + int nInputChar; + bool fEnterReceived = false; + + while(!fEnterReceived) + { + wprintf(L" "); + SetConsole(cDisplaySize+2, TRUE); + wprintf(L" Press ENTER to continue, Q to quit (height:%hd)", gHeight); + SetConsole(cDisplaySize+2, FALSE); + + nInputChar = _getch(); + wprintf(L"\n"); + if ((nInputChar == 'Q') || (nInputChar == 'q')) + { + goto Exit; + } + else if ('\r' == nInputChar) + { + fEnterReceived = true; + } + // else loop back to display prompt again + } + + iCount = 1; + DisplayTitles(hStmt, cDisplaySize+1, pFirstBinding); + } + + TRYODBC(hStmt, SQL_HANDLE_STMT, RetCode = SQLFetch(hStmt)); + + if (RetCode == SQL_NO_DATA_FOUND) + { + fNoData = true; + } + else + { + + // Display the data. Ignore truncations + + for (pThisBinding = pFirstBinding; + pThisBinding; + pThisBinding = pThisBinding->sNext) + { + if (pThisBinding->indPtr != SQL_NULL_DATA) + { + wprintf(pThisBinding->fChar ? DISPLAY_FORMAT_C:DISPLAY_FORMAT, + PIPE, + pThisBinding->cDisplaySize, + pThisBinding->cDisplaySize, + pThisBinding->wszBuffer); + } + else + { + wprintf(DISPLAY_FORMAT_C, + PIPE, + pThisBinding->cDisplaySize, + pThisBinding->cDisplaySize, + L""); + } + } + wprintf(L" %c\n",PIPE); + } + } while (!fNoData); + + SetConsole(cDisplaySize+2, TRUE); + wprintf(L"%*.*s", cDisplaySize+2, cDisplaySize+2, L" "); + SetConsole(cDisplaySize+2, FALSE); + wprintf(L"\n"); + +Exit: + // Clean up the allocated buffers + + while (pFirstBinding) + { + pThisBinding = pFirstBinding->sNext; + free(pFirstBinding->wszBuffer); + free(pFirstBinding); + pFirstBinding = pThisBinding; + } +} + +/************************************************************************ +/* AllocateBindings: Get column information and allocate bindings +/* for each column. +/* +/* Parameters: +/* hStmt Statement handle +/* cCols Number of columns in the result set +/* *lppBinding Binding pointer (returned) +/* lpDisplay Display size of one line +/************************************************************************/ + +void AllocateBindings(HSTMT hStmt, + SQLSMALLINT cCols, + BINDING **ppBinding, + SQLSMALLINT *pDisplay) +{ + SQLSMALLINT iCol; + BINDING *pThisBinding, *pLastBinding = NULL; + SQLLEN cchDisplay, ssType; + SQLSMALLINT cchColumnNameLength; + + *pDisplay = 0; + + for (iCol = 1; iCol <= cCols; iCol++) + { + pThisBinding = (BINDING *)(malloc(sizeof(BINDING))); + if (!(pThisBinding)) + { + fwprintf(stderr, L"Out of memory!\n"); + exit(-100); + } + + if (iCol == 1) + { + *ppBinding = pThisBinding; + } + else + { + pLastBinding->sNext = pThisBinding; + } + pLastBinding = pThisBinding; + + + // Figure out the display length of the column (we will + // bind to char since we are only displaying data, in general + // you should bind to the appropriate C type if you are going + // to manipulate data since it is much faster...) + + TRYODBC(hStmt, + SQL_HANDLE_STMT, + SQLColAttribute(hStmt, + iCol, + SQL_DESC_DISPLAY_SIZE, + NULL, + 0, + NULL, + &cchDisplay)); + + + // Figure out if this is a character or numeric column; this is + // used to determine if we want to display the data left- or right- + // aligned. + + // SQL_DESC_CONCISE_TYPE maps to the 1.x SQL_COLUMN_TYPE. + // This is what you must use if you want to work + // against a 2.x driver. + + TRYODBC(hStmt, + SQL_HANDLE_STMT, + SQLColAttribute(hStmt, + iCol, + SQL_DESC_CONCISE_TYPE, + NULL, + 0, + NULL, + &ssType)); + + pThisBinding->fChar = (ssType == SQL_CHAR || + ssType == SQL_VARCHAR || + ssType == SQL_LONGVARCHAR); + + pThisBinding->sNext = NULL; + + // Arbitrary limit on display size + if (cchDisplay > DISPLAY_MAX) + cchDisplay = DISPLAY_MAX; + + // Allocate a buffer big enough to hold the text representation + // of the data. Add one character for the null terminator + + pThisBinding->wszBuffer = (WCHAR *)malloc((cchDisplay+1) * sizeof(WCHAR)); + + if (!(pThisBinding->wszBuffer)) + { + fwprintf(stderr, L"Out of memory!\n"); + exit(-100); + } + + // Map this buffer to the driver's buffer. At Fetch time, + // the driver will fill in this data. Note that the size is + // count of bytes (for Unicode). All ODBC functions that take + // SQLPOINTER use count of bytes; all functions that take only + // strings use count of characters. + + TRYODBC(hStmt, + SQL_HANDLE_STMT, + SQLBindCol(hStmt, + iCol, + SQL_C_TCHAR, + (SQLPOINTER) pThisBinding->wszBuffer, + (cchDisplay + 1) * sizeof(WCHAR), + &pThisBinding->indPtr)); + + + // Now set the display size that we will use to display + // the data. Figure out the length of the column name + + TRYODBC(hStmt, + SQL_HANDLE_STMT, + SQLColAttribute(hStmt, + iCol, + SQL_DESC_NAME, + NULL, + 0, + &cchColumnNameLength, + NULL)); + + pThisBinding->cDisplaySize = max((SQLSMALLINT)cchDisplay, cchColumnNameLength); + if (pThisBinding->cDisplaySize < NULL_SIZE) + pThisBinding->cDisplaySize = NULL_SIZE; + + *pDisplay += pThisBinding->cDisplaySize + DISPLAY_FORMAT_EXTRA; + + } + + return; + +Exit: + + exit(-1); + + return; +} + + +/************************************************************************ +/* DisplayTitles: print the titles of all the columns and set the +/* shell window's width +/* +/* Parameters: +/* hStmt Statement handle +/* cDisplaySize Total display size +/* pBinding list of binding information +/************************************************************************/ + +void DisplayTitles(HSTMT hStmt, + DWORD cDisplaySize, + BINDING *pBinding) +{ + WCHAR wszTitle[DISPLAY_MAX]; + SQLSMALLINT iCol = 1; + + SetConsole(cDisplaySize+2, TRUE); + + for (; pBinding; pBinding = pBinding->sNext) + { + TRYODBC(hStmt, + SQL_HANDLE_STMT, + SQLColAttribute(hStmt, + iCol++, + SQL_DESC_NAME, + wszTitle, + sizeof(wszTitle), // Note count of bytes! + NULL, + NULL)); + + wprintf(DISPLAY_FORMAT_C, + PIPE, + pBinding->cDisplaySize, + pBinding->cDisplaySize, + wszTitle); + } + +Exit: + + wprintf(L" %c", PIPE); + SetConsole(cDisplaySize+2, FALSE); + wprintf(L"\n"); + +} + + +/************************************************************************ +/* SetConsole: sets console display size and video mode +/* +/* Parameters +/* siDisplaySize Console display size +/* fInvert Invert video? +/************************************************************************/ + +void SetConsole(DWORD dwDisplaySize, + BOOL fInvert) +{ + HANDLE hConsole; + CONSOLE_SCREEN_BUFFER_INFO csbInfo; + + // Reset the console screen buffer size if necessary + + hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + + if (hConsole != INVALID_HANDLE_VALUE) + { + if (GetConsoleScreenBufferInfo(hConsole, &csbInfo)) + { + if (csbInfo.dwSize.X < (SHORT) dwDisplaySize) + { + csbInfo.dwSize.X = (SHORT) dwDisplaySize; + SetConsoleScreenBufferSize(hConsole, csbInfo.dwSize); + } + + gHeight = csbInfo.dwSize.Y; + } + + if (fInvert) + { + SetConsoleTextAttribute(hConsole, (WORD)(csbInfo.wAttributes | BACKGROUND_BLUE)); + } + else + { + SetConsoleTextAttribute(hConsole, (WORD)(csbInfo.wAttributes & ~(BACKGROUND_BLUE))); + } + } +} + + +/************************************************************************ +/* HandleDiagnosticRecord : display error/warning information +/* +/* Parameters: +/* hHandle ODBC handle +/* hType Type of handle (HANDLE_STMT, HANDLE_ENV, HANDLE_DBC) +/* RetCode Return code of failing command +/************************************************************************/ + +void HandleDiagnosticRecord (SQLHANDLE hHandle, + SQLSMALLINT hType, + RETCODE RetCode) +{ + SQLSMALLINT iRec = 0; + SQLINTEGER iError; + WCHAR wszMessage[1000]; + WCHAR wszState[SQL_SQLSTATE_SIZE+1]; + + + if (RetCode == SQL_INVALID_HANDLE) + { + fwprintf(stderr, L"Invalid handle!\n"); + return; + } + + while (SQLGetDiagRec(hType, + hHandle, + ++iRec, + wszState, + &iError, + wszMessage, + (SQLSMALLINT)(sizeof(wszMessage) / sizeof(WCHAR)), + (SQLSMALLINT *)NULL) == SQL_SUCCESS) + { + // Hide data truncated.. + if (wcsncmp(wszState, L"01004", 5)) + { + fwprintf(stderr, L"[%5.5s] %s (%d)\n", wszState, wszMessage, iError); + } + } +} diff --git a/src/connector/odbc/examples/go/odbc.go b/src/connector/odbc/examples/go/odbc.go new file mode 100644 index 0000000000000000000000000000000000000000..4d9c760c4e87a4a899051edc74692ecca8a19d15 --- /dev/null +++ b/src/connector/odbc/examples/go/odbc.go @@ -0,0 +1,84 @@ +package main + +import ( + "context" + "database/sql" + "flag" + "log" + "os" + "os/signal" + "time" + _ "github.com/alexbrainman/odbc" +) + +var pool *sql.DB // Database connection pool. + +func main() { + id := flag.Int64("id", 32768, "person ID to find") + dsn := flag.String("dsn", os.Getenv("DSN"), "connection data source name") + flag.Parse() + + if len(*dsn) == 0 { + log.Fatal("missing dsn flag") + } + if *id == 0 { + log.Fatal("missing person ID") + } + var err error + + // Opening a driver typically will not attempt to connect to the database. + pool, err = sql.Open("odbc", *dsn) + if err != nil { + // This will not be a connection error, but a DSN parse error or + // another initialization error. + log.Fatal("unable to use data source name", err) + } + defer pool.Close() + + pool.SetConnMaxLifetime(0) + pool.SetMaxIdleConns(3) + pool.SetMaxOpenConns(3) + + ctx, stop := context.WithCancel(context.Background()) + defer stop() + + appSignal := make(chan os.Signal, 3) + signal.Notify(appSignal, os.Interrupt) + + go func() { + select { + case <-appSignal: + stop() + } + }() + + Ping(ctx) + + Query(ctx, *id) +} + +// Ping the database to verify DSN provided by the user is valid and the +// server accessible. If the ping fails exit the program with an error. +func Ping(ctx context.Context) { + ctx, cancel := context.WithTimeout(ctx, 1*time.Second) + defer cancel() + + if err := pool.PingContext(ctx); err != nil { + log.Fatalf("unable to connect to database: %v", err) + } +} + +// Query the database for the information requested and prints the results. +// If the query fails exit the program with an error. +func Query(ctx context.Context, id int64) { + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + var name string + err := pool.QueryRowContext(ctx, "select name from m.t").Scan(&name) + if err != nil { + log.Fatal("unable to execute search query", err) + } + log.Println("name=", name) +} + diff --git a/src/connector/odbc/examples/js/.gitignore b/src/connector/odbc/examples/js/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/connector/odbc/examples/js/odbc.js b/src/connector/odbc/examples/js/odbc.js new file mode 100755 index 0000000000000000000000000000000000000000..78a4365c11ddec66666bc54755c9429c34f53af3 --- /dev/null +++ b/src/connector/odbc/examples/js/odbc.js @@ -0,0 +1,122 @@ +#!/usr/bin/env node + +const odbc = require('odbc'); +const path = require('path'); + +function usage() { + var arg = path.basename(process.argv[1]); + console.error(`usage:`); + console.error(`${arg} --DSN --UID --PWD --Server `); + console.error(`${arg} -C `); + console.error(` conn_str eg: 'DSN={TAOS_DSN};UID=root;PWD=taosdata;Server=host:port'`); +} + +var cfg = { }; + +if (process.argv.length==2) { + usage(); + process.exit(0); +} + +var i; +for (i=2; i=process.argv.length) { + console.error(`expecting after --DSN but got nothing`); + usage(process.argv[1]); + process.exit(1); + } + arg = process.argv[i]; + cfg.dsn = arg; + continue; + } + if (arg=="--UID") { + ++i; + if (i>=process.argv.length) { + console.error(`expecting after --UID but got nothing`); + usage(process.argv[1]); + process.exit(1); + } + arg = process.argv[i]; + cfg.uid = arg; + continue; + } + if (arg=="--PWD") { + ++i; + if (i>=process.argv.length) { + console.error(`expecting after --PWD but got nothing`); + usage(process.argv[1]); + process.exit(1); + } + arg = process.argv[i]; + cfg.pwd = arg; + continue; + } + if (arg=="--Server") { + ++i; + if (i>=process.argv.length) { + console.error(`expecting after --Server but got nothing`); + usage(process.argv[1]); + process.exit(1); + } + arg = process.argv[i]; + cfg.server = arg; + continue; + } + if (arg=="-C") { + ++i; + if (i>=process.argv.length) { + console.error(`expecting after -C but got nothing`); + console.error(` conn_str eg: 'DSN={TAOS_DSN};UID=root;PWD=taosdata;Server=host:port'`); + process.exit(1); + } + arg = process.argv[i]; + cfg.conn_str = arg; + continue; + } + console.error(`unknown argument: [${arg}]`); + usage(process.argv[1]); + process.exit(1); +} + +var connectionString = cfg.conn_str; + +if (!cfg.conn_str) { + connectionString = `DSN={${cfg.dsn}}; UID=${cfg.uid}; PWD=${cfg.pwd}; Server=${cfg.server}`; +} + +(async function () { + const connStr = connectionString; + try { + console.log(`connecting [${connStr}]...`); + const connection = await odbc.connect(connStr); + await connection.query('create database if not exists m'); + await connection.query('use m'); + await connection.query('drop table if exists t'); + await connection.query('create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(10), name nchar(3))'); + await connection.query('insert into t values("2020-01-02 12:34:56.781", 1, 127, 32767, 32768, 32769, 123.456, 789.987, "hello", "我和你")'); + console.log('.........'); + result = await connection.query('select * from t'); + console.log(result[0]); + + + statement = await connection.createStatement(); + await statement.prepare('INSERT INTO t (ts, v1) VALUES(?, ?)'); + await statement.bind(['2020-02-02 11:22:33.449', 89]); + result = await statement.execute(); + console.log(result); + + result = await connection.query('select * from t'); + console.log(result[0]); + console.log(result[1]); + } catch (e) { + console.log('error:', e); + } +})(); + diff --git a/src/connector/odbc/examples/js/package.json b/src/connector/odbc/examples/js/package.json new file mode 100644 index 0000000000000000000000000000000000000000..28a04dc32f0d1fc9f1c06de174241b10606f8639 --- /dev/null +++ b/src/connector/odbc/examples/js/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "odbc": "^2.3.6" + } +} diff --git a/src/connector/odbc/examples/lua/odbc.lua b/src/connector/odbc/examples/lua/odbc.lua new file mode 100644 index 0000000000000000000000000000000000000000..e3388358cdab53d7513650192c6a272fadd0e185 --- /dev/null +++ b/src/connector/odbc/examples/lua/odbc.lua @@ -0,0 +1,48 @@ +package.cpath = package.cpath .. ";/usr/local/lib/lib?.dylib" +-- load driver +local driver = require "luasql.odbc" +-- create environment object +env = assert (driver.odbc()) +-- connect to data source +con = assert (env:connect("TAOS_DSN", "root", "taosdata")) +-- reset our table +-- res = con:execute"DROP TABLE people" +-- res = assert (con:execute[[ +-- CREATE TABLE people( +-- name varchar(50), +-- email varchar(50) +-- ) +-- ]]) +-- -- add a few elements +-- list = { +-- { name="Jose das Couves", email="jose@couves.com", }, +-- { name="Manoel Joaquim", email="manoel.joaquim@cafundo.com", }, +-- { name="Maria das Dores", email="maria@dores.com", }, +-- } +-- for i, p in pairs (list) do +-- res = assert (con:execute(string.format([[ +-- INSERT INTO people +-- VALUES ('%s', '%s')]], p.name, p.email) +-- )) +-- end +-- -- retrieve a cursor +-- cur = assert (con:execute"SELECT name, email from people") +-- -- print all rows, the rows will be indexed by field names +-- row = cur:fetch ({}, "a") +-- while row do +-- print(string.format("Name: %s, E-mail: %s", row.name, row.email)) +-- -- reusing the table of results +-- row = cur:fetch (row, "a") +-- end +cur = assert(con:execute"select * from m.t") +row = cur:fetch({}, "a") +while row do + print(string.format("Name: %s", row.name)) + row = cur:fetch(row, "a") +end + +-- close everything +cur:close() -- already closed because all the result set was consumed +con:close() +env:close() + diff --git a/src/connector/odbc/examples/py/odbc.py b/src/connector/odbc/examples/py/odbc.py new file mode 100644 index 0000000000000000000000000000000000000000..e6a4bc73aef3e19bc56e817325acd62d21156d67 --- /dev/null +++ b/src/connector/odbc/examples/py/odbc.py @@ -0,0 +1,111 @@ +import pyodbc +import argparse +import sys + +parser = argparse.ArgumentParser(description='Access TDengine via ODBC.') +parser.add_argument('--DSN', help='DSN to use') +parser.add_argument('--UID', help='UID to use') +parser.add_argument('--PWD', help='PWD to use') +parser.add_argument('--Server', help='Server to use') +parser.add_argument('-C', metavar='CONNSTR', help='Connection string to use') + +args = parser.parse_args() + +a = 'DSN=%s'%args.DSN if args.DSN else None +b = 'UID=%s'%args.UID if args.UID else None +c = 'PWD=%s'%args.PWD if args.PWD else None +d = 'Server=%s'%args.Server if args.Server else None +conn_str = ';'.join(filter(None, [a,b,c,d])) if args.DSN else None +conn_str = conn_str if conn_str else args.C +if not conn_str: + parser.print_help(file=sys.stderr) + exit() + +print('connecting: [%s]' % conn_str) +cnxn = pyodbc.connect(conn_str, autocommit=True) +cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8') + +cursor = cnxn.cursor() +cursor.execute("drop database if exists db"); +cursor.close() + +cursor = cnxn.cursor() +cursor.execute("create database db"); +cursor.close() + +cursor = cnxn.cursor() +cursor.execute("create table db.mt (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(10), blob nchar(10))"); +cursor.close() + +cursor = cnxn.cursor() +cursor.execute("insert into db.mt values('2020-10-13 06:44:00.123', 1, 127, 32767, 2147483647, 32769, 123.456, 789.987, 'hello', 'helloworld')") +cursor.close() + +cursor = cnxn.cursor() +cursor.execute("insert into db.mt values(?,?,?,?,?,?,?,?,?,?)", "2020-10-13 07:06:00.234", 0, 127, 32767, 32768, 32769, 123.456, 789.987, "hel后lo".encode('utf-8'), "wo哈rlxd129") +##cursor.execute("insert into db.mt values(?,?,?,?,?,?,?,?,?,?)", 1502535178128, 9223372036854775807, 127, 32767, 32768, 32769, 123.456, 789.987, "hel后lo".encode('utf-8'), "wo哈rlxd123"); +cursor.close() + +cursor = cnxn.cursor() +cursor.execute(""" +INSERT INTO db.mt (ts,b,v1,v2,v4,v8,f4,f8,bin,blob) values (?,?,?,?,?,?,?,?,?,?) +""", +"2020-12-12 00:00:00", +'true', +'-127', +'-32767', +'-2147483647', +'-9223372036854775807', +'-1.23e10', +'-11.23e6', +'abcdefghij'.encode('utf-8'), +"人啊大发测试及abc") +cursor.close() + +cursor = cnxn.cursor() +cursor.execute("drop database if exists db"); +cursor.close() + +cursor = cnxn.cursor() +cursor.execute("create database db"); +cursor.close() + +cursor = cnxn.cursor() +cursor.execute("create table db.t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(4), blob nchar(4))"); +cursor.close() + +cursor = cnxn.cursor() +cursor.execute("insert into db.t values('2020-10-13 06:44:00', 1, 127, 32767, 32768, 32769, 123.456, 789.987, 'hell', 'w我你z')") +cursor.close() + +cursor = cnxn.cursor() +cursor.execute("create table db.v (ts timestamp, v1 tinyint, v2 smallint, name nchar(10), ts2 timestamp)") +cursor.close() + +params = [ ('2020-10-16 00:00:00.123', 19, '2111-01-02 01:02:03.123'), + ('2020-10-16 00:00:01', 41, '2111-01-02 01:02:03.423'), + ('2020-10-16 00:00:02', 57, '2111-01-02 01:02:03.153'), + ('2020-10-16 00:00:03.009', 26, '2111-01-02 01:02:03.623') ] +cursor = cnxn.cursor() +cursor.fast_executemany = True +print('py:...................') +cursor.executemany("insert into db.v (ts, v1, ts2) values (?, ?, ?)", params) +print('py:...................') +cursor.close() + +## cursor = cnxn.cursor() +## cursor.execute("SELECT * from db.v where v1 > ?", 4) +## row = cursor.fetchone() +## while row: +## print(row) +## row = cursor.fetchone() +## cursor.close() +## +## cursor = cnxn.cursor() +## cursor.execute("SELECT * from db.v where v1 > ?", '5') +## row = cursor.fetchone() +## while row: +## print(row) +## row = cursor.fetchone() +## cursor.close() + diff --git a/src/connector/odbc/examples/rust/.gitignore b/src/connector/odbc/examples/rust/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..03314f77b5aa454994bf08c40943f4012964eb0a --- /dev/null +++ b/src/connector/odbc/examples/rust/.gitignore @@ -0,0 +1 @@ +Cargo.lock diff --git a/src/connector/odbc/examples/rust/main/Cargo.toml b/src/connector/odbc/examples/rust/main/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..171dcf52b2bfcf3bb56fa49c4e228871311e90aa --- /dev/null +++ b/src/connector/odbc/examples/rust/main/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "main" +version = "0.1.0" +authors = ["freemine "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +odbc = "0.17.0" +env_logger = "0.8.2" + diff --git a/src/connector/odbc/examples/rust/main/src/main.rs b/src/connector/odbc/examples/rust/main/src/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..112f0d309b51a0a75a7e580f764c697a2215b9da --- /dev/null +++ b/src/connector/odbc/examples/rust/main/src/main.rs @@ -0,0 +1,49 @@ +extern crate odbc; +// Use this crate and set environmet variable RUST_LOG=odbc to see ODBC warnings +extern crate env_logger; +use odbc::*; +use odbc_safe::AutocommitOn; +use std::env; + +fn main() { + + env_logger::init(); + + let conn_str = env::var("DSN").unwrap(); + match connect(&conn_str) { + Ok(()) => println!("Success"), + Err(diag) => println!("Error: {}", diag), + } +} + +fn connect(conn_str: &str) -> std::result::Result<(), DiagnosticRecord> { + + let env = create_environment_v3().map_err(|e| e.unwrap())?; + + let conn = env.connect_with_connection_string(conn_str)?; + execute_statement(&conn) +} + +fn execute_statement<'env>(conn: &Connection<'env, AutocommitOn>) -> Result<()> { + let stmt = Statement::with_parent(conn)?; + + match stmt.exec_direct("select * from m.t")? { + Data(mut stmt) => { + let cols = stmt.num_result_cols()?; + println!("cols: {}", cols); + while let Some(mut cursor) = stmt.fetch()? { + for i in 1..(cols + 1) { + match cursor.get_data::<&str>(i as u16)? { + Some(val) => print!(" {}", val), + None => print!(" NULL"), + } + } + println!(""); + } + } + NoData(_) => println!("Query executed, no data returned"), + } + + Ok(()) +} + diff --git a/src/connector/odbc/tests/create_data.stmts b/src/connector/odbc/samples/create_data.stmts similarity index 51% rename from src/connector/odbc/tests/create_data.stmts rename to src/connector/odbc/samples/create_data.stmts index 549cb583d8322906b4bdaffafde8eb510cb91c90..3d41c0db6447ed8a45390c2a50d73697992dbf52 100644 --- a/src/connector/odbc/tests/create_data.stmts +++ b/src/connector/odbc/samples/create_data.stmts @@ -1,12 +1,17 @@ +#P: positive sample +#N: negative sample + P:drop database if exists m; P:create database m; P:use m; P:drop table if exists t; -P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(3), name nchar(1)); -P:insert into t (ts, blob, name) values('2020-10-10 00:00:00', 0, 1); -P:insert into t (ts, blob, name) values('2020-10-10 00:00:00.001', 1, 2); +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(3), name nchar(1), ts2 nchar(148)); +#P:insert into t (ts, blob, name) values('2020-10-10 00:00:00', 0, 1); +#P:insert into t (ts, blob, name) values('2020-10-10 00:00:00.001', 1, 2); P:insert into t (ts, blob, name) values('2020-10-10 00:00:00.002', '你', '好'); P:insert into t (ts, blob, name) values('2020-10-10 00:00:00.003', 'abc', 'd'); P:select * from t; +P:create table v (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(3), name nchar(1), ts2 nchar(23)); + diff --git a/src/connector/odbc/tests/query_data.stmts b/src/connector/odbc/samples/query_data.stmts similarity index 100% rename from src/connector/odbc/tests/query_data.stmts rename to src/connector/odbc/samples/query_data.stmts diff --git a/src/connector/odbc/tests/select.stmts b/src/connector/odbc/samples/select.stmts similarity index 100% rename from src/connector/odbc/tests/select.stmts rename to src/connector/odbc/samples/select.stmts diff --git a/src/connector/odbc/tests/simples.stmts b/src/connector/odbc/samples/simples.stmts similarity index 100% rename from src/connector/odbc/tests/simples.stmts rename to src/connector/odbc/samples/simples.stmts diff --git a/src/connector/odbc/src/CMakeLists.txt b/src/connector/odbc/src/CMakeLists.txt index 2699e1bc90e162c80d27d690e1f7163747616526..f0e50415e2e4f14e1c247b834e1e52a2c2fd2868 100644 --- a/src/connector/odbc/src/CMakeLists.txt +++ b/src/connector/odbc/src/CMakeLists.txt @@ -1,6 +1,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) +add_subdirectory(base) + IF (TD_LINUX_64) FLEX_TARGET(todbcFlexScanner todbc_scanner.l @@ -15,12 +17,35 @@ IF (TD_LINUX_64) ADD_LIBRARY(todbc SHARED ${SRC} ${todbc_flex_scanner_src}) SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1) SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1) - TARGET_LINK_LIBRARIES(todbc taos odbcinst) + TARGET_LINK_LIBRARIES(todbc todbc_base taos odbcinst) target_include_directories(todbc PUBLIC .) install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/install.sh ${CMAKE_BINARY_DIR})") ENDIF () +IF (TD_DARWIN) + FLEX_TARGET(todbcFlexScanner + todbc_scanner.l + ${CMAKE_CURRENT_BINARY_DIR}/todbc_scanner.c + ) + set(todbc_flex_scanner_src + ${FLEX_todbcFlexScanner_OUTPUTS} + ) + set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/todbc_scanner.c PROPERTIES COMPILE_OPTIONS "-Wno-conversion") + AUX_SOURCE_DIRECTORY(. SRC) + + # generate dynamic library (*.dylib) + ADD_LIBRARY(todbc SHARED ${SRC} ${todbc_flex_scanner_src}) + SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1) + TARGET_LINK_LIBRARIES(todbc todbc_base taos odbcinst) + target_include_directories(todbc PUBLIC .) + target_include_directories(todbc PRIVATE /usr/local/include) + target_link_directories(todbc PUBLIC /usr/local/lib) + + install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/install.sh ${CMAKE_BINARY_DIR})") +ENDIF () + IF (TD_WINDOWS_64) FLEX_TARGET(todbcFlexScanner todbc_scanner.l @@ -37,7 +62,7 @@ IF (TD_WINDOWS_64) ${todbc_flex_scanner_src} ${CMAKE_CURRENT_BINARY_DIR}/todbc.rc todbc.def) - TARGET_LINK_LIBRARIES(todbc taos_static odbccp32 legacy_stdio_definitions) + TARGET_LINK_LIBRARIES(todbc todbc_base taos_static odbccp32 legacy_stdio_definitions) target_include_directories(todbc PUBLIC .) target_compile_definitions(todbc PRIVATE "todbc_EXPORT") @@ -52,3 +77,4 @@ IF (TD_WINDOWS_64) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.exp DESTINATION driver) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.dll DESTINATION driver) ENDIF () + diff --git a/src/connector/odbc/src/base.c b/src/connector/odbc/src/base.c new file mode 100644 index 0000000000000000000000000000000000000000..54b55b48edcc63c444e05e2b3a234ac98025506e --- /dev/null +++ b/src/connector/odbc/src/base.c @@ -0,0 +1,2713 @@ +#include "base.h" + +#include "base/env.h" +#include "base/null_conn.h" +#include "base/tsdb_impl.h" + +#include "todbc_flex.h" +#include "todbc_tls.h" +#include "todbc_util.h" + +#ifdef _MSC_VER +#include +#endif // _MSC_VER + +#define PROFILING 0 +#define LOGGING 0 + +#define PROFILE(r_0911, statement) \ +do { \ + if (!PROFILING) { \ + if (LOGGING) D(""); \ + statement; \ + if (LOGGING) D("r=%zx", (size_t)r_0911); \ + break; \ + } \ + if (LOGGING) D(""); \ + struct timeval tv0, tv1; \ + gettimeofday(&tv0, NULL); \ + statement; \ + gettimeofday(&tv1, NULL); \ + double delta = difftime(tv1.tv_sec, tv0.tv_sec); \ + delta *= 1000000; \ + delta += (double)(tv1.tv_usec-tv0.tv_usec); \ + delta /= 1000000; \ + D("%s: elapsed: [%.6f]s", #statement, delta); \ + if (LOGGING) D("r=%zx", (size_t)r_0911); \ +} while (0) + +#define P(fmt,...) do { \ + if (LOGGING) { \ + D(fmt, ##__VA_ARGS__); \ + } \ +} while (0) + + + +static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle, SQLHDBC *ConnectionHandle); + +SQLRETURN SQL_API SQLAllocConnect(SQLHENV EnvironmentHandle, SQLHDBC *ConnectionHandle) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_ENV, EnvironmentHandle); + PROFILE(r, r = doSQLAllocConnect(EnvironmentHandle, ConnectionHandle)); + todbc_tls_buf_reclaim(); + return r; +} + + +static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle); + +SQLRETURN SQL_API SQLAllocEnv(SQLHENV *EnvironmentHandle) +{ + SQLRETURN r; + PROFILE(r, r = doSQLAllocEnv(EnvironmentHandle)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE *OutputHandle); + +SQLRETURN SQL_API SQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE *OutputHandle) +{ + SQLRETURN r; + // HandleType is NOT the type of InputHandle + PROFILE(r, r = doSQLAllocHandle(HandleType, InputHandle, OutputHandle)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLAllocStmt(SQLHDBC ConnectionHandle, SQLHSTMT *StatementHandle); + +SQLRETURN SQL_API SQLAllocStmt(SQLHDBC ConnectionHandle, SQLHSTMT *StatementHandle) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_DBC, ConnectionHandle); + PROFILE(r, r = doSQLAllocStmt(ConnectionHandle, StatementHandle)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLBindCol(SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, + SQLPOINTER TargetValue, + SQLLEN BufferLength, SQLLEN *StrLen_or_IndPtr); + +SQLRETURN SQL_API SQLBindCol(SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, + SQLPOINTER TargetValue, + SQLLEN BufferLength, SQLLEN *StrLen_or_IndPtr) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLBindCol(StatementHandle, ColumnNumber, TargetType, + TargetValue, BufferLength, StrLen_or_IndPtr)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLBindParam(SQLHSTMT StatementHandle, + SQLUSMALLINT ParameterNumber, SQLSMALLINT ValueType, + SQLSMALLINT ParameterType, SQLULEN LengthPrecision, + SQLSMALLINT ParameterScale, SQLPOINTER ParameterValue, + SQLLEN *StrLen_or_IndPtr) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLCancel(SQLHSTMT StatementHandle) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLCancelHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle) +{ + SQLRETURN r; + errs_clear(HandleType, InputHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLCloseCursor(SQLHSTMT StatementHandle); + +SQLRETURN SQL_API SQLCloseCursor(SQLHSTMT StatementHandle) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLCloseCursor(StatementHandle)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLColAttribute (SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, + SQLPOINTER CharacterAttribute, SQLSMALLINT BufferLength, + SQLSMALLINT *StringLength, SQLLEN *NumericAttribute) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLColumns(SQLHSTMT StatementHandle, + SQLCHAR *CatalogName, SQLSMALLINT NameLength1, + SQLCHAR *SchemaName, SQLSMALLINT NameLength2, + SQLCHAR *TableName, SQLSMALLINT NameLength3, + SQLCHAR *ColumnName, SQLSMALLINT NameLength4) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLCompleteAsync(SQLSMALLINT HandleType, SQLHANDLE Handle, RETCODE* AsyncRetCodePtr) +{ + SQLRETURN r; + errs_clear(HandleType, Handle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, + SQLCHAR *ServerName, SQLSMALLINT NameLength1, + SQLCHAR *UserName, SQLSMALLINT NameLength2, + SQLCHAR *Authentication, SQLSMALLINT NameLength3); + +SQLRETURN SQL_API SQLConnect(SQLHDBC ConnectionHandle, + SQLCHAR *ServerName, SQLSMALLINT NameLength1, + SQLCHAR *UserName, SQLSMALLINT NameLength2, + SQLCHAR *Authentication, SQLSMALLINT NameLength3) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_DBC, ConnectionHandle); + PROFILE(r, r = doSQLConnect(ConnectionHandle, ServerName, NameLength1, UserName, NameLength2, Authentication, NameLength3)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLCopyDesc(SQLHDESC SourceDescHandle, SQLHDESC TargetDescHandle) +{ + SQLRETURN r; + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLDataSources(SQLHENV EnvironmentHandle, + SQLUSMALLINT Direction, SQLCHAR *ServerName, SQLSMALLINT BufferLength1, SQLSMALLINT *NameLength1Ptr, + SQLCHAR *Description, SQLSMALLINT BufferLength2, + SQLSMALLINT *NameLength2Ptr) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_ENV, EnvironmentHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, SQLCHAR *ColumnName, SQLSMALLINT BufferLength, + SQLSMALLINT *NameLength, + SQLSMALLINT *DataType, SQLULEN *ColumnSize, + SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable); + +SQLRETURN SQL_API SQLDescribeCol(SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, SQLCHAR *ColumnName, SQLSMALLINT BufferLength, + SQLSMALLINT *NameLength, + SQLSMALLINT *DataType, SQLULEN *ColumnSize, + SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLDescribeCol(StatementHandle, ColumnNumber, ColumnName, BufferLength, + NameLength, DataType, ColumnSize, DecimalDigits, Nullable)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLDisconnect(SQLHDBC ConnectionHandle); + +SQLRETURN SQL_API SQLDisconnect(SQLHDBC ConnectionHandle) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_DBC, ConnectionHandle); + PROFILE(r, r = doSQLDisconnect(ConnectionHandle)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLEndTran(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT CompletionType) +{ + SQLRETURN r; + errs_clear(HandleType, Handle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLError(SQLHENV EnvironmentHandle, + SQLHDBC ConnectionHandle, SQLHSTMT StatementHandle, + SQLCHAR *Sqlstate, SQLINTEGER *NativeError, + SQLCHAR *MessageText, SQLSMALLINT BufferLength, + SQLSMALLINT *TextLength); + +SQLRETURN SQL_API not_support_SQLError(SQLHENV EnvironmentHandle, + SQLHDBC ConnectionHandle, SQLHSTMT StatementHandle, + SQLCHAR *Sqlstate, SQLINTEGER *NativeError, + SQLCHAR *MessageText, SQLSMALLINT BufferLength, + SQLSMALLINT *TextLength) +{ + SQLRETURN r; + PROFILE(r, r = doSQLError(EnvironmentHandle, ConnectionHandle, StatementHandle, + Sqlstate, NativeError, MessageText, BufferLength, TextLength)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, SQLCHAR* StatementText, SQLINTEGER TextLength); + +SQLRETURN SQL_API SQLExecDirect(SQLHSTMT StatementHandle, SQLCHAR* StatementText, SQLINTEGER TextLength) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLExecDirect(StatementHandle, StatementText, TextLength)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLExecute(SQLHSTMT StatementHandle); + +SQLRETURN SQL_API SQLExecute(SQLHSTMT StatementHandle) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLExecute(StatementHandle)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLFetch(SQLHSTMT StatementHandle); + +SQLRETURN SQL_API SQLFetch(SQLHSTMT StatementHandle) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLFetch(StatementHandle)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLFetchScroll(SQLHSTMT StatementHandle, SQLSMALLINT FetchOrientation, SQLLEN FetchOffset) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLFreeConnect(SQLHDBC ConnectionHandle); + +SQLRETURN SQL_API SQLFreeConnect(SQLHDBC ConnectionHandle) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_DBC, ConnectionHandle); + PROFILE(r, r = doSQLFreeConnect(ConnectionHandle)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLFreeEnv(SQLHENV EnvironmentHandle); + +SQLRETURN SQL_API SQLFreeEnv(SQLHENV EnvironmentHandle) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_ENV, EnvironmentHandle); + PROFILE(r, r = doSQLFreeEnv(EnvironmentHandle)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle); + +SQLRETURN SQL_API SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle) +{ + SQLRETURN r; + errs_clear(HandleType, Handle); + PROFILE(r, r = doSQLFreeHandle(HandleType, Handle)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLFreeStmt(SQLHSTMT StatementHandle, SQLUSMALLINT Option); + +SQLRETURN SQL_API SQLFreeStmt(SQLHSTMT StatementHandle, SQLUSMALLINT Option) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLFreeStmt(StatementHandle, Option)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLGetConnectAttr(SQLHDBC ConnectionHandle, + SQLINTEGER Attribute, SQLPOINTER Value, + SQLINTEGER BufferLength, SQLINTEGER *StringLengthPtr) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_DBC, ConnectionHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLGetConnectOption(SQLHDBC ConnectionHandle, SQLUSMALLINT Option, SQLPOINTER Value) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_DBC, ConnectionHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLGetCursorName(SQLHSTMT StatementHandle, SQLCHAR *CursorName, SQLSMALLINT BufferLength, SQLSMALLINT *NameLengthPtr) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, + SQLPOINTER TargetValue, SQLLEN BufferLength, + SQLLEN *StrLen_or_IndPtr); + +SQLRETURN SQL_API SQLGetData(SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, + SQLPOINTER TargetValue, SQLLEN BufferLength, + SQLLEN *StrLen_or_IndPtr) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLGetData(StatementHandle, ColumnNumber, TargetType, TargetValue, BufferLength, StrLen_or_IndPtr)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLGetDescField(SQLHDESC DescriptorHandle, + SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier, + SQLPOINTER Value, SQLINTEGER BufferLength, + SQLINTEGER *StringLength) +{ + SQLRETURN r; + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLGetDescRec(SQLHDESC DescriptorHandle, + SQLSMALLINT RecNumber, SQLCHAR *Name, + SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr, + SQLSMALLINT *TypePtr, SQLSMALLINT *SubTypePtr, + SQLLEN *LengthPtr, SQLSMALLINT *PrecisionPtr, + SQLSMALLINT *ScalePtr, SQLSMALLINT *NullablePtr) +{ + SQLRETURN r; + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier, + SQLPOINTER DiagInfo, SQLSMALLINT BufferLength, SQLSMALLINT *StringLength); + +SQLRETURN SQL_API SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier, + SQLPOINTER DiagInfo, SQLSMALLINT BufferLength, SQLSMALLINT *StringLength) +{ + SQLRETURN r; + PROFILE(r, r = doSQLGetDiagField(HandleType, Handle, RecNumber, DiagIdentifier, + DiagInfo, BufferLength, StringLength)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, + SQLCHAR *Sqlstate, SQLINTEGER *NativeError, SQLCHAR* MessageText, SQLSMALLINT BufferLength, SQLSMALLINT *TextLength); + +SQLRETURN SQL_API SQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, + SQLCHAR *Sqlstate, SQLINTEGER *NativeError, SQLCHAR* MessageText, SQLSMALLINT BufferLength, SQLSMALLINT *TextLength) +{ + SQLRETURN r; + PROFILE(r, r = doSQLGetDiagRec(HandleType, Handle, RecNumber, Sqlstate, NativeError, MessageText, BufferLength, TextLength)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLGetEnvAttr(SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER Value, + SQLINTEGER BufferLength, SQLINTEGER *StringLength); + +SQLRETURN SQL_API SQLGetEnvAttr(SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER Value, + SQLINTEGER BufferLength, SQLINTEGER *StringLength) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_ENV, EnvironmentHandle); + PROFILE(r, r = doSQLGetEnvAttr(EnvironmentHandle, Attribute, Value, BufferLength, StringLength)); + todbc_tls_buf_reclaim(); + return r; +} + +// SQLRETURN SQL_API SQLGetFunctions(SQLHDBC ConnectionHandle, SQLUSMALLINT FunctionId, SQLUSMALLINT *Supported) +// { +// SQLRETURN r; +// errs_clear(SQL_HANDLE_DBC, ConnectionHandle); +// PROFILE(r, r = SQL_ERROR); +// todbc_tls_buf_reclaim(); +// return r; +// } + +static SQLRETURN doSQLGetInfo(SQLHDBC ConnectionHandle, SQLUSMALLINT InfoType, SQLPOINTER InfoValue, + SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr); + +SQLRETURN SQL_API SQLGetInfo(SQLHDBC ConnectionHandle, SQLUSMALLINT InfoType, SQLPOINTER InfoValue, + SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_DBC, ConnectionHandle); + PROFILE(r, r = doSQLGetInfo(ConnectionHandle, InfoType, InfoValue, BufferLength, StringLengthPtr)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLGetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER Value, + SQLINTEGER BufferLength, SQLINTEGER *StringLength); + +SQLRETURN SQL_API SQLGetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER Value, + SQLINTEGER BufferLength, SQLINTEGER *StringLength) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLGetStmtAttr(StatementHandle, Attribute, Value, BufferLength, StringLength)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLGetStmtOption(SQLHSTMT StatementHandle, + SQLUSMALLINT Option, SQLPOINTER Value) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLGetTypeInfo(SQLHSTMT StatementHandle, SQLSMALLINT DataType); + +SQLRETURN SQL_API SQLGetTypeInfo(SQLHSTMT StatementHandle, SQLSMALLINT DataType) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLGetTypeInfo(StatementHandle, DataType)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLNumResultCols(SQLHSTMT StatementHandle, SQLSMALLINT *ColumnCount); + +SQLRETURN SQL_API SQLNumResultCols(SQLHSTMT StatementHandle, SQLSMALLINT *ColumnCount) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLNumResultCols(StatementHandle, ColumnCount)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLParamData(SQLHSTMT StatementHandle, SQLPOINTER *Value) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, SQLCHAR* StatementText, SQLINTEGER TextLength); + +SQLRETURN SQL_API SQLPrepare(SQLHSTMT StatementHandle, SQLCHAR* StatementText, SQLINTEGER TextLength) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLPrepare(StatementHandle, StatementText, TextLength)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLPutData(SQLHSTMT StatementHandle, SQLPOINTER Data, SQLLEN StrLen_or_Ind) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLRowCount(SQLHSTMT StatementHandle, SQLLEN* RowCount); + +SQLRETURN SQL_API SQLRowCount(SQLHSTMT StatementHandle, SQLLEN* RowCount) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLRowCount(StatementHandle, RowCount)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLSetConnectAttr(SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_DBC, ConnectionHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLSetConnectOption(SQLHDBC ConnectionHandle, SQLUSMALLINT Option, SQLULEN Value) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_DBC, ConnectionHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLSetCursorName(SQLHSTMT StatementHandle, SQLCHAR* CursorName, SQLSMALLINT NameLength) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLSetDescField(SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier, + SQLPOINTER Value, SQLINTEGER BufferLength) +{ + SQLRETURN r; + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLSetDescRec(SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber, SQLSMALLINT Type, + SQLSMALLINT SubType, SQLLEN Length, SQLSMALLINT Precision, SQLSMALLINT Scale, + SQLPOINTER Data, SQLLEN *StringLength, SQLLEN *Indicator) +{ + SQLRETURN r; + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLSetEnvAttr(SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength); + +SQLRETURN SQL_API SQLSetEnvAttr(SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_ENV, EnvironmentHandle); + PROFILE(r, r = doSQLSetEnvAttr(EnvironmentHandle, Attribute, Value, StringLength)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLSetParam(SQLHSTMT StatementHandle, SQLUSMALLINT ParameterNumber, SQLSMALLINT ValueType, + SQLSMALLINT ParameterType, SQLULEN LengthPrecision, SQLSMALLINT ParameterScale, SQLPOINTER ParameterValue, + SQLLEN *StrLen_or_IndPtr) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLSetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength); + +SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLSetStmtAttr(StatementHandle, Attribute, Value, StringLength)); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLSetStmtOption(SQLHSTMT StatementHandle, SQLUSMALLINT Option, SQLULEN Value) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLSpecialColumns(SQLHSTMT StatementHandle, SQLUSMALLINT IdentifierType, + SQLCHAR *CatalogName, SQLSMALLINT NameLength1, + SQLCHAR *SchemaName, SQLSMALLINT NameLength2, + SQLCHAR *TableName, SQLSMALLINT NameLength3, + SQLUSMALLINT Scope, SQLUSMALLINT Nullable) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLStatistics(SQLHSTMT StatementHandle, + SQLCHAR *CatalogName, SQLSMALLINT NameLength1, + SQLCHAR *SchemaName, SQLSMALLINT NameLength2, + SQLCHAR *TableName, SQLSMALLINT NameLength3, + SQLUSMALLINT Unique, SQLUSMALLINT Reserved) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLTables(SQLHSTMT StatementHandle, + SQLCHAR *CatalogName, SQLSMALLINT NameLength1, + SQLCHAR *SchemaName, SQLSMALLINT NameLength2, + SQLCHAR *TableName, SQLSMALLINT NameLength3, + SQLCHAR *TableType, SQLSMALLINT NameLength4) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + +SQLRETURN SQL_API SQLTransact(SQLHENV EnvironmentHandle, SQLHDBC ConnectionHandle, SQLUSMALLINT CompletionType) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_ENV, EnvironmentHandle); + errs_clear(SQL_HANDLE_DBC, ConnectionHandle); + PROFILE(r, r = SQL_ERROR); + todbc_tls_buf_reclaim(); + return r; +} + + + + +static SQLRETURN doSQLDriverConnect( + SQLHDBC ConnectionHandle, + SQLHWND WindowHandle, + SQLCHAR *InConnectionString, + SQLSMALLINT StringLength1, + SQLCHAR *OutConnectionString, + SQLSMALLINT BufferLength, + SQLSMALLINT *StringLength2Ptr, + SQLUSMALLINT DriverCompletion); + +SQLRETURN SQL_API SQLDriverConnect( + SQLHDBC ConnectionHandle, + SQLHWND WindowHandle, + SQLCHAR *InConnectionString, + SQLSMALLINT StringLength1, + SQLCHAR *OutConnectionString, + SQLSMALLINT BufferLength, + SQLSMALLINT *StringLength2Ptr, + SQLUSMALLINT DriverCompletion) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_DBC, ConnectionHandle); + PROFILE(r, r = doSQLDriverConnect(ConnectionHandle, WindowHandle, InConnectionString, StringLength1, + OutConnectionString, BufferLength, StringLength2Ptr, DriverCompletion)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLBindParameter( + SQLHSTMT StatementHandle, + SQLUSMALLINT ParameterNumber, + SQLSMALLINT InputOutputType, + SQLSMALLINT ValueType, + SQLSMALLINT ParameterType, + SQLULEN ColumnSize, + SQLSMALLINT DecimalDigits, + SQLPOINTER ParameterValuePtr, + SQLLEN BufferLength, + SQLLEN * StrLen_or_IndPtr); + +SQLRETURN SQL_API SQLBindParameter( + SQLHSTMT StatementHandle, + SQLUSMALLINT ParameterNumber, + SQLSMALLINT InputOutputType, + SQLSMALLINT ValueType, + SQLSMALLINT ParameterType, + SQLULEN ColumnSize, + SQLSMALLINT DecimalDigits, + SQLPOINTER ParameterValuePtr, + SQLLEN BufferLength, + SQLLEN * StrLen_or_IndPtr) +{ + SQLRETURN r; + P("ParameterNumber:[%d]; InputOutputType:[%d]%s; ValueType:[%d]%s; ParameterType:[%d]%s; " + "ColumnSize:[%ld]; DecimalDigits:[%d]; ParameterValuePtr:[%p]; BufferLength:[%ld]; StrLen_or_IndPtr:[%p]", + ParameterNumber, InputOutputType, sql_input_output_type(InputOutputType), + ValueType, sql_c_type(ValueType), + ParameterType, sql_sql_type(ParameterType), + ColumnSize, DecimalDigits, ParameterValuePtr, BufferLength, StrLen_or_IndPtr); + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLBindParameter(StatementHandle, ParameterNumber, InputOutputType, ValueType, ParameterType, + ColumnSize, DecimalDigits, ParameterValuePtr, BufferLength, StrLen_or_IndPtr)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLNumParams(SQLHSTMT StatementHandle, SQLSMALLINT *ParameterCountPtr); + +SQLRETURN SQL_API SQLNumParams(SQLHSTMT StatementHandle, SQLSMALLINT *ParameterCountPtr) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLNumParams(StatementHandle, ParameterCountPtr)); + todbc_tls_buf_reclaim(); + return r; +} + +static SQLRETURN doSQLDescribeParam( + SQLHSTMT StatementHandle, + SQLUSMALLINT ParameterNumber, + SQLSMALLINT * DataTypePtr, + SQLULEN * ParameterSizePtr, + SQLSMALLINT * DecimalDigitsPtr, + SQLSMALLINT * NullablePtr); + +SQLRETURN SQL_API SQLDescribeParam( + SQLHSTMT StatementHandle, + SQLUSMALLINT ParameterNumber, + SQLSMALLINT * DataTypePtr, + SQLULEN * ParameterSizePtr, + SQLSMALLINT * DecimalDigitsPtr, + SQLSMALLINT * NullablePtr) +{ + SQLRETURN r; + errs_clear(SQL_HANDLE_STMT, StatementHandle); + PROFILE(r, r = doSQLDescribeParam(StatementHandle, ParameterNumber, DataTypePtr, + ParameterSizePtr, DecimalDigitsPtr, NullablePtr)); + todbc_tls_buf_reclaim(); + return r; +} + + + + + +SQLRETURN SQL_API SQLBrowseConnect( + SQLHDBC hdbc, + SQLCHAR *szConnStrIn, + SQLSMALLINT cchConnStrIn, + SQLCHAR *szConnStrOut, + SQLSMALLINT cchConnStrOutMax, + SQLSMALLINT *pcchConnStrOut); + +SQLRETURN SQL_API SQLBulkOperations( + SQLHSTMT StatementHandle, + SQLSMALLINT Operation); + +SQLRETURN SQL_API SQLColAttributes( + SQLHSTMT hstmt, + SQLUSMALLINT icol, + SQLUSMALLINT fDescType, + SQLPOINTER rgbDesc, + SQLSMALLINT cbDescMax, + SQLSMALLINT *pcbDesc, + SQLLEN * pfDesc); + +SQLRETURN SQL_API SQLColumnPrivileges( + SQLHSTMT hstmt, + SQLCHAR *szCatalogName, + SQLSMALLINT cchCatalogName, + SQLCHAR *szSchemaName, + SQLSMALLINT cchSchemaName, + SQLCHAR *szTableName, + SQLSMALLINT cchTableName, + SQLCHAR *szColumnName, + SQLSMALLINT cchColumnName); + +SQLRETURN SQL_API SQLExtendedFetch( + SQLHSTMT hstmt, + SQLUSMALLINT fFetchType, + SQLLEN irow, + SQLULEN *pcrow, + SQLUSMALLINT *rgfRowStatus); + +SQLRETURN SQL_API SQLForeignKeys( + SQLHSTMT hstmt, + SQLCHAR *szPkCatalogName, + SQLSMALLINT cchPkCatalogName, + SQLCHAR *szPkSchemaName, + SQLSMALLINT cchPkSchemaName, + SQLCHAR *szPkTableName, + SQLSMALLINT cchPkTableName, + SQLCHAR *szFkCatalogName, + SQLSMALLINT cchFkCatalogName, + SQLCHAR *szFkSchemaName, + SQLSMALLINT cchFkSchemaName, + SQLCHAR *szFkTableName, + SQLSMALLINT cchFkTableName); + +SQLRETURN SQL_API SQLMoreResults( + SQLHSTMT hstmt); + +SQLRETURN SQL_API SQLNativeSql +( + SQLHDBC hdbc, + SQLCHAR* szSqlStrIn, + SQLINTEGER cchSqlStrIn, + SQLCHAR* szSqlStr, + SQLINTEGER cchSqlStrMax, + SQLINTEGER *pcbSqlStr +); + +SQLRETURN SQL_API SQLParamOptions( + SQLHSTMT hstmt, + SQLULEN crow, + SQLULEN *pirow); + +SQLRETURN SQL_API SQLPrimaryKeys( + SQLHSTMT hstmt, + SQLCHAR *szCatalogName, + SQLSMALLINT cchCatalogName, + SQLCHAR *szSchemaName, + SQLSMALLINT cchSchemaName, + SQLCHAR *szTableName, + SQLSMALLINT cchTableName); + +SQLRETURN SQL_API SQLProcedureColumns( + SQLHSTMT hstmt, + SQLCHAR *szCatalogName, + SQLSMALLINT cchCatalogName, + SQLCHAR *szSchemaName, + SQLSMALLINT cchSchemaName, + SQLCHAR *szProcName, + SQLSMALLINT cchProcName, + SQLCHAR *szColumnName, + SQLSMALLINT cchColumnName); + +SQLRETURN SQL_API SQLProcedures( + SQLHSTMT hstmt, + SQLCHAR *szCatalogName, + SQLSMALLINT cchCatalogName, + SQLCHAR *szSchemaName, + SQLSMALLINT cchSchemaName, + SQLCHAR *szProcName, + SQLSMALLINT cchProcName); + + + +SQLRETURN SQL_API SQLSetPos( + SQLHSTMT hstmt, + SQLSETPOSIROW irow, + SQLUSMALLINT fOption, + SQLUSMALLINT fLock); + +SQLRETURN SQL_API SQLTablePrivileges( + SQLHSTMT hstmt, + SQLCHAR *szCatalogName, + SQLSMALLINT cchCatalogName, + SQLCHAR *szSchemaName, + SQLSMALLINT cchSchemaName, + SQLCHAR *szTableName, + SQLSMALLINT cchTableName); + +SQLRETURN SQL_API SQLDrivers( + SQLHENV henv, + SQLUSMALLINT fDirection, + SQLCHAR *szDriverDesc, + SQLSMALLINT cchDriverDescMax, + SQLSMALLINT *pcchDriverDesc, + SQLCHAR *szDriverAttributes, + SQLSMALLINT cchDrvrAttrMax, + SQLSMALLINT *pcchDrvrAttr); + +SQLRETURN SQL_API SQLAllocHandleStd( + SQLSMALLINT fHandleType, + SQLHANDLE hInput, + SQLHANDLE *phOutput); +SQLRETURN SQL_API SQLSetScrollOptions( + SQLHSTMT hstmt, + SQLUSMALLINT fConcurrency, + SQLLEN crowKeyset, + SQLUSMALLINT crowRowset); + + + + +static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle) +{ + env_t *env = (env_t*)calloc(1, sizeof(*env)); + OILE(env, ""); + + int r = env_init(env); + if (r) return SQL_ERROR; + + *EnvironmentHandle = env; + + return SQL_SUCCESS; +} + +static SQLRETURN doSQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE *OutputHandle) +{ + P("HandleType:[%d]%s", HandleType, sql_handle_type(HandleType)); + switch (HandleType) + { + case SQL_HANDLE_ENV: + { + return doSQLAllocEnv(OutputHandle); + } break; + case SQL_HANDLE_DBC: + { + errs_clear(SQL_HANDLE_ENV, InputHandle); + return doSQLAllocConnect(InputHandle, OutputHandle); + } break; + case SQL_HANDLE_STMT: + { + errs_clear(SQL_HANDLE_DBC, InputHandle); + return doSQLAllocStmt(InputHandle, OutputHandle); + } break; + default: + { + ONIY(0, ""); + } break; + } +} + +static SQLRETURN doSQLSetEnvAttr(SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength) +{ + P("Attribute:[%d]%s", Attribute, sql_env_attr_type(Attribute)); + env_t *env = (env_t*)EnvironmentHandle; + OILE(env, ""); + + switch (Attribute) + { + case SQL_ATTR_ODBC_VERSION: + { + int32_t ver = (int32_t)(size_t)Value; + P("client odbc ver:[%d]", ver); + if (ver < env->odbc_ver) { + // fall back to lower version + env->odbc_ver = ver; + } + return SQL_SUCCESS; + } break; + default: + { + ONIY(0, ""); + } break; + } +} + +static SQLRETURN doSQLGetEnvAttr(SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER Value, + SQLINTEGER BufferLength, SQLINTEGER *StringLength) +{ + P("Attribute:[%d]%s; Value:[%p]; BufferLength:[%d]; StringLength:[%p][%d]", + Attribute, sql_env_attr_type(Attribute), Value, BufferLength, + StringLength, StringLength ? *StringLength : 0); + env_t *env = (env_t*)EnvironmentHandle; + OILE(env, ""); + + switch (Attribute) + { + case SQL_ATTR_ODBC_VERSION: + { + *(int32_t*)Value = env->odbc_ver; + P("odbc ver:[%d]", env->odbc_ver); + return SQL_SUCCESS; + } break; + default: + { + ONIY(0, ""); + } break; + } +} + +static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle, SQLHDBC *ConnectionHandle) +{ + env_t *env = (env_t*)EnvironmentHandle; + OILE(env, ""); + errs_t *errs = env_get_errs(env); + + conn_t *conn = conn_new(env); + if (!conn) { + SET_OOM(errs, "alloc conn failed"); + return SQL_ERROR; + } + + do { + *ConnectionHandle = conn; + + return SQL_SUCCESS; + } while (0); + + conn_free(conn); + + return SQL_ERROR; +} + +static SQLRETURN doSQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle) +{ + switch (HandleType) + { + case SQL_HANDLE_ENV: + { + return doSQLFreeEnv(Handle); + } break; + case SQL_HANDLE_DBC: + { + return doSQLFreeConnect(Handle); + } break; + case SQL_HANDLE_STMT: + { + stmt_t *stmt = (stmt_t*)Handle; + stmt_free(stmt); + return SQL_SUCCESS; + } break; + default: + { + ONIY(0, "HandleType:[%d]%s", HandleType, sql_handle_type(HandleType)); + } break; + } +} + +static SQLRETURN do_connect(conn_t *conn) { + errs_t *errs = &conn->errs; + + OD("enc:src/char/wchar/db/locale:[%s/%s/%s/%s/%s]", + conn->enc_src, conn->enc_char, conn->enc_wchar, conn->enc_db, conn->enc_locale); + + SQLRETURN r; + + r = conn_check_charset(conn, errs); + if (r!=SQL_SUCCESS) return r; + + if (0) { + // test with null_conn + if (conn_init_null_conn(conn)) { + SET_GENERAL(errs, "failed to init null conn for test"); + return SQL_ERROR; + } + } else { + if (conn_init_tsdb_conn(conn)) { + SET_GENERAL(errs, "failed to init taos conn for test"); + return SQL_ERROR; + } + } + + return conn_connect(conn); +} + +static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, + SQLCHAR *ServerName, SQLSMALLINT NameLength1, + SQLCHAR *UserName, SQLSMALLINT NameLength2, + SQLCHAR *Authentication, SQLSMALLINT NameLength3) +{ + conn_t *conn = (conn_t*)ConnectionHandle; + OILE(conn, ""); + ONIY(ServerName, ""); + + errs_t *errs = &conn->errs; + + const char *enc_to = conn->enc_locale; + const char *enc_from = conn->enc_char; + + SQLRETURN ok = SQL_ERROR; + + conn_val_t *val = &conn->val; + conn_val_reset(val); + + do { + if (ServerName) { + size_t slen = (size_t)NameLength1; + todbc_string_t dsn = todbc_tls_conv(NULL, enc_to, enc_from, (const unsigned char*)ServerName, &slen); + if (!dsn.buf) { + SET_OOM(errs, "alloc buf failed"); + return SQL_ERROR; + } + val->dsn = strdup((const char*)dsn.buf); + if (!val->dsn) { + SET_OOM(errs, "strdup failed"); + return SQL_ERROR; + } + } + if (UserName) { + size_t slen = (size_t)NameLength2; + todbc_string_t uid = todbc_tls_conv(NULL, enc_to, enc_from, (const unsigned char*)UserName, &slen); + if (!uid.buf) { + SET_OOM(errs, "alloc buf failed"); + return SQL_ERROR; + } + val->uid = strdup((const char*)uid.buf); + if (!val->uid) { + SET_OOM(errs, "strdup failed"); + return SQL_ERROR; + } + } + if (Authentication) { + size_t slen = (size_t)NameLength3; + todbc_string_t pwd = todbc_tls_conv(NULL, enc_to, enc_from, (const unsigned char*)Authentication, &slen); + if (!pwd.buf) { + SET_OOM(errs, "alloc buf failed"); + return SQL_ERROR; + } + val->pwd = strdup((const char*)pwd.buf); + if (!val->pwd) { + SET_OOM(errs, "strdup failed"); + return SQL_ERROR; + } + } + + OD("................."); + ok = do_connect(conn); + OD("................."); + if (ok!=SQL_SUCCESS) break; + + CONN_SET_CONNECTED(conn); + return SQL_SUCCESS; + } while (0); + + conn_val_reset(val); + + return ok; +} + +static SQLRETURN doSQLDriverConnect( + SQLHDBC ConnectionHandle, + SQLHWND WindowHandle, + SQLCHAR *InConnectionString, + SQLSMALLINT StringLength1, + SQLCHAR *OutConnectionString, + SQLSMALLINT BufferLength, + SQLSMALLINT *StringLength2Ptr, + SQLUSMALLINT DriverCompletion) +{ + conn_t *conn = (conn_t*)ConnectionHandle; + OILE(conn, ""); + ONIY(InConnectionString, ""); + + errs_t *errs = &conn->errs; + +#ifndef _MSC_VER + if (DriverCompletion!=SQL_DRIVER_NOPROMPT) { + SET_NIY(errs, "option[%d] other than SQL_DRIVER_NOPROMPT not supported yet", DriverCompletion); + return SQL_ERROR; + } +#endif + + const char *enc_to = conn->enc_locale; + const char *enc_from = conn->enc_char; + + size_t slen = (size_t)StringLength1; + todbc_string_t ts = todbc_tls_conv(NULL, enc_to, enc_from, (const unsigned char*)InConnectionString, &slen); + const char *connStr = (const char*)ts.buf; + if (!connStr) { + SET_OOM(errs, "alloc buf failed"); + return SQL_ERROR; + } + + SQLRETURN ok = SQL_ERROR; + + conn_val_t *val = &conn->val; + conn_val_reset(val); + + do { + // TO_DO: genralize + int n = todbc_parse_conn_string(connStr, val); + if (n) { + SET_GENERAL(errs, "unrecognized connection string:[%s]", connStr); + break; + } + + todbc_enc_t enc; + if (val->enc_char) { + enc = todbc_tls_iconv_enc(val->enc_char); + if (enc.enc[0]=='\0') { + SET_GENERAL(errs, "unrecognized charset:[%s]", val->enc_char); + break; + } + snprintf(conn->enc_char, sizeof(conn->enc_char), "%s", val->enc_char); + } + if (val->enc_wchar) { + enc = todbc_tls_iconv_enc(val->enc_wchar); + if (enc.enc[0]=='\0') { + SET_GENERAL(errs, "unrecognized charset:[%s]", val->enc_wchar); + break; + } + snprintf(conn->enc_wchar, sizeof(conn->enc_wchar), "%s", val->enc_wchar); + } + if (val->enc_db) { + enc = todbc_tls_iconv_enc(val->enc_db); + if (enc.enc[0]=='\0') { + SET_GENERAL(errs, "unrecognized charset:[%s]", val->enc_db); + break; + } + snprintf(conn->enc_db, sizeof(conn->enc_db), "%s", val->enc_db); + } + if (val->enc_local) { + enc = todbc_tls_iconv_enc(val->enc_local); + if (enc.enc[0]=='\0') { + SET_GENERAL(errs, "unrecognized charset:[%s]", val->enc_local); + break; + } + snprintf(conn->enc_locale, sizeof(conn->enc_locale), "%s", val->enc_local); + } + + ok = do_connect(conn); + if (ok!=SQL_SUCCESS) break; + ok = SQL_ERROR; + + n = 0; + if (OutConnectionString) { + n = snprintf((char*)OutConnectionString, (size_t)BufferLength, "%s", connStr); + } + if (StringLength2Ptr) { + *StringLength2Ptr = (SQLSMALLINT)n; + } + + CONN_SET_CONNECTED(conn); + return SQL_SUCCESS; + } while (0); + + conn_val_reset(val); + + return ok; +} + +static SQLRETURN doSQLGetInfo(SQLHDBC ConnectionHandle, SQLUSMALLINT InfoType, SQLPOINTER InfoValue, + SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr) +{ + P("InfoType:[%d]%s; BufferLength:[%d]; StringLengthPtr:[%p]%d", + InfoType, sql_info_type(InfoType), BufferLength, + StringLengthPtr, StringLengthPtr ? *StringLengthPtr : 0); + + switch (InfoType) + { + case SQL_DRIVER_ODBC_VER: + { + // how to sync with env->odbc_ver ? + const char *v = "03.00"; + int n = snprintf((char*)InfoValue, (size_t)BufferLength, "%s", v); + OILE(n>0, ""); + *StringLengthPtr = (SQLSMALLINT)n; + } break; + case SQL_DESCRIBE_PARAMETER: + { + const char *v = "Y"; + int n = snprintf((char*)InfoValue, (size_t)BufferLength, "%s", v); + OILE(n>0, ""); + *StringLengthPtr = (SQLSMALLINT)n; + } break; + case SQL_NEED_LONG_DATA_LEN: + { + const char *v = "Y"; + int n = snprintf((char*)InfoValue, (size_t)BufferLength, "%s", v); + OILE(n>0, ""); + *StringLengthPtr = (SQLSMALLINT)n; + } break; + case SQL_MAX_COLUMN_NAME_LEN: + { + SQLUSMALLINT v = 64; + OILE(BufferLength==sizeof(v), ""); + *(SQLUSMALLINT*)InfoValue = v; + if (StringLengthPtr) *StringLengthPtr = sizeof(v); + } break; + case SQL_TXN_ISOLATION_OPTION: + { + SQLUINTEGER v = SQL_TXN_READ_UNCOMMITTED; + OILE(BufferLength==sizeof(v), ""); + *(SQLUINTEGER*)InfoValue = v; + if (StringLengthPtr) *StringLengthPtr = sizeof(v); + } break; + case SQL_CURSOR_COMMIT_BEHAVIOR: + { + SQLUSMALLINT v = SQL_CB_PRESERVE; + OILE(BufferLength==sizeof(v), ""); + *(SQLUSMALLINT*)InfoValue = v; + if (StringLengthPtr) *StringLengthPtr = sizeof(v); + } break; + case SQL_CURSOR_ROLLBACK_BEHAVIOR: + { + SQLUSMALLINT v = SQL_CB_PRESERVE; + OILE(BufferLength==sizeof(v), ""); + *(SQLUSMALLINT*)InfoValue = v; + if (StringLengthPtr) *StringLengthPtr = sizeof(v); + } break; + case SQL_GETDATA_EXTENSIONS: + { + SQLUINTEGER v = SQL_GD_ANY_COLUMN; + OILE(BufferLength==sizeof(v), ""); + *(SQLUINTEGER*)InfoValue = v; + if (StringLengthPtr) *StringLengthPtr = sizeof(v); + } break; + case SQL_DTC_TRANSITION_COST: + { + SQLUINTEGER v = SQL_DTC_ENLIST_EXPENSIVE | SQL_DTC_UNENLIST_EXPENSIVE; + OILE(BufferLength==sizeof(v), ""); + *(SQLUINTEGER*)InfoValue = v; + if (StringLengthPtr) *StringLengthPtr = sizeof(v); + } break; + case SQL_MAX_CONCURRENT_ACTIVITIES: + { + SQLUSMALLINT v = 10240; + OILE(BufferLength==sizeof(v), ""); + *(SQLUSMALLINT*)InfoValue = v; + if (StringLengthPtr) *StringLengthPtr = sizeof(v); + } break; + default: + { + ONIY(0, ""); + // return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_fill_error(errs_t *errs, const char *enc_to, const char *enc_from, + SQLSMALLINT RecNumber, SQLCHAR *Sqlstate, SQLINTEGER *NativeError, + SQLCHAR* MessageText, SQLSMALLINT BufferLength, SQLSMALLINT *TextLength) +{ + if (errs_count(errs)<=0) return SQL_NO_DATA; + + const char *sql_state = NULL; + const char *err_str = NULL; + int r = errs_fetch(errs, RecNumber-1, &sql_state, &err_str); + if (r) return SQL_NO_DATA; + OILE(sql_state && err_str, ""); + const unsigned char *src = (const unsigned char*)err_str; + size_t slen = strlen(err_str); + unsigned char *dst = (unsigned char*)MessageText; + size_t dlen = (size_t)BufferLength; + // OILE(dst, ""); + if (!MessageText) { + OILE(TextLength, ""); + *TextLength = 4096; + return SQL_SUCCESS; + } + todbc_string_t s = todbc_tls_write(enc_to, enc_from, src, &slen, dst, dlen); + *NativeError = 0; + *TextLength = (SQLSMALLINT)s.bytes; + snprintf((char*)Sqlstate, 6, "%s", sql_state); + return SQL_SUCCESS; +} + +static SQLRETURN doSQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, + SQLCHAR *Sqlstate, SQLINTEGER *NativeError, SQLCHAR* MessageText, SQLSMALLINT BufferLength, SQLSMALLINT *TextLength) +{ + OILE(RecNumber>0, ""); + OILE(Sqlstate, ""); + // OILE(NativeError, ""); + OILE(TextLength, ""); + switch (HandleType) + { + // case SQL_HANDLE_ENV: + // { + // env_t *env = (env_t*)Handle; + // FILL_ERROR(env); + // return SQL_SUCCESS; + // } break; + case SQL_HANDLE_DBC: + { + conn_t *conn = (conn_t*)Handle; + OILE(conn, ""); + errs_t *errs = conn_get_errs(conn); + OILE(errs, ""); + const char *enc_to = conn->enc_char; + const char *enc_from = conn->enc_src; + return do_fill_error(errs, enc_to, enc_from, RecNumber, Sqlstate, NativeError, MessageText, BufferLength, TextLength); + } break; + case SQL_HANDLE_STMT: + { + stmt_t *stmt = (stmt_t*)Handle; + OILE(stmt, ""); + if (!stmt->owner) return SQL_NO_DATA; + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + errs_t *errs = stmt_get_errs(stmt); + OILE(errs, ""); + const char *enc_to = conn->enc_char; + const char *enc_from = conn->enc_src; + return do_fill_error(errs, enc_to, enc_from, RecNumber, Sqlstate, NativeError, MessageText, BufferLength, TextLength); + } break; + default: + { + ONIY(0, "HandleType:[%d]%s", HandleType, sql_handle_type(HandleType)); + // return SQL_ERROR; + } break; + } +} + +static SQLRETURN doSQLAllocStmt(SQLHDBC ConnectionHandle, SQLHSTMT *StatementHandle) +{ + conn_t *conn = (conn_t*)ConnectionHandle; + OILE(conn, ""); + + errs_t *errs = &conn->errs; + + stmt_t *stmt = stmt_new(conn); + if (!stmt) { + SET_OOM(errs, "alloc stmt failed"); + return SQL_ERROR; + } + + do { + if (!StatementHandle) break; + + *StatementHandle = stmt; + return SQL_SUCCESS; + } while (0); + + stmt_free(stmt); + OILE(0, ""); +} + +static SQLRETURN doSQLFreeStmt(SQLHSTMT StatementHandle, SQLUSMALLINT Option) +{ + P("Option:[%d]%s", Option, sql_freestmt_option_type(Option)); + + switch (Option) + { + case SQL_CLOSE: + { + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + if (STMT_IS_NORM(stmt)) break; + return doSQLCloseCursor(StatementHandle); + } break; + // case SQL_UNBIND: + // { + // } break; + case SQL_RESET_PARAMS: + { + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + stmt_reset_params(stmt); + } break; + default: + { + ONIY(0, ""); + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN doSQLGetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER Value, + SQLINTEGER BufferLength, SQLINTEGER *StringLength) +{ + P("Attribute:[%d]%s; BufferLength:[%d]; StringLength:[%p][%d]", + Attribute, sql_stmt_attr_type(Attribute), BufferLength, + StringLength, StringLength ? *StringLength : 0); + stmt_t *stmt = (stmt_t*)StatementHandle; + descs_t *descs = &stmt->descs; + + switch (Attribute) + { + case SQL_ATTR_APP_ROW_DESC: + { + OILE(BufferLength==sizeof(descs->app_row) || BufferLength==SQL_IS_POINTER, ""); + *(void**)Value = descs->app_row; + } break; + case SQL_ATTR_APP_PARAM_DESC: + { + OILE(BufferLength==sizeof(descs->app_param) || BufferLength==SQL_IS_POINTER, ""); + *(void**)Value = descs->app_param; + } break; + case SQL_ATTR_IMP_ROW_DESC: + { + OILE(BufferLength==sizeof(descs->imp_row) || BufferLength==SQL_IS_POINTER, ""); + *(void**)Value = descs->imp_row; + } break; + case SQL_ATTR_IMP_PARAM_DESC: + { + OILE(BufferLength==sizeof(descs->imp_param) || BufferLength==SQL_IS_POINTER, ""); + *(void**)Value = descs->imp_param; + } break; + default: + { + ONIY(0, ""); + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, SQLCHAR* StatementText, SQLINTEGER TextLength) +{ + P("TextLength:[%d]%s", TextLength, sql_soi_type(TextLength)); + + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(!STMT_IS_EXECUTING(stmt), ""); + stmt_close_rs(stmt); + OILE(STMT_IS_NORM(stmt), ""); + OILE(stmt->owner, ""); + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + + errs_t *errs = &stmt->errs; + + const char *enc = conn->enc_char; + + OILE(StatementText, ""); + OILE(TextLength>=0 || TextLength==SQL_NTS, ""); + size_t slen = (TextLength>=0) ? (size_t)TextLength : (size_t)-1; + todbc_string_t sql = todbc_string_init(enc, StatementText, slen); + if (!sql.buf) { + SET_OOM(errs, ""); + return SQL_ERROR; + } + + return stmt_exec_direct(stmt, &sql); + + + // stmt_t *stmt = (stmt_t*)StatementHandle; + // rs_t *rs = &stmt->rs; + // rs_close(rs); + // OILE(rs->stmt==NULL); + + // if (1) { + // // taos_stmt_prepare fails to prepare a non-param-stmt-statement + // // thus we fall-back to use taos_query + // OILE(stmt->owner); + // conn_t *conn = stmt->owner->conn; + // OILE(conn); + + // OILE(rs->stmt==NULL); + // paramset_t *paramset = &stmt->paramset; + // paramset_close(paramset); + + // SQLRETURN e = stmt_set_statement(stmt, StatementText, TextLength); + // if (e!=SQL_SUCCESS) return e; + + // taos_rs_t *taos_rs = &rs->taos_rs; + + // const char *buf = (const char*)stmt->statement_db.buf; + // taos_rs->rs = taos_query(conn->taos, buf); + + // if (!taos_rs->rs) { + // int err = terrno; + // SET_ERROR(stmt, "HY000", "failed to execute statement:[%d]%s", err, tstrerror(err)); + // // keep executing/executed state unchanged + // return SQL_ERROR; + // } + + // taos_rs->owner = rs; + // taos_rs->rs_is_opened_by_taos_query = 1; + + // SET_EXECUTED(stmt); + // return stmt_after_exec(stmt); + // } else { + // SQLRETURN r = doSQLPrepare(StatementHandle, StatementText, TextLength); + // if (r!=SQL_SUCCESS) return r; + + // return doSQLExecute(StatementHandle); + // } +} + +static SQLRETURN doSQLRowCount(SQLHSTMT StatementHandle, SQLLEN* RowCount) +{ + OILE(RowCount, ""); + + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(STMT_IS_EXECUTED(stmt), ""); + + OILE(stmt->ext.get_affected_rows, ""); + SQLRETURN r = stmt->ext.get_affected_rows(stmt, RowCount); + if (r!=SQL_SUCCESS) return r; + + P("RowCount:[%ld]", *RowCount); + + return SQL_SUCCESS; +} + +static SQLRETURN doSQLNumResultCols(SQLHSTMT StatementHandle, SQLSMALLINT *ColumnCount) +{ + OILE(ColumnCount, ""); + + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(STMT_IS_EXECUTED(stmt), ""); + + OILE(stmt->ext.get_fields_count, ""); + SQLRETURN r = stmt->ext.get_fields_count(stmt, ColumnCount); + if (r!=SQL_SUCCESS) return r; + + P("ColumnCount:[%d]", *ColumnCount); + + return SQL_SUCCESS; +} + +static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, SQLCHAR *ColumnName, SQLSMALLINT BufferLength, + SQLSMALLINT *NameLength, + SQLSMALLINT *DataType, SQLULEN *ColumnSize, + SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable) +{ + P("ColumnNumber:[%d]; BufferLength:[%d]", ColumnNumber, BufferLength); + + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(STMT_IS_EXECUTED(stmt), ""); + + field_arg_t field_arg = {0}; + field_arg.ColumnNumber = ColumnNumber; + field_arg.ColumnName = ColumnName; + field_arg.BufferLength = BufferLength; + field_arg.NameLength = NameLength; + field_arg.DataType = DataType; + field_arg.ColumnSize = ColumnSize; + field_arg.DecimalDigits = DecimalDigits; + field_arg.Nullable = Nullable; + + OILE(stmt->ext.get_field, ""); + return stmt->ext.get_field(stmt, &field_arg); + + // sql_t *sql = (sql_t*)StatementHandle; + // rs_t *rs = &sql->rs; + // OILE(rs->sql==sql); + // OILE(BufferLength>=0); + // OILE(NameLength); + // OILE(DataType); + // OILE(ColumnSize); + // OILE(DecimalDigits); + // OILE(Nullable); + + // OILE(ColumnNumber>0 && ColumnNumber<=rs->n_fields); + // field_t *field = rs->fields + (ColumnNumber-1); + + // int n = snprintf((char*)ColumnName, (size_t)BufferLength, "%s", field->name); + // *NameLength = (SQLSMALLINT)n; + // *DataType = (SQLSMALLINT)field->data_type; + // *ColumnSize = (SQLUSMALLINT)field->col_size; + // *DecimalDigits = (SQLSMALLINT)field->decimal_digits; + // *Nullable = (SQLSMALLINT)field->nullable; + + + // P("ColumnNumber:[%d]; DataType:[%d]%s; Name:[%s]; ColumnSize:[%ld]; DecimalDigits:[%d]; Nullable:[%d]%s", + // ColumnNumber, *DataType, sql_sql_type(*DataType), field->name, + // *ColumnSize, *DecimalDigits, *Nullable, sql_nullable_type(*Nullable)); + + // return SQL_SUCCESS; +} + +static SQLRETURN doSQLDisconnect(SQLHDBC ConnectionHandle) +{ + conn_t *conn = (conn_t*)ConnectionHandle; + OILE(conn, ""); + OILE(CONN_IS_CONNECTED(conn), ""); + + conn_disconnect(conn); + + CONN_SET_NORM(conn); + return SQL_SUCCESS; + + + // OILE(conn->taos); + + // // conn/stmts which ever to close first? + // // as for ODBC, it's suggested to close connection first, then release all dangling statements + // // but we are not sure if doing so will result in memory leakage for taos + // // thus we choose to close dangling statements before shutdown connection + // conn_release_sqls(conn); + + // taos_close(conn->taos); + // conn->taos = 0; + + // return SQL_SUCCESS; +} + +static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, SQLCHAR* StatementText, SQLINTEGER TextLength) +{ + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(!STMT_IS_EXECUTING(stmt), ""); + stmt_close_rs(stmt); + OILE(STMT_IS_NORM(stmt), ""); + OILE(stmt->owner, ""); + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + + errs_t *errs = &stmt->errs; + + const char *enc = conn->enc_char; + + OILE(StatementText, ""); + OILE(TextLength>=0 || TextLength==SQL_NTS, ""); + size_t slen = (TextLength>=0) ? (size_t)TextLength : (size_t)-1; + todbc_string_t sql = todbc_string_init(enc, StatementText, slen); + if (!sql.buf) { + SET_OOM(errs, ""); + return SQL_ERROR; + } + + if (1) { + todbc_string_t l = todbc_string_conv_to(&sql, conn->enc_src, NULL); + P("prepare:[%s]", (const char*)l.buf); + } + + return stmt_prepare(stmt, &sql); + + // sql_t *sql = (sql_t*)StatementHandle; + // rs_t *rs = &sql->rs; + + // OILE(rs->taos_rs.rs_is_opened_by_taos_query==0); + + // OILE(sql->owner); + // conn_t *conn = sql->owner->conn; + // OILE(conn); + + // OILE(rs->sql==NULL); + // paramset_t *paramset = &sql->paramset; + // paramset_close(paramset); + + // SQLRETURN r = sql_set_statement(sql, StatementText, TextLength); + // if (r!=SQL_SUCCESS) return r; + // + // int n_params = 0; + // r = sql_prepare(sql, &n_params); + // if (r!=SQL_SUCCESS) return r; + + // paramset_init_params(paramset, n_params); + // if (!paramset->params_cache || !paramset->params || !paramset->taos_binds) { + // sql_close_taos_stmt(sql); + // SET_ERROR(sql, "HY001", ""); + // return SQL_ERROR; + // } + + // // for (int i=0; iparams + i; + + // // } + + // paramset->sql = sql; + // paramset->n_params = n_params; + + // return sql_after_prepare(sql); +} + +static SQLRETURN doSQLNumParams(SQLHSTMT StatementHandle, SQLSMALLINT *ParameterCountPtr) +{ + OILE(ParameterCountPtr, ""); + + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(stmt->prepared, ""); + + *ParameterCountPtr = (SQLSMALLINT)stmt->paramset.n_params; + + P("ParameterCount:[%d]", *ParameterCountPtr); + + return SQL_SUCCESS; +} + +static SQLRETURN doSQLBindParameter( + SQLHSTMT StatementHandle, + SQLUSMALLINT ParameterNumber, + SQLSMALLINT InputOutputType, + SQLSMALLINT ValueType, + SQLSMALLINT ParameterType, + SQLULEN ColumnSize, + SQLSMALLINT DecimalDigits, + SQLPOINTER ParameterValuePtr, + SQLLEN BufferLength, + SQLLEN * StrLen_or_IndPtr) +{ + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(!STMT_IS_EXECUTING(stmt), ""); + OILE(stmt->owner, ""); + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + + param_binding_t arg = {0}; + arg.ParameterNumber = ParameterNumber; + arg.InputOutputType = InputOutputType; + arg.ValueType = ValueType; // sql c data type + arg.ParameterType = ParameterType; // sql data type + arg.ColumnSize = ColumnSize; + arg.DecimalDigits = DecimalDigits; + arg.ParameterValuePtr = ParameterValuePtr; + arg.BufferLength = BufferLength; + arg.StrLen_or_IndPtr = StrLen_or_IndPtr; + + return stmt_bind_param(stmt, &arg); + + // sql_t *sql = (sql_t*)StatementHandle; + // rs_t *rs = &sql->rs; + // OILE(rs->sql==NULL); + // OILE(IS_PREPARED(sql)); + // paramset_t *paramset = &sql->paramset; + // OILE(ParameterNumber>0); + + // OILE(StrLen_or_IndPtr); + + // paramset_realloc_bps(paramset, ParameterNumber); + // if (!paramset->bps_cache || !paramset->bps || paramset->n_bpsbps + (ParameterNumber-1); + // bp->ParameterNumber = ParameterNumber; + // bp->InputOutputType = InputOutputType; + // bp->ValueType = ValueType; + // bp->ParameterType = ParameterType; + // bp->ColumnSize = ColumnSize; + // bp->DecimalDigits = DecimalDigits; + // bp->ParameterValuePtr = ParameterValuePtr; + // bp->BufferLength = BufferLength; + // bp->StrLen_or_IndPtr = StrLen_or_IndPtr; + + // return SQL_SUCCESS; +} + +static SQLRETURN doSQLSetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength) +{ + P("Attribute:[%d]%s; Value:[%p]; StringLength:[%d]%s", + Attribute, sql_stmt_attr_type(Attribute), Value, + StringLength, sql_soi_type(StringLength)); + + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(!STMT_IS_EXECUTING(stmt), ""); + OILE(stmt->owner, ""); + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + + stmt_attr_t *attr = &stmt->attr; + + errs_t *errs = &stmt->errs; + + switch (Attribute) + { + case SQL_ATTR_PARAM_BIND_TYPE: + { + SQLULEN v = (SQLULEN)Value; + ONIY(v!=SQL_PARAM_BIND_BY_COLUMN, ""); + attr->bind_type = v; + P("%s:[%ld]", sql_stmt_attr_type(Attribute), v); + } break; + case SQL_ATTR_PARAMSET_SIZE: + { + SQLULEN v = (SQLULEN)Value; + ONIY(v!=0, ""); + attr->paramset_size = v; + P("%s:[%ld]", sql_stmt_attr_type(Attribute), v); + } break; + case SQL_ATTR_PARAM_BIND_OFFSET_PTR: + { + SQLULEN *v = (SQLULEN*)Value; + attr->bind_offset_ptr = v; + P("%s:[%p]", sql_stmt_attr_type(Attribute), v); + } break; + default: + { + P("Attribute:[%d]%s not implemented yet", Attribute, sql_stmt_attr_type(Attribute)); + SET_NIY(errs, "Attribute:[%d]%s", Attribute, sql_stmt_attr_type(Attribute)); + // ONSP(0, "Attribute:[%d]%s", Attribute, sql_stmt_attr_type(Attribute)); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN doSQLExecute(SQLHSTMT StatementHandle) +{ + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(!STMT_IS_EXECUTING(stmt), ""); + stmt_close_rs(stmt); + OILE(STMT_IS_NORM(stmt), ""); + OILE(stmt->owner, ""); + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + + return stmt_execute(stmt); + + // sql_t *sql = (sql_t*)StatementHandle; + // OILE(sql); + // OILE(IS_PREPARED(sql)); + // OILE(!IS_EXECUTING(sql)); + + // rs_t *rs = &sql->rs; + // OILE(rs->taos_rs.rs_is_opened_by_taos_query==0); + // rs_close(rs); + // OILE(rs->sql==NULL); + + // SET_EXECUTING(sql); + + // paramset_t *paramset = &sql->paramset; + // OILE(paramset); + + // // fetch parameters + // OILE(paramset->n_bps==paramset->n_params); + // if (paramset->paramset_size==0) { + // // nodejs workaround + // paramset->paramset_size = 1; + // } + // for (unsigned int i=0; iparamset_size; ++i) { + // for (unsigned int j=0; jn_bps && jn_params; ++j) { + // SQLRETURN r = sql_process_param(sql, i, j); + // if (r!=SQL_SUCCESS) return r; + // } + // OILE(paramset->taos_binds); + // int tr = taos_stmt_bind_param(sql->stmt, paramset->taos_binds); + // if (tr) { + // SET_ERROR(sql, "HY000", "failed to bind parameters[%d in total][%d]%s", paramset->n_params, tr, tstrerror(tr)); + // // keep executing/executed state unchanged + // return SQL_ERROR; + // } + + // tr = taos_stmt_add_batch(sql->stmt); + // if (tr) { + // SET_ERROR(sql, "HY000", "failed to add batch:[%d]%s", tr, tstrerror(tr)); + // // keep executing/executed state unchanged + // return SQL_ERROR; + // } + // } + + // if (1) { + // int r = taos_stmt_execute(sql->stmt); + // if (r) { + // SET_ERROR(sql, "HY000", "failed to execute statement:[%d]%s", r, tstrerror(r)); + // // keep executing/executed state unchanged + // return SQL_ERROR; + // } + + // taos_rs_t *taos_rs = &rs->taos_rs; + // OILE(taos_rs->owner==NULL); + // taos_rs->owner = rs; + // taos_rs->rs = taos_stmt_use_result(sql->stmt); + // } + + // SET_EXECUTED(sql); + + // return sql_after_exec(sql); +} + +static SQLRETURN doSQLFetch(SQLHSTMT StatementHandle) +{ + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(STMT_IS_EXECUTED(stmt), ""); + + if (STMT_TYPEINFO(stmt)) { + return SQL_SUCCESS; + } + + return stmt_fetch(stmt); + // sql_t *sql = (sql_t*)StatementHandle; + // OILE(sql); + // rs_t *rs = &sql->rs; + // OILE(rs->n_rows==-1 || rs->curr_rown_rows); + // row_t *row = &rs->row; + // taos_rs_t *taos_rs = &rs->taos_rs; + // OA(rs->n_fields==taos_rs->n_fields, "%d/%d", rs->n_fields, taos_rs->n_fields); + + // if (rs->eof) return SQL_NO_DATA; + + // if (rs->n_rows!=-1 && rs->curr_row + 1 >= rs->n_rows) { + // row_release(row); + // taos_rs->row = NULL; + // rs->eof = 1; + // return SQL_NO_DATA; + // } + + // row_release(row); + // taos_rs->row = NULL; + // ++rs->curr_row; + // row->valid = 1; + // taos_rs->row = taos_fetch_row(taos_rs->rs); + // D("row:[%p]", taos_rs->row); + // if (!taos_rs->row) { + // row->valid = 0; + // rs->eof = 1; + // D("..."); + // return SQL_NO_DATA; + // } + + // // column bound? + // if (!rs->bcs) return SQL_SUCCESS; + // for (int i=0; in_fields; ++i) { + // SQLRETURN r = sql_get_data(sql, (unsigned int)i); + // if (r!=SQL_SUCCESS) return r; + // } + + // return SQL_SUCCESS; +} + +static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, + SQLPOINTER TargetValue, SQLLEN BufferLength, + SQLLEN *StrLen_or_IndPtr) +{ + P("ColumnNumber:[%d]; TargetType:[%d]%s; BufferLength:[%ld]; StrLen_or_IndPtr:[%p]", + ColumnNumber, + TargetType, sql_c_type(TargetType), + BufferLength, StrLen_or_IndPtr); + + OILE(TargetValue, ""); + + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(STMT_IS_EXECUTED(stmt), ""); + + if (STMT_TYPEINFO(stmt)) { + ONIY(ColumnNumber==3, ""); + ONIY(TargetType==SQL_C_LONG, ""); + int32_t v = 255; + switch (stmt->typeinfo) { + case SQL_VARCHAR: + case SQL_WVARCHAR: + case SQL_VARBINARY: + break; + case SQL_TIMESTAMP: + case SQL_TYPE_TIMESTAMP: + v = 23; + break; + default: + { + OILE(0, ""); + } break; + } + *(int32_t*)TargetValue = v; + return SQL_SUCCESS; + } + + errs_t *errs = &stmt->errs; + + OILE(ColumnNumber>=0, ""); + if (ColumnNumber==0) { + SET_ERR(errs, "07009", "invalid ColumnNumber[%d]", ColumnNumber); + return SQL_ERROR; + } + + col_binding_t binding = { + .ColumnNumber = ColumnNumber, + .TargetType = TargetType, + .TargetValue = TargetValue, + .BufferLength = BufferLength, + .StrLen_or_IndPtr = StrLen_or_IndPtr + }; + + return stmt_get_data(stmt, &binding); + + // ONIY(TargetValue); + + // sql_t *sql = (sql_t*)StatementHandle; + // OILE(sql); + // rs_t *rs = &sql->rs; + // OILE(rs->sql==sql); + + // if (rs->eof) return SQL_NO_DATA; + // OILE(rs->curr_row>=0); + // OILE(rs->n_rows==-1 || rs->curr_rown_rows); + + // field_t *fields = rs->fields; + // if (!fields) return SQL_NO_DATA; + + // row_t *row = &rs->row; + // OILE(row->valid); + + // col_t *cols = row->cols; + + // if (cols==cols_timestamp || cols==cols_varchar || cols==cols_wvarchar || cols==cols_varbinary) { + // ONIY(ColumnNumber==3); + // ONIY(ColumnNumber<=row->n_cols); + // col_t *col = cols + (ColumnNumber-1); + // OILE(col->valid); + // ONIY(col->c_type==TargetType); + // OILE(col->c_type==SQL_C_LONG); + // int32_t v = col->u.c_long; + // ONIY(BufferLength>=sizeof(v)); + // ONIY(StrLen_or_IndPtr==0); + // *(int32_t*)TargetValue = v; + // return SQL_SUCCESS; + // } + + // OILE(StrLen_or_IndPtr); + // *StrLen_or_IndPtr = SQL_NULL_DATA; + + // return SQL_SUCCESS; +} + +static SQLRETURN doSQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier, + SQLPOINTER DiagInfo, SQLSMALLINT BufferLength, SQLSMALLINT *StringLength) +{ + P("HandleType:[%d]%s; RecNumber:[%d]; DiagIdentifier:[%d]%s; BufferLength:[%d]", + HandleType, sql_handle_type(HandleType), RecNumber, + DiagIdentifier, sql_diag_identifier(DiagIdentifier), + BufferLength); + OILE(0, ""); + // terror_t *err = NULL; + // switch (HandleType) + // { + // case SQL_HANDLE_ENV: + // { + // env_t *env = (env_t*)Handle; + // err = &env->err; + // } break; + // case SQL_HANDLE_DBC: + // { + // conn_t *conn = (conn_t*)Handle; + // err = &conn->err; + // } break; + // case SQL_HANDLE_STMT: + // { + // sql_t *sql = (sql_t*)Handle; + // err = &sql->err; + // } break; + // default: + // { + // OILE(0); + // return SQL_ERROR; + // } break; + // } + + // OILE(err); + // return SQL_NO_DATA; +} + +static SQLRETURN doSQLGetTypeInfo(SQLHSTMT StatementHandle, SQLSMALLINT DataType) +{ + P("DataType:[%d]%s", DataType, sql_sql_type(DataType)); + + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(!STMT_IS_EXECUTING(stmt), ""); + stmt_close_rs(stmt); + OILE(STMT_IS_NORM(stmt), ""); + OILE(stmt->owner, ""); + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + + switch (DataType) + { + case SQL_VARCHAR: + case SQL_WVARCHAR: + case SQL_VARBINARY: + case SQL_TIMESTAMP: + case SQL_TYPE_TIMESTAMP: + { + stmt->typeinfo = DataType; + } break; + default: + { + ONIY(0, ""); + return SQL_ERROR; + } break; + } + + STMT_SET_EXECUTED(stmt); + + return SQL_SUCCESS; +} + +static SQLRETURN doSQLDescribeParam( + SQLHSTMT StatementHandle, + SQLUSMALLINT ParameterNumber, + SQLSMALLINT * DataTypePtr, + SQLULEN * ParameterSizePtr, + SQLSMALLINT * DecimalDigitsPtr, + SQLSMALLINT * NullablePtr) +{ + // SQLRETURN r; + + OILE(ParameterNumber>0, ""); + + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(stmt->prepared, ""); + OILE(stmt->owner, ""); + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + + errs_t *errs = &stmt->errs; + + // const char *enc = conn->enc_char; + + paramset_t *paramset = &stmt->paramset; + param_t *params = paramset->params; + int n_params = paramset->n_params; + + if (ParameterNumber>n_params) { + SET_ERR(errs, "07009", "invalid ParameterNumber/#params [%d/%d]", ParameterNumber, n_params); + return SQL_ERROR; + } + + param_t *param = params + (ParameterNumber-1); + if (DataTypePtr) *DataTypePtr = param->DataType; + if (ParameterSizePtr) *ParameterSizePtr = param->ParameterSize; + if (DecimalDigitsPtr) *DecimalDigitsPtr = param->DecimalDigits; + if (NullablePtr) *NullablePtr = param->Nullable; + + return SQL_SUCCESS; + + // sql_t *sql = (sql_t*)StatementHandle; + // rs_t *rs = &sql->rs; + // OILE(rs->sql==NULL); + // OILE(IS_PREPARED(sql)); + // OILE(DataTypePtr); + // OILE(ParameterSizePtr); + // OILE(DecimalDigitsPtr); + + // paramset_t *paramset = &sql->paramset; + // OILE(paramset->sql); + // OILE(ParameterNumber>0 && ParameterNumber<=paramset->n_params); + + // *DataTypePtr = SQL_C_CHAR; + // *ParameterSizePtr = 23; + // *DecimalDigitsPtr = 0; + // if (NullablePtr) *NullablePtr = SQL_NULLABLE; + + // param_t *param = paramset->params + (ParameterNumber-1); + // int taos_type = param->taos_type; + // switch (taos_type) + // { + // case TSDB_DATA_TYPE_TIMESTAMP: + // { + // *DataTypePtr = SQL_CHAR; + // *ParameterSizePtr = 23; + // *DecimalDigitsPtr = 0; + // if (NullablePtr) *NullablePtr = SQL_NULLABLE; + // } break; + // case TSDB_DATA_TYPE_TINYINT: + // { + // *DataTypePtr = SQL_TINYINT; + // *ParameterSizePtr = 1; + // *DecimalDigitsPtr = 0; + // if (NullablePtr) *NullablePtr = SQL_NULLABLE; + // } break; + // default: + // { + // OA(0, "taos param:[%d][%d]%s", ParameterNumber, taos_type, taos_data_type(taos_type)); + // return SQL_ERROR; + // } break; + // } + + // P("ParameterNumber:[%d]; DataTypePtr:[%p]%s; ParameterSizePtr:[%p]%ld; DecimalDigitsPtr:[%p]%d; NullablePtr:[%p]%d", + // ParameterNumber, + // DataTypePtr, DataTypePtr ? sql_sql_type(*DataTypePtr) : "UNKNOWN", + // ParameterSizePtr, ParameterSizePtr ? *ParameterSizePtr : 0, + // DecimalDigitsPtr, DecimalDigitsPtr ? *DecimalDigitsPtr : 0, + // NullablePtr, NullablePtr ? *NullablePtr : 0); + // return SQL_SUCCESS; +} + +static SQLRETURN doSQLFreeConnect(SQLHDBC ConnectionHandle) +{ + conn_t *conn = (conn_t*)ConnectionHandle; + OILE(conn->stmts.count==0, ""); + conn_free(conn); + return SQL_SUCCESS; +} + +static SQLRETURN doSQLFreeEnv(SQLHENV EnvironmentHandle) +{ + env_t *env = (env_t*)EnvironmentHandle; + env_dec_ref(env); + return SQL_SUCCESS; +} + +static SQLRETURN doSQLBindCol(SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, + SQLPOINTER TargetValue, + SQLLEN BufferLength, SQLLEN *StrLen_or_IndPtr) +{ + P("ColumnNumber:[%d]; TargetType:[%d]%s; BufferLength:[%ld]", + ColumnNumber, TargetType, sql_c_type(TargetType), BufferLength); + + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + OILE(STMT_IS_EXECUTED(stmt), ""); + + errs_t *errs = &stmt->errs; + + OILE(ColumnNumber>=0, ""); + if (ColumnNumber==0) { + SET_ERR(errs, "07009", "invalid ColumnNumber[%d]", ColumnNumber); + return SQL_ERROR; + } + + col_binding_t binding = { + .ColumnNumber = ColumnNumber, + .TargetType = TargetType, + .TargetValue = TargetValue, + .BufferLength = BufferLength, + .StrLen_or_IndPtr = StrLen_or_IndPtr + }; + + return stmt_bind_col(stmt, &binding); + + + // OILE(ColumnNumber>0); + // sql_t *sql = (sql_t*)StatementHandle; + // OILE(!IS_EXECUTING(sql)); + + // rs_t *rs = &sql->rs; + // OILE(rs->fields); + // OILE(rs->n_fields>=ColumnNumber); + + // if (!rs->bcs_cache) { + // rs->bcs_cache = todbc_buf_create(); + // if (!rs->bcs_cache) { + // SET_ERROR(sql, "HY001", ""); + // return SQL_ERROR; + // } + // OILE(rs->bcs==NULL); + // rs->bcs = (bc_t*)todbc_buf_calloc(rs->bcs_cache, (size_t)rs->n_fields, sizeof(*rs->bcs)); + // if (!rs->bcs) { + // SET_ERROR(sql, "HY001", ""); + // return SQL_ERROR; + // } + // } + // OILE(rs->bcs); + + // bc_t *bc = rs->bcs + (ColumnNumber-1); + // bc->ColumnNumber = ColumnNumber; + // bc->TargetType = TargetType; + // bc->TargetValue = TargetValue; + // bc->BufferLength = BufferLength; + // bc->StrLen_or_IndPtr = StrLen_or_IndPtr; + + // return SQL_SUCCESS; +} + +static SQLRETURN doSQLCloseCursor(SQLHSTMT StatementHandle) +{ + stmt_t *stmt = (stmt_t*)StatementHandle; + OILE(stmt, ""); + errs_t *errs = &stmt->errs; + + if (STMT_IS_NORM(stmt)) { + OW("no cursor was opened previously"); + SET_ERR(errs, "24000", ""); + return SQL_ERROR; + } + + OILE(STMT_IS_EXECUTED(stmt), ""); + stmt_close_rs(stmt); + + return SQL_SUCCESS; + + // sql_t *sql = (sql_t*)StatementHandle; + // OILE(!IS_EXECUTING(sql)); + + // rs_t *rs = &sql->rs; + // if (!rs->sql) { + // SET_ERROR(sql, "24000", ""); + // OW("no cursor was opened previously"); + // return SQL_ERROR; + // } + + // OILE(rs->sql==sql); + // rs_close(rs); + + // return SQL_SUCCESS; +} + +static SQLRETURN doSQLError(SQLHENV EnvironmentHandle, + SQLHDBC ConnectionHandle, SQLHSTMT StatementHandle, + SQLCHAR *Sqlstate, SQLINTEGER *NativeError, + SQLCHAR *MessageText, SQLSMALLINT BufferLength, + SQLSMALLINT *TextLength) +{ + env_t *env = (env_t*)EnvironmentHandle; + conn_t *conn = (conn_t*)ConnectionHandle; + stmt_t *stmt = (stmt_t*)StatementHandle; + OD("env/conn/stmt:[%p/%p/%p]", env, conn, stmt); + + SQLSMALLINT HandleType; + SQLHANDLE Handle; + if (stmt) { + HandleType = SQL_HANDLE_STMT; + Handle = StatementHandle; + } else if (conn) { + HandleType = SQL_HANDLE_DBC; + Handle = ConnectionHandle; + } else if (env) { + HandleType = SQL_HANDLE_ENV; + Handle = EnvironmentHandle; + } else { + return SQL_NO_DATA; + } + + return doSQLGetDiagRec(HandleType, Handle, 1, Sqlstate, NativeError, MessageText, BufferLength, TextLength); +} + + +#ifdef _MSC_VER + +#define POST_INSTALLER_ERROR(hwndParent, code, fmt, ...) \ +do { \ + char buf[4096]; \ + snprintf(buf, sizeof(buf), "%s[%d]%s():" fmt "", \ + basename((char*)__FILE__), __LINE__, __func__, \ + ##__VA_ARGS__); \ + SQLPostInstallerError(code, buf); \ + if (hwndParent) { \ + MessageBox(hwndParent, buf, "Error", MB_OK|MB_ICONEXCLAMATION); \ + } \ +} while (0) + +typedef struct kv_s kv_t; +struct kv_s { + char *line; + size_t val; +}; + +static BOOL get_driver_dll_path(HWND hwndParent, char *buf, size_t len) +{ + HMODULE hm = NULL; + + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCSTR) &ConfigDSN, &hm) == 0) + { + int ret = GetLastError(); + POST_INSTALLER_ERROR(hwndParent, ODBC_ERROR_REQUEST_FAILED, "GetModuleHandle failed, error = %d\n", ret); + return FALSE; + } + if (GetModuleFileName(hm, buf, (DWORD)len) == 0) + { + int ret = GetLastError(); + POST_INSTALLER_ERROR(hwndParent, ODBC_ERROR_REQUEST_FAILED, "GetModuleFileName failed, error = %d\n", ret); + return FALSE; + } + return TRUE; +} + +static BOOL doDSNAdd(HWND hwndParent, LPCSTR lpszDriver, LPCSTR lpszAttributes) +{ + BOOL r = TRUE; + + kv_t *kvs = NULL; + + kv_t dsn = {0}; + char *line = NULL; + + do { + char driver_dll[MAX_PATH + 1]; + r = get_driver_dll_path(hwndParent, driver_dll, sizeof(driver_dll)); + if (!r) break; + + dsn.line = strdup("DSN=TAOS_DEMO"); + if (!dsn.line) { r = FALSE; break; } + + const char *p = lpszAttributes; + int ikvs = 0; + while (p && *p) { + line = strdup(p); + if (!line) { r = FALSE; break; } + char *v = strchr(line, '='); + if (!v) { r = FALSE; break; } + + if (strstr(line, "DSN")==line) { + if (dsn.line) { + free(dsn.line); + dsn.line = NULL; + dsn.val = 0; + } + dsn.line = line; + line = NULL; + } else { + kv_t *t = (kv_t*)realloc(kvs, (ikvs+1)*sizeof(*t)); + if (!t) { r = FALSE; free(line); break; } + t[ikvs].line = line; + *v = '\0'; + if (v) t[ikvs].val = v - line + 1; + line = NULL; + + kvs = t; + ++ikvs; + } + + p += strlen(p) + 1; + } + + if (hwndParent) { + MessageBox(hwndParent, "Please use odbcconf to add DSN for TAOS ODBC Driver", "Warning!", MB_OK|MB_ICONEXCLAMATION); + } + if (!r) break; + + char *v = NULL; + v = strchr(dsn.line, '='); + if (!v) { r = FALSE; break; } + *v = '\0'; + dsn.val = v - dsn.line + 1; + + if ((!dsn.line)) { + if (!r) POST_INSTALLER_ERROR(hwndParent, ODBC_ERROR_REQUEST_FAILED, "lack of either DSN or Driver"); + } else { + if (r) r = SQLWritePrivateProfileString("ODBC Data Sources", dsn.line+dsn.val, lpszDriver, "Odbc.ini"); + if (r) r = SQLWritePrivateProfileString(dsn.line+dsn.val, "Driver", driver_dll, "Odbc.ini"); + } + + for (int i=0; r && i + * + * 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 . + */ + +#ifndef _base_h_ +#define _base_h_ + +#include "todbc_buf.h" +#include "todbc_iconv.h" +#include "todbc_log.h" + +#include "taos.h" +#include "taoserror.h" + +#include +#include + +typedef struct errs_s errs_t; +typedef struct env_s env_t; +typedef struct conn_s conn_t; +typedef struct stmt_s stmt_t; +typedef struct param_s param_t; +typedef struct field_s field_t; +typedef struct rs_s rs_t; +typedef struct col_s col_t; + +#define GET_REF(obj) atomic_load_64(&obj->refcount) +#define INC_REF(obj) atomic_add_fetch_64(&obj->refcount, 1) +#define DEC_REF(obj) atomic_sub_fetch_64(&obj->refcount, 1) + +// public +#ifdef __GNUC__ + __attribute__((format(printf, 6, 7))) +#endif +SQLRETURN errs_append(errs_t *errs, const char sql_state[6], const char *file, int line, const char *func, const char *fmt, ...); +int errs_count(errs_t *errs); +// 0/-1: ok/no-error +int errs_fetch(errs_t *errs, int idx, const char **sql_state, const char **err_str); +void errs_clear(SQLSMALLINT HandleType, SQLHANDLE InputHandle); + +// err: if <>0, will generate strerror +#define SET_ERR(errs, sql_state, fmt, ...) \ + errs_append(errs, sql_state, __FILE__, __LINE__, __func__, "%s" fmt "", "", ##__VA_ARGS__) + +#define SET_OOM(errs, fmt, ...) SET_ERR(errs, "TD001", "OOM:" fmt, ##__VA_ARGS__) +#define SET_NIY(errs, fmt, ...) SET_ERR(errs, "TDC00", "NIY:" fmt, ##__VA_ARGS__) +#define SET_GENERAL(errs, fmt, ...) SET_ERR(errs, "TD000", "GEN:" fmt, ##__VA_ARGS__) + + +// public +errs_t* env_get_errs(env_t *env); +void env_clr_errs(env_t *env); +void env_inc_ref(env_t *env); +void env_dec_ref(env_t *env); + +// public +errs_t* conn_get_errs(conn_t *conn); +void conn_clr_errs(conn_t *conn); + +// public +errs_t* stmt_get_errs(stmt_t *stmt); +void stmt_clr_errs(stmt_t *stmt); + +#endif // _base_h_ + + diff --git a/src/connector/odbc/src/base/CMakeLists.txt b/src/connector/odbc/src/base/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fa13f3e07737bb6c2a36e5296a49a9f282346e3b --- /dev/null +++ b/src/connector/odbc/src/base/CMakeLists.txt @@ -0,0 +1,10 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +aux_source_directory(. SRC) +add_library(todbc_base STATIC ${SRC}) + +if (TD_DARWIN) + target_include_directories(todbc_base PRIVATE /usr/local/include) +endif () + diff --git a/src/connector/odbc/src/base/conn.c b/src/connector/odbc/src/base/conn.c new file mode 100644 index 0000000000000000000000000000000000000000..6e0554d88552330e2589eceb419a06d2135b54ce --- /dev/null +++ b/src/connector/odbc/src/base/conn.c @@ -0,0 +1,223 @@ +/* + * 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 . + */ + +#include "conn.h" + +#include "env.h" + +#include "../todbc_tls.h" + +static void init_encodes(conn_t *conn, env_t *env) { + OILE(conn, ""); + OILE(env, ""); + const char *enc_charset = env->enc_charset; + + snprintf(conn->enc_src, sizeof(conn->enc_src), "%s", UTF8_ENC); // compile-time constant + snprintf(conn->enc_wchar, sizeof(conn->enc_wchar), "%s", UTF16_ENC); // compile-time constant + snprintf(conn->enc_char, sizeof(conn->enc_char), "%s", enc_charset); // runtime default + snprintf(conn->enc_db, sizeof(conn->enc_db), "%s", enc_charset); // runtime default + snprintf(conn->enc_locale, sizeof(conn->enc_locale), "%s", enc_charset); // runtime default + + OD("enc_src:[%s]; enc_wchar:[%s]; enc_char:[%s]; enc_db:[%s]; enc_locale:[%s]", + conn->enc_src, conn->enc_wchar, conn->enc_char, conn->enc_db, conn->enc_locale); +} + +static int conn_init(conn_t *conn, env_t *env) { + OILE(conn, ""); + OILE(env, ""); + errs_t *errs = &env->errs; + + OILE(conn->env==NULL, ""); + + int r = errs_init(&conn->errs); + if (r) return -1; + + init_encodes(conn, env); + if (SQL_SUCCESS!=conn_check_charset(conn, errs)) { + return -1; + } + + conn->env = env; + env_inc_ref(env); + + return 0; +}; + +static void conn_release(conn_t *conn) { + if (!conn) return; + env_t *env = conn->env; + if (!env) return; + + conn->env = NULL; + env_dec_ref(env); +} + +conn_t* conn_new(env_t *env) { + conn_t *conn = (conn_t*)calloc(1, sizeof(*conn)); + if (!conn) return NULL; + + if (conn_init(conn, env)) { + OILE(conn->env==NULL, ""); + free(conn); + return NULL; + } + + return conn; +} + +void conn_free(conn_t *conn) { + if (!conn) return; + + // clean ext stuff + if (conn->ext.free_conn) { + conn->ext.free_conn(conn); + } + + // clean conn stuffs + conn_release(conn); + + free(conn); +} + +static SQLRETURN do_check_charset(errs_t *errs, const char *enc_charset, todbc_enc_t *enc) { + *enc = todbc_tls_iconv_enc(enc_charset); + if (enc->enc[0]=='\0') { + if (errs) { + SET_GENERAL(errs, "unknown charset [%s]", enc_charset); + } + return SQL_ERROR; + } + + return SQL_SUCCESS; +} + +SQLRETURN conn_check_charset(conn_t *conn, errs_t *errs) { + OILE(conn, ""); + + todbc_enc_t enc; + + SQLRETURN r; + r = do_check_charset(errs, conn->enc_char, &enc); + if (r!=SQL_SUCCESS) return r; + r = do_check_charset(errs, conn->enc_db, &enc); + if (r!=SQL_SUCCESS) return r; + r = do_check_charset(errs, conn->enc_locale, &enc); + if (r!=SQL_SUCCESS) return r; + r = do_check_charset(errs, conn->enc_src, &enc); + if (r!=SQL_SUCCESS) return r; + + r = do_check_charset(errs, conn->enc_wchar, &enc); + if (r!=SQL_SUCCESS) return r; + + if (enc.variable_char_size!=-1) { + OE("does not support [%s] for WCHAR", conn->enc_wchar); + if (errs) { + SET_GENERAL(errs, "does not support [%s] for WCHAR", conn->enc_wchar); + } + return SQL_ERROR; + } + if (enc.char_size<=0) { + if (errs) { + SET_GENERAL(errs, "unknown [%s] for WCHAR", conn->enc_wchar); + } + return SQL_ERROR; + } + + conn->wchar_size = (size_t)enc.char_size; + + return SQL_SUCCESS; +} + +int conn_add_stmt(conn_t *conn, stmt_t *stmt) { + OILE(conn, ""); + OILE(stmt, ""); + OILE(stmt->owner==NULL, ""); + OILE(stmt->next==NULL, ""); + OILE(stmt->prev==NULL, ""); + OILE(conn->ext.init_stmt, ""); + + if (conn->ext.init_stmt(stmt)) { + return -1; + } + + stmts_t *owner = &conn->stmts; + + stmt->owner = owner; + + stmt->prev = owner->tail; + if (owner->tail) owner->tail->next = stmt; + else owner->head = stmt; + owner->tail = stmt; + + ++owner->count; + owner->conn = conn; + + return 0; +} + +void conn_del_stmt(conn_t *conn, stmt_t *stmt) { + OILE(conn, ""); + OILE(stmt, ""); + OILE(stmt->owner, ""); + OILE(stmt->owner==&conn->stmts, ""); + OILE(stmt->owner->conn==conn, ""); + + stmts_t *owner = stmt->owner; + + stmt_t *next = stmt->next; + stmt_t *prev = stmt->prev; + + if (next) next->prev = prev; + else owner->tail = prev; + + if (prev) prev->next = next; + else owner->head = next; + + --owner->count; + + stmt->next = NULL; + stmt->prev = NULL; + stmt->owner = NULL; +} + +SQLRETURN conn_connect(conn_t *conn) { + OILE(conn, ""); + OILE(conn->ext.connect, ""); + return conn->ext.connect(conn); +} + +void conn_disconnect(conn_t *conn) { + OILE(conn, ""); + OILE(conn->ext.disconnect, ""); + conn->ext.disconnect(conn); +} + +// public +errs_t* conn_get_errs(conn_t *conn) { + OILE(conn, ""); + + return &conn->errs; +} + +void conn_clr_errs(conn_t *conn) { + if (!conn) return; + + errs_reclaim(&conn->errs); +} + + + + + diff --git a/src/connector/odbc/src/base/conn.h b/src/connector/odbc/src/base/conn.h new file mode 100644 index 0000000000000000000000000000000000000000..d82cbc37d4bb6a5a4c0f82e13396fa0f5342147b --- /dev/null +++ b/src/connector/odbc/src/base/conn.h @@ -0,0 +1,81 @@ +/* + * 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 . + */ + +#ifndef _conn_h_ +#define _conn_h_ + +#include "../base.h" + +#include "stmt.h" + + +#include "../todbc_flex.h" + +typedef struct conn_ext_s conn_ext_t; +struct conn_ext_s { + void *ext; + void (*free_conn)(conn_t *conn); + int (*init_stmt)(stmt_t *stmt); + + SQLRETURN (*connect)(conn_t *conn); + void (*disconnect)(conn_t *conn); +}; + +struct conn_s { + env_t *env; + + char enc_src[64]; // c source file encoding + char enc_char[64]; // SQL_CHAR encoding + char enc_wchar[64]; // SQL_WCHAR encoding + char enc_db[64]; // taos client encoding + // use this for system i/o, such as reading from stdin, writing to stdout/stderr + char enc_locale[64]; // default: current localee + + size_t wchar_size; // shall be fix-length + + conn_val_t val; + + stmts_t stmts; + + errs_t errs; + + conn_ext_t ext; + + unsigned int connect:2; +}; + +#define CONN_SET_CONNECTING(conn) (conn->connect=0x01) +#define CONN_SET_CONNECTED(conn) (conn->connect=0x02) +#define CONN_SET_NORM(conn) (conn->connect=0x00) + +#define CONN_IS_CONNECTING(conn) (conn->connect==0x01) +#define CONN_IS_CONNECTED(conn) (conn->connect==0x02) +#define CONN_IS_NORM(conn) (conn->connect==0x00) + +conn_t* conn_new(env_t *env); +void conn_free(conn_t *conn); + +SQLRETURN conn_check_charset(conn_t *conn, errs_t *errs); + +int conn_add_stmt(conn_t *conn, stmt_t *stmt); +void conn_del_stmt(conn_t *conn, stmt_t *stmt); + +SQLRETURN conn_connect(conn_t *conn); +void conn_disconnect(conn_t *conn); + + +#endif // _conn_h_ + + diff --git a/src/connector/odbc/src/base/env.c b/src/connector/odbc/src/base/env.c new file mode 100644 index 0000000000000000000000000000000000000000..75b5b8360209f221b69b66e34c58cb7da439affe --- /dev/null +++ b/src/connector/odbc/src/base/env.c @@ -0,0 +1,117 @@ +/* + * 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 . + */ + +#include "env.h" + +#include + +static pthread_once_t init_once = PTHREAD_ONCE_INIT; +static char default_charset[64] = {0}; + +static void init_routine(void) { + OD("compiled with ODBCVER:[0x%04x]", ODBCVER); + + const char *charset = NULL; + setlocale(LC_ALL, ""); + const char *locale = setlocale(LC_CTYPE, NULL); + if (locale) { + const char *dot = strrchr(locale, '.'); + if (dot) charset = dot + 1; + } + if (!charset) { +#ifdef _MSC_VER + charset = "CP936"; +#else + charset = "UTF-8"; +#endif + OD("failed to find original locale, fall back to [%s]", charset); + } else { +#ifdef _MSC_VER + char buf[64]; + snprintf(buf, sizeof(buf), "CP%s", charset); + charset = buf; +#endif + OD("system default charset: [%s]", charset); + } + + snprintf(default_charset, sizeof(default_charset), "%s", charset); +} + + +static void env_release(env_t *env) { + if (!env) return; + OILE(env->refcount==0, ""); + + env_clr_errs(env); +} + +int env_init(env_t *env) { + OILE(env, ""); + OILE(env->refcount==0, ""); + + pthread_once(&init_once, init_routine); + + int r = errs_init(&env->errs); + if (r) return -1; + + snprintf(env->enc_charset, sizeof(env->enc_charset), "%s", default_charset); + env->odbc_ver = SQL_OV_ODBC3; + + env->refcount = 1; + + return 0; +} + +// public +errs_t* env_get_errs(env_t *env) { + OILE(env, ""); + + return &env->errs; +} + +void env_clr_errs(env_t *env) { + if (!env) return; + + errs_reclaim(&env->errs); +} + +void env_inc_ref(env_t *env) { + OILE(env, ""); + int64_t rc = INC_REF(env); + OILE(rc>=2, ""); +} + +void env_dec_ref(env_t *env) { + OILE(env, ""); + int64_t rc = DEC_REF(env); + if (rc>0) return; + OILE(rc==0, ""); + + env_release(env); + free(env); +} + +env_t* env_create(void) { + env_t *env = (env_t*)calloc(1, sizeof(*env)); + if (!env) return NULL; + + if (env_init(env)) { + free(env); + return NULL; + } + + return env; +} + diff --git a/src/connector/odbc/src/base/env.h b/src/connector/odbc/src/base/env.h new file mode 100644 index 0000000000000000000000000000000000000000..b4f420ad64d541fac92c8a4105e1d89b1cd0e9a0 --- /dev/null +++ b/src/connector/odbc/src/base/env.h @@ -0,0 +1,43 @@ +/* + * 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 . + */ + +#ifndef _env_h_ +#define _env_h_ + +#include "../base.h" + +#include "err.h" + +struct env_s { + int64_t refcount; + + char enc_charset[64]; // default charset from system locale + int32_t odbc_ver; // default SQL_OV_ODBC3 + + errs_t errs; + + void (*env_free)(env_t* env); +}; + +int env_init(env_t *env); + +env_t* env_create(void); + + + + +#endif // _env_h_ + + diff --git a/src/connector/odbc/src/base/err.c b/src/connector/odbc/src/base/err.c new file mode 100644 index 0000000000000000000000000000000000000000..c1547288076fa5c4e53099560ae211ce14f61b65 --- /dev/null +++ b/src/connector/odbc/src/base/err.c @@ -0,0 +1,177 @@ +/* + * 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 . + */ + +#include "err.h" + +#include "env.h" +#include "conn.h" +#include "stmt.h" + +struct err_s { + char sql_state[6]; + char *err_str; // no ownership +}; + +static void errs_clr(errs_t *errs) { + if (!errs) return; + + errs->count = 0; + errs->errs = NULL; +} + +int errs_init(errs_t *errs) { + OILE(errs && errs->cache==NULL, ""); + OILE(errs->count==0 && errs->errs==NULL, ""); + + errs->cache = todbc_buf_create(); + + return errs->cache ? 0 : -1; +} + +void errs_reclaim(errs_t *errs) { + if (!errs) return; + if (!errs->cache) return; + + errs_clr(errs); + + todbc_buf_reclaim(errs->cache); +} + +void errs_release(errs_t *errs) { + if (!errs) return; + if (!errs->cache) return; + + errs_clr(errs); + + todbc_buf_free(errs->cache); + errs->cache = NULL; +} + +// public +#ifdef __GNUC__ + __attribute__((format(printf, 6, 7))) +#endif +SQLRETURN errs_append(errs_t *errs, const char sql_state[6], const char *file, int line, const char *func, const char *fmt, ...) +{ + OILE(errs, ""); + OILE(errs->cache, ""); + todbc_buf_t *cache = errs->cache; + + const char *name = basename((char*)file); + + char *buf = NULL; + size_t blen = 0; + while (1) { + char *p = buf; + size_t bytes = blen; + + int count = 0; + int n = 0; + + va_list ap; + va_start(ap, fmt); + if (bytes<0) bytes = 0; + n = vsnprintf(p, bytes, fmt, ap); + va_end(ap); + + OILE(n>=0, ""); + + count += n; + if (p) p += n; + if (bytes) bytes -= (size_t)n; + + if (bytes<0) bytes = 0; + n = snprintf(p, bytes, "@%s[%d]%s()\n", name, line, func); + + OILE(n>=0, ""); + count += n; + + if (p) break; + + buf = todbc_buf_alloc(cache, (size_t)count + 1); + if (!buf) return SQL_ERROR; + blen = (size_t)count; + } + + size_t bytes = (size_t)(errs->count + 1) * sizeof(err_t); + + err_t *es = (err_t*)todbc_buf_realloc(cache, errs->errs, bytes); + if (!es) return SQL_ERROR; + errs->errs = es; + errs->count += 1; + + err_t *err = errs->errs + errs->count - 1; + snprintf(err->sql_state, sizeof(err->sql_state), "%s", sql_state); + err->err_str = buf; + + + return SQL_SUCCESS; +} + +int errs_count(errs_t *errs) { + OILE(errs, ""); + OILE(errs->cache, ""); + + return errs->count; +} + +// 0/-1: ok/no-error +int errs_fetch(errs_t *errs, int idx, const char **sql_state, const char **err_str) { + OILE(errs, ""); + OILE(errs->cache, ""); + + if (errs->count<=0) return -1; + if (idx<0 || idx>=errs->count) return -1; + + err_t *err = errs->errs + idx; + + if (sql_state) *sql_state = err->sql_state; + if (err_str) *err_str = err->err_str; + + return 0; +} + +void errs_clear(SQLSMALLINT HandleType, SQLHANDLE InputHandle) { + errs_t *errs = NULL; + + if (InputHandle==NULL) return; + + switch (HandleType) + { + case SQL_HANDLE_ENV: + { + env_t *env = (env_t*)InputHandle; + errs = &env->errs; + } break; + case SQL_HANDLE_DBC: + { + conn_t *conn = (conn_t*)InputHandle; + errs = &conn->errs; + } break; + case SQL_HANDLE_STMT: + { + stmt_t *stmt = (stmt_t*)InputHandle; + errs = &stmt->errs; + } break; + default: + { + ONIY(0, ""); + } break; + } + + if (!errs) return; + errs_reclaim(errs); +} + diff --git a/src/connector/odbc/src/base/err.h b/src/connector/odbc/src/base/err.h new file mode 100644 index 0000000000000000000000000000000000000000..ae8f9a8085e90acd4f614cdccbfe04f4709ae510 --- /dev/null +++ b/src/connector/odbc/src/base/err.h @@ -0,0 +1,35 @@ +/* + * 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 . + */ + +#ifndef _err_h_ +#define _err_h_ + +#include "../base.h" + +typedef struct err_s err_t; + +struct errs_s { + todbc_buf_t *cache; + + int count; + err_t *errs; +}; + +int errs_init(errs_t *errs); +void errs_reclaim(errs_t *errs); +void errs_release(errs_t *errs); + +#endif // _err_h_ + diff --git a/src/connector/odbc/src/base/field.c b/src/connector/odbc/src/base/field.c new file mode 100644 index 0000000000000000000000000000000000000000..41a466069fb8f40252c923ac78e3bdfcd864c425 --- /dev/null +++ b/src/connector/odbc/src/base/field.c @@ -0,0 +1,78 @@ +/* + * 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 . + */ + +#include "field.h" + +static void fieldset_clr_fields(fieldset_t *fieldset) { + if (!fieldset) return; + + fieldset->fields = NULL; + fieldset->n_fields = 0; +} + +static void fieldset_clr_bindings(fieldset_t *fieldset) { + if (!fieldset) return; + + fieldset->bindings = NULL; + fieldset->n_bindings = 0; +} + +void fieldset_init_fields(fieldset_t *fieldset) { + if (!fieldset) return; + if (fieldset->fields_cache) return; + fieldset->fields_cache = todbc_buf_create(); +} + +void fieldset_init_bindings(fieldset_t *fieldset) { + if (!fieldset) return; + if (fieldset->bindings_cache) return; + fieldset->bindings_cache = todbc_buf_create(); +} + +void fieldset_reclaim_fields(fieldset_t *fieldset) { + if (!fieldset) return; + + if (!fieldset->fields_cache) return; + + todbc_buf_reclaim(fieldset->fields_cache); + fieldset_clr_fields(fieldset); +} + +void fieldset_reclaim_bindings(fieldset_t *fieldset) { + if (!fieldset) return; + + if (!fieldset->bindings_cache) return; + + todbc_buf_reclaim(fieldset->bindings_cache); + fieldset_clr_bindings(fieldset); +} + +void fieldset_release(fieldset_t *fieldset) { + if (!fieldset) return; + + fieldset_reclaim_fields(fieldset); + fieldset_reclaim_bindings(fieldset); + + if (fieldset->fields_cache) { + todbc_buf_free(fieldset->fields_cache); + fieldset->fields_cache = NULL; + } + + if (fieldset->bindings_cache) { + todbc_buf_free(fieldset->bindings_cache); + fieldset->bindings_cache = NULL; + } +} + diff --git a/src/connector/odbc/src/base/field.h b/src/connector/odbc/src/base/field.h new file mode 100644 index 0000000000000000000000000000000000000000..667dc65ff66e8095e97804ad412adbbd88ed8969 --- /dev/null +++ b/src/connector/odbc/src/base/field.h @@ -0,0 +1,77 @@ +/* + * 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 . + */ + +#ifndef _field_h_ +#define _field_h_ + +#include "../base.h" + +typedef struct fieldset_s fieldset_t; +typedef struct col_binding_s col_binding_t; +typedef struct field_arg_s field_arg_t; + +// SQLDescribeCol +struct field_arg_s { + SQLUSMALLINT ColumnNumber; + SQLCHAR *ColumnName; + SQLSMALLINT BufferLength; + SQLSMALLINT *NameLength; + SQLSMALLINT *DataType; // sql data type + SQLULEN *ColumnSize; + SQLSMALLINT *DecimalDigits; + SQLSMALLINT *Nullable; +}; + +struct field_s { + SQLUSMALLINT ColumnNumber; + SQLCHAR ColumnName[64]; // hard-coded + SQLSMALLINT DataType; // sql data type + SQLULEN ColumnSize; + SQLSMALLINT DecimalDigits; + SQLSMALLINT Nullable; +}; + +// SQLBindCol; SQLGetData +struct col_binding_s { + SQLUSMALLINT ColumnNumber; + SQLSMALLINT TargetType; // sql c data type + SQLPOINTER TargetValue; + SQLLEN BufferLength; + SQLLEN *StrLen_or_IndPtr; +}; + + +struct fieldset_s { + todbc_buf_t *fields_cache; + field_t *fields; + int n_fields; + + todbc_buf_t *bindings_cache; + col_binding_t *bindings; + int n_bindings; +}; + +void fieldset_init_fields(fieldset_t *fieldset); +void fieldset_init_bindings(fieldset_t *fieldset); + +void fieldset_reclaim_fields(fieldset_t *fieldset); +void fieldset_reclaim_bindings(fieldset_t *fieldset); + +void fieldset_release(fieldset_t *fields); + +#endif // _field_h_ + + + diff --git a/src/connector/odbc/src/base/null_conn.c b/src/connector/odbc/src/base/null_conn.c new file mode 100644 index 0000000000000000000000000000000000000000..29fe86991ac43095bd843a8df961ee2c443ade11 --- /dev/null +++ b/src/connector/odbc/src/base/null_conn.c @@ -0,0 +1,115 @@ +/* + * 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 . + */ + +#include "null_conn.h" + +#include "env.h" + +// null_conn + +static void null_conn_free(conn_t *conn) { + OILE(conn, ""); + null_conn_t *null_conn = (null_conn_t*)conn->ext.ext; + OILE(null_conn, ""); + + conn->ext.ext = NULL; + conn->ext.free_conn = NULL; + + free(null_conn); +} + +static SQLRETURN null_conn_connect(conn_t *conn) { + OILE(conn, ""); + null_conn_t *null_conn = (null_conn_t*)conn->ext.ext; + OILE(null_conn && null_conn->conn==conn, ""); + OILE(CONN_IS_NORM(conn), ""); + return SQL_SUCCESS; +} + +static void null_conn_disconnect(conn_t *conn) { + OILE(conn, ""); + OILE(CONN_IS_CONNECTED(conn), ""); +} + +static void null_conn_free_stmt(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->owner, ""); +} + +static SQLRETURN null_conn_exec_direct(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + OILE(!STMT_IS_EXECUTED(stmt), ""); + STMT_SET_EXECUTED(stmt); + return SQL_SUCCESS; +} + +static SQLRETURN null_conn_prepare(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + return SQL_SUCCESS; +} + +static SQLRETURN null_conn_proc_param(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + return SQL_SUCCESS; +} + +static SQLRETURN null_conn_execute(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + OILE(!STMT_IS_EXECUTED(stmt), ""); + STMT_SET_EXECUTED(stmt); + return SQL_SUCCESS; +} + +static int null_conn_init_stmt(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->ext.ext==NULL, ""); + OILE(stmt->ext.free_stmt==NULL, ""); + + OILE(stmt->owner==NULL, ""); + + stmt->ext.ext = NULL; + stmt->ext.free_stmt = null_conn_free_stmt; + stmt->ext.exec_direct = null_conn_exec_direct; + stmt->ext.prepare = null_conn_prepare; + stmt->ext.proc_param = null_conn_proc_param; + stmt->ext.execute = null_conn_execute; + + return 0; +} + +int conn_init_null_conn(conn_t *conn) { + OILE(conn, ""); + OILE(conn->ext.ext==NULL, ""); + OILE(conn->ext.free_conn==NULL, ""); + + null_conn_t *null_conn = (null_conn_t*)calloc(1, sizeof(*null_conn)); + if (!null_conn) return -1; + + null_conn->conn = conn; + conn->ext.ext = null_conn; + conn->ext.free_conn = null_conn_free; + conn->ext.connect = null_conn_connect; + conn->ext.disconnect = null_conn_disconnect; + conn->ext.init_stmt = null_conn_init_stmt; + + return 0; +} + + + diff --git a/src/connector/odbc/src/base/null_conn.h b/src/connector/odbc/src/base/null_conn.h new file mode 100644 index 0000000000000000000000000000000000000000..9940cda5848a9e9dbccf866853e154b7e5868d6b --- /dev/null +++ b/src/connector/odbc/src/base/null_conn.h @@ -0,0 +1,33 @@ +/* + * 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 . + */ + +#ifndef _null_conn_h_ +#define _null_conn_h_ + +#include "../base.h" + +#include "conn.h" + +typedef struct null_conn_s null_conn_t; +struct null_conn_s { + conn_t *conn; +}; + +int conn_init_null_conn(conn_t *conn); + + +#endif // _null_conn_h_ + + diff --git a/src/connector/odbc/src/base/param.c b/src/connector/odbc/src/base/param.c new file mode 100644 index 0000000000000000000000000000000000000000..59b2871f6ed9324e07c5fb23f20b6bcde734644d --- /dev/null +++ b/src/connector/odbc/src/base/param.c @@ -0,0 +1,89 @@ +/* + * 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 . + */ + +#include "param.h" + +static void paramset_clr_params(paramset_t *paramset) { + if (!paramset) return; + + paramset->params = NULL; + paramset->n_params = 0; + + paramset->i_row = 0; + paramset->i_col = 0; +} + +static void paramset_clr_bindings(paramset_t *paramset) { + if (!paramset) return; + + paramset->bindings = NULL; + paramset->n_bindings = 0; +} + +void paramset_reclaim_params(paramset_t *paramset) { + if (!paramset) return; + + if (!paramset->params_cache) return; + + todbc_buf_reclaim(paramset->params_cache); + paramset_clr_params(paramset); +} + +void paramset_reclaim_bindings(paramset_t *paramset) { + if (!paramset) return; + + if (!paramset->bindings_cache) return; + + todbc_buf_reclaim(paramset->bindings_cache); + paramset_clr_bindings(paramset); +} + +void paramset_init_params_cache(paramset_t *paramset) { + if (!paramset) return; + if (paramset->params_cache) return; + + OILE(paramset->params==NULL, ""); + OILE(paramset->n_params==0, ""); + + paramset->params_cache = todbc_buf_create(); +} + +void paramset_init_bindings_cache(paramset_t *paramset) { + if (!paramset) return; + if (paramset->bindings_cache) return; + + OILE(paramset->bindings==NULL, ""); + OILE(paramset->n_bindings==0, ""); + + paramset->bindings_cache = todbc_buf_create(); +} + +void paramset_release(paramset_t *paramset) { + if (!paramset) return; + + paramset_reclaim_params(paramset); + paramset_reclaim_bindings(paramset); + + if (paramset->params_cache) { + todbc_buf_free(paramset->params_cache); + paramset->params_cache = NULL; + } + + if (paramset->bindings_cache) { + todbc_buf_free(paramset->bindings_cache); + paramset->bindings_cache = NULL; + } +} + diff --git a/src/connector/odbc/src/base/param.h b/src/connector/odbc/src/base/param.h new file mode 100644 index 0000000000000000000000000000000000000000..6175add47b706e927329c78111232aa9617f9b08 --- /dev/null +++ b/src/connector/odbc/src/base/param.h @@ -0,0 +1,71 @@ +/* + * 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 . + */ + +#ifndef _param_h_ +#define _param_h_ + +#include "../base.h" + +typedef struct paramset_s paramset_t; +typedef struct param_binding_s param_binding_t; +typedef struct param_val_s param_val_t; + +// SQLDescribeParam +struct param_s { + SQLUSMALLINT ParameterNumber; + SQLSMALLINT DataType; // sql data type + SQLULEN ParameterSize; + SQLSMALLINT DecimalDigits; + SQLSMALLINT Nullable; +}; + +// SQLBindParameter +struct param_binding_s { + SQLUSMALLINT ParameterNumber; + SQLSMALLINT InputOutputType; + SQLSMALLINT ValueType; // sql c data type + SQLSMALLINT ParameterType; // sql data type + SQLULEN ColumnSize; + SQLSMALLINT DecimalDigits; + SQLPOINTER ParameterValuePtr; + SQLLEN BufferLength; + SQLLEN *StrLen_or_IndPtr; +}; + +struct paramset_s { + todbc_buf_t *params_cache; + param_t *params; + int n_params; + + todbc_buf_t *bindings_cache; + param_binding_t *bindings; + int n_bindings; + + int i_row; + int i_col; +}; + +void paramset_reclaim_params(paramset_t *paramset); +void paramset_reclaim_bindings(paramset_t *paramset); + +void paramset_init_params_cache(paramset_t *paramset); +void paramset_init_bindings_cache(paramset_t *paramset); + +void paramset_release(paramset_t *paramset); + +#endif // _param_h_ + + + diff --git a/src/connector/odbc/src/base/rs.c b/src/connector/odbc/src/base/rs.c new file mode 100644 index 0000000000000000000000000000000000000000..068cdec4fd00d8e00ee5976ad2a54feb1da10f12 --- /dev/null +++ b/src/connector/odbc/src/base/rs.c @@ -0,0 +1,18 @@ +/* + * 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 . + */ + +#include "rs.h" + + diff --git a/src/connector/odbc/src/base/rs.h b/src/connector/odbc/src/base/rs.h new file mode 100644 index 0000000000000000000000000000000000000000..6a7e0a2b3ac73047456260bce915278fe473fb5b --- /dev/null +++ b/src/connector/odbc/src/base/rs.h @@ -0,0 +1,29 @@ +/* + * 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 . + */ + +#ifndef _rs_h_ +#define _rs_h_ + +#include "../base.h" + + +struct rs_s { + int affected_rows; +}; + + + +#endif // _rs_h_ + diff --git a/src/connector/odbc/src/base/stmt.c b/src/connector/odbc/src/base/stmt.c new file mode 100644 index 0000000000000000000000000000000000000000..2818b46ed2dbb11594b6c6cb63c61198c558e05f --- /dev/null +++ b/src/connector/odbc/src/base/stmt.c @@ -0,0 +1,465 @@ +/* + * 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 . + */ + +#include "stmt.h" + +#include "conn.h" +#include "param.h" + +static int static_app_row; // SQL_ATTR_APP_ROW_DESC +static int static_app_param; // SQL_ATTR_APP_PARAM_DESC +static int static_imp_row; // SQL_ATTR_IMP_ROW_DESC +static int static_imp_param; // SQL_ATTR_IMP_PARAM_DESC + +static int stmt_init_descs(stmt_t *stmt) { + OILE(stmt, ""); + descs_t *descs = &stmt->descs; + + descs->app_row = &static_app_row; // SQL_ATTR_APP_ROW_DESC + descs->app_param = &static_app_param; // SQL_ATTR_APP_PARAM_DESC + descs->imp_row = &static_imp_row; // SQL_ATTR_IMP_ROW_DESC + descs->imp_param = &static_imp_param; // SQL_ATTR_IMP_PARAM_DESC + + return 0; +} + +static int stmt_init_sql(stmt_t *stmt) { + OILE(stmt, ""); + sql_t *sql = &stmt->sql; + OILE(sql->cache==NULL, ""); + OILE(sql->txt.buf==NULL, ""); + OILE(sql->txt.bytes==0, ""); + OILE(sql->txt.total_bytes==0, ""); + + sql->cache = todbc_buf_create(); + if (!sql->cache) return -1; + + return 0; +} + +static void stmt_release_sql(stmt_t *stmt) { + OILE(stmt, ""); + sql_t *sql = &stmt->sql; + if (!sql->cache) return; + todbc_buf_free(sql->cache); + sql->cache = NULL; + sql->txt.buf = NULL; + sql->txt.bytes = 0; + sql->txt.total_bytes = 0; +} + +static int stmt_init(stmt_t *stmt, conn_t *conn) { + OILE(stmt, ""); + OILE(conn, ""); + OILE(stmt->owner==NULL, ""); + + stmt->typeinfo = SQL_UNKNOWN_TYPE; + + int r = errs_init(&stmt->errs); + if (r) return -1; + + r = stmt_init_descs(stmt); + if (r) return -1; + + r = stmt_init_sql(stmt); + if (r) return -1; + + stmt->attr.bind_type = SQL_PARAM_BIND_BY_COLUMN; + + r = conn_add_stmt(conn, stmt); + OILE(r==0, ""); + OILE(stmt->owner && stmt->owner->conn==conn, ""); + + return 0; +} + +static void stmt_release(stmt_t *stmt) { + if (!stmt) return; + OILE(stmt->owner, ""); + conn_t *conn = stmt->owner->conn; + + conn_del_stmt(conn, stmt); + + paramset_release(&stmt->paramset); + fieldset_release(&stmt->fieldset); + stmt_release_sql(stmt); + errs_release(&stmt->errs); +} + +static SQLRETURN do_process_param(stmt_t *stmt) { + OILE(stmt->ext.proc_param, ""); + return stmt->ext.proc_param(stmt); +} + +static SQLRETURN do_process_param_row(stmt_t *stmt) { + paramset_t *paramset = &stmt->paramset; + int n_params = paramset->n_params; + + SQLRETURN r = SQL_SUCCESS; + + paramset->i_col = 0; + for (; paramset->i_coli_col) { + r = do_process_param(stmt); + if (r!=SQL_SUCCESS) return r; + } + + return SQL_SUCCESS; +} + +stmt_t* stmt_new(conn_t *conn) { + stmt_t *stmt = (stmt_t*)calloc(1, sizeof(*stmt)); + if (!stmt) return NULL; + + if (stmt_init(stmt, conn)) { + free(stmt); + return NULL; + } + + return stmt; +} + +void stmt_free(stmt_t *stmt) { + if (!stmt) return; + + // clean ext stuff + if (stmt->ext.free_stmt) { + stmt->ext.free_stmt(stmt); + stmt->ext.free_stmt = NULL; + } + + // clean stmt stuff + stmt_release(stmt); + + free(stmt); +} + +conn_t* stmt_get_conn(stmt_t *stmt) { + if (!stmt) return NULL; + if (!stmt->owner) return NULL; + + return stmt->owner->conn; +} + +void stmt_reclaim_params(stmt_t *stmt) { + if (!stmt) return; + paramset_reclaim_params(&stmt->paramset); +} + +void stmt_reclaim_param_bindings(stmt_t *stmt) { + if (!stmt) return; + paramset_reclaim_bindings(&stmt->paramset); +} + +void stmt_reclaim_field_bindings(stmt_t *stmt) { + if (!stmt) return; + fieldset_reclaim_bindings(&stmt->fieldset); +} + +void stmt_close_rs(stmt_t *stmt) { + if (!stmt) return; + + OILE(stmt->ext.close_rs, ""); + stmt->ext.close_rs(stmt); + + stmt->typeinfo = SQL_UNKNOWN_TYPE; + + stmt->eof = 0; + + fieldset_reclaim_fields(&stmt->fieldset); + // for the performance + // we don't reclaim field-binds here + // https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlbindcol-function?view=sql-server-ver15 + STMT_SET_NORM(stmt); +} + +void stmt_reset_params(stmt_t *stmt) { + if (!stmt) return; + + stmt->attr.paramset_size = 0; + stmt_reclaim_param_bindings(stmt); +} + +static SQLRETURN stmt_set_sql(stmt_t *stmt, todbc_string_t *txt) { + OILE(stmt, ""); + OILE(txt, ""); + errs_t *errs = &stmt->errs; + sql_t *sql = &stmt->sql; + + OILE(txt!=&sql->txt, ""); + + todbc_buf_t *cache = sql->cache; + OILE(sql->cache, ""); + + conn_t *conn = stmt_get_conn(stmt); + OILE(conn, ""); + const char *enc = conn->enc_db; + + todbc_buf_reclaim(cache); + + sql->txt = todbc_string_conv_to(txt, enc, cache); + if (!sql->txt.buf) { + SET_OOM(errs, ""); + return SQL_ERROR; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_stmt_prepare(stmt_t *stmt) { + OILE(stmt->ext.prepare, ""); + return stmt->ext.prepare(stmt); +} + +static void do_stmt_clear_param_vals(stmt_t *stmt) { + OILE(stmt->ext.clear_param_vals, ""); + stmt->ext.clear_param_vals(stmt); +} + +static void do_stmt_clear_params(stmt_t *stmt) { + stmt->prepared = 0; + paramset_t *paramset = &stmt->paramset; + paramset_reclaim_params(paramset); + do_stmt_clear_param_vals(stmt); +} + +SQLRETURN stmt_exec_direct(stmt_t *stmt, todbc_string_t *txt) { + OILE(stmt, ""); + OILE(txt, ""); + + SQLRETURN r = stmt_set_sql(stmt, txt); + if (r!=SQL_SUCCESS) return r; + + do_stmt_clear_params(stmt); + + if (stmt->ext.exec_direct) { + r = stmt->ext.exec_direct(stmt); + } else { + r = do_stmt_prepare(stmt); + if (r!=SQL_SUCCESS) return r; + stmt->prepared = 1; + OILE(0, ""); + } + + return r; +} + +SQLRETURN stmt_prepare(stmt_t *stmt, todbc_string_t *txt) { + OILE(stmt, ""); + OILE(txt, ""); + + SQLRETURN r = stmt_set_sql(stmt, txt); + if (r!=SQL_SUCCESS) return r; + + do_stmt_clear_params(stmt); + + r = do_stmt_prepare(stmt); + if (r!=SQL_SUCCESS) return r; + stmt->prepared = 1; + + return SQL_SUCCESS; +} + +SQLRETURN stmt_bind_param(stmt_t *stmt, param_binding_t *arg) { + OILE(stmt, ""); + OILE(arg, ""); + OILE(arg->ParameterNumber>0, ""); + int idx = arg->ParameterNumber - 1; + + errs_t *errs = &stmt->errs; + paramset_t *paramset = &stmt->paramset; + + paramset_init_bindings_cache(paramset); + if (!paramset->bindings_cache) { + SET_OOM(errs, "failed to alloc cache for param binds"); + return SQL_ERROR; + } + + todbc_buf_t *cache = paramset->bindings_cache; + OILE(cache, ""); + + param_binding_t *bindings = paramset->bindings; + if (idx>=paramset->n_bindings) { + size_t num = (size_t)(idx + 1); + // align + const size_t block = 10; + num = (num + block-1) / block * block; + bindings = (param_binding_t*)todbc_buf_realloc(cache, bindings, num * sizeof(*bindings)); + if (!bindings) { + SET_OOM(errs, "failed to realloc buf for param binds"); + return SQL_ERROR; + } + paramset->bindings = bindings; + paramset->n_bindings = idx + 1; + } + OILE(paramset->bindings, ""); + OILE(idxn_bindings, ""); + + param_binding_t *binding = bindings + idx; + *binding = *arg; + + if (paramset->n_bindings>paramset->n_params) return SQL_SUCCESS; + + OILE(stmt->ext.set_param_conv, ""); + return stmt->ext.set_param_conv(stmt, idx); +} + +SQLRETURN stmt_execute(stmt_t *stmt) { + OILE(stmt, ""); + OILE(!STMT_IS_EXECUTING(stmt), ""); + + SQLRETURN r = SQL_SUCCESS; + + if (stmt->prepared==0) { + do_stmt_clear_params(stmt); + + r = do_stmt_prepare(stmt); + if (r!=SQL_SUCCESS) return r; + stmt->prepared = 1; + } + OILE(stmt->prepared==1, ""); + + + errs_t *errs = &stmt->errs; + + paramset_t *paramset = &stmt->paramset; + int n_params = paramset->n_params; + int n_bindings = paramset->n_bindings; + + if (n_params>n_bindings) { + SET_GENERAL(errs, "parameters need to be bound first"); + return SQL_ERROR; + } + + if (n_params>0) { + int paramset_size = (int)stmt->attr.paramset_size; + if (paramset_size==0) paramset_size = 1; + stmt->attr.paramset_size = (SQLULEN)paramset_size; + + paramset->i_row = 0; + for (; paramset->i_rowi_row) { + r = do_process_param_row(stmt); + if (r) return r; + + OILE(stmt->ext.param_row_processed, ""); + r = stmt->ext.param_row_processed(stmt); + if (r) return r; + } + } + + OILE(stmt->ext.execute, ""); + return stmt->ext.execute(stmt); +} + +SQLRETURN stmt_fetch(stmt_t *stmt) { + OILE(stmt, ""); + OILE(STMT_IS_EXECUTED(stmt), ""); + + if (stmt->eof) return SQL_NO_DATA; + + OILE(stmt->ext.fetch, ""); + SQLRETURN r = stmt->ext.fetch(stmt); + if (r!=SQL_SUCCESS) return r; + + fieldset_t *fieldset = &stmt->fieldset; + if (fieldset->n_bindings==0) return SQL_SUCCESS; + OILE(fieldset->n_bindings>0, ""); + + for (size_t i=0; in_bindings; ++i) { + OILE(fieldset->bindings, ""); + col_binding_t *binding = fieldset->bindings + i; + if (binding->ColumnNumber!=i+1) { + OILE(binding->ColumnNumber==0, ""); + continue; + } + OILE(stmt->ext.get_data, ""); + r = stmt->ext.get_data(stmt, binding); + if (r!=SQL_SUCCESS) return r; + } + + return SQL_SUCCESS; +} + +SQLRETURN stmt_get_data(stmt_t *stmt, col_binding_t *binding) { + OILE(stmt, ""); + OILE(STMT_IS_EXECUTED(stmt), ""); + + OILE(stmt->eof==0, ""); + + OILE(stmt->ext.get_data, ""); + return stmt->ext.get_data(stmt, binding); +} + +SQLRETURN stmt_bind_col(stmt_t *stmt, col_binding_t *binding) { + OILE(stmt, ""); + // shall we check execute state? + + errs_t *errs = &stmt->errs; + + fieldset_t *fieldset = &stmt->fieldset; + + todbc_buf_t *cache = fieldset->bindings_cache; + if (cache==NULL) { + fieldset_init_bindings(fieldset); + cache = fieldset->bindings_cache; + if (!cache) { + SET_OOM(errs, ""); + return SQL_ERROR; + } + } + OILE(cache, ""); + + col_binding_t *bindings = fieldset->bindings; + + OILE(binding->ColumnNumber>0, ""); + if (binding->ColumnNumber>=fieldset->n_bindings) { + size_t num = (size_t)binding->ColumnNumber; + const size_t block = 10; + size_t align = (num+block-1)/block*block; + size_t total = align * sizeof(*bindings); + bindings = (col_binding_t*)todbc_buf_realloc(cache, bindings, total); + if (!bindings) { + SET_OOM(errs, ""); + return SQL_ERROR; + } + for (size_t i = (size_t)fieldset->n_bindings; ibindings = bindings; + fieldset->n_bindings = (int)num; + } + OILE(bindings, ""); + OILE(binding->ColumnNumber<=fieldset->n_bindings, ""); + bindings[binding->ColumnNumber-1] = *binding; + + return SQL_SUCCESS; +} + + + + +// public +errs_t* stmt_get_errs(stmt_t *stmt) { + OILE(stmt, ""); + + return &stmt->errs; +} + +void stmt_clr_errs(stmt_t *stmt) { + if (!stmt) return; + + errs_reclaim(&stmt->errs); +} + diff --git a/src/connector/odbc/src/base/stmt.h b/src/connector/odbc/src/base/stmt.h new file mode 100644 index 0000000000000000000000000000000000000000..905cb6a00323446736f130642d0e250e4ba24dd9 --- /dev/null +++ b/src/connector/odbc/src/base/stmt.h @@ -0,0 +1,143 @@ +/* + * 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 . + */ + +#ifndef _stmt_h_ +#define _stmt_h_ + +#include "../base.h" + +#include "err.h" +#include "field.h" +#include "param.h" +#include "rs.h" + +typedef struct descs_s descs_t; +typedef struct stmts_s stmts_t; +typedef struct stmt_ext_s stmt_ext_t; +typedef struct stmt_attr_s stmt_attr_t; +typedef struct sql_s sql_t; + +struct descs_s { + void *app_row; // SQL_ATTR_APP_ROW_DESC + void *app_param; // SQL_ATTR_APP_PARAM_DESC + void *imp_row; // SQL_ATTR_IMP_ROW_DESC + void *imp_param; // SQL_ATTR_IMP_PARAM_DESC +}; + +struct stmt_ext_s { + void *ext; + void (*free_stmt)(stmt_t *stmt); + + void (*clear_params)(stmt_t *stmt); + void (*clear_param_vals)(stmt_t *stmt); + + SQLRETURN (*get_param)(stmt_t *stmt, param_t *arg); + SQLRETURN (*set_param_conv)(stmt_t *stmt, int idx); + + SQLRETURN (*exec_direct)(stmt_t *stmt); + SQLRETURN (*prepare)(stmt_t *stmt); + SQLRETURN (*proc_param)(stmt_t *stmt); + SQLRETURN (*param_row_processed)(stmt_t *stmt); + SQLRETURN (*execute)(stmt_t *stmt); + SQLRETURN (*get_affected_rows)(stmt_t *stmt, SQLLEN *RowCount); + SQLRETURN (*get_fields_count)(stmt_t *stmt, SQLSMALLINT *ColumnCount); + SQLRETURN (*get_field)(stmt_t *stmt, field_arg_t *arg); + SQLRETURN (*fetch)(stmt_t *stmt); + SQLRETURN (*get_data)(stmt_t *stmt, col_binding_t *col); + void (*close_rs)(stmt_t *stmt); +}; + +struct stmt_attr_s { + // SQL_ATTR_PARAM_BIND_TYPE: SQL_PARAM_BIND_BY_COLUMN or row size + SQLULEN bind_type; // default: SQL_PARAM_BIND_BY_COLUMN + // SQL_ATTR_PARAM_BIND_OFFSET_PTR + SQLULEN *bind_offset_ptr; // default: NULL + // SQL_ATTR_PARAMSET_SIZE + SQLULEN paramset_size; // default: 0 +}; + +struct sql_s { + todbc_buf_t *cache; + todbc_string_t txt; +}; + +struct stmt_s { + stmts_t *owner; + stmt_t *next; + stmt_t *prev; + + SQLSMALLINT typeinfo; + + descs_t descs; + + sql_t sql; + + stmt_attr_t attr; + + paramset_t paramset; + fieldset_t fieldset; + + int affected_rows; + rs_t rs; + + errs_t errs; + + stmt_ext_t ext; + + unsigned int prepared:1; + unsigned int execute:2; + unsigned int eof:1; +}; + +struct stmts_s { + conn_t *conn; + + int count; + stmt_t *head; + stmt_t *tail; +}; + +#define STMT_TYPEINFO(stmt) (stmt->typeinfo!=SQL_UNKNOWN_TYPE) + +#define STMT_SET_EXECUTING(stmt) (stmt->execute=0x01) +#define STMT_SET_EXECUTED(stmt) (stmt->execute=0x02) +#define STMT_SET_NORM(stmt) (stmt->execute=0x00) + +#define STMT_IS_EXECUTING(stmt) (stmt->execute==0x01) +#define STMT_IS_EXECUTED(stmt) (stmt->execute==0x02) +#define STMT_IS_NORM(stmt) (stmt->execute==0x00) + +stmt_t* stmt_new(conn_t *conn); +void stmt_free(stmt_t *stmt); + +conn_t* stmt_get_conn(stmt_t *stmt); + +void stmt_reclaim_params(stmt_t *stmt); +void stmt_reclaim_param_binds(stmt_t *stmt); +void stmt_reclaim_field_binds(stmt_t *stmt); +void stmt_close_rs(stmt_t *stmt); +void stmt_reset_params(stmt_t *stmt); +SQLRETURN stmt_exec_direct(stmt_t *stmt, todbc_string_t *txt); +SQLRETURN stmt_prepare(stmt_t *stmt, todbc_string_t *txt); +SQLRETURN stmt_bind_param(stmt_t *stmt, param_binding_t *arg); +SQLRETURN stmt_execute(stmt_t *stmt); +SQLRETURN stmt_fetch(stmt_t *stmt); +SQLRETURN stmt_get_data(stmt_t *stmt, col_binding_t *binding); +SQLRETURN stmt_bind_col(stmt_t *stmt, col_binding_t *binding); + +#endif // _stmt_h_ + + + diff --git a/src/connector/odbc/src/base/tsdb_impl.c b/src/connector/odbc/src/base/tsdb_impl.c new file mode 100644 index 0000000000000000000000000000000000000000..d913aebd7df55ceef337d48131f7bab634219e1b --- /dev/null +++ b/src/connector/odbc/src/base/tsdb_impl.c @@ -0,0 +1,2598 @@ +/* + * 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 . + */ + +#include "tsdb_impl.h" + +#include "env.h" +#include "../todbc_tls.h" +#include "../todbc_util.h" + +#include "ttype.h" + + +#include + +// tsdb_conn + +typedef struct tsdb_conn_s tsdb_conn_t; +typedef struct tsdb_stmt_s tsdb_stmt_t; +typedef struct tsdb_param_s tsdb_param_t; +typedef struct tsdb_param_val_s tsdb_param_val_t; +typedef struct tsdb_param_conv_arg_s tsdb_param_conv_arg_t; + +struct tsdb_conn_s { + conn_t *conn; + + char svr_info[64]; + char cli_info[64]; + + TAOS *taos; +}; + +struct tsdb_param_s { + int tsdb_type; // TSDB_DATA_TYPE_xxx + int tsdb_bytes; + + SQLRETURN (*conv)(stmt_t *stmt, tsdb_param_conv_arg_t *arg); +}; + +struct tsdb_param_val_s { + SQLUSMALLINT ParameterNumber; + int is_null; +}; + +struct tsdb_stmt_s { + stmt_t *stmt; + + TAOS_STMT *tsdb_stmt; // prepared-statement + TAOS_RES *tsdb_res; + + tsdb_param_t *tsdb_params; + + todbc_buf_t *tsdb_param_vals_cache; + tsdb_param_val_t *tsdb_param_vals; + TAOS_BIND *taos_binds; + + TAOS_FIELD *tsdb_fields; + TAOS_ROW tsdb_curr; + + unsigned int by_query:1; +}; + +struct tsdb_param_conv_arg_s { + conn_t *conn; + todbc_buf_t *cache; + int idx; + SQLPOINTER val; + SQLLEN soi; + tsdb_param_t *tsdb_param; + tsdb_param_val_t *tsdb_param_val; + TAOS_BIND *taos_bind; +}; + +static void tsdb_stmt_init_param_vals_cache(tsdb_stmt_t *tsdb_stmt) { + OILE(tsdb_stmt, ""); + if (tsdb_stmt->tsdb_param_vals_cache) return; + tsdb_stmt->tsdb_param_vals_cache = todbc_buf_create(); +} + +static void tsdb_stmt_reclaim_param_vals(tsdb_stmt_t *tsdb_stmt) { + if (!tsdb_stmt) return; + if (tsdb_stmt->tsdb_param_vals_cache) { + tsdb_stmt->tsdb_param_vals = NULL; + tsdb_stmt->taos_binds = NULL; + todbc_buf_reclaim(tsdb_stmt->tsdb_param_vals_cache); + } + OILE(tsdb_stmt->tsdb_param_vals==NULL, ""); + OILE(tsdb_stmt->taos_binds==NULL, ""); +} + +static void tsdb_stmt_cleanup_param_vals(tsdb_stmt_t *tsdb_stmt) { + if (!tsdb_stmt) return; + tsdb_stmt_reclaim_param_vals(tsdb_stmt); + + if (tsdb_stmt->tsdb_param_vals_cache) { + todbc_buf_free(tsdb_stmt->tsdb_param_vals_cache); + } +} + +static void tsdb_stmt_calloc_param_vals(tsdb_stmt_t *tsdb_stmt) { + OILE(tsdb_stmt, ""); + stmt_t *stmt = tsdb_stmt->stmt; + OILE(stmt, ""); + paramset_t *paramset = &stmt->paramset; + int n_params = paramset->n_params; + OILE(n_params>0, ""); + todbc_buf_t *cache = tsdb_stmt->tsdb_param_vals_cache; + OILE(cache, ""); + OILE(tsdb_stmt->tsdb_param_vals==NULL, ""); + OILE(tsdb_stmt->taos_binds==NULL, ""); + tsdb_stmt->tsdb_param_vals = (tsdb_param_val_t*)todbc_buf_calloc(cache, (size_t)n_params, sizeof(*tsdb_stmt->tsdb_param_vals)); + tsdb_stmt->taos_binds = (TAOS_BIND*)todbc_buf_calloc(cache, (size_t)n_params, sizeof(*tsdb_stmt->taos_binds)); +} + +static SQLRETURN tsdb_stmt_init_stmt(tsdb_stmt_t *tsdb_stmt) { + OILE(tsdb_stmt && tsdb_stmt->stmt, ""); + errs_t *errs = &tsdb_stmt->stmt->errs; + + if (tsdb_stmt->tsdb_stmt) return SQL_SUCCESS; + OILE(tsdb_stmt->stmt->owner, ""); + conn_t *conn = tsdb_stmt->stmt->owner->conn; + OILE(conn, ""); + tsdb_conn_t *tsdb_conn = (tsdb_conn_t*)conn->ext.ext; + OILE(tsdb_conn && tsdb_conn->taos, ""); + tsdb_stmt->tsdb_stmt = taos_stmt_init(tsdb_conn->taos); + if (!tsdb_stmt->tsdb_stmt) { + SET_GENERAL(errs, "failed to init taos stmt"); + return SQL_ERROR; + } + + return SQL_SUCCESS; +} + +static void tsdb_stmt_close_stmt(tsdb_stmt_t *tsdb_stmt) { + if (!tsdb_stmt) return; + if (!tsdb_stmt->tsdb_stmt) return; + + int r = taos_stmt_close(tsdb_stmt->tsdb_stmt); + tsdb_stmt->tsdb_stmt= NULL; + tsdb_stmt->stmt->prepared = 0; + if (r) OD("[%d]%s", r, tstrerror(r)); +} + +static void tsdb_stmt_close_rs(tsdb_stmt_t *tsdb_stmt) { + if (!tsdb_stmt) return; + if (!tsdb_stmt->tsdb_res) return; + + tsdb_stmt->tsdb_curr = NULL; + + if (tsdb_stmt->by_query) { + taos_stop_query(tsdb_stmt->tsdb_res); + } else { + OILE(tsdb_stmt->tsdb_stmt==NULL, ""); + taos_free_result(tsdb_stmt->tsdb_res); + } + tsdb_stmt->tsdb_res = NULL; +} + +static void tsdb_conn_free(conn_t *conn) { + OILE(conn, ""); + + tsdb_conn_t *tsdb_conn = (tsdb_conn_t*)conn->ext.ext; + OILE(tsdb_conn, ""); + OILE(tsdb_conn->taos==NULL, ""); + + conn->ext.ext = NULL; + conn->ext.free_conn = NULL; + + free(tsdb_conn); +} + +static SQLRETURN tsdb_conn_connect(conn_t *conn) { + OILE(conn, ""); + OILE(CONN_IS_NORM(conn), ""); + errs_t *errs = &conn->errs; + tsdb_conn_t *tsdb_conn = (tsdb_conn_t*)conn->ext.ext; + OILE(tsdb_conn, ""); + OILE(tsdb_conn->conn==conn, ""); + + conn_val_t *val = &conn->val; + const char *dsn = val->dsn; + const char *uid = val->uid; + const char *pwd = val->pwd; + const char *db = val->db; + const char *svr = val->server; + + OILE(dsn, ""); + + int use_default = 0; + char server[4096]; server[0] = '\0'; + if (!svr || !svr[0]) { + int n = SQLGetPrivateProfileString(dsn, "Server", "", server, sizeof(server)-1, "Odbc.ini"); + if (n<=0) { + snprintf(server, sizeof(server), DEFAULT_SERVER); + n = (int)strlen(server); + use_default = 1; + } else { + server[n] = '\0'; + } + svr = server; + + if (!svr || !svr[0]) { + SET_GENERAL(errs, "please specify Server entry in connection string or odbc.ini or windows registry for DSN:[%s]", dsn); + return SQL_ERROR; + } + } + + char *ip = NULL; + int port = 0; + char *p = strchr(svr, ':'); + if (p) { + ip = todbc_tls_strndup(svr, (size_t)(p-svr)); + port = atoi(p+1); + } + + tsdb_conn->taos = taos_connect(ip, uid, pwd, db, (uint16_t)port); + if (!tsdb_conn->taos) { + int e = terrno; + const char * es = tstrerror(e); + if (use_default) { + SET_GENERAL(errs, "no Server entry in odbc.ini or windows registry for DSN[%s], fallback to svr[%s:%d] db[%s]", dsn, ip, port, db); + } + SET_GENERAL(errs, "connect to DSN[%s] svr[%s:%d] db[%s] failed", dsn, ip, port, db); + SET_GENERAL(errs, "[%x]%s", e, es); + return SQL_ERROR; + } + + const char *svr_info = taos_get_server_info(tsdb_conn->taos); + const char *cli_info = taos_get_client_info(tsdb_conn->taos); + snprintf(tsdb_conn->svr_info, sizeof(tsdb_conn->svr_info), "%s", svr_info); + snprintf(tsdb_conn->cli_info, sizeof(tsdb_conn->cli_info), "%s", cli_info); + + return SQL_SUCCESS; +} + +static void tsdb_conn_disconnect(conn_t *conn) { + OILE(conn, ""); + OILE(CONN_IS_CONNECTED(conn), ""); + + tsdb_conn_t *tsdb_conn = (tsdb_conn_t*)conn->ext.ext; + OILE(tsdb_conn, ""); + OILE(tsdb_conn->conn==conn, ""); + + TAOS *taos = tsdb_conn->taos; + + if (!taos) return; + taos_close(taos); + taos = NULL; + tsdb_conn->taos = NULL; +} + +static void tsdb_conn_free_stmt(stmt_t *stmt) { + OILE(stmt, ""); + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt && tsdb_stmt->stmt==stmt, ""); + + tsdb_stmt_close_rs(tsdb_stmt); + tsdb_stmt_close_stmt(tsdb_stmt); + tsdb_stmt_cleanup_param_vals(tsdb_stmt); + + tsdb_stmt->tsdb_params = NULL; + + stmt_ext_t ext = {0}; + stmt->ext = ext; + + free(tsdb_stmt); +} + +static void tsdb_conn_clear_param_vals(stmt_t *stmt) { + OILE(stmt, ""); + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt && tsdb_stmt->stmt==stmt, ""); + + tsdb_stmt_reclaim_param_vals(tsdb_stmt); +} + +static SQLRETURN tsdb_conn_exec_direct(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + OILE(!STMT_IS_EXECUTED(stmt), ""); + + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + tsdb_conn_t *tsdb_conn = (tsdb_conn_t*)conn->ext.ext; + OILE(tsdb_conn && tsdb_conn->conn==conn, ""); + TAOS *taos = tsdb_conn->taos; + OILE(taos, ""); + + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt && tsdb_stmt->stmt==stmt, ""); + OILE(tsdb_stmt->tsdb_stmt==NULL, ""); + OILE(tsdb_stmt->tsdb_res==NULL, ""); + + errs_t *errs = &stmt->errs; + + tsdb_stmt_reclaim_param_vals(tsdb_stmt); + + const char *txt = (const char*)stmt->sql.txt.buf; + TAOS_RES *tsdb_res = taos_query(taos, txt); + OILE(tsdb_res, ""); + int r = taos_errno(tsdb_res); + if (r) { + SET_GENERAL(errs, "taos query failed:[%d]%s", r, tstrerror(r)); + taos_stop_query(tsdb_res); + STMT_SET_NORM(stmt); + return SQL_ERROR; + } + + tsdb_stmt->tsdb_res = tsdb_res; + tsdb_stmt->by_query = 1; + + STMT_SET_EXECUTED(stmt); + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_int64_to_tsdb_timestamp(stmt_t *stmt, const int64_t v, tsdb_param_conv_arg_t *arg) { + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + taos_bind->u.ts = v; + taos_bind->buffer_length = sizeof(taos_bind->u.ts); + taos_bind->buffer = &taos_bind->u.ts; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_int64_to_tsdb_tinyint(stmt_t *stmt, const int64_t v, tsdb_param_conv_arg_t *arg) { + errs_t *errs = &stmt->errs; + + if (vINT8_MAX) { + SET_GENERAL(errs, "integer overflow for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_TINYINT; + taos_bind->u.v1 = (int8_t)v; + taos_bind->buffer_length = sizeof(taos_bind->u.v1); + taos_bind->buffer = &taos_bind->u.v1; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_int64_to_tsdb_smallint(stmt_t *stmt, const int64_t v, tsdb_param_conv_arg_t *arg) { + errs_t *errs = &stmt->errs; + + if (vINT16_MAX) { + SET_GENERAL(errs, "integer overflow for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_SMALLINT; + taos_bind->u.v2 = (int16_t)v; + taos_bind->buffer_length = sizeof(taos_bind->u.v2); + taos_bind->buffer = &taos_bind->u.v2; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_int64_to_tsdb_int(stmt_t *stmt, const int64_t v, tsdb_param_conv_arg_t *arg) { + errs_t *errs = &stmt->errs; + + if (vINT32_MAX) { + SET_GENERAL(errs, "integer overflow for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_INT; + taos_bind->u.v4 = (int32_t)v; + taos_bind->buffer_length = sizeof(taos_bind->u.v4); + taos_bind->buffer = &taos_bind->u.v4; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_int64_to_tsdb_bigint(stmt_t *stmt, const int64_t v, tsdb_param_conv_arg_t *arg) { + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_BIGINT; + taos_bind->u.v8 = v; + taos_bind->buffer_length = sizeof(taos_bind->u.v8); + taos_bind->buffer = &taos_bind->u.v8; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_double_to_tsdb_float(stmt_t *stmt, const double v, tsdb_param_conv_arg_t *arg) { + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_FLOAT; + taos_bind->u.f4 = (float)v; + taos_bind->buffer_length = sizeof(taos_bind->u.f4); + taos_bind->buffer = &taos_bind->u.f4; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_double_to_tsdb_double(stmt_t *stmt, const double v, tsdb_param_conv_arg_t *arg) { + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_DOUBLE; + taos_bind->u.f8 = v; + taos_bind->buffer_length = sizeof(taos_bind->u.f8); + taos_bind->buffer = &taos_bind->u.f8; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + + +static SQLRETURN do_conv_sql_string_to_int64(stmt_t *stmt, const char *enc_from, tsdb_param_conv_arg_t *arg, int64_t *v) { + todbc_buf_t *cache = arg->cache; + const char *enc_to = arg->conn->enc_src; // ?locale or src?, windows iconv!!! + const unsigned char *src = (const unsigned char*)arg->val; + size_t slen = (size_t)arg->soi; + + errs_t *errs = &stmt->errs; + + todbc_string_t txt = todbc_tls_conv(cache, enc_to, enc_from, src, &slen); + if (!txt.buf) { + SET_OOM(errs, "failed to alloc space to convert from [%s->%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + if (txt.bytes%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + + const char *buf = (const char*)txt.buf; + int bytes = 0; + int64_t i64 = 0; + sscanf(buf, "%" PRId64 " %n", &i64, &bytes); + if (strlen(buf)!=bytes) { + SET_GENERAL(errs, "failed to convert to integer for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + *v = i64; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_sql_string_to_double(stmt_t *stmt, const char *enc_from, tsdb_param_conv_arg_t *arg, double *v) { + todbc_buf_t *cache = arg->cache; + const char *enc_to = arg->conn->enc_src; // ?locale or src?, windows iconv!!! + const unsigned char *src = (const unsigned char*)arg->val; + size_t slen = (size_t)arg->soi; + + errs_t *errs = &stmt->errs; + + todbc_string_t txt = todbc_tls_conv(cache, enc_to, enc_from, src, &slen); + if (!txt.buf) { + SET_OOM(errs, "failed to alloc space to convert from [%s->%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + if (txt.bytes%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + + const char *buf = (const char*)txt.buf; + int bytes = 0; + double dbl = 0.0; + sscanf(buf, "%lf%n", &dbl, &bytes); + if (strlen(buf)!=bytes) { + SET_GENERAL(errs, "failed to convert to double for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + *v = dbl; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_sql_string_to_tsdb_timestamp(stmt_t *stmt, const char *enc_from, tsdb_param_conv_arg_t *arg) { + todbc_buf_t *cache = arg->cache; + const char *enc_to = arg->conn->enc_src; // ?locale or src?, windows iconv!!! + const unsigned char *src = (const unsigned char*)arg->val; + size_t slen = (size_t)arg->soi; + + errs_t *errs = &stmt->errs; + + todbc_string_t txt = todbc_tls_conv(cache, enc_to, enc_from, src, &slen); + if (!txt.buf) { + SET_OOM(errs, "failed to alloc space to convert from [%s->%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + if (txt.bytes%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + + char *buf = (char*)txt.buf; + int32_t bytes = (int32_t)txt.bytes; + + int64_t ts = 0; + int r = taosParseTime(buf, &ts, bytes, TSDB_TIME_PRECISION_MILLI, 0); + if (r) { + SET_GENERAL(errs, "failed to parse as timestamp for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + taos_bind->u.ts = ts; + taos_bind->buffer_length = sizeof(taos_bind->u.ts); + taos_bind->buffer = &taos_bind->u.ts; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_sql_string_to_tsdb_nchar(stmt_t *stmt, const char *enc_from, tsdb_param_conv_arg_t *arg) { + todbc_buf_t *cache = arg->cache; + const char *enc_to = arg->conn->enc_db; + const unsigned char *src = (const unsigned char*)arg->val; + size_t slen = (size_t)arg->soi; + + errs_t *errs = &stmt->errs; + + todbc_string_t txt_db = todbc_tls_conv(cache, enc_to, enc_from, src, &slen); + if (!txt_db.buf) { + SET_OOM(errs, "failed to alloc space to convert from [%s->%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + if (txt_db.bytes%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + + char *buf = (char*)txt_db.buf; + int32_t bytes = (int32_t)txt_db.bytes; + if (bytes > arg->tsdb_param->tsdb_bytes) { + SET_OOM(errs, "failed to convert from [%s->%s] for param [%d], string too long [%d/%d]", + enc_from, enc_to, arg->idx+1, bytes, arg->tsdb_param->tsdb_bytes); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_NCHAR; + taos_bind->u.nchar = buf; + taos_bind->buffer_length = (uintptr_t)((size_t)bytes); + taos_bind->buffer = taos_bind->u.nchar; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_sql_string_to_tsdb_bool(stmt_t *stmt, const char *enc_from, tsdb_param_conv_arg_t *arg) { + int64_t v = 0; + + todbc_buf_t *cache = arg->cache; + const char *enc_to = arg->conn->enc_src; // ?locale or src?, windows iconv!!! + const unsigned char *src = (const unsigned char*)arg->val; + size_t slen = (size_t)arg->soi; + + errs_t *errs = &stmt->errs; + + todbc_string_t txt_db = todbc_tls_conv(cache, enc_to, enc_from, src, &slen); + if (!txt_db.buf) { + SET_OOM(errs, "failed to alloc space to convert from [%s->%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + if (txt_db.bytes%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + + const char *buf = (const char*)txt_db.buf; + int bytes = 0; + if (strcasecmp(buf, "true")==0) { + v = 1; + } else if (strcasecmp(buf, "false")==0) { + v = 0; + } else { + sscanf(buf, "%" PRId64 " %n", &v, &bytes); + if (strlen(buf)!=bytes) { + SET_GENERAL(errs, "failed to convert to integer for param [%d]", arg->idx+1); + return SQL_ERROR; + } + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_BOOL; + taos_bind->u.b = v ? 1 : 0; + taos_bind->buffer_length = sizeof(taos_bind->u.b); + taos_bind->buffer = &taos_bind->u.b; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_sql_string_to_tsdb_tinyint(stmt_t *stmt, const char *enc_from, tsdb_param_conv_arg_t *arg) { + int64_t v = 0; + + todbc_buf_t *cache = arg->cache; + const char *enc_to = arg->conn->enc_src; // ?locale or src?, windows iconv!!! + const unsigned char *src = (const unsigned char*)arg->val; + size_t slen = (size_t)arg->soi; + + errs_t *errs = &stmt->errs; + + todbc_string_t txt_db = todbc_tls_conv(cache, enc_to, enc_from, src, &slen); + if (!txt_db.buf) { + SET_OOM(errs, "failed to alloc space to convert from [%s->%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + if (txt_db.bytes%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + + const char *buf = (const char*)txt_db.buf; + int bytes = 0; + sscanf(buf, "%" PRId64 " %n", &v, &bytes); + if (strlen(buf)!=bytes) { + SET_GENERAL(errs, "failed to convert to integer for param [%d]", arg->idx+1); + return SQL_ERROR; + } + if (vINT8_MAX) { + SET_GENERAL(errs, "failed to convert to tinyint for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_TINYINT; + taos_bind->u.v1 = (int8_t)v; + taos_bind->buffer_length = sizeof(taos_bind->u.v1); + taos_bind->buffer = &taos_bind->u.v1; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_sql_string_to_tsdb_smallint(stmt_t *stmt, const char *enc_from, tsdb_param_conv_arg_t *arg) { + int64_t v = 0; + + todbc_buf_t *cache = arg->cache; + const char *enc_to = arg->conn->enc_src; // ?locale or src?, windows iconv!!! + const unsigned char *src = (const unsigned char*)arg->val; + size_t slen = (size_t)arg->soi; + + errs_t *errs = &stmt->errs; + + todbc_string_t txt_db = todbc_tls_conv(cache, enc_to, enc_from, src, &slen); + if (!txt_db.buf) { + SET_OOM(errs, "failed to alloc space to convert from [%s->%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + if (txt_db.bytes%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + + const char *buf = (const char*)txt_db.buf; + int bytes = 0; + sscanf(buf, "%" PRId64 " %n", &v, &bytes); + if (strlen(buf)!=bytes) { + SET_GENERAL(errs, "failed to convert to integer for param [%d]", arg->idx+1); + return SQL_ERROR; + } + if (vINT16_MAX) { + SET_GENERAL(errs, "failed to convert to smallint for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_SMALLINT; + taos_bind->u.v2 = (int16_t)v; + taos_bind->buffer_length = sizeof(taos_bind->u.v2); + taos_bind->buffer = &taos_bind->u.v2; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_sql_string_to_tsdb_int(stmt_t *stmt, const char *enc_from, tsdb_param_conv_arg_t *arg) { + int64_t v = 0; + + todbc_buf_t *cache = arg->cache; + const char *enc_to = arg->conn->enc_src; // ?locale or src?, windows iconv!!! + const unsigned char *src = (const unsigned char*)arg->val; + size_t slen = (size_t)arg->soi; + + errs_t *errs = &stmt->errs; + + todbc_string_t txt_db = todbc_tls_conv(cache, enc_to, enc_from, src, &slen); + if (!txt_db.buf) { + SET_OOM(errs, "failed to alloc space to convert from [%s->%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + if (txt_db.bytes%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + + const char *buf = (const char*)txt_db.buf; + int bytes = 0; + sscanf(buf, "%" PRId64 " %n", &v, &bytes); + if (strlen(buf)!=bytes) { + SET_GENERAL(errs, "failed to convert to integer for param [%d]", arg->idx+1); + return SQL_ERROR; + } + if (vINT32_MAX) { + SET_GENERAL(errs, "failed to convert to int for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_INT; + taos_bind->u.v4 = (int32_t)v; + taos_bind->buffer_length = sizeof(taos_bind->u.v4); + taos_bind->buffer = &taos_bind->u.v4; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_sql_string_to_tsdb_bigint(stmt_t *stmt, const char *enc_from, tsdb_param_conv_arg_t *arg) { + int64_t v = 0; + + todbc_buf_t *cache = arg->cache; + const char *enc_to = arg->conn->enc_src; // ?locale or src?, windows iconv!!! + const unsigned char *src = (const unsigned char*)arg->val; + size_t slen = (size_t)arg->soi; + + errs_t *errs = &stmt->errs; + + todbc_string_t txt_db = todbc_tls_conv(cache, enc_to, enc_from, src, &slen); + if (!txt_db.buf) { + SET_OOM(errs, "failed to alloc space to convert from [%s->%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + if (txt_db.bytes%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + + const char *buf = (const char*)txt_db.buf; + int bytes = 0; + sscanf(buf, "%" PRId64 " %n", &v, &bytes); + if (strlen(buf)!=bytes) { + SET_GENERAL(errs, "failed to convert to integer for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_BIGINT; + taos_bind->u.v8 = (int64_t)v; + taos_bind->buffer_length = sizeof(taos_bind->u.v8); + taos_bind->buffer = &taos_bind->u.v8; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_sql_string_to_tsdb_float(stmt_t *stmt, const char *enc_from, tsdb_param_conv_arg_t *arg) { + double v = 0; + + todbc_buf_t *cache = arg->cache; + const char *enc_to = arg->conn->enc_src; // ?locale or src?, windows iconv!!! + const unsigned char *src = (const unsigned char*)arg->val; + size_t slen = (size_t)arg->soi; + + errs_t *errs = &stmt->errs; + + todbc_string_t txt_db = todbc_tls_conv(cache, enc_to, enc_from, src, &slen); + if (!txt_db.buf) { + SET_OOM(errs, "failed to alloc space to convert from [%s->%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + if (txt_db.bytes%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + + const char *buf = (const char*)txt_db.buf; + int bytes = 0; + sscanf(buf, "%lf %n", &v, &bytes); + if (strlen(buf)!=bytes) { + SET_GENERAL(errs, "failed to convert to integer for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_FLOAT; + taos_bind->u.f4 = (float)v; + taos_bind->buffer_length = sizeof(taos_bind->u.f4); + taos_bind->buffer = &taos_bind->u.f4; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_sql_string_to_tsdb_double(stmt_t *stmt, const char *enc_from, tsdb_param_conv_arg_t *arg) { + double v = 0; + + todbc_buf_t *cache = arg->cache; + const char *enc_to = arg->conn->enc_src; // ?locale or src?, windows iconv!!! + const unsigned char *src = (const unsigned char*)arg->val; + size_t slen = (size_t)arg->soi; + + errs_t *errs = &stmt->errs; + + todbc_string_t txt_db = todbc_tls_conv(cache, enc_to, enc_from, src, &slen); + if (!txt_db.buf) { + SET_OOM(errs, "failed to alloc space to convert from [%s->%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + if (txt_db.bytes%s] for param [%d]", enc_from, enc_to, arg->idx+1); + return SQL_ERROR; + } + + const char *buf = (const char*)txt_db.buf; + int bytes = 0; + sscanf(buf, "%lf %n", &v, &bytes); + if (strlen(buf)!=bytes) { + SET_GENERAL(errs, "failed to convert to integer for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_DOUBLE; + taos_bind->u.f8 = v; + taos_bind->buffer_length = sizeof(taos_bind->u.f8); + taos_bind->buffer = &taos_bind->u.f8; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_sql_wchar_to_tsdb_timestamp(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_wchar; + return do_conv_sql_string_to_tsdb_timestamp(stmt, enc_from, arg); +} + +static SQLRETURN do_conv_sql_wchar_to_tsdb_nchar(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_wchar; + return do_conv_sql_string_to_tsdb_nchar(stmt, enc_from, arg); +} + +static SQLRETURN do_conv_sql_wchar_to_tsdb_bool(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_wchar; + return do_conv_sql_string_to_tsdb_bool(stmt, enc_from, arg); +} + +static SQLRETURN do_conv_sql_wchar_to_tsdb_tinyint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_wchar; + int64_t v = 0; + SQLRETURN r = do_conv_sql_string_to_int64(stmt, enc_from, arg, &v); + if (r!=SQL_SUCCESS) return r; + return do_conv_int64_to_tsdb_tinyint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_wchar_to_tsdb_smallint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_wchar; + int64_t v = 0; + SQLRETURN r = do_conv_sql_string_to_int64(stmt, enc_from, arg, &v); + if (r!=SQL_SUCCESS) return r; + return do_conv_int64_to_tsdb_smallint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_wchar_to_tsdb_int(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_wchar; + int64_t v = 0; + SQLRETURN r = do_conv_sql_string_to_int64(stmt, enc_from, arg, &v); + if (r!=SQL_SUCCESS) return r; + return do_conv_int64_to_tsdb_int(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_wchar_to_tsdb_bigint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_wchar; + int64_t v = 0; + SQLRETURN r = do_conv_sql_string_to_int64(stmt, enc_from, arg, &v); + if (r!=SQL_SUCCESS) return r; + return do_conv_int64_to_tsdb_bigint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_wchar_to_tsdb_float(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_wchar; + double v = 0; + SQLRETURN r = do_conv_sql_string_to_double(stmt, enc_from, arg, &v); + if (r!=SQL_SUCCESS) return r; + return do_conv_double_to_tsdb_float(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_wchar_to_tsdb_double(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_wchar; + double v = 0; + SQLRETURN r = do_conv_sql_string_to_double(stmt, enc_from, arg, &v); + if (r!=SQL_SUCCESS) return r; + return do_conv_double_to_tsdb_double(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_char_to_tsdb_timestamp(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_char; + return do_conv_sql_string_to_tsdb_timestamp(stmt, enc_from, arg); +} + +static SQLRETURN do_conv_sql_char_to_tsdb_nchar(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_char; + return do_conv_sql_string_to_tsdb_nchar(stmt, enc_from, arg); +} + +static SQLRETURN do_conv_sql_char_to_tsdb_bool(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_char; + return do_conv_sql_string_to_tsdb_bool(stmt, enc_from, arg); +} + +static SQLRETURN do_conv_sql_char_to_tsdb_tinyint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_char; + return do_conv_sql_string_to_tsdb_tinyint(stmt, enc_from, arg); +} + +static SQLRETURN do_conv_sql_char_to_tsdb_smallint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_char; + return do_conv_sql_string_to_tsdb_smallint(stmt, enc_from, arg); +} + +static SQLRETURN do_conv_sql_char_to_tsdb_int(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_char; + return do_conv_sql_string_to_tsdb_int(stmt, enc_from, arg); +} + +static SQLRETURN do_conv_sql_char_to_tsdb_bigint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_char; + return do_conv_sql_string_to_tsdb_bigint(stmt, enc_from, arg); +} + +static SQLRETURN do_conv_sql_char_to_tsdb_float(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_char; + return do_conv_sql_string_to_tsdb_float(stmt, enc_from, arg); +} + +static SQLRETURN do_conv_sql_char_to_tsdb_double(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + const char *enc_from = arg->conn->enc_char; + return do_conv_sql_string_to_tsdb_double(stmt, enc_from, arg); +} + +static SQLRETURN do_conv_int64_to_tsdb_bool(stmt_t *stmt, const int64_t v, tsdb_param_conv_arg_t *arg) { + errs_t *errs = &stmt->errs; + + if (v!=1 && v!=0) { + SET_GENERAL(errs, "integer overflow for param [%d]", arg->idx+1); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_BOOL; + taos_bind->u.b = v ? 1 : 0; + taos_bind->buffer_length = sizeof(taos_bind->u.b); + taos_bind->buffer = &taos_bind->u.b; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_sql_sbigint_to_tsdb_bigint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int64_t v = *(int64_t*)arg->val; + + return do_conv_int64_to_tsdb_bigint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_sbigint_to_tsdb_tinyint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int64_t v = *(int64_t*)arg->val; + + return do_conv_int64_to_tsdb_tinyint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_sbigint_to_tsdb_int(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int64_t v = *(int64_t*)arg->val; + + return do_conv_int64_to_tsdb_int(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_sbigint_to_tsdb_timestamp(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int64_t v = *(int64_t*)arg->val; + + return do_conv_int64_to_tsdb_timestamp(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_long_to_tsdb_bool(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int32_t v = *(int32_t*)arg->val; + + return do_conv_int64_to_tsdb_bool(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_long_to_tsdb_tinyint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int32_t v = *(int32_t*)arg->val; + + return do_conv_int64_to_tsdb_tinyint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_long_to_tsdb_smallint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int32_t v = *(int32_t*)arg->val; + + return do_conv_int64_to_tsdb_smallint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_long_to_tsdb_int(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int32_t v = *(int32_t*)arg->val; + + return do_conv_int64_to_tsdb_int(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_long_to_tsdb_bigint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int32_t v = *(int32_t*)arg->val; + + return do_conv_int64_to_tsdb_bigint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_tinyint_to_tsdb_bool(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int8_t v = *(int8_t*)arg->val; + + return do_conv_int64_to_tsdb_bool(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_tinyint_to_tsdb_tinyint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int8_t v = *(int8_t*)arg->val; + + return do_conv_int64_to_tsdb_tinyint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_tinyint_to_tsdb_smallint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int8_t v = *(int8_t*)arg->val; + + return do_conv_int64_to_tsdb_smallint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_tinyint_to_tsdb_int(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int8_t v = *(int8_t*)arg->val; + + return do_conv_int64_to_tsdb_int(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_tinyint_to_tsdb_bigint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int8_t v = *(int8_t*)arg->val; + + return do_conv_int64_to_tsdb_bigint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_short_to_tsdb_bool(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int16_t v = *(int16_t*)arg->val; + + return do_conv_int64_to_tsdb_bool(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_short_to_tsdb_tinyint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int16_t v = *(int16_t*)arg->val; + + return do_conv_int64_to_tsdb_tinyint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_short_to_tsdb_smallint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int16_t v = *(int16_t*)arg->val; + + return do_conv_int64_to_tsdb_smallint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_short_to_tsdb_int(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int16_t v = *(int16_t*)arg->val; + + return do_conv_int64_to_tsdb_int(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_short_to_tsdb_bigint(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + int16_t v = *(int16_t*)arg->val; + + return do_conv_int64_to_tsdb_bigint(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_double_to_tsdb_float(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + double v = *(double*)arg->val; + + return do_conv_double_to_tsdb_float(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_double_to_tsdb_double(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + double v = *(double*)arg->val; + + return do_conv_double_to_tsdb_double(stmt, v, arg); +} + +static SQLRETURN do_conv_sql_binary_to_tsdb_binary(stmt_t *stmt, tsdb_param_conv_arg_t *arg) { + unsigned char *buf = (unsigned char*)arg->val; + size_t len = (size_t)arg->soi; + OILE(len>0, ""); + + errs_t *errs = &stmt->errs; + + if (len > arg->tsdb_param->tsdb_bytes) { + SET_OOM(errs, "failed to convert binary for param [%d], binary too long [%zd/%d]", arg->idx+1, len, arg->tsdb_param->tsdb_bytes); + return SQL_ERROR; + } + + tsdb_param_val_t *tsdb_param_val = arg->tsdb_param_val; + TAOS_BIND *taos_bind = arg->taos_bind; + + taos_bind->buffer_type = TSDB_DATA_TYPE_BINARY; + taos_bind->u.bin = buf; + taos_bind->buffer_length = len; + taos_bind->buffer = taos_bind->u.bin; + taos_bind->length = &taos_bind->buffer_length; + taos_bind->is_null = &tsdb_param_val->is_null; + + return SQL_SUCCESS; +} + +static SQLRETURN do_set_param_wchar_conv_func(stmt_t *stmt, int idx, param_binding_t *binding, tsdb_param_t *tsdb_param) { + errs_t *errs = &stmt->errs; + + SQLSMALLINT valueType = binding->ValueType; + int tsdb_type = tsdb_param->tsdb_type; + + switch (tsdb_type) + { + case TSDB_DATA_TYPE_TIMESTAMP: + { + tsdb_param->conv = do_conv_sql_wchar_to_tsdb_timestamp; + } break; + case TSDB_DATA_TYPE_NCHAR: + { + tsdb_param->conv = do_conv_sql_wchar_to_tsdb_nchar; + } break; + case TSDB_DATA_TYPE_BOOL: + { + tsdb_param->conv = do_conv_sql_wchar_to_tsdb_bool; + } break; + case TSDB_DATA_TYPE_TINYINT: + { + tsdb_param->conv = do_conv_sql_wchar_to_tsdb_tinyint; + } break; + case TSDB_DATA_TYPE_SMALLINT: + { + tsdb_param->conv = do_conv_sql_wchar_to_tsdb_smallint; + } break; + case TSDB_DATA_TYPE_INT: + { + tsdb_param->conv = do_conv_sql_wchar_to_tsdb_int; + } break; + case TSDB_DATA_TYPE_BIGINT: + { + tsdb_param->conv = do_conv_sql_wchar_to_tsdb_bigint; + } break; + case TSDB_DATA_TYPE_FLOAT: + { + tsdb_param->conv = do_conv_sql_wchar_to_tsdb_float; + } break; + case TSDB_DATA_TYPE_DOUBLE: + { + tsdb_param->conv = do_conv_sql_wchar_to_tsdb_double; + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s to [%d] %s for param [%d]", + valueType, sql_c_type(valueType), + tsdb_type, taos_data_type(tsdb_type), idx+1); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_set_param_char_conv_func(stmt_t *stmt, int idx, param_binding_t *binding, tsdb_param_t *tsdb_param) { + errs_t *errs = &stmt->errs; + + SQLSMALLINT valueType = binding->ValueType; + int tsdb_type = tsdb_param->tsdb_type; + + switch (tsdb_type) + { + case TSDB_DATA_TYPE_TIMESTAMP: + { + tsdb_param->conv = do_conv_sql_char_to_tsdb_timestamp; + } break; + case TSDB_DATA_TYPE_NCHAR: + { + tsdb_param->conv = do_conv_sql_char_to_tsdb_nchar; + } break; + case TSDB_DATA_TYPE_BOOL: + { + tsdb_param->conv = do_conv_sql_char_to_tsdb_bool; + } break; + case TSDB_DATA_TYPE_TINYINT: + { + tsdb_param->conv = do_conv_sql_char_to_tsdb_tinyint; + } break; + case TSDB_DATA_TYPE_SMALLINT: + { + tsdb_param->conv = do_conv_sql_char_to_tsdb_smallint; + } break; + case TSDB_DATA_TYPE_INT: + { + tsdb_param->conv = do_conv_sql_char_to_tsdb_int; + } break; + case TSDB_DATA_TYPE_BIGINT: + { + tsdb_param->conv = do_conv_sql_char_to_tsdb_bigint; + } break; + case TSDB_DATA_TYPE_FLOAT: + { + tsdb_param->conv = do_conv_sql_char_to_tsdb_float; + } break; + case TSDB_DATA_TYPE_DOUBLE: + { + tsdb_param->conv = do_conv_sql_char_to_tsdb_double; + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s to [%d] %s for param [%d]", + valueType, sql_c_type(valueType), + tsdb_type, taos_data_type(tsdb_type), idx+1); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_set_param_sbigint_conv_func(stmt_t *stmt, int idx, param_binding_t *binding, tsdb_param_t *tsdb_param) { + errs_t *errs = &stmt->errs; + + SQLSMALLINT valueType = binding->ValueType; + int tsdb_type = tsdb_param->tsdb_type; + + switch (tsdb_type) + { + case TSDB_DATA_TYPE_BIGINT: + { + tsdb_param->conv = do_conv_sql_sbigint_to_tsdb_bigint; + } break; + case TSDB_DATA_TYPE_TINYINT: + { + tsdb_param->conv = do_conv_sql_sbigint_to_tsdb_tinyint; + } break; + case TSDB_DATA_TYPE_INT: + { + tsdb_param->conv = do_conv_sql_sbigint_to_tsdb_int; + } break; + case TSDB_DATA_TYPE_TIMESTAMP: + { + tsdb_param->conv = do_conv_sql_sbigint_to_tsdb_timestamp; + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s to [%d] %s for param [%d]", + valueType, sql_c_type(valueType), + tsdb_type, taos_data_type(tsdb_type), idx+1); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_set_param_long_conv_func(stmt_t *stmt, int idx, param_binding_t *binding, tsdb_param_t *tsdb_param) { + errs_t *errs = &stmt->errs; + + SQLSMALLINT valueType = binding->ValueType; + int tsdb_type = tsdb_param->tsdb_type; + + switch (tsdb_type) + { + case TSDB_DATA_TYPE_BOOL: + { + tsdb_param->conv = do_conv_sql_long_to_tsdb_bool; + } break; + case TSDB_DATA_TYPE_TINYINT: + { + tsdb_param->conv = do_conv_sql_long_to_tsdb_tinyint; + } break; + case TSDB_DATA_TYPE_SMALLINT: + { + tsdb_param->conv = do_conv_sql_long_to_tsdb_smallint; + } break; + case TSDB_DATA_TYPE_INT: + { + tsdb_param->conv = do_conv_sql_long_to_tsdb_int; + } break; + case TSDB_DATA_TYPE_BIGINT: + { + tsdb_param->conv = do_conv_sql_long_to_tsdb_bigint; + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s to [%d] %s for param [%d]", + valueType, sql_c_type(valueType), + tsdb_type, taos_data_type(tsdb_type), idx+1); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_set_param_tinyint_conv_func(stmt_t *stmt, int idx, param_binding_t *binding, tsdb_param_t *tsdb_param) { + errs_t *errs = &stmt->errs; + + SQLSMALLINT valueType = binding->ValueType; + int tsdb_type = tsdb_param->tsdb_type; + + switch (tsdb_type) + { + case TSDB_DATA_TYPE_BOOL: + { + tsdb_param->conv = do_conv_sql_tinyint_to_tsdb_bool; + } break; + case TSDB_DATA_TYPE_TINYINT: + { + tsdb_param->conv = do_conv_sql_tinyint_to_tsdb_tinyint; + } break; + case TSDB_DATA_TYPE_SMALLINT: + { + tsdb_param->conv = do_conv_sql_tinyint_to_tsdb_smallint; + } break; + case TSDB_DATA_TYPE_INT: + { + tsdb_param->conv = do_conv_sql_tinyint_to_tsdb_int; + } break; + case TSDB_DATA_TYPE_BIGINT: + { + tsdb_param->conv = do_conv_sql_tinyint_to_tsdb_bigint; + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s to [%d] %s for param [%d]", + valueType, sql_c_type(valueType), + tsdb_type, taos_data_type(tsdb_type), idx+1); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_set_param_short_conv_func(stmt_t *stmt, int idx, param_binding_t *binding, tsdb_param_t *tsdb_param) { + errs_t *errs = &stmt->errs; + + SQLSMALLINT valueType = binding->ValueType; + int tsdb_type = tsdb_param->tsdb_type; + + switch (tsdb_type) + { + case TSDB_DATA_TYPE_BOOL: + { + tsdb_param->conv = do_conv_sql_short_to_tsdb_bool; + } break; + case TSDB_DATA_TYPE_TINYINT: + { + tsdb_param->conv = do_conv_sql_short_to_tsdb_tinyint; + } break; + case TSDB_DATA_TYPE_SMALLINT: + { + tsdb_param->conv = do_conv_sql_short_to_tsdb_smallint; + } break; + case TSDB_DATA_TYPE_INT: + { + tsdb_param->conv = do_conv_sql_short_to_tsdb_int; + } break; + case TSDB_DATA_TYPE_BIGINT: + { + tsdb_param->conv = do_conv_sql_short_to_tsdb_bigint; + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s to [%d] %s for param [%d]", + valueType, sql_c_type(valueType), + tsdb_type, taos_data_type(tsdb_type), idx+1); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_set_param_double_conv_func(stmt_t *stmt, int idx, param_binding_t *binding, tsdb_param_t *tsdb_param) { + errs_t *errs = &stmt->errs; + + SQLSMALLINT valueType = binding->ValueType; + int tsdb_type = tsdb_param->tsdb_type; + + switch (tsdb_type) + { + case TSDB_DATA_TYPE_FLOAT: + { + tsdb_param->conv = do_conv_sql_double_to_tsdb_float; + } break; + case TSDB_DATA_TYPE_DOUBLE: + { + tsdb_param->conv = do_conv_sql_double_to_tsdb_double; + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s to [%d] %s for param [%d]", + valueType, sql_c_type(valueType), + tsdb_type, taos_data_type(tsdb_type), idx+1); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_set_param_binary_conv_func(stmt_t *stmt, int idx, param_binding_t *binding, tsdb_param_t *tsdb_param) { + errs_t *errs = &stmt->errs; + + SQLSMALLINT valueType = binding->ValueType; + int tsdb_type = tsdb_param->tsdb_type; + + switch (tsdb_type) + { + case TSDB_DATA_TYPE_BINARY: + { + tsdb_param->conv = do_conv_sql_binary_to_tsdb_binary; + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s to [%d] %s for param [%d]", + valueType, sql_c_type(valueType), + tsdb_type, taos_data_type(tsdb_type), idx+1); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + + +static SQLRETURN do_set_param_conv_func(stmt_t *stmt, int idx, param_binding_t *binding) { + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + tsdb_param_t *tsdb_params = tsdb_stmt->tsdb_params; + tsdb_param_t *tsdb_param = tsdb_params + idx; + + errs_t *errs = &stmt->errs; + + SQLSMALLINT valueType = binding->ValueType; + + switch (valueType) + { + case SQL_C_CHAR: + { + return do_set_param_char_conv_func(stmt, idx, binding, tsdb_param); + } break; + case SQL_C_WCHAR: + { + return do_set_param_wchar_conv_func(stmt, idx, binding, tsdb_param); + } break; + case SQL_C_SBIGINT: + { + return do_set_param_sbigint_conv_func(stmt, idx, binding, tsdb_param); + } break; + case SQL_C_LONG: + { + return do_set_param_long_conv_func(stmt, idx, binding, tsdb_param); + } break; + case SQL_C_TINYINT: + { + return do_set_param_tinyint_conv_func(stmt, idx, binding, tsdb_param); + } break; + case SQL_C_SHORT: + { + return do_set_param_short_conv_func(stmt, idx, binding, tsdb_param); + } break; + case SQL_C_DOUBLE: + { + return do_set_param_double_conv_func(stmt, idx, binding, tsdb_param); + } break; + case SQL_C_BINARY: + { + return do_set_param_binary_conv_func(stmt, idx, binding, tsdb_param); + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s for param [%d]", + valueType, sql_c_type(valueType), idx+1); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN tsdb_conn_set_param_conv(stmt_t *stmt, int idx) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt && tsdb_stmt->stmt==stmt, ""); + OILE(tsdb_stmt->tsdb_res==NULL, ""); + OILE(idx>=0, ""); + + paramset_t *paramset = &stmt->paramset; + param_t *params = paramset->params; + if (!params || idx>=paramset->n_params) return SQL_SUCCESS; + param_binding_t *bindings = paramset->bindings; + if (!bindings || idx>=paramset->n_bindings) return SQL_SUCCESS; + tsdb_param_t *tsdb_params = tsdb_stmt->tsdb_params; + OILE(tsdb_params, ""); + + param_binding_t *binding = bindings + idx; + + return do_set_param_conv_func(stmt, idx, binding); +} + +static SQLRETURN do_fill_param(stmt_t *stmt, int idx) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt && tsdb_stmt->stmt==stmt, ""); + OILE(tsdb_stmt->tsdb_res==NULL, ""); + + paramset_t *paramset = &stmt->paramset; + param_t *params = paramset->params; + tsdb_param_t *tsdb_params = tsdb_stmt->tsdb_params; + OILE(params, ""); + OILE(tsdb_params, ""); + OILE(idx>=0, ""); + OILE(idxn_params, ""); + param_t *param = params + idx; + tsdb_param_t *tsdb_param = tsdb_params + idx; + + errs_t *errs = &stmt->errs; + + int tsdb_type = 0; + int tsdb_bytes = 0; + int r = taos_stmt_get_param(tsdb_stmt->tsdb_stmt, idx, &tsdb_type, &tsdb_bytes); + if (r) { + SET_GENERAL(errs, "failed to get param[%d]", idx+1); + return SQL_ERROR; + } + + // https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/column-size-decimal-digits-transfer-octet-length-and-display-size?view=sql-server-ver15 + param->DecimalDigits = 0; + param->Nullable = SQL_NULLABLE; + tsdb_param->tsdb_type = tsdb_type; + tsdb_param->tsdb_bytes = tsdb_bytes; + switch (tsdb_type) + { + case TSDB_DATA_TYPE_TIMESTAMP: + { + param->DataType = SQL_CHAR; + param->ParameterSize = 23; + } break; + case TSDB_DATA_TYPE_NCHAR: + { + size_t bytes = ((size_t)tsdb_bytes - VARSTR_HEADER_SIZE); + size_t chars = bytes / TSDB_NCHAR_SIZE; + tsdb_param->tsdb_bytes = (int)bytes; + param->DataType = SQL_WCHAR; + param->ParameterSize = (SQLULEN)chars; + } break; + case TSDB_DATA_TYPE_BINARY: + { + size_t bytes = ((size_t)tsdb_bytes - VARSTR_HEADER_SIZE); + tsdb_param->tsdb_bytes = (int)bytes; + param->DataType = SQL_BINARY; + param->ParameterSize = (SQLULEN)bytes; + } break; + case TSDB_DATA_TYPE_BOOL: + { + param->DataType = SQL_BIT; + param->ParameterSize = 1; + } break; + case TSDB_DATA_TYPE_TINYINT: + { + param->DataType = SQL_TINYINT; + param->ParameterSize = 3; + } break; + case TSDB_DATA_TYPE_SMALLINT: + { + param->DataType = SQL_SMALLINT; + param->ParameterSize = 5; + } break; + case TSDB_DATA_TYPE_INT: + { + param->DataType = SQL_INTEGER; + param->ParameterSize = 10; + } break; + case TSDB_DATA_TYPE_BIGINT: + { + param->DataType = SQL_BIGINT; + param->ParameterSize = 20; + } break; + case TSDB_DATA_TYPE_FLOAT: + { + param->DataType = SQL_FLOAT; + param->ParameterSize = 15; + } break; + case TSDB_DATA_TYPE_DOUBLE: + { + param->DataType = SQL_DOUBLE; + param->ParameterSize = 15; + } break; + default: + { + SET_GENERAL(errs, "failed to map param[%d] type[%d]%s to SQL DATA TYPE", + idx+1, tsdb_type, taos_data_type(tsdb_type)); + return SQL_ERROR; + } break; + } + + param->ParameterNumber = (SQLUSMALLINT)(idx + 1); + + param_binding_t *bindings = paramset->bindings; + if (!bindings) return SQL_SUCCESS; + if (idx>=paramset->n_bindings) return SQL_SUCCESS; + + param_binding_t *binding = bindings + idx; + + return do_set_param_conv_func(stmt, idx, binding); +} + +static SQLRETURN tsdb_conn_prepare(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + OILE(stmt->prepared==0, ""); + OILE(STMT_IS_NORM(stmt), ""); + errs_t *errs = &stmt->errs; + + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + tsdb_conn_t *tsdb_conn = (tsdb_conn_t*)conn->ext.ext; + OILE(tsdb_conn && tsdb_conn->conn==conn, ""); + TAOS *taos = tsdb_conn->taos; + OILE(taos, ""); + + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt && tsdb_stmt->stmt==stmt, ""); + OILE(tsdb_stmt->tsdb_res==NULL, ""); + // OILE(tsdb_stmt->tsdb_stmt==NULL, ""); + + tsdb_stmt->tsdb_params = NULL; + + if (!tsdb_stmt->tsdb_stmt) { + SQLRETURN r = tsdb_stmt_init_stmt(tsdb_stmt); + if (r!=SQL_SUCCESS) return r; + } + OILE(tsdb_stmt->tsdb_stmt, ""); + + tsdb_stmt_reclaim_param_vals(tsdb_stmt); + + do { + const char *txt = (const char*)stmt->sql.txt.buf; + size_t len = stmt->sql.txt.bytes; + OILE(txt, ""); + OILE(len>0, ""); + int r = taos_stmt_prepare(tsdb_stmt->tsdb_stmt, txt, (unsigned int)len); + if (r) { + SET_GENERAL(errs, "failed to prepare taos stmt:[%d]%s", r, tstrerror(r)); + break; + } + + int nums = 0; + r = taos_stmt_num_params(tsdb_stmt->tsdb_stmt, &nums); + if (r) { + SET_GENERAL(errs, "failed to prepare taos stmt:[%d]%s", r, tstrerror(r)); + break; + } + + paramset_t *paramset = &stmt->paramset; + OILE(paramset->params==NULL, ""); + OILE(paramset->n_params==0, ""); + OILE(tsdb_stmt->tsdb_params==NULL, ""); + + if (nums>0) { + paramset_init_params_cache(paramset); + tsdb_stmt_init_param_vals_cache(tsdb_stmt); + + if (!tsdb_stmt->tsdb_param_vals_cache) { + SET_OOM(errs, "failed to alloc val cache for params"); + return SQL_ERROR; + } + + todbc_buf_t *cache = stmt->paramset.params_cache; + if (!cache) { + SET_OOM(errs, "failed to alloc cache buffer for params"); + return SQL_ERROR; + } + OILE(cache, ""); + + param_t *params = (param_t*)todbc_buf_calloc(cache, (size_t)nums, sizeof(*params)); + if (!params) { + SET_OOM(errs, "failed to alloc buffer for params"); + return SQL_ERROR; + } + + tsdb_param_t *tsdb_params = (tsdb_param_t*)todbc_buf_calloc(cache, (size_t)nums, sizeof(*tsdb_params)); + if (!tsdb_params) { + SET_OOM(errs, "failed to alloc buffer for tsdb params"); + return SQL_ERROR; + } + + paramset->params = params; + paramset->n_params = nums; + tsdb_stmt->tsdb_params = tsdb_params; + + for (int i=0; iowner, ""); + + errs_t *errs = &stmt->errs; + + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + + const char *enc_to = conn->enc_char; + const char *enc_from = conn->enc_src; // UTF8 + const unsigned char *src = (const unsigned char*)buf; + size_t slen = strlen(buf); + unsigned char *dst = (unsigned char*)col->TargetValue; + size_t dlen = (size_t)col->BufferLength; + todbc_string_t s = todbc_tls_write(enc_to, enc_from, src, &slen, dst, dlen); + if (!s.buf) { + SET_OOM(errs, "failed to convert timestamp"); + return SQL_ERROR; + } + OILE(s.bytes==s.total_bytes, ""); + if (col->StrLen_or_IndPtr) { + *col->StrLen_or_IndPtr = (SQLLEN)s.bytes; + } + for(size_t i=s.bytes; ierrs; + + switch (binding->TargetType) + { + case SQL_C_CHAR: + { + size_t len = (size_t)binding->BufferLength; + OILE(len>0, ""); + if (bytesTargetValue) { + memcpy(binding->TargetValue, val, len); + } + if (binding->StrLen_or_IndPtr) { + *binding->StrLen_or_IndPtr = (SQLLEN)len; + } + // do we really need this? + size_t dlen = (size_t)binding->BufferLength; + unsigned char *dst = (unsigned char*)binding->TargetValue; + for(size_t i=len; iBufferLength; + OILE(len>0, ""); + if (bytesTargetValue) { + memcpy(binding->TargetValue, val, len); + } + if (binding->StrLen_or_IndPtr) { + *binding->StrLen_or_IndPtr = (SQLLEN)len; + } + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s to [%d] %s for binding[%d]", + field->type, taos_data_type(field->type), + binding->TargetType, sql_c_type(binding->TargetType), + binding->ColumnNumber); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_nchar_to_sql_c(stmt_t *stmt, TAOS_FIELD *field, void *val, size_t bytes, col_binding_t *binding) { + errs_t *errs = &stmt->errs; + + OILE(stmt->owner, ""); + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + + switch (binding->TargetType) + { + case SQL_C_CHAR: + { + const char *enc_to = conn->enc_char; + const char *enc_from = conn->enc_db; + const unsigned char *src = (const unsigned char*)val; + size_t slen = bytes; + unsigned char *dst = (unsigned char*)binding->TargetValue; + size_t dlen = (size_t)binding->BufferLength; + todbc_string_t s = todbc_tls_write(enc_to, enc_from, src, &slen, dst, dlen); + if (!s.buf) { + SET_OOM(errs, "failed to convert nchar"); + return SQL_ERROR; + } + OILE(s.bytes==s.total_bytes, ""); + if (binding->StrLen_or_IndPtr) { + *binding->StrLen_or_IndPtr = (SQLLEN)s.bytes; // com-on, it's NOT character-size + } + for(size_t i=s.bytes; ienc_wchar; + const char *enc_from = conn->enc_db; + const unsigned char *src = (const unsigned char*)val; + size_t slen = bytes; + unsigned char *dst = (unsigned char*)binding->TargetValue; + size_t dlen = (size_t)binding->BufferLength; + todbc_string_t s = todbc_tls_write(enc_to, enc_from, src, &slen, dst, dlen); + if (!s.buf) { + SET_OOM(errs, "failed to convert nchar"); + return SQL_ERROR; + } + OILE(s.bytes==s.total_bytes, ""); + if (binding->StrLen_or_IndPtr) { + *binding->StrLen_or_IndPtr = (SQLLEN)s.bytes; // com-on, it's NOT character-size + } + for(size_t i=s.bytes; itype, taos_data_type(field->type), + binding->TargetType, sql_c_type(binding->TargetType), + binding->ColumnNumber); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_int64_to_sql_c(stmt_t *stmt, TAOS_FIELD *field, int64_t val, col_binding_t *binding) { + errs_t *errs = &stmt->errs; + + char buf[128]; + + switch (binding->TargetType) + { + case SQL_C_CHAR: + { + snprintf(buf, sizeof(buf), "%" PRId64 "", val); + return do_conv_utf8_to_sql_c_char(stmt, buf, binding); + } break; + case SQL_C_UTINYINT: + { + if (val>UINT8_MAX || val<0) { + SET_GENERAL(errs, ""); + return SQL_ERROR; + } + if (binding->TargetValue) { + *(uint8_t*)binding->TargetValue = (uint8_t)val; + } + } break; + case SQL_C_USHORT: + { + if (val>UINT16_MAX || val<0) { + SET_GENERAL(errs, ""); + return SQL_ERROR; + } + if (binding->TargetValue) { + *(uint16_t*)binding->TargetValue = (uint16_t)val; + } + } break; + case SQL_C_SLONG: + { + if (val>INT32_MAX || valTargetValue) { + *(int32_t*)binding->TargetValue = (int32_t)val; + } + } break; + case SQL_C_UBIGINT: + { + if (binding->TargetValue) { + *(uint64_t*)binding->TargetValue = (uint64_t)val; + } + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s to [%d] %s for binding[%d]", + field->type, taos_data_type(field->type), + binding->TargetType, sql_c_type(binding->TargetType), + binding->ColumnNumber); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_timestamp_to_utf8(stmt_t *stmt, int64_t v, char *buf, size_t len) { + errs_t *errs = &stmt->errs; + + // microsecond precision, based on test + time_t secs = v / 1000; + int msecs = (int)(v % 1000); + + struct tm vtm = {0}; + if (&vtm!=localtime_r(&secs, &vtm)) { + SET_ERR(errs, "22007", "invalid timestamp"); + return SQL_ERROR; // ? SQL_SUCCESS_WITH_INFO + } + + char *p = buf; + size_t bytes = len; + + OILE(bytes>0, ""); + size_t n = strftime(p, bytes, "%Y-%m-%d %H:%M:%S", &vtm); + if (n==0) { + SET_GENERAL(errs, "failed to convert timestamp"); + return SQL_ERROR; // ? SQL_SUCCESS_WITH_INFO + } + p += n; + bytes -= n; + + OILE(bytes>0, ""); + int m = snprintf(p, bytes, ".%03d", msecs); + if (m>=bytes) { + SET_GENERAL(errs, "failed to convert timestamp"); + return SQL_ERROR; // ? SQL_SUCCESS_WITH_INFO + } + p += (size_t)m; + bytes -= (size_t)m; + + OILE(bytes>=0, ""); + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_timestamp_to_sql_c(stmt_t *stmt, TAOS_FIELD *field, int64_t val, col_binding_t *col) { + errs_t *errs = &stmt->errs; + + OILE(stmt, ""); + OILE(stmt->owner, ""); + + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + + SQLRETURN r; + char buf[128]; + + switch (col->TargetType) + { + case SQL_C_CHAR: + { + r = do_conv_timestamp_to_utf8(stmt, val, buf, sizeof(buf)); + if (r!=SQL_SUCCESS) return r; + return do_conv_utf8_to_sql_c_char(stmt, buf, col); + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s to [%d] %s for col[%d]", + field->type, taos_data_type(field->type), + col->TargetType, sql_c_type(col->TargetType), + col->ColumnNumber); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN do_conv_double_to_sql_c(stmt_t *stmt, TAOS_FIELD *field, double val, col_binding_t *binding) { + errs_t *errs = &stmt->errs; + + char buf[256]; + + switch (binding->TargetType) + { + case SQL_C_DOUBLE: + { + if (binding->TargetValue) { + *(double*)binding->TargetValue = val; + } + } break; + case SQL_C_FLOAT: + { + // shall we check overflow/underflow here? + if (binding->TargetValue) { + *(float*)binding->TargetValue = (float)val; + } + } break; + case SQL_C_CHAR: + { + snprintf(buf, sizeof(buf), "%lf", val); + return do_conv_utf8_to_sql_c_char(stmt, buf, binding); + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s to [%d] %s for binding[%d]", + field->type, taos_data_type(field->type), + binding->TargetType, sql_c_type(binding->TargetType), + binding->ColumnNumber); + return SQL_ERROR; + } break; + } + + return SQL_SUCCESS; +} + +static SQLRETURN tsdb_conn_proc_param(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt && tsdb_stmt->stmt==stmt, ""); + + paramset_t *paramset = &stmt->paramset; + param_t *params = paramset->params; + int n_params = paramset->n_params; + param_binding_t *bindings = paramset->bindings; + int n_bindings = paramset->n_bindings; + tsdb_param_t *tsdb_params = tsdb_stmt->tsdb_params; + int i_row = paramset->i_row; + int i_col = paramset->i_col; + + OILE(params && n_params>0, ""); + OILE(bindings && n_bindings>=0, ""); + OILE(tsdb_params, ""); + OILE(n_params==n_bindings, ""); + OILE(i_row>=0, ""); + OILE(i_col>=0 && i_colattr.bind_type; // default: SQL_PARAM_BIND_BY_COLUMN + // SQL_ATTR_PARAM_BIND_OFFSET_PTR + SQLULEN *bind_offset_ptr = stmt->attr.bind_offset_ptr; // default: NULL + // SQL_ATTR_PARAMSET_SIZE + SQLULEN paramset_size = stmt->attr.paramset_size; // default: 0 + + // OILE(bind_type && bind_type!=SQL_PARAM_BIND_BY_COLUMN, "[%ld]", bind_type); + // OILE(bind_offset_ptr, ""); + OILE(paramset_size>0, ""); + + OILE(i_rowParameterNumber>0 && param->ParameterNumber<=n_params, ""); + tsdb_param_t *tsdb_param = tsdb_params + i_col; + OILE(tsdb_param->conv, ""); + + tsdb_param_val_t *tsdb_param_vals = tsdb_stmt->tsdb_param_vals; + if (!tsdb_param_vals) { + errs_t *errs = &stmt->errs; + tsdb_stmt_calloc_param_vals(tsdb_stmt); + if (tsdb_stmt->tsdb_param_vals==NULL) { + SET_OOM(errs, "failed to alloc tsdb param vals for tsdb params"); + return SQL_ERROR; + } + if (tsdb_stmt->taos_binds==NULL) { + SET_OOM(errs, "failed to alloc taos binds for tsdb params"); + return SQL_ERROR; + } + tsdb_param_vals = tsdb_stmt->tsdb_param_vals; + } + OILE(tsdb_param_vals, ""); + TAOS_BIND *taos_binds = tsdb_stmt->taos_binds; + OILE(taos_binds, ""); + + + tsdb_param_val_t *tsdb_param_val = tsdb_param_vals + i_col; + tsdb_param_val->ParameterNumber = (SQLUSMALLINT)(i_col + 1); + tsdb_param_val->is_null = 1; + TAOS_BIND *taos_bind = taos_binds + i_col; + + param_binding_t *binding = bindings + (size_t)i_col; + OILE(binding->ParameterNumber==i_col+1, ""); + if (binding->ParameterValuePtr==NULL) return SQL_SUCCESS; + + SQLPOINTER val = binding->ParameterValuePtr; + SQLLEN *soip = binding->StrLen_or_IndPtr; + OILE(soip, ""); + + size_t offset = (size_t)i_row * (size_t)bind_type; + size_t bind_offset = 0; + if (bind_offset_ptr) bind_offset = *bind_offset_ptr; + + val = (SQLPOINTER)(((char*)val) + offset + bind_offset); + soip = (SQLLEN*)(((char*)soip) + offset + bind_offset); + + SQLLEN soi = *soip; + + if (soi == SQL_NULL_DATA) return SQL_SUCCESS; + + OILE(soi>=0 || soi==SQL_NTS, ""); + + tsdb_param_val->is_null = 0; + + conn_t *conn = stmt->owner->conn; + OILE(conn, ""); + todbc_buf_t *cache = tsdb_stmt->tsdb_param_vals_cache; + OILE(cache, ""); + + tsdb_param_conv_arg_t arg = { + .conn = conn, + .cache = cache, + .idx = i_col, + .val = val, + .soi = soi, + .tsdb_param = tsdb_param, + .tsdb_param_val = tsdb_param_val, + .taos_bind = taos_bind + }; + return tsdb_param->conv(stmt, &arg); +} + +static SQLRETURN tsdb_conn_param_row_processed(stmt_t *stmt) { + paramset_t *paramset = &stmt->paramset; + OILE(paramset->n_params>0, ""); + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt, ""); + TAOS_BIND *taos_binds = tsdb_stmt->taos_binds; + OILE(taos_binds, ""); + OILE(tsdb_stmt->tsdb_stmt, ""); + + errs_t *errs = &stmt->errs; + + if (1) { + int r = taos_stmt_bind_param(tsdb_stmt->tsdb_stmt, taos_binds); + if (r) { + SET_GENERAL(errs, "failed to bind params:[%d]%s", r, tstrerror(r)); + // keep executing/executed state unchanged + return SQL_ERROR; + } + + r = taos_stmt_add_batch(tsdb_stmt->tsdb_stmt); + if (r) { + SET_GENERAL(errs, "failed to add batch params:[%d]%s", r, tstrerror(r)); + // keep executing/executed state unchanged + return SQL_ERROR; + } + } + + return SQL_SUCCESS; +} + +static SQLRETURN tsdb_conn_execute(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + OILE(!STMT_IS_EXECUTED(stmt), ""); + + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt, ""); + if (!tsdb_stmt->tsdb_stmt) { + SQLRETURN r = tsdb_stmt_init_stmt(tsdb_stmt); + if (r!=SQL_SUCCESS) return r; + OILE(0, ""); + } + OILE(tsdb_stmt->tsdb_stmt, ""); + + errs_t * errs = &stmt->errs; + + if (1) { + int r = 0; + + r = taos_stmt_execute(tsdb_stmt->tsdb_stmt); + if (r) { + SET_GENERAL(errs, "failed to execute:[%d]%s", r, tstrerror(r)); + // keep executing/executed state unchanged + return SQL_ERROR; + } + + tsdb_stmt->by_query = 0; + } + + STMT_SET_EXECUTED(stmt); + return SQL_SUCCESS; +} + +static void do_fetch_tsdb_res(tsdb_stmt_t *tsdb_stmt) { + if (!tsdb_stmt->tsdb_res) { + OILE(tsdb_stmt->by_query==0, ""); + OILE(tsdb_stmt->tsdb_stmt, ""); + tsdb_stmt->tsdb_res = taos_stmt_use_result(tsdb_stmt->tsdb_stmt); + OILE(tsdb_stmt->tsdb_res, ""); + // currently, TAOS_STMT does NOT co-exist with TAOS_RES + tsdb_stmt_close_stmt(tsdb_stmt); + } +} + +SQLRETURN tsdb_conn_get_affected_rows(stmt_t *stmt, SQLLEN *RowCount) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt, ""); + + do_fetch_tsdb_res(tsdb_stmt); + + int rows = taos_affected_rows(tsdb_stmt->tsdb_res); + OILE(RowCount, ""); + *RowCount = rows; + + return SQL_SUCCESS; +} + +static void do_fetch_tsdb_fields(tsdb_stmt_t *tsdb_stmt) { + if (!tsdb_stmt->tsdb_fields) { + tsdb_stmt->tsdb_fields = taos_fetch_fields(tsdb_stmt->tsdb_res); + } +} + +SQLRETURN tsdb_conn_get_fields_count(stmt_t *stmt, SQLSMALLINT *ColumnCount) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt, ""); + + do_fetch_tsdb_res(tsdb_stmt); + OILE(tsdb_stmt->tsdb_res, ""); + + int n_fields = taos_num_fields(tsdb_stmt->tsdb_res); + OILE(ColumnCount, ""); + *ColumnCount = (SQLSMALLINT)n_fields; + + return SQL_SUCCESS; +} + +SQLRETURN tsdb_conn_get_field(stmt_t *stmt, field_arg_t *arg) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + + errs_t *errs = &stmt->errs; + + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt, ""); + + do_fetch_tsdb_res(tsdb_stmt); + OILE(tsdb_stmt->tsdb_res, ""); + + int n_fields = taos_num_fields(tsdb_stmt->tsdb_res); + OILE(arg->ColumnNumber>0, ""); + OILE(arg->ColumnNumber<=n_fields, ""); + do_fetch_tsdb_fields(tsdb_stmt); + OILE(tsdb_stmt->tsdb_fields, ""); + + TAOS_FIELD *field = tsdb_stmt->tsdb_fields + (arg->ColumnNumber-1); + int len = 0; + // charset ? + len = snprintf((char*)arg->ColumnName, (size_t)arg->BufferLength, "%s", field->name); + if (arg->NameLength) *arg->NameLength = (SQLSMALLINT)len; + if (arg->DecimalDigits) *arg->DecimalDigits = 0; + if (arg->Nullable) *arg->Nullable = SQL_NULLABLE; + + SQLSMALLINT DataType; + SQLULEN ColumnSize; + + // https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/column-size-decimal-digits-transfer-octet-length-and-display-size?view=sql-server-ver15 + switch (field->type) { + case TSDB_DATA_TYPE_TIMESTAMP: + { + DataType = SQL_CHAR; + ColumnSize = 23; + } break; + case TSDB_DATA_TYPE_NCHAR: + { + DataType = SQL_WCHAR; + ColumnSize = (SQLULEN)field->bytes; + } break; + case TSDB_DATA_TYPE_BINARY: + { + DataType = SQL_BINARY; + ColumnSize = (SQLULEN)field->bytes; + } break; + case TSDB_DATA_TYPE_BOOL: + { + DataType = SQL_BIT; + ColumnSize = 1; + } break; + case TSDB_DATA_TYPE_TINYINT: + { + DataType = SQL_TINYINT; + ColumnSize = 3; + } break; + case TSDB_DATA_TYPE_SMALLINT: + { + DataType = SQL_SMALLINT; + ColumnSize = 5; + } break; + case TSDB_DATA_TYPE_INT: + { + DataType = SQL_INTEGER; + ColumnSize = 10; + } break; + case TSDB_DATA_TYPE_BIGINT: + { + DataType = SQL_BIGINT; + ColumnSize = 20; + } break; + case TSDB_DATA_TYPE_FLOAT: + { + DataType = SQL_FLOAT; + ColumnSize = 15; + } break; + case TSDB_DATA_TYPE_DOUBLE: + { + DataType = SQL_DOUBLE; + ColumnSize = 15; + } break; + default: + { + SET_GENERAL(errs, "failed to map field[%d] type[%d]%s to SQL DATA TYPE", + arg->ColumnNumber, field->type, taos_data_type(field->type)); + return SQL_ERROR; + } break; + } + + if (arg->DataType) *arg->DataType = DataType; + if (arg->ColumnSize) *arg->ColumnSize = ColumnSize; + + return SQL_SUCCESS; +} + +SQLRETURN tsdb_conn_fetch(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt, ""); + + OILE(stmt->eof==0, ""); + + do_fetch_tsdb_res(tsdb_stmt); + OILE(tsdb_stmt->tsdb_res, ""); + + tsdb_stmt->tsdb_curr = taos_fetch_row(tsdb_stmt->tsdb_res); + if (!tsdb_stmt->tsdb_curr) { + stmt->eof = 1; + return SQL_NO_DATA; + } + + return SQL_SUCCESS; +} + +static SQLRETURN tsdb_conn_get_data(stmt_t *stmt, col_binding_t *col) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt, ""); + + OILE(stmt->eof==0, ""); + OILE(tsdb_stmt->tsdb_curr, ""); + OILE(tsdb_stmt->tsdb_res, ""); + + int n_fields = taos_num_fields(tsdb_stmt->tsdb_res); + int idx = (int)(col->ColumnNumber-1); + OILE(idx>=0, ""); + OILE(idxtsdb_fields, ""); + + TAOS_FIELD *field = tsdb_stmt->tsdb_fields + idx; + + OILE(col->StrLen_or_IndPtr, ""); + void *val = tsdb_stmt->tsdb_curr[idx]; + if (!val) { + *col->StrLen_or_IndPtr = SQL_NULL_DATA; + return SQL_SUCCESS; + } + + errs_t *errs = &stmt->errs; + + int64_t i64; + double dbl; + int is_dbl = 0; + + switch (field->type) + { + case TSDB_DATA_TYPE_TINYINT: + { + i64 = *(int8_t*)val; + } break; + case TSDB_DATA_TYPE_SMALLINT: + { + i64 = *(int16_t*)val; + } break; + case TSDB_DATA_TYPE_INT: + { + i64 = *(int32_t*)val; + } break; + case TSDB_DATA_TYPE_BIGINT: + { + i64 = *(int64_t*)val; + } break; + case TSDB_DATA_TYPE_FLOAT: + { + dbl = GET_FLOAT_VAL(val); + is_dbl = 1; + } break; + case TSDB_DATA_TYPE_DOUBLE: + { + dbl = GET_DOUBLE_VAL(val); + is_dbl = 1; + } break; + case TSDB_DATA_TYPE_BINARY: + { + size_t bytes = (size_t)varDataLen((char*)val - VARSTR_HEADER_SIZE); + return do_conv_binary_to_sql_c(stmt, field, val, bytes, col); + } break; + case TSDB_DATA_TYPE_NCHAR: + { + size_t bytes = (size_t)varDataLen((char*)val - VARSTR_HEADER_SIZE); + return do_conv_nchar_to_sql_c(stmt, field, val, bytes, col); + } break; + case TSDB_DATA_TYPE_TIMESTAMP: + { + i64 = *(int64_t*)val; + return do_conv_timestamp_to_sql_c(stmt, field, i64, col); + break; + } + case TSDB_DATA_TYPE_BOOL: + { + i64 = *(int8_t*)val; + } break; + default: + { + SET_GENERAL(errs, "not convertion from [%d]%s for col[%d]", + field->type, taos_data_type(field->type), col->ColumnNumber); + return SQL_ERROR; + } break; + } + if (is_dbl) return do_conv_double_to_sql_c(stmt, field, dbl, col); + else return do_conv_int64_to_sql_c(stmt, field, i64, col); +} + +static void tsdb_conn_close_rs(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->owner, ""); + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)stmt->ext.ext; + OILE(tsdb_stmt && tsdb_stmt->stmt==stmt, ""); + + tsdb_stmt_close_rs(tsdb_stmt); +} + +static int tsdb_conn_init_stmt(stmt_t *stmt) { + OILE(stmt, ""); + OILE(stmt->ext.ext==NULL, ""); + OILE(stmt->ext.free_stmt==NULL, ""); + + OILE(stmt->owner==NULL, ""); + + tsdb_stmt_t *tsdb_stmt = (tsdb_stmt_t*)calloc(1, sizeof(*tsdb_stmt)); + if (!tsdb_stmt) return -1; + + stmt_ext_t *ext = &stmt->ext; + + tsdb_stmt->stmt = stmt; + ext->ext = tsdb_stmt; + ext->free_stmt = tsdb_conn_free_stmt; + ext->clear_param_vals = tsdb_conn_clear_param_vals; + ext->exec_direct = tsdb_conn_exec_direct; + ext->prepare = tsdb_conn_prepare; + ext->set_param_conv = tsdb_conn_set_param_conv; + ext->proc_param = tsdb_conn_proc_param; + ext->param_row_processed = tsdb_conn_param_row_processed; + ext->execute = tsdb_conn_execute; + ext->get_affected_rows = tsdb_conn_get_affected_rows; + ext->get_fields_count = tsdb_conn_get_fields_count; + ext->get_field = tsdb_conn_get_field; + ext->fetch = tsdb_conn_fetch; + ext->get_data = tsdb_conn_get_data; + ext->close_rs = tsdb_conn_close_rs; + + return 0; +} + +static pthread_once_t init_once = PTHREAD_ONCE_INIT; +static int inited = 0; +// static char tsdb_svr_info[128] = ""; +// static char tsdb_cli_info[128] = ""; + +static void init_routine(void) { + int r = taos_init(); + if (r) { + OW("taos init failed: [%d]%s", r, tstrerror(r)); + return; + } + OI("taos inited"); + inited = 1; +} + +int conn_init_tsdb_conn(conn_t *conn) { + OILE(conn, ""); + OILE(conn->ext.ext==NULL, ""); + OILE(conn->ext.free_conn==NULL, ""); + + pthread_once(&init_once, init_routine); + if (!inited) return -1; + + tsdb_conn_t *tsdb_conn = (tsdb_conn_t*)calloc(1, sizeof(*tsdb_conn)); + if (!tsdb_conn) return -1; + + tsdb_conn->conn = conn; + conn->ext.ext = tsdb_conn; + conn->ext.free_conn = tsdb_conn_free; + conn->ext.connect = tsdb_conn_connect; + conn->ext.disconnect = tsdb_conn_disconnect; + conn->ext.init_stmt = tsdb_conn_init_stmt; + + return 0; +} + + diff --git a/src/connector/odbc/src/base/tsdb_impl.h b/src/connector/odbc/src/base/tsdb_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..f217a4be410db8f69b82836e33c905481aa91ec8 --- /dev/null +++ b/src/connector/odbc/src/base/tsdb_impl.h @@ -0,0 +1,30 @@ +/* + * 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 . + */ + +#ifndef _tsdb_impl_h_ +#define _tsdb_impl_h_ + +#include "../base.h" + +#include "conn.h" + +#define DEFAULT_SERVER "localhost:6030" + +int conn_init_tsdb_conn(conn_t *conn); + + +#endif // _tsdb_impl_h_ + + diff --git a/src/connector/odbc/src/col.h b/src/connector/odbc/src/col.h new file mode 100644 index 0000000000000000000000000000000000000000..f7cdc240813c5d96a6df0491132671e05fdfe374 --- /dev/null +++ b/src/connector/odbc/src/col.h @@ -0,0 +1,28 @@ +/* + * 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 . + */ + +#ifndef _col_h_ +#define _col_h_ + +#include "base.h" + +struct col_s { +}; + + +#endif // _col_h_ + + + diff --git a/src/connector/odbc/src/install.cmd b/src/connector/odbc/src/install.cmd new file mode 100644 index 0000000000000000000000000000000000000000..4da8a2d9764686884d13318339ac5d1c3c8a8d15 --- /dev/null +++ b/src/connector/odbc/src/install.cmd @@ -0,0 +1,6 @@ +@echo off +REM install driver +odbcconf /A {INSTALLDRIVER "TAOS|Driver=C:\TDengine\driver\todbc.dll|ConnectFunctions=YYN|DriverODBCVer=03.00|FileUsage=0|SQLLevel=0"} +REM config user dsn +odbcconf /A {CONFIGDSN "TAOS" "DSN=TAOS_DSN"} + diff --git a/src/connector/odbc/src/install.sh b/src/connector/odbc/src/install.sh index 02f31de70ed76e150fbef5d388cbd8a3e9ba73b3..c08ac9208e56a8b4ead270d48825e13cd113a078 100755 --- a/src/connector/odbc/src/install.sh +++ b/src/connector/odbc/src/install.sh @@ -2,6 +2,13 @@ set -u +EXT="so" +[[ `uname` == 'Darwin' ]] && EXT="dylib" + +SUDO="sudo" +[[ `uname` == 'Darwin' ]] && SUDO="" + + BLD_DIR="$1" rm -f "${BLD_DIR}/template.ini" @@ -10,18 +17,30 @@ rm -f "${BLD_DIR}/template.dsn" cat > "${BLD_DIR}/template.ini" < "${BLD_DIR}/template.dsn" < - * - * 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 . - */ - -// #define _BSD_SOURCE -#define _XOPEN_SOURCE -#define _DEFAULT_SOURCE -#define _GNU_SOURCE - -#include "todbc_log.h" -#include "todbc_flex.h" - -#include "taos.h" - -#include "tglobal.h" -#include "taoserror.h" -#include "todbc_util.h" -#include "todbc_conv.h" - -#include "os.h" - -#include -#include - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#define UTF8_ENC "UTF-8" -#define UTF16_ENC "UCS-2LE" -#define UNICODE_ENC "UCS-4LE" -#define GB18030_ENC "GB18030" - -#define GET_REF(obj) atomic_load_64(&obj->refcount) -#define INC_REF(obj) atomic_add_fetch_64(&obj->refcount, 1) -#define DEC_REF(obj) atomic_sub_fetch_64(&obj->refcount, 1) - -#define LOCK(obj) pthread_mutex_lock(&obj->lock); -#define UNLOCK(obj) pthread_mutex_unlock(&obj->lock); - -#define SET_ERROR(obj, sqlstate, eno, err_fmt, ...) \ -do { \ - obj->err.err_no = eno; \ - const char* estr = tstrerror(eno); \ - if (!estr) estr = "Unknown error"; \ - int n = snprintf(NULL, 0, "[TSDB:%x]%s: @%s[%d]" err_fmt "", \ - eno, estr, \ - basename((char*)__FILE__), __LINE__, \ - ##__VA_ARGS__); \ - if (n<0) break; \ - char *err_str = (char*)realloc(obj->err.err_str, (size_t)n+1); \ - if (!err_str) break; \ - obj->err.err_str = err_str; \ - snprintf(obj->err.err_str, (size_t)n+1, "[TSDB:%x]%s: @%s[%d]" err_fmt "", \ - eno, estr, \ - basename((char*)__FILE__), __LINE__, \ - ##__VA_ARGS__); \ - snprintf((char*)obj->err.sql_state, sizeof(obj->err.sql_state), "%s", sqlstate); \ -} while (0) - - -#define CLR_ERROR(obj) \ -do { \ - obj->err.err_no = TSDB_CODE_SUCCESS; \ - if (obj->err.err_str) obj->err.err_str[0] = '\0'; \ - obj->err.sql_state[0] = '\0'; \ -} while (0) - -#define FILL_ERROR(obj) \ -do { \ - size_t n = sizeof(obj->err.sql_state); \ - if (Sqlstate) strncpy((char*)Sqlstate, (char*)obj->err.sql_state, n); \ - if (NativeError) *NativeError = obj->err.err_no; \ - snprintf((char*)MessageText, (size_t)BufferLength, "%s", obj->err.err_str); \ - if (TextLength && obj->err.err_str) *TextLength = (SQLSMALLINT)utf8_chars(obj->err.err_str); \ -} while (0) - -#define FREE_ERROR(obj) \ -do { \ - obj->err.err_no = TSDB_CODE_SUCCESS; \ - if (obj->err.err_str) { \ - free(obj->err.err_str); \ - obj->err.err_str = NULL; \ - } \ - obj->err.sql_state[0] = '\0'; \ -} while (0) - -#define SET_UNSUPPORT_ERROR(obj, sqlstate, err_fmt, ...) \ -do { \ - SET_ERROR(obj, sqlstate, TSDB_CODE_ODBC_NOT_SUPPORT, err_fmt, ##__VA_ARGS__); \ -} while (0) \ - -#define SET_HANDLE_INVALID(obj, sqlstate, err_fmt, ...) \ -do { \ - SET_ERROR(obj, sqlstate, TSDB_CODE_QRY_INVALID_QHANDLE, err_fmt, ##__VA_ARGS__); \ -} while (0); - -#define SDUP(s,n) (s ? (s[(size_t)n] ? (const char*)strndup((const char*)s,(size_t)n) : (const char*)s) : strdup("")) -#define SFRE(x,s,n) \ -do { \ - if (x==(const char*)s) break; \ - if (x) { \ - free((char*)x); \ - x = NULL; \ - } \ -} while (0) - -#define CHK_CONN(obj) \ -do { \ - if (!obj->conn) { \ - SET_ERROR(obj, "HY000", TSDB_CODE_ODBC_INVALID_HANDLE, "connection closed or not ready"); \ - return SQL_ERROR; \ - } \ -} while (0); - -#define CHK_CONN_TAOS(obj) \ -do { \ - if (!obj->conn->taos) { \ - SET_ERROR(obj, "HY000", TSDB_CODE_ODBC_INVALID_HANDLE, "connection to data source closed or not ready"); \ - return SQL_ERROR; \ - } \ -} while (0); - -#define CHK_RS(r_091c, sql_091c, fmt_091c, ...) \ -do { \ - r_091c = SQL_ERROR; \ - int e = sql_091c->rs ? taos_errno(sql_091c->rs) : terrno; \ - if (e != TSDB_CODE_SUCCESS) { \ - SET_ERROR(sql_091c, "HY000", e, fmt_091c, ##__VA_ARGS__); \ - break; \ - } \ - r_091c = SQL_SUCCESS; \ -} while (0) - -#define NORM_STR_LENGTH(obj, ptr, len) \ -do { \ - if ((len) < 0 && (len)!=SQL_NTS) { \ - SET_ERROR((obj), "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); \ - return SQL_ERROR; \ - } \ - if (len==SQL_NTS) len = (ptr) ? (SQLSMALLINT)strlen((const char*)(ptr)) : 0; \ -} while (0) - -#define PROFILING 0 - -#define PROFILE(statement) \ -do { \ - if (!PROFILING) { \ - statement; \ - break; \ - } \ - struct timeval tv0, tv1; \ - gettimeofday(&tv0, NULL); \ - statement; \ - gettimeofday(&tv1, NULL); \ - double delta = difftime(tv1.tv_sec, tv0.tv_sec); \ - delta *= 1000000; \ - delta += (double)(tv1.tv_usec-tv0.tv_usec); \ - delta /= 1000000; \ - D("%s: elapsed: [%.6f]s", #statement, delta); \ -} while (0) - -#define CHK_CONV(todb, statement) \ -do { \ - TSDB_CONV_CODE code_0c80 = (statement); \ - switch (code_0c80) { \ - case TSDB_CONV_OK: return SQL_SUCCESS; \ - case TSDB_CONV_OOM: \ - case TSDB_CONV_NOT_AVAIL: { \ - SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); \ - return SQL_ERROR; \ - } break; \ - case TSDB_CONV_OOR: { \ - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_OOR, ""); \ - return SQL_ERROR; \ - } break; \ - case TSDB_CONV_CHAR_NOT_NUM: \ - case TSDB_CONV_CHAR_NOT_TS: { \ - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_CHAR_NOT_NUM, ""); \ - return SQL_ERROR; \ - } break; \ - case TSDB_CONV_NOT_VALID_TS: { \ - SET_ERROR(sql, "22007", TSDB_CODE_ODBC_CONV_NOT_VALID_TS, ""); \ - return SQL_ERROR; \ - } break; \ - case TSDB_CONV_TRUNC_FRACTION: { \ - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC_FRAC, ""); \ - return todb ? SQL_ERROR : SQL_SUCCESS_WITH_INFO; \ - } break; \ - case TSDB_CONV_TRUNC: { \ - SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_TRUNC, ""); \ - return SQL_ERROR; \ - } break; \ - case TSDB_CONV_SRC_TOO_LARGE: { \ - SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_SRC_TOO_LARGE, ""); \ - return SQL_ERROR; \ - } break; \ - case TSDB_CONV_SRC_BAD_SEQ: { \ - SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_SRC_BAD_SEQ, ""); \ - return SQL_ERROR; \ - } break; \ - case TSDB_CONV_SRC_INCOMPLETE: { \ - SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_SRC_INCOMPLETE, ""); \ - return SQL_ERROR; \ - } break; \ - case TSDB_CONV_SRC_GENERAL: { \ - SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_SRC_GENERAL, ""); \ - return SQL_ERROR; \ - } break; \ - case TSDB_CONV_BAD_CHAR: { \ - SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_TRUNC, ""); \ - return SQL_ERROR; \ - } break; \ - default: { \ - DASSERTX(0, "internal logic error: %d", code_0c80); \ - return SQL_ERROR; /* never reached here */ \ - } break; \ - } \ -} while (0) - -typedef struct env_s env_t; -typedef struct conn_s conn_t; -typedef struct sql_s sql_t; -typedef struct taos_error_s taos_error_t; -typedef struct param_bind_s param_bind_t; - -struct param_bind_s { - SQLUSMALLINT ParameterNumber; - SQLSMALLINT ValueType; - SQLSMALLINT ParameterType; - SQLULEN LengthPrecision; - SQLSMALLINT ParameterScale; - SQLPOINTER ParameterValue; - SQLLEN *StrLen_or_Ind; - - unsigned int valid; -}; - -struct taos_error_s { - char *err_str; - int err_no; - - SQLCHAR sql_state[6]; -}; - -struct env_s { - uint64_t refcount; - unsigned int destroying:1; - - char env_locale[64]; - char env_charset[64]; - - taos_error_t err; -}; - -struct conn_s { - uint64_t refcount; - env_t *env; - - char client_enc[64]; // ODBC client that communicates with this driver - char server_enc[64]; // taos dynamic library that's loaded by this driver - - tsdb_conv_t *client_to_server; - tsdb_conv_t *server_to_client; - tsdb_conv_t *utf8_to_client; - tsdb_conv_t *utf16_to_utf8; - tsdb_conv_t *utf16_to_server; - tsdb_conv_t *client_to_utf8; - - TAOS *taos; - - taos_error_t err; -}; - -struct sql_s { - uint64_t refcount; - conn_t *conn; - - TAOS_STMT *stmt; - param_bind_t *params; - int n_params; - size_t rowlen; - size_t n_rows; - size_t ptr_offset; - - TAOS_RES *rs; - TAOS_ROW row; - - taos_error_t err; - unsigned int is_prepared:1; - unsigned int is_insert:1; - unsigned int is_executed:1; -}; - -typedef struct c_target_s c_target_t; -struct c_target_s { - SQLUSMALLINT col; - SQLSMALLINT ct; // c type: SQL_C_XXX - char *ptr; - SQLLEN len; - SQLLEN *soi; -}; - -static pthread_once_t init_once = PTHREAD_ONCE_INIT; -static void init_routine(void); - -static size_t do_field_display_size(TAOS_FIELD *field); - -static tsdb_conv_t* tsdb_conn_client_to_server(conn_t *conn) { - if (!conn->client_to_server) { - conn->client_to_server = tsdb_conv_open(conn->client_enc, conn->server_enc); - } - return conn->client_to_server; -} - -static tsdb_conv_t* tsdb_conn_server_to_client(conn_t *conn) { - if (!conn->server_to_client) { - conn->server_to_client = tsdb_conv_open(conn->server_enc, conn->client_enc); - } - return conn->server_to_client; -} - -static tsdb_conv_t* tsdb_conn_utf8_to_client(conn_t *conn) { - if (!conn->utf8_to_client) { - conn->utf8_to_client = tsdb_conv_open(UTF8_ENC, conn->client_enc); - } - return conn->utf8_to_client; -} - -static tsdb_conv_t* tsdb_conn_utf16_to_utf8(conn_t *conn) { - if (!conn->utf16_to_utf8) { - conn->utf16_to_utf8 = tsdb_conv_open(UTF16_ENC, UTF8_ENC); - } - return conn->utf16_to_utf8; -} - -static tsdb_conv_t* tsdb_conn_utf16_to_server(conn_t *conn) { - if (!conn->utf16_to_server) { - conn->utf16_to_server = tsdb_conv_open(UTF16_ENC, conn->server_enc); - } - return conn->utf16_to_server; -} - -static tsdb_conv_t* tsdb_conn_client_to_utf8(conn_t *conn) { - if (!conn->client_to_utf8) { - conn->client_to_utf8 = tsdb_conv_open(conn->client_enc, UTF8_ENC); - } - return conn->client_to_utf8; -} - -static void tsdb_conn_close_convs(conn_t *conn) { - if (conn->client_to_server) { - tsdb_conv_close(conn->client_to_server); - conn->client_to_server = NULL; - } - if (conn->server_to_client) { - tsdb_conv_close(conn->server_to_client); - conn->server_to_client = NULL; - } - if (conn->utf8_to_client) { - tsdb_conv_close(conn->utf8_to_client); - conn->utf8_to_client = NULL; - } - if (conn->utf16_to_utf8) { - tsdb_conv_close(conn->utf16_to_utf8); - conn->utf16_to_utf8 = NULL; - } - if (conn->utf16_to_server) { - tsdb_conv_close(conn->utf16_to_server); - conn->utf16_to_server = NULL; - } - if (conn->client_to_utf8) { - tsdb_conv_close(conn->client_to_utf8); - conn->client_to_utf8 = NULL; - } -} - -#define SFREE(buffer, v, src) \ -do { \ - const char *v_096a = (const char*)(v); \ - const char *src_6a = (const char*)(src); \ - if (v_096a && v_096a!=src_6a && !is_owned_by_stack_buffer((buffer), v_096a)) { \ - free((char*)v_096a); \ - } \ -} while (0) - -static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle) -{ - pthread_once(&init_once, init_routine); - - env_t *env = (env_t*)calloc(1, sizeof(*env)); - if (!env) return SQL_INVALID_HANDLE; - - DASSERT(INC_REF(env)>0); - - snprintf(env->env_locale, sizeof(env->env_locale), "%s", tsLocale); - snprintf(env->env_charset, sizeof(env->env_charset), "%s", tsCharset); - - *EnvironmentHandle = env; - - CLR_ERROR(env); - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLAllocEnv(SQLHENV *EnvironmentHandle) -{ - SQLRETURN r; - r = doSQLAllocEnv(EnvironmentHandle); - return r; -} - -static SQLRETURN doSQLFreeEnv(SQLHENV EnvironmentHandle) -{ - env_t *env = (env_t*)EnvironmentHandle; - if (!env) return SQL_INVALID_HANDLE; - - DASSERT(GET_REF(env)==1); - - DASSERT(!env->destroying); - - env->destroying = 1; - DASSERT(env->destroying == 1); - - DASSERT(DEC_REF(env)==0); - - FREE_ERROR(env); - free(env); - - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLFreeEnv(SQLHENV EnvironmentHandle) -{ - SQLRETURN r; - r = doSQLFreeEnv(EnvironmentHandle); - return r; -} - -static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle, - SQLHDBC *ConnectionHandle) -{ - env_t *env = (env_t*)EnvironmentHandle; - if (!env) return SQL_INVALID_HANDLE; - - if (!ConnectionHandle) { - SET_ERROR(env, "HY009", TSDB_CODE_ODBC_BAD_ARG, "ConnectionHandle [%p] not valid", ConnectionHandle); - return SQL_ERROR; - } - - DASSERT(INC_REF(env)>1); - - conn_t *conn = NULL; - do { - conn = (conn_t*)calloc(1, sizeof(*conn)); - if (!conn) { - SET_ERROR(env, "HY001", TSDB_CODE_ODBC_OOM, ""); - break; - } - - conn->env = env; - - snprintf(conn->client_enc, sizeof(conn->client_enc), "%s", conn->env->env_charset); - snprintf(conn->server_enc, sizeof(conn->server_enc), "%s", conn->env->env_charset); - - *ConnectionHandle = conn; - - DASSERT(INC_REF(conn)>0); - - return SQL_SUCCESS; - } while (0); - - DASSERT(DEC_REF(env)>0); - - return SQL_ERROR; -} - -SQLRETURN SQL_API SQLAllocConnect(SQLHENV EnvironmentHandle, - SQLHDBC *ConnectionHandle) -{ - SQLRETURN r; - r = doSQLAllocConnect(EnvironmentHandle, ConnectionHandle); - return r; -} - -static SQLRETURN doSQLFreeConnect(SQLHDBC ConnectionHandle) -{ - conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_INVALID_HANDLE; - - DASSERT(GET_REF(conn)==1); - - DASSERT(conn->env); - - do { - if (conn->taos) { - taos_close(conn->taos); - conn->taos = NULL; - } - - DASSERT(DEC_REF(conn->env)>0); - DASSERT(DEC_REF(conn)==0); - - conn->env = NULL; - FREE_ERROR(conn); - tsdb_conn_close_convs(conn); - free(conn); - } while (0); - - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLFreeConnect(SQLHDBC ConnectionHandle) -{ - SQLRETURN r; - r = doSQLFreeConnect(ConnectionHandle); - return r; -} - -static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, - SQLCHAR *ServerName, SQLSMALLINT NameLength1, - SQLCHAR *UserName, SQLSMALLINT NameLength2, - SQLCHAR *Authentication, SQLSMALLINT NameLength3) -{ - stack_buffer_t buffer; buffer.next = 0; - - conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_ERROR; - - if (conn->taos) { - SET_ERROR(conn, "08002", TSDB_CODE_ODBC_CONNECTION_BUSY, "connection still in use"); - return SQL_ERROR; - } - - NORM_STR_LENGTH(conn, ServerName, NameLength1); - NORM_STR_LENGTH(conn, UserName, NameLength2); - NORM_STR_LENGTH(conn, Authentication, NameLength3); - - if (NameLength1>SQL_MAX_DSN_LENGTH) { - SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - - tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); - const char *dsn = NULL; - const char *uid = NULL; - const char *pwd = NULL; - const char *svr = NULL; - char server[4096]; server[0] = '\0'; - - do { - tsdb_conv(client_to_server, &buffer, (const char*)ServerName, (size_t)NameLength1, &dsn, NULL); - tsdb_conv(client_to_server, &buffer, (const char*)UserName, (size_t)NameLength2, &uid, NULL); - tsdb_conv(client_to_server, &buffer, (const char*)Authentication, (size_t)NameLength3, &pwd, NULL); - int n = SQLGetPrivateProfileString(dsn, "Server", "", server, sizeof(server)-1, "Odbc.ini"); - if (n<=0) { - snprintf(server, sizeof(server), "localhost:6030"); // all 7-bit ascii - } - tsdb_conv(client_to_server, &buffer, (const char*)server, (size_t)strlen(server), &svr, NULL); - - if ((!dsn) || (!uid) || (!pwd) || (!svr)) { - SET_ERROR(conn, "HY001", TSDB_CODE_ODBC_OOM, ""); - break; - } - - char *ip = NULL; - int port = 0; - char *p = strchr(svr, ':'); - if (p) { - ip = strndup(svr, (size_t)(p-svr)); - port = atoi(p+1); - } - - // TODO: data-race - // TODO: shall receive ip/port from odbc.ini - conn->taos = taos_connect(ip, uid, pwd, NULL, (uint16_t)port); - if (!conn->taos) { - SET_ERROR(conn, "08001", terrno, "failed to connect to data source for DSN[%s] @[%s:%d]", dsn, ip, port); - break; - } - } while (0); - - tsdb_conv_free(client_to_server, dsn, &buffer, (const char*)ServerName); - tsdb_conv_free(client_to_server, uid, &buffer, (const char*)UserName); - tsdb_conv_free(client_to_server, pwd, &buffer, (const char*)Authentication); - tsdb_conv_free(client_to_server, svr, &buffer, (const char*)server); - - return conn->taos ? SQL_SUCCESS : SQL_ERROR; -} - -SQLRETURN SQL_API SQLConnect(SQLHDBC ConnectionHandle, - SQLCHAR *ServerName, SQLSMALLINT NameLength1, - SQLCHAR *UserName, SQLSMALLINT NameLength2, - SQLCHAR *Authentication, SQLSMALLINT NameLength3) -{ - SQLRETURN r; - r = doSQLConnect(ConnectionHandle, ServerName, NameLength1, - UserName, NameLength2, - Authentication, NameLength3); - return r; -} - -static SQLRETURN doSQLDisconnect(SQLHDBC ConnectionHandle) -{ - conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_INVALID_HANDLE; - - if (conn->taos) { - taos_close(conn->taos); - conn->taos = NULL; - } - - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLDisconnect(SQLHDBC ConnectionHandle) -{ - SQLRETURN r; - r = doSQLDisconnect(ConnectionHandle); - return r; -} - -static SQLRETURN doSQLAllocStmt(SQLHDBC ConnectionHandle, - SQLHSTMT *StatementHandle) -{ - conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_INVALID_HANDLE; - - if (!StatementHandle) { - SET_ERROR(conn, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StatementHandle [%p] not valid", StatementHandle); - return SQL_ERROR; - } - - DASSERT(INC_REF(conn)>1); - - do { - sql_t *sql = (sql_t*)calloc(1, sizeof(*sql)); - if (!sql) { - SET_ERROR(conn, "HY001", TSDB_CODE_ODBC_OOM, ""); - break; - } - - sql->conn = conn; - DASSERT(INC_REF(sql)>0); - - *StatementHandle = sql; - - return SQL_SUCCESS; - } while (0); - - DASSERT(DEC_REF(conn)>0); - - return SQL_ERROR; -} - -SQLRETURN SQL_API SQLAllocStmt(SQLHDBC ConnectionHandle, - SQLHSTMT *StatementHandle) -{ - SQLRETURN r; - r = doSQLAllocStmt(ConnectionHandle, StatementHandle); - return r; -} - -static SQLRETURN doSQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE *OutputHandle) -{ - switch (HandleType) { - case SQL_HANDLE_ENV: { - SQLHENV env = {0}; - if (!OutputHandle) return SQL_ERROR; - SQLRETURN r = doSQLAllocEnv(&env); - if (r==SQL_SUCCESS) *OutputHandle = env; - return r; - } break; - case SQL_HANDLE_DBC: { - SQLRETURN r = doSQLAllocConnect(InputHandle, OutputHandle); - return r; - } break; - case SQL_HANDLE_STMT: { - SQLRETURN r = doSQLAllocStmt(InputHandle, OutputHandle); - return r; - } break; - default: { - return SQL_ERROR; - } break; - } -} - -SQLRETURN SQL_API SQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE *OutputHandle) -{ - SQLRETURN r; - r = doSQLAllocHandle(HandleType, InputHandle, OutputHandle); - return r; -} - -static SQLRETURN doSQLFreeStmt(SQLHSTMT StatementHandle, - SQLUSMALLINT Option) -{ - sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_INVALID_HANDLE; - - switch (Option) { - case SQL_CLOSE: return SQL_SUCCESS; - case SQL_DROP: break; - case SQL_UNBIND: - case SQL_RESET_PARAMS: { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, "free statement with Option[%x] not supported yet", Option); - return SQL_ERROR; - } break; - default: { - SET_ERROR(sql, "HY092", TSDB_CODE_ODBC_OUT_OF_RANGE, "free statement with Option[%x] not supported yet", Option); - return SQL_ERROR; - } break; - } - - DASSERT(GET_REF(sql)==1); - - if (sql->rs) { - taos_free_result(sql->rs); - sql->rs = NULL; - } - - if (sql->stmt) { - taos_stmt_close(sql->stmt); - sql->stmt = NULL; - } - - if (sql->params) { - free(sql->params); - sql->params = NULL; - } - sql->n_params = 0; - - DASSERT(DEC_REF(sql->conn)>0); - DASSERT(DEC_REF(sql)==0); - - sql->conn = NULL; - - FREE_ERROR(sql); - - free(sql); - - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLFreeStmt(SQLHSTMT StatementHandle, - SQLUSMALLINT Option) -{ - SQLRETURN r; - r = doSQLFreeStmt(StatementHandle, Option); - return r; -} - -static SQLRETURN do_exec_direct(sql_t *sql, TSDB_CONV_CODE code, const char *statement) { - if (code) CHK_CONV(1, code); - DASSERT(code==TSDB_CONV_OK); - - SQLRETURN r = SQL_ERROR; - do { - sql->rs = taos_query(sql->conn->taos, statement); - CHK_RS(r, sql, "failed to execute"); - } while (0); - - return r; -} - -static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, - SQLCHAR *StatementText, SQLINTEGER TextLength) -{ - sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_INVALID_HANDLE; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - conn_t *conn = sql->conn; - - NORM_STR_LENGTH(sql, StatementText, TextLength); - - if (sql->rs) { - taos_free_result(sql->rs); - sql->rs = NULL; - sql->row = NULL; - } - - if (sql->stmt) { - taos_stmt_close(sql->stmt); - sql->stmt = NULL; - } - - if (sql->params) { - free(sql->params); - sql->params = NULL; - } - sql->n_params = 0; - - SQLRETURN r = SQL_SUCCESS; - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); - const char *stxt = NULL; - do { - TSDB_CONV_CODE code = tsdb_conv(client_to_server, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL); - r = do_exec_direct(sql, code, stxt); - } while (0); - tsdb_conv_free(client_to_server, stxt, &buffer, (const char*)StatementText); - - return r; -} - -SQLRETURN SQL_API SQLExecDirect(SQLHSTMT StatementHandle, - SQLCHAR *StatementText, SQLINTEGER TextLength) -{ - SQLRETURN r; - r = doSQLExecDirect(StatementHandle, StatementText, TextLength); - return r; -} - -static SQLRETURN doSQLExecDirectW(SQLHSTMT hstmt, SQLWCHAR *szSqlStr, SQLINTEGER cbSqlStr) -{ - sql_t *sql = (sql_t*)hstmt; - if (!sql) return SQL_INVALID_HANDLE; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - conn_t *conn = sql->conn; - - if (!szSqlStr) { - SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "szSqlStr [%p] not allowed", szSqlStr); - return SQL_ERROR; - } - if (cbSqlStr < 0) { - SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - - SQLRETURN r = SQL_SUCCESS; - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn); - const char *stxt = NULL; - do { - size_t slen = (size_t)cbSqlStr * sizeof(*szSqlStr); - TSDB_CONV_CODE code = tsdb_conv(utf16_to_server, &buffer, (const char*)szSqlStr, slen, &stxt, NULL); - r = do_exec_direct(sql, code, stxt); - } while (0); - tsdb_conv_free(utf16_to_server, stxt, &buffer, (const char*)szSqlStr); - - return r; -} - -SQLRETURN SQL_API SQLExecDirectW(SQLHSTMT hstmt, SQLWCHAR *szSqlStr, SQLINTEGER cbSqlStr) -{ - SQLRETURN r = doSQLExecDirectW(hstmt, szSqlStr, cbSqlStr); - return r; -} - -static SQLRETURN doSQLNumResultCols(SQLHSTMT StatementHandle, - SQLSMALLINT *ColumnCount) -{ - sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_INVALID_HANDLE; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - if (sql->is_insert) { - if (ColumnCount) { - *ColumnCount = 0; - } - return SQL_SUCCESS; - } - - if (!sql->rs) { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NO_RESULT, ""); - return SQL_ERROR; - } - - int fields = taos_field_count(sql->rs); - if (ColumnCount) { - *ColumnCount = (SQLSMALLINT)fields; - } - - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLNumResultCols(SQLHSTMT StatementHandle, - SQLSMALLINT *ColumnCount) -{ - SQLRETURN r; - r = doSQLNumResultCols(StatementHandle, ColumnCount); - return r; -} - -static SQLRETURN doSQLRowCount(SQLHSTMT StatementHandle, - SQLLEN *RowCount) -{ - sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - // ref: https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlrowcount-function?view=sql-server-ver15 - // Summary - // SQLRowCount returns the number of rows affected by an UPDATE, INSERT, or DELETE statement; - // an SQL_ADD, SQL_UPDATE_BY_BOOKMARK, or SQL_DELETE_BY_BOOKMARK operation in SQLBulkOperations; - // or an SQL_UPDATE or SQL_DELETE operation in SQLSetPos. - - // how to fetch affected rows from taos? - // taos_affected_rows? - - if (1) { - SET_ERROR(sql, "IM001", TSDB_CODE_ODBC_NOT_SUPPORT, ""); - // if (RowCount) *RowCount = 0; - return SQL_SUCCESS_WITH_INFO; - } - - if (!sql->is_insert) { - if (RowCount) *RowCount = 0; - return SQL_SUCCESS; - } - - if (!sql->rs) { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NO_RESULT, ""); - return SQL_ERROR; - } - - int rows = taos_affected_rows(sql->rs); - if (RowCount) { - *RowCount = rows; - } - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLRowCount(SQLHSTMT StatementHandle, - SQLLEN *RowCount) -{ - SQLRETURN r; - r = doSQLRowCount(StatementHandle, RowCount); - return r; -} - -static SQLRETURN doSQLColAttribute(SQLHSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, - SQLPOINTER CharacterAttribute, SQLSMALLINT BufferLength, - SQLSMALLINT *StringLength, SQLLEN *NumericAttribute ) -{ - sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - if (!sql->rs) { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NO_RESULT, ""); - return SQL_ERROR; - } - - int nfields = taos_field_count(sql->rs); - TAOS_FIELD *fields = taos_fetch_fields(sql->rs); - - if (nfields==0 || fields==NULL) { - SET_ERROR(sql, "07005", TSDB_CODE_ODBC_NO_FIELDS, ""); - return SQL_ERROR; - } - - if (ColumnNumber<=0 || ColumnNumber>nfields) { - SET_ERROR(sql, "07009", TSDB_CODE_ODBC_OUT_OF_RANGE, "invalid column number [%d]", ColumnNumber); - return SQL_ERROR; - } - - TAOS_FIELD *field = fields + ColumnNumber-1; - - switch (FieldIdentifier) { - case SQL_COLUMN_DISPLAY_SIZE: { - *NumericAttribute = (SQLLEN)do_field_display_size(field); - } break; - case SQL_COLUMN_LABEL: { - // todo: check BufferLength - size_t n = sizeof(field->name); - strncpy(CharacterAttribute, field->name, (n>BufferLength ? (size_t)BufferLength : n)); - } break; - case SQL_COLUMN_UNSIGNED: { - *NumericAttribute = SQL_FALSE; - } break; - default: { - SET_ERROR(sql, "HY091", TSDB_CODE_ODBC_OUT_OF_RANGE, - "FieldIdentifier[%d/0x%x] for Column [%d] not supported yet", - FieldIdentifier, FieldIdentifier, ColumnNumber); - return SQL_ERROR; - } break; - } - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLColAttribute(SQLHSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, - SQLPOINTER CharacterAttribute, SQLSMALLINT BufferLength, - SQLSMALLINT *StringLength, SQLLEN *NumericAttribute ) -{ - SQLRETURN r; - r = doSQLColAttribute(StatementHandle, ColumnNumber, FieldIdentifier, - CharacterAttribute, BufferLength, - StringLength, NumericAttribute); - return r; -} - -static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, - SQLPOINTER TargetValue, SQLLEN BufferLength, - SQLLEN *StrLen_or_Ind) -{ - sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_INVALID_HANDLE; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - conn_t *conn = sql->conn; - - if (!sql->rs) { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NO_RESULT, ""); - return SQL_ERROR; - } - - if (!sql->row) { - SET_ERROR(sql, "24000", TSDB_CODE_ODBC_INVALID_CURSOR, ""); - return SQL_ERROR; - } - - int nfields = taos_field_count(sql->rs); - TAOS_FIELD *fields = taos_fetch_fields(sql->rs); - - if (ColumnNumber<=0 || ColumnNumber>nfields) { - SET_ERROR(sql, "07009", TSDB_CODE_ODBC_OUT_OF_RANGE, "invalid column number [%d]", ColumnNumber); - return SQL_ERROR; - } - - if (TargetValue == NULL) { - SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "NULL TargetValue not allowed for col [%d]", ColumnNumber); - return SQL_ERROR; - } - if (BufferLength<0) { - SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - - TAOS_FIELD *field = fields + ColumnNumber-1; - void *row = sql->row[ColumnNumber-1]; - - if (!row) { - if (!StrLen_or_Ind) { - SET_ERROR(sql, "22002", TSDB_CODE_ODBC_BAD_ARG, "NULL StrLen_or_Ind not allowed for col [%d]", ColumnNumber); - return SQL_ERROR; - } - *StrLen_or_Ind = SQL_NULL_DATA; - return SQL_SUCCESS; - } - - c_target_t target = {0}; - target.col = ColumnNumber; - target.ct = TargetType; - target.ptr = TargetValue; - target.len = BufferLength; - target.soi = StrLen_or_Ind; - - switch (field->type) { - case TSDB_DATA_TYPE_BOOL: - case TSDB_DATA_TYPE_TINYINT: - case TSDB_DATA_TYPE_SMALLINT: - case TSDB_DATA_TYPE_INT: - case TSDB_DATA_TYPE_BIGINT: { - int64_t v; - switch (field->type) { - case TSDB_DATA_TYPE_BOOL: v = *(int8_t*)row; if (v) v = 1; break; - case TSDB_DATA_TYPE_TINYINT: v = *(int8_t*)row; break; - case TSDB_DATA_TYPE_SMALLINT: v = *(int16_t*)row; break; - case TSDB_DATA_TYPE_INT: v = *(int32_t*)row; break; - case TSDB_DATA_TYPE_BIGINT: // fall through - default: v = *(int64_t*)row; break; - } - switch (target.ct) { - case SQL_C_BIT: { - CHK_CONV(0, tsdb_int64_to_bit(v, TargetValue)); - } break; - case SQL_C_TINYINT: { - CHK_CONV(0, tsdb_int64_to_tinyint(v, TargetValue)); - } break; - case SQL_C_SHORT: { - CHK_CONV(0, tsdb_int64_to_smallint(v, TargetValue)); - } break; - case SQL_C_LONG: { - CHK_CONV(0, tsdb_int64_to_int(v, TargetValue)); - } break; - case SQL_C_SBIGINT: { - CHK_CONV(0, tsdb_int64_to_bigint(v, TargetValue)); - } break; - case SQL_C_FLOAT: { - CHK_CONV(0, tsdb_int64_to_float(v, TargetValue)); - } break; - case SQL_C_DOUBLE: { - CHK_CONV(0, tsdb_int64_to_double(v, TargetValue)); - } break; - case SQL_C_CHAR: { - tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn); - size_t len = (size_t)BufferLength; - TSDB_CONV_CODE code = tsdb_conv_write_int64(utf8_to_client, v, (char*)TargetValue, &len); - if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; - CHK_CONV(0, code); - } break; - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; - case TSDB_DATA_TYPE_FLOAT: { - float v = *(float*)row; - switch (target.ct) { - case SQL_C_FLOAT: { - *(float*)TargetValue = v; - return SQL_SUCCESS; - } break; - case SQL_C_DOUBLE: { - *(double*)TargetValue = v; - return SQL_SUCCESS; - } break; - case SQL_C_CHAR: { - tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn); - size_t len = (size_t)BufferLength; - TSDB_CONV_CODE code = tsdb_conv_write_double(utf8_to_client, v, (char*)TargetValue, &len); - if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; - CHK_CONV(0, code); - } break; - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; - case TSDB_DATA_TYPE_DOUBLE: { - double v = *(double*)row; - switch (target.ct) { - case SQL_C_DOUBLE: { - *(double*)TargetValue = v; - return SQL_SUCCESS; - } break; - case SQL_C_CHAR: { - tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn); - size_t len = (size_t)BufferLength; - TSDB_CONV_CODE code = tsdb_conv_write_double(utf8_to_client, v, (char*)TargetValue, &len); - if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; - CHK_CONV(0, code); - } break; - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; - case TSDB_DATA_TYPE_TIMESTAMP: { - SQL_TIMESTAMP_STRUCT ts = {0}; - int64_t v = *(int64_t*)row; - time_t t = v/1000; - struct tm vtm = {0}; - localtime_r(&t, &vtm); - ts.year = (SQLSMALLINT)(vtm.tm_year + 1900); - ts.month = (SQLUSMALLINT)(vtm.tm_mon + 1); - ts.day = (SQLUSMALLINT)(vtm.tm_mday); - ts.hour = (SQLUSMALLINT)(vtm.tm_hour); - ts.minute = (SQLUSMALLINT)(vtm.tm_min); - ts.second = (SQLUSMALLINT)(vtm.tm_sec); - ts.fraction = (SQLUINTEGER)(v%1000 * 1000000); - switch (target.ct) { - case SQL_C_SBIGINT: { - *(int64_t*)TargetValue = v; - return SQL_SUCCESS; - } break; - case SQL_C_CHAR: { - tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn); - size_t len = (size_t)BufferLength; - TSDB_CONV_CODE code = tsdb_conv_write_timestamp(utf8_to_client, ts, (char*)TargetValue, &len); - if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; - CHK_CONV(0, code); - } break; - case SQL_C_TYPE_TIMESTAMP: { - *(SQL_TIMESTAMP_STRUCT*)TargetValue = ts; - return SQL_SUCCESS; - } break; - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; - case TSDB_DATA_TYPE_BINARY: { - size_t field_bytes = (size_t)field->bytes; - field_bytes -= VARSTR_HEADER_SIZE; - switch (target.ct) { - case SQL_C_CHAR: { - // taos cares nothing about what would be stored in 'binary' as most sql implementations do - // but the client requires to fetch it as a SQL_C_CHAR - // thus, we first try to decode binary to client charset - // if failed, we then do hex-serialization - - tsdb_conv_t *server_to_client = tsdb_conn_server_to_client(conn); - size_t slen = strnlen((const char*)row, field_bytes); - size_t len = (size_t)BufferLength; - TSDB_CONV_CODE code = tsdb_conv_write(server_to_client, - (const char*)row, &slen, - (char*)TargetValue, &len); - if (code==TSDB_CONV_OK) { - if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)((size_t)BufferLength - len); - CHK_CONV(0, code); - // code never reached here - } - - // todo: hex-serialization - const char *bad = ""; - int n = snprintf((char*)TargetValue, (size_t)BufferLength, "%s", bad); - // what if n < 0 ? - if (StrLen_or_Ind) *StrLen_or_Ind = n; - CHK_CONV(0, n>=BufferLength ? TSDB_CONV_TRUNC : TSDB_CONV_OK); - } break; - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; - case TSDB_DATA_TYPE_NCHAR: { - size_t field_bytes = (size_t)field->bytes; - field_bytes -= VARSTR_HEADER_SIZE; - switch (target.ct) { - case SQL_C_CHAR: { - tsdb_conv_t *server_to_client = tsdb_conn_server_to_client(conn); - size_t slen = strnlen((const char*)row, field_bytes); - size_t len = (size_t)BufferLength; - TSDB_CONV_CODE code = tsdb_conv_write(server_to_client, - (const char*)row, &slen, - (char*)TargetValue, &len); - if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)((size_t)BufferLength - len); - CHK_CONV(0, code); - } break; - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for col [%d]", - taos_data_type(field->type), field->type, field->type, - sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } break; - } -} - -SQLRETURN SQL_API SQLGetData(SQLHSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, - SQLPOINTER TargetValue, SQLLEN BufferLength, - SQLLEN *StrLen_or_Ind) -{ - SQLRETURN r; - r = doSQLGetData(StatementHandle, ColumnNumber, TargetType, - TargetValue, BufferLength, - StrLen_or_Ind); - return r; -} - -static SQLRETURN doSQLFetch(SQLHSTMT StatementHandle) -{ - sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_INVALID_HANDLE; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - if (!sql->rs) { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NO_RESULT, ""); - return SQL_ERROR; - } - - sql->row = taos_fetch_row(sql->rs); - return sql->row ? SQL_SUCCESS : SQL_NO_DATA; -} - -SQLRETURN SQL_API SQLFetch(SQLHSTMT StatementHandle) -{ - SQLRETURN r; - r = doSQLFetch(StatementHandle); - return r; -} - -static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, - SQLCHAR *StatementText, SQLINTEGER TextLength) -{ - stack_buffer_t buffer; buffer.next = 0; - - sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_INVALID_HANDLE; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - conn_t *conn = sql->conn; - - NORM_STR_LENGTH(sql, StatementText, TextLength); - - if (sql->rs) { - taos_free_result(sql->rs); - sql->rs = NULL; - sql->row = NULL; - } - - if (sql->stmt) { - taos_stmt_close(sql->stmt); - sql->stmt = NULL; - } - - if (sql->params) { - free(sql->params); - sql->params = NULL; - } - sql->n_params = 0; - sql->is_insert = 0; - - do { - sql->stmt = taos_stmt_init(sql->conn->taos); - if (!sql->stmt) { - SET_ERROR(sql, "HY001", terrno, "failed to initialize TAOS statement internally"); - break; - } - - tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); - const char *stxt = NULL; - int ok = 0; - do { - tsdb_conv(client_to_server, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL); - if ((!stxt)) { - SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); - break; - } - - int r = taos_stmt_prepare(sql->stmt, stxt, (unsigned long)strlen(stxt)); - if (r) { - SET_ERROR(sql, "HY000", r, "failed to prepare a TAOS statement"); - break; - } - sql->is_prepared = 1; - - int is_insert = 0; - r = taos_stmt_is_insert(sql->stmt, &is_insert); - if (r) { - SET_ERROR(sql, "HY000", r, "failed to determine if a prepared-statement is of insert"); - break; - } - sql->is_insert = is_insert ? 1 : 0; - - int params = 0; - r = taos_stmt_num_params(sql->stmt, ¶ms); - if (r) { - SET_ERROR(sql, "HY000", terrno, "fetch num of statement params failed"); - break; - } - DASSERT(params>=0); - - if (params>0) { - param_bind_t *ar = (param_bind_t*)calloc(1, ((size_t)params) * sizeof(*ar)); - if (!ar) { - SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); - break; - } - sql->params = ar; - } - - sql->n_params = params; - - ok = 1; - } while (0); - - tsdb_conv_free(client_to_server, stxt, &buffer, (const char*)StatementText); - - if (!ok) { - taos_stmt_close(sql->stmt); - sql->stmt = NULL; - sql->is_prepared = 0; - sql->is_insert = 0; - sql->is_executed = 0; - } - } while (0); - - return sql->stmt ? SQL_SUCCESS : SQL_ERROR; -} - -SQLRETURN SQL_API SQLPrepare(SQLHSTMT StatementHandle, - SQLCHAR *StatementText, SQLINTEGER TextLength) -{ - SQLRETURN r; - r = doSQLPrepare(StatementHandle, StatementText, TextLength); - return r; -} - -static const int yes = 1; -static const int no = 0; - -static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bind_t *param, TAOS_BIND *bind) -{ - if (!param->valid) { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, "parameter [@%d] not bound yet", idx+1); - return SQL_ERROR; - } - if (param->ParameterValue==NULL) { - SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "ParameterValue [@%p] not allowed", param->ParameterValue); - return SQL_ERROR; - } - if (param->StrLen_or_Ind==NULL) { - SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StrLen_or_Ind [@%p] not allowed", param->StrLen_or_Ind); - return SQL_ERROR; - } - - conn_t *conn = sql->conn; - - unsigned char *paramValue = param->ParameterValue; - SQLSMALLINT valueType = param->ValueType; - SQLLEN *soi = param->StrLen_or_Ind; - - size_t offset = ((size_t)idx_row) * sql->rowlen + sql->ptr_offset; - - paramValue += offset; - soi = (SQLLEN*)((char*)soi + offset); - - - if (*soi == SQL_NULL_DATA) { - bind->is_null = (int*)&yes; - return SQL_SUCCESS; - } - bind->is_null = (int*)&no; - int tsdb_type = 0; // taos internal data tsdb_type to be bound to - int tsdb_bytes = 0; // we don't rely much on 'tsdb_bytes' here, we delay until taos to check it internally - if (sql->is_insert) { - int r = taos_stmt_get_param(sql->stmt, idx, &tsdb_type, &tsdb_bytes); - if (r) { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_OUT_OF_RANGE, "parameter [@%d] not valid", idx+1); - return SQL_ERROR; - } - } else { - // we don't have correspondent data type from taos api - // we have to give a good guess here - switch (valueType) { - case SQL_C_BIT: { - tsdb_type = TSDB_DATA_TYPE_BOOL; - } break; - case SQL_C_STINYINT: - case SQL_C_TINYINT: { - tsdb_type = TSDB_DATA_TYPE_TINYINT; - } break; - case SQL_C_SSHORT: - case SQL_C_SHORT: { - tsdb_type = TSDB_DATA_TYPE_SMALLINT; - } break; - case SQL_C_SLONG: - case SQL_C_LONG: { - tsdb_type = TSDB_DATA_TYPE_INT; - } break; - case SQL_C_SBIGINT: { - tsdb_type = TSDB_DATA_TYPE_BIGINT; - } break; - case SQL_C_FLOAT: { - tsdb_type = TSDB_DATA_TYPE_FLOAT; - } break; - case SQL_C_DOUBLE: { - tsdb_type = TSDB_DATA_TYPE_DOUBLE; - } break; - case SQL_C_TIMESTAMP: { - tsdb_type = TSDB_DATA_TYPE_TIMESTAMP; - } break; - case SQL_C_CHAR: { - tsdb_type = TSDB_DATA_TYPE_BINARY; - tsdb_bytes = SQL_NTS; - } break; - case SQL_C_WCHAR: { - tsdb_type = TSDB_DATA_TYPE_NCHAR; - tsdb_bytes = SQL_NTS; - } break; - case SQL_C_USHORT: - case SQL_C_ULONG: - case SQL_C_UTINYINT: - case SQL_C_UBIGINT: - case SQL_C_BINARY: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - idx+1); - return SQL_ERROR; - } break; - } - } - - // ref: https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/converting-data-from-c-to-sql-data-types?view=sql-server-ver15 - switch (tsdb_type) { - case TSDB_DATA_TYPE_BOOL: { - bind->buffer_type = tsdb_type; - bind->buffer_length = sizeof(bind->u.b); - bind->buffer = &bind->u.b; - bind->length = &bind->buffer_length; - switch (valueType) { - case SQL_C_BIT: { - CHK_CONV(1, tsdb_int64_to_bit(*(int8_t*)paramValue, &bind->u.b)); - } break; - case SQL_C_TINYINT: - case SQL_C_STINYINT: { - CHK_CONV(1, tsdb_int64_to_bit(*(int8_t*)paramValue, &bind->u.b)); - } break; - case SQL_C_SHORT: - case SQL_C_SSHORT: { - CHK_CONV(1, tsdb_int64_to_bit(*(int16_t*)paramValue, &bind->u.b)); - } break; - case SQL_C_LONG: - case SQL_C_SLONG: { - CHK_CONV(1, tsdb_int64_to_bit(*(int32_t*)paramValue, &bind->u.b)); - } break; - case SQL_C_SBIGINT: { - CHK_CONV(1, tsdb_int64_to_bit(*(int64_t*)paramValue, &bind->u.b)); - } break; - case SQL_C_FLOAT: { - CHK_CONV(1, tsdb_double_to_bit(*(float*)paramValue, &bind->u.b)); - } break; - case SQL_C_DOUBLE: { - CHK_CONV(1, tsdb_double_to_bit(*(double*)paramValue, &bind->u.b)); - } break; - case SQL_C_CHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); - size_t slen = (size_t)*soi; - if (slen==SQL_NTS) slen = strlen((const char*)paramValue); - CHK_CONV(1, tsdb_conv_chars_to_bit(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.b)); - } break; - case SQL_C_WCHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); - size_t slen = (size_t)*soi; - DASSERT(slen != SQL_NTS); - CHK_CONV(1, tsdb_conv_chars_to_bit(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.b)); - } break; - case SQL_C_USHORT: - case SQL_C_ULONG: - case SQL_C_UTINYINT: - case SQL_C_UBIGINT: - case SQL_C_BINARY: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TIMESTAMP: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); - return SQL_ERROR; - } break; - } - } break; - case TSDB_DATA_TYPE_TINYINT: { - bind->buffer_type = tsdb_type; - bind->buffer_length = sizeof(bind->u.v1); - bind->buffer = &bind->u.v1; - bind->length = &bind->buffer_length; - switch (valueType) { - case SQL_C_BIT: { - CHK_CONV(1, tsdb_int64_to_tinyint(*(int8_t*)paramValue, &bind->u.v1)); - } break; - case SQL_C_STINYINT: - case SQL_C_TINYINT: { - CHK_CONV(1, tsdb_int64_to_tinyint(*(int8_t*)paramValue, &bind->u.v1)); - } break; - case SQL_C_SSHORT: - case SQL_C_SHORT: { - CHK_CONV(1, tsdb_int64_to_tinyint(*(int16_t*)paramValue, &bind->u.v1)); - } break; - case SQL_C_SLONG: - case SQL_C_LONG: { - CHK_CONV(1, tsdb_int64_to_tinyint(*(int32_t*)paramValue, &bind->u.v1)); - } break; - case SQL_C_SBIGINT: { - CHK_CONV(1, tsdb_int64_to_tinyint(*(int64_t*)paramValue, &bind->u.v1)); - } break; - case SQL_C_CHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); - size_t slen = (size_t)*soi; - if (slen==SQL_NTS) slen = strlen((const char*)paramValue); - CHK_CONV(1, tsdb_conv_chars_to_tinyint(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v1)); - // CHK_CONV(1, tsdb_chars_to_tinyint((const char *)paramValue, (size_t)*soi, &bind->u.v1)); - } break; - case SQL_C_WCHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); - size_t slen = (size_t)*soi; - DASSERT(slen != SQL_NTS); - CHK_CONV(1, tsdb_conv_chars_to_tinyint(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v1)); - } break; - case SQL_C_USHORT: - case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: - case SQL_C_UTINYINT: - case SQL_C_UBIGINT: - case SQL_C_BINARY: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TIMESTAMP: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); - return SQL_ERROR; - } break; - } - } break; - case TSDB_DATA_TYPE_SMALLINT: { - bind->buffer_type = tsdb_type; - bind->buffer_length = sizeof(bind->u.v2); - bind->buffer = &bind->u.v2; - bind->length = &bind->buffer_length; - switch (valueType) { - case SQL_C_BIT: { - CHK_CONV(1, tsdb_int64_to_smallint(*(int8_t*)paramValue, &bind->u.v2)); - } break; - case SQL_C_STINYINT: - case SQL_C_TINYINT: { - CHK_CONV(1, tsdb_int64_to_smallint(*(int8_t*)paramValue, &bind->u.v2)); - } break; - case SQL_C_SSHORT: - case SQL_C_SHORT: { - CHK_CONV(1, tsdb_int64_to_smallint(*(int16_t*)paramValue, &bind->u.v2)); - } break; - case SQL_C_SLONG: - case SQL_C_LONG: { - CHK_CONV(1, tsdb_int64_to_smallint(*(int32_t*)paramValue, &bind->u.v2)); - } break; - case SQL_C_SBIGINT: { - CHK_CONV(1, tsdb_int64_to_smallint(*(int64_t*)paramValue, &bind->u.v2)); - } break; - case SQL_C_CHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); - size_t slen = (size_t)*soi; - if (slen==SQL_NTS) slen = strlen((const char*)paramValue); - CHK_CONV(1, tsdb_conv_chars_to_smallint(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v2)); - // CHK_CONV(1, tsdb_chars_to_smallint((const char*)paramValue, (size_t)*soi, &bind->u.v2)); - } break; - case SQL_C_WCHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); - size_t slen = (size_t)*soi; - DASSERT(slen != SQL_NTS); - CHK_CONV(1, tsdb_conv_chars_to_smallint(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v2)); - } break; - case SQL_C_USHORT: - case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: - case SQL_C_UTINYINT: - case SQL_C_UBIGINT: - case SQL_C_BINARY: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TIMESTAMP: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); - return SQL_ERROR; - } break; - } - } break; - case TSDB_DATA_TYPE_INT: { - bind->buffer_type = tsdb_type; - bind->buffer_length = sizeof(bind->u.v4); - bind->buffer = &bind->u.v4; - bind->length = &bind->buffer_length; - switch (valueType) { - case SQL_C_BIT: { - CHK_CONV(1, tsdb_int64_to_int(*(int8_t*)paramValue, &bind->u.v4)); - } break; - case SQL_C_STINYINT: - case SQL_C_TINYINT: { - CHK_CONV(1, tsdb_int64_to_int(*(int8_t*)paramValue, &bind->u.v4)); - } break; - case SQL_C_SSHORT: - case SQL_C_SHORT: { - CHK_CONV(1, tsdb_int64_to_int(*(int16_t*)paramValue, &bind->u.v4)); - } break; - case SQL_C_SLONG: - case SQL_C_LONG: { - CHK_CONV(1, tsdb_int64_to_int(*(int32_t*)paramValue, &bind->u.v4)); - } break; - case SQL_C_SBIGINT: { - CHK_CONV(1, tsdb_int64_to_int(*(int64_t*)paramValue, &bind->u.v4)); - } break; - case SQL_C_CHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); - size_t slen = (size_t)*soi; - if (slen==SQL_NTS) slen = strlen((const char*)paramValue); - CHK_CONV(1, tsdb_conv_chars_to_int(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v4)); - // CHK_CONV(1, tsdb_chars_to_int((const char*)paramValue, (size_t)*soi, &bind->u.v4)); - } break; - case SQL_C_WCHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); - size_t slen = (size_t)*soi; - DASSERT(slen != SQL_NTS); - CHK_CONV(1, tsdb_conv_chars_to_int(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v4)); - } break; - case SQL_C_USHORT: - case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: - case SQL_C_UTINYINT: - case SQL_C_UBIGINT: - case SQL_C_BINARY: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TIMESTAMP: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); - return SQL_ERROR; - } break; - } - } break; - case TSDB_DATA_TYPE_BIGINT: { - bind->buffer_type = tsdb_type; - bind->buffer_length = sizeof(bind->u.v8); - bind->buffer = &bind->u.v8; - bind->length = &bind->buffer_length; - switch (valueType) { - case SQL_C_BIT: { - CHK_CONV(1, tsdb_int64_to_bigint(*(int8_t*)paramValue, &bind->u.v8)); - } break; - case SQL_C_STINYINT: - case SQL_C_TINYINT: { - CHK_CONV(1, tsdb_int64_to_bigint(*(int8_t*)paramValue, &bind->u.v8)); - } break; - case SQL_C_SSHORT: - case SQL_C_SHORT: { - CHK_CONV(1, tsdb_int64_to_bigint(*(int16_t*)paramValue, &bind->u.v8)); - } break; - case SQL_C_SLONG: - case SQL_C_LONG: { - CHK_CONV(1, tsdb_int64_to_bigint(*(int32_t*)paramValue, &bind->u.v8)); - } break; - case SQL_C_SBIGINT: { - CHK_CONV(1, tsdb_int64_to_bigint(*(int64_t*)paramValue, &bind->u.v8)); - } break; - case SQL_C_CHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); - size_t slen = (size_t)*soi; - if (slen==SQL_NTS) slen = strlen((const char*)paramValue); - CHK_CONV(1, tsdb_conv_chars_to_bigint(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8)); - // CHK_CONV(1, tsdb_chars_to_bigint((const char*)paramValue, (size_t)*soi, &bind->u.v8)); - } break; - case SQL_C_WCHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); - size_t slen = (size_t)*soi; - DASSERT(slen != SQL_NTS); - CHK_CONV(1, tsdb_conv_chars_to_bigint(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8)); - } break; - case SQL_C_USHORT: - case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: - case SQL_C_UTINYINT: - case SQL_C_UBIGINT: - case SQL_C_BINARY: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TIMESTAMP: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); - return SQL_ERROR; - } break; - } - } break; - case TSDB_DATA_TYPE_FLOAT: { - bind->buffer_type = tsdb_type; - bind->buffer_length = sizeof(bind->u.f4); - bind->buffer = &bind->u.f4; - bind->length = &bind->buffer_length; - switch (valueType) { - case SQL_C_BIT: { - CHK_CONV(1, tsdb_int64_to_float(*(int8_t*)paramValue, &bind->u.f4)); - } break; - case SQL_C_STINYINT: - case SQL_C_TINYINT: { - CHK_CONV(1, tsdb_int64_to_float(*(int8_t*)paramValue, &bind->u.f4)); - } break; - case SQL_C_SSHORT: - case SQL_C_SHORT: { - CHK_CONV(1, tsdb_int64_to_float(*(int16_t*)paramValue, &bind->u.f4)); - } break; - case SQL_C_SLONG: - case SQL_C_LONG: { - CHK_CONV(1, tsdb_int64_to_float(*(int32_t*)paramValue, &bind->u.f4)); - } break; - case SQL_C_SBIGINT: { - CHK_CONV(1, tsdb_int64_to_float(*(int64_t*)paramValue, &bind->u.f4)); - } break; - case SQL_C_FLOAT: { - bind->u.f4 = *(float*)paramValue; - } break; - case SQL_C_DOUBLE: { - bind->u.f4 = (float)*(double*)paramValue; - } break; - case SQL_C_CHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); - size_t slen = (size_t)*soi; - if (slen==SQL_NTS) slen = strlen((const char*)paramValue); - CHK_CONV(1, tsdb_conv_chars_to_float(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f4)); - } break; - case SQL_C_WCHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); - size_t slen = (size_t)*soi; - DASSERT(slen != SQL_NTS); - CHK_CONV(1, tsdb_conv_chars_to_float(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f4)); - } break; - case SQL_C_USHORT: - case SQL_C_ULONG: - case SQL_C_UTINYINT: - case SQL_C_UBIGINT: - case SQL_C_BINARY: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TIMESTAMP: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); - return SQL_ERROR; - } break; - } - } break; - case TSDB_DATA_TYPE_DOUBLE: { - bind->buffer_type = tsdb_type; - bind->buffer_length = sizeof(bind->u.f8); - bind->buffer = &bind->u.f8; - bind->length = &bind->buffer_length; - switch (valueType) { - case SQL_C_BIT: { - CHK_CONV(1, tsdb_int64_to_double(*(int8_t*)paramValue, &bind->u.f8)); - } break; - case SQL_C_STINYINT: - case SQL_C_TINYINT: { - CHK_CONV(1, tsdb_int64_to_double(*(int8_t*)paramValue, &bind->u.f8)); - } break; - case SQL_C_SSHORT: - case SQL_C_SHORT: { - CHK_CONV(1, tsdb_int64_to_double(*(int16_t*)paramValue, &bind->u.f8)); - } break; - case SQL_C_SLONG: - case SQL_C_LONG: { - CHK_CONV(1, tsdb_int64_to_double(*(int32_t*)paramValue, &bind->u.f8)); - } break; - case SQL_C_SBIGINT: { - CHK_CONV(1, tsdb_int64_to_double(*(int64_t*)paramValue, &bind->u.f8)); - } break; - case SQL_C_FLOAT: { - bind->u.f8 = *(float*)paramValue; - } break; - case SQL_C_DOUBLE: { - bind->u.f8 = *(double*)paramValue; - } break; - case SQL_C_CHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); - size_t slen = (size_t)*soi; - if (slen==SQL_NTS) slen = strlen((const char*)paramValue); - CHK_CONV(1, tsdb_conv_chars_to_double(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f8)); - // CHK_CONV(1, tsdb_chars_to_double((const char*)paramValue, (size_t)*soi, &bind->u.f8)); - } break; - case SQL_C_WCHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); - size_t slen = (size_t)*soi; - DASSERT(slen != SQL_NTS); - CHK_CONV(1, tsdb_conv_chars_to_double(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f8)); - } break; - case SQL_C_USHORT: - case SQL_C_ULONG: - case SQL_C_UTINYINT: - case SQL_C_UBIGINT: - case SQL_C_BINARY: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TIMESTAMP: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); - return SQL_ERROR; - } break; - } - } break; - case TSDB_DATA_TYPE_TIMESTAMP: { - bind->buffer_type = tsdb_type; - bind->buffer_length = sizeof(bind->u.v8); - bind->buffer = &bind->u.v8; - bind->length = &bind->buffer_length; - switch (valueType) { - case SQL_C_CHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); - size_t slen = (size_t)*soi; - DASSERT(slen != SQL_NTS); - CHK_CONV(1, tsdb_conv_chars_to_timestamp_ts(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8)); - } break; - case SQL_C_WCHAR: { - stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); - size_t slen = (size_t)*soi; - DASSERT(slen != SQL_NTS); - CHK_CONV(1, tsdb_conv_chars_to_timestamp_ts(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8)); - } break; - case SQL_C_SBIGINT: { - int64_t t = *(int64_t*)paramValue; - bind->u.v8 = t; - } break; - case SQL_C_TYPE_TIMESTAMP: { - SQL_TIMESTAMP_STRUCT ts = *(SQL_TIMESTAMP_STRUCT*)paramValue; - struct tm vtm = {0}; - vtm.tm_year = ts.year - 1900; - vtm.tm_mon = ts.month - 1; - vtm.tm_mday = ts.day; - vtm.tm_hour = ts.hour; - vtm.tm_min = ts.minute; - vtm.tm_sec = ts.second; - int64_t t = (int64_t) mktime(&vtm); - if (t==-1) { - CHK_CONV(1, TSDB_CONV_NOT_VALID_TS); - // code never reached here - } - bind->u.ts = t * 1000 + ts.fraction / 1000000; - } break; - case SQL_C_SHORT: - case SQL_C_SSHORT: - case SQL_C_USHORT: - case SQL_C_LONG: - case SQL_C_SLONG: - case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: - case SQL_C_UTINYINT: - case SQL_C_UBIGINT: - case SQL_C_BINARY: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TIMESTAMP: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); - return SQL_ERROR; - } break; - } - } break; - case TSDB_DATA_TYPE_BINARY: { - bind->buffer_type = tsdb_type; - bind->length = &bind->buffer_length; - switch (valueType) { - case SQL_C_WCHAR: { - // taos cares nothing about what would be stored in 'binary' as most sql implementations do - // thus, we just copy it as is - // it's caller's responsibility to maintain data-consistency - // if he/she is going to use 'binary' to store characters - // taos might extend it's sql syntax to let user specify - // what charset is to be used for specific 'binary' field when - // table is to be created - // in such way, 'binary' would be 'internationalized' - // but actually speaking, normally, 'char' field is a better - // one for this purpose - size_t slen = (size_t)*soi; - DASSERT(slen != SQL_NTS); - bind->u.bin = (unsigned char*)malloc(slen + 1); // add null-terminator, just for case of use - if (!bind->u.bin) { - CHK_CONV(1, TSDB_CONV_OOM); - // code never reached here - } - memcpy(bind->u.bin, paramValue, slen); - bind->buffer_length = slen; - bind->buffer = bind->u.bin; - CHK_CONV(1, TSDB_CONV_OK); - - // tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn); - // size_t slen = (size_t)*soi; - // DASSERT(slen != SQL_NTS); - // const char *buf = NULL; - // size_t blen = 0; - // TSDB_CONV_CODE code = tsdb_conv(utf16_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); - // if (code==TSDB_CONV_OK) { - // if (buf!=(const char*)paramValue) { - // bind->allocated = 1; - // } - // bind->u.bin = (unsigned char*)buf; - // bind->buffer_length = blen; - // bind->buffer = bind->u.bin; - // } - // CHK_CONV(1, code); - } break; - case SQL_C_CHAR: { - // taos cares nothing about what would be stored in 'binary' as most sql implementations do - // thus, we just copy it as is - // it's caller's responsibility to maintain data-consistency - // if he/she is going to use 'binary' to store characters - // taos might extend it's sql syntax to let user specify - // what charset is to be used for specific 'binary' field when - // table is to be created - // in such way, 'binary' would be 'internationalized' - // but actually speaking, normally, 'char' field is a better - // one for this purpose - size_t slen = (size_t)*soi; - if (slen==SQL_NTS) slen = strlen((const char*)paramValue); - // we can not use strndup, because ODBC client might pass in a buffer without null-terminated - bind->u.bin = (unsigned char*)malloc(slen + 1); // add null-terminator, just for case of use - if (!bind->u.bin) { - CHK_CONV(1, TSDB_CONV_OOM); - // code never reached here - } - memcpy(bind->u.bin, paramValue, slen); - bind->buffer_length = slen; - bind->buffer = bind->u.bin; - CHK_CONV(1, TSDB_CONV_OK); - // code never reached here - - // tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); - // size_t slen = (size_t)*soi; - // if (slen==SQL_NTS) slen = strlen((const char*)paramValue); - // const char *buf = NULL; - // size_t blen = 0; - // TSDB_CONV_CODE code = tsdb_conv(client_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); - // if (code==TSDB_CONV_OK) { - // if (buf!=(const char*)paramValue) { - // bind->allocated = 1; - // } - // bind->u.bin = (unsigned char*)buf; - // bind->buffer_length = blen; - // bind->buffer = bind->u.bin; - // } - // CHK_CONV(1, code); - } break; - case SQL_C_SHORT: - case SQL_C_SSHORT: - case SQL_C_USHORT: - case SQL_C_LONG: - case SQL_C_SLONG: - case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: - case SQL_C_UTINYINT: - case SQL_C_SBIGINT: - case SQL_C_UBIGINT: - case SQL_C_BINARY: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TIMESTAMP: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: // we don't provide auto-converstion - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); - return SQL_ERROR; - } break; - } - } break; - case TSDB_DATA_TYPE_NCHAR: { - bind->buffer_type = tsdb_type; - bind->length = &bind->buffer_length; - switch (valueType) { - case SQL_C_WCHAR: { - tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn); - size_t slen = (size_t)*soi; - if (slen==SQL_NTS) slen = strlen((const char*)paramValue); - const char *buf = NULL; - size_t blen = 0; - TSDB_CONV_CODE code = tsdb_conv(utf16_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); - if (code==TSDB_CONV_OK) { - if (buf!=(const char*)paramValue) { - bind->allocated = 1; - } - bind->u.nchar = (char*)buf; - bind->buffer_length = blen; - bind->buffer = bind->u.nchar; - } - CHK_CONV(1, code); - } break; - case SQL_C_CHAR: { - tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); - size_t slen = (size_t)*soi; - if (slen==SQL_NTS) slen = strlen((const char*)paramValue); - const char *buf = NULL; - size_t blen = 0; - TSDB_CONV_CODE code = tsdb_conv(client_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); - if (code==TSDB_CONV_OK) { - if (buf!=(const char*)paramValue) { - bind->allocated = 1; - } - bind->u.bin = (unsigned char*)buf; - bind->buffer_length = blen; - bind->buffer = bind->u.bin; - } - CHK_CONV(1, code); - } break; - case SQL_C_SHORT: - case SQL_C_SSHORT: - case SQL_C_USHORT: - case SQL_C_LONG: - case SQL_C_SLONG: - case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: - case SQL_C_UTINYINT: - case SQL_C_SBIGINT: - case SQL_C_UBIGINT: - case SQL_C_BINARY: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TIMESTAMP: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: // we don't provide auto-converstion - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); - return SQL_ERROR; - } break; - } - } break; - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); - return SQL_ERROR; - } break; - } - return SQL_SUCCESS; -} - -static SQLRETURN do_bind_batch(sql_t *sql, int idx_row, TAOS_BIND *binds) -{ - for (int j=0; jn_params; ++j) { - SQLRETURN r = do_bind_param_value(sql, idx_row, j, sql->params+j, binds+j); - if (r==SQL_SUCCESS) continue; - return r; - } - if (sql->n_params > 0) { - int tr = 0; - PROFILE(tr = taos_stmt_bind_param(sql->stmt, binds)); - if (tr) { - SET_ERROR(sql, "HY000", tr, "failed to bind parameters[%d in total]", sql->n_params); - return SQL_ERROR; - } - - if (sql->is_insert) { - int r = 0; - PROFILE(r = taos_stmt_add_batch(sql->stmt)); - if (r) { - SET_ERROR(sql, "HY000", r, "failed to add batch"); - return SQL_ERROR; - } - } - } - return SQL_SUCCESS; -} - -static SQLRETURN do_execute(sql_t *sql) -{ - int tr = TSDB_CODE_SUCCESS; - if (sql->n_rows==0) sql->n_rows = 1; - for (int i=0; in_rows; ++i) { - TAOS_BIND *binds = NULL; - if (sql->n_params>0) { - binds = (TAOS_BIND*)calloc((size_t)sql->n_params, sizeof(*binds)); - if (!binds) { - SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); - return SQL_ERROR; - } - } - - SQLRETURN r = do_bind_batch(sql, i, binds); - - if (binds) { - for (int i = 0; in_params; ++i) { - TAOS_BIND *bind = binds + i; - if (bind->allocated) { - free(bind->u.nchar); - bind->u.nchar = NULL; - } - } - free(binds); - } - - if (r) return r; - } - - PROFILE(tr = taos_stmt_execute(sql->stmt)); - if (tr) { - SET_ERROR(sql, "HY000", tr, "failed to execute statement"); - return SQL_ERROR; - } - - sql->is_executed = 1; - // if (sql->is_insert) return SQL_SUCCESS; - - SQLRETURN r = SQL_SUCCESS; - PROFILE(sql->rs = taos_stmt_use_result(sql->stmt)); - CHK_RS(r, sql, "failed to use result"); - - return r; -} - -static SQLRETURN doSQLExecute(SQLHSTMT StatementHandle) -{ - sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - if (!sql->stmt) { - SET_ERROR(sql, "HY010", TSDB_CODE_ODBC_STATEMENT_NOT_READY, ""); - return SQL_ERROR; - } - - if (sql->rs) { - taos_free_result(sql->rs); - sql->rs = NULL; - sql->row = NULL; - } - - SQLRETURN r = do_execute(sql); - - return r; -} - -SQLRETURN SQL_API SQLExecute(SQLHSTMT StatementHandle) -{ - SQLRETURN r; - PROFILE(r = doSQLExecute(StatementHandle)); - return r; -} - -static SQLRETURN doSQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, - SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier, - SQLPOINTER DiagInfo, SQLSMALLINT BufferLength, - SQLSMALLINT *StringLength) -{ - switch (DiagIdentifier) { - case SQL_DIAG_CLASS_ORIGIN: { - *StringLength = 0; - } break; - } - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, - SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier, - SQLPOINTER DiagInfo, SQLSMALLINT BufferLength, - SQLSMALLINT *StringLength) -{ - SQLRETURN r; - r = doSQLGetDiagField(HandleType, Handle, - RecNumber, DiagIdentifier, - DiagInfo, BufferLength, - StringLength); - return r; -} - -static SQLRETURN doSQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, - SQLSMALLINT RecNumber, SQLCHAR *Sqlstate, - SQLINTEGER *NativeError, SQLCHAR *MessageText, - SQLSMALLINT BufferLength, SQLSMALLINT *TextLength) -{ - if (RecNumber>1) return SQL_NO_DATA; - - switch (HandleType) { - case SQL_HANDLE_ENV: { - env_t *env = (env_t*)Handle; - if (!env) break; - FILL_ERROR(env); - return SQL_SUCCESS; - } break; - case SQL_HANDLE_DBC: { - conn_t *conn = (conn_t*)Handle; - if (!conn) break; - FILL_ERROR(conn); - return SQL_SUCCESS; - } break; - case SQL_HANDLE_STMT: { - sql_t *sql = (sql_t*)Handle; - if (!sql) break; - FILL_ERROR(sql); - return SQL_SUCCESS; - } break; - default: { - } break; - } - - // how to return error? - return SQL_ERROR; -} - -SQLRETURN SQL_API SQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, - SQLSMALLINT RecNumber, SQLCHAR *Sqlstate, - SQLINTEGER *NativeError, SQLCHAR *MessageText, - SQLSMALLINT BufferLength, SQLSMALLINT *TextLength) -{ - SQLRETURN r; - r = doSQLGetDiagRec(HandleType, Handle, - RecNumber, Sqlstate, - NativeError, MessageText, - BufferLength, TextLength); - return r; -} - -static SQLRETURN doSQLBindParameter( - SQLHSTMT StatementHandle, - SQLUSMALLINT ParameterNumber, - SQLSMALLINT fParamType, - SQLSMALLINT ValueType, - SQLSMALLINT ParameterType, - SQLULEN LengthPrecision, - SQLSMALLINT ParameterScale, - SQLPOINTER ParameterValue, - SQLLEN cbValueMax, // ignore for now, since only SQL_PARAM_INPUT is supported now - SQLLEN *StrLen_or_Ind) -{ - sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_INVALID_HANDLE; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - if (!sql->stmt) { - SET_ERROR(sql, "HY010", TSDB_CODE_ODBC_STATEMENT_NOT_READY, ""); - return SQL_ERROR; - } - - if (ParameterNumber<=0 || ParameterNumber>sql->n_params) { - SET_ERROR(sql, "07009", TSDB_CODE_ODBC_BAD_ARG, - "parameter [@%d] invalid", ParameterNumber); - return SQL_ERROR; - } - - if (fParamType != SQL_PARAM_INPUT) { - SET_ERROR(sql, "HY105", TSDB_CODE_ODBC_NOT_SUPPORT, "non-input parameter [@%d] not supported yet", ParameterNumber); - return SQL_ERROR; - } - - if (ValueType == SQL_C_DEFAULT) { - SET_ERROR(sql, "HY003", TSDB_CODE_ODBC_NOT_SUPPORT, "default value for parameter [@%d] not supported yet", ParameterNumber); - return SQL_ERROR; - } - - if (!is_valid_sql_c_type(ValueType)) { - SET_ERROR(sql, "HY003", TSDB_CODE_ODBC_NOT_SUPPORT, - "SQL_C_TYPE [%s/%d/0x%x] for parameter [@%d] unknown", - sql_c_type(ValueType), ValueType, ValueType, ParameterNumber); - return SQL_ERROR; - } - - if (!is_valid_sql_sql_type(ParameterType)) { - SET_ERROR(sql, "HY004", TSDB_CODE_ODBC_NOT_SUPPORT, - "SQL_TYPE [%s/%d/0x%x] for parameter [@%d] unknown", - sql_c_type(ParameterType), ParameterType, ParameterType, ParameterNumber); - return SQL_ERROR; - } - - if (ParameterValue==NULL) { - SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "ParameterValue [@%p] not allowed", ParameterValue); - return SQL_ERROR; - } - - if (StrLen_or_Ind==NULL) { - SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StrLen_or_Ind [@%p] not allowed", StrLen_or_Ind); - return SQL_ERROR; - } - - param_bind_t *pb = sql->params + ParameterNumber - 1; - - pb->ParameterNumber = ParameterNumber; - pb->ValueType = ValueType; - pb->ParameterType = ParameterType; - pb->LengthPrecision = LengthPrecision; - pb->ParameterScale = ParameterScale; - pb->ParameterValue = ParameterValue; - pb->StrLen_or_Ind = StrLen_or_Ind; - - pb->valid = 1; - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLBindParameter( - SQLHSTMT StatementHandle, - SQLUSMALLINT ParameterNumber, - SQLSMALLINT fParamType, - SQLSMALLINT ValueType, - SQLSMALLINT ParameterType, - SQLULEN LengthPrecision, - SQLSMALLINT ParameterScale, - SQLPOINTER ParameterValue, - SQLLEN cbValueMax, // ignore for now, since only SQL_PARAM_INPUT is supported now - SQLLEN *StrLen_or_Ind) -{ - SQLRETURN r; - r = doSQLBindParameter(StatementHandle, ParameterNumber, fParamType, ValueType, ParameterType, - LengthPrecision, ParameterScale, ParameterValue, cbValueMax, StrLen_or_Ind); - return r; -} - -static SQLRETURN doSQLDriverConnect( - SQLHDBC hdbc, - SQLHWND hwnd, - SQLCHAR *szConnStrIn, - SQLSMALLINT cbConnStrIn, - SQLCHAR *szConnStrOut, - SQLSMALLINT cbConnStrOutMax, - SQLSMALLINT *pcbConnStrOut, - SQLUSMALLINT fDriverCompletion) -{ - conn_t *conn = (conn_t*)hdbc; - if (!conn) return SQL_INVALID_HANDLE; - - if (conn->taos) { - SET_ERROR(conn, "08002", TSDB_CODE_ODBC_CONNECTION_BUSY, "connection still in use"); - return SQL_ERROR; - } - - if (fDriverCompletion!=SQL_DRIVER_NOPROMPT) { - SET_ERROR(conn, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "option[%d] other than SQL_DRIVER_NOPROMPT not supported yet", fDriverCompletion); - return SQL_ERROR; - } - - NORM_STR_LENGTH(conn, szConnStrIn, cbConnStrIn); - - // DSN=; UID=; PWD= - - const char *connStr = SDUP(szConnStrIn, cbConnStrIn); - - conn_val_t val = {0}; - - do { - if (szConnStrIn && !connStr) { - SET_ERROR(conn, "HY001", TSDB_CODE_ODBC_OOM, ""); - break; - } - - int n = todbc_parse_conn_string((const char *)connStr, &val); - if (n) { - SET_ERROR(conn, "HY000", TSDB_CODE_ODBC_BAD_CONNSTR, "unrecognized connection string: [%s]", (const char*)szConnStrIn); - break; - } - char *ip = NULL; - int port = 0; - if (val.server) { - char *p = strchr(val.server, ':'); - if (p) { - ip = strndup(val.server, (size_t)(p-val.server)); - port = atoi(p+1); - } - } - - if ((val.cli_enc && strcmp(val.cli_enc, conn->client_enc)) || - (val.svr_enc && strcmp(val.svr_enc, conn->server_enc)) ) - { - tsdb_conn_close_convs(conn); - if (val.cli_enc) { - snprintf(conn->client_enc, sizeof(conn->client_enc), "%s", val.cli_enc); - } - if (val.svr_enc) { - snprintf(conn->server_enc, sizeof(conn->server_enc), "%s", val.svr_enc); - } - } - - // TODO: data-race - // TODO: shall receive ip/port from odbc.ini - // shall we support non-ansi uid/pwd/db etc? - conn->taos = taos_connect(ip ? ip : "localhost", val.uid, val.pwd, val.db, (uint16_t)port); - free(ip); ip = NULL; - if (!conn->taos) { - SET_ERROR(conn, "HY000", terrno, "failed to connect to data source"); - break; - } - - if (szConnStrOut) { - snprintf((char*)szConnStrOut, (size_t)cbConnStrOutMax, "%s", connStr); - } - if (pcbConnStrOut) { - *pcbConnStrOut = cbConnStrIn; - } - } while (0); - - conn_val_reset(&val); - - SFRE(connStr, szConnStrIn, cbConnStrIn); - - return conn->taos ? SQL_SUCCESS : SQL_ERROR; -} - -SQLRETURN SQL_API SQLDriverConnect( - SQLHDBC hdbc, - SQLHWND hwnd, - SQLCHAR *szConnStrIn, - SQLSMALLINT cbConnStrIn, - SQLCHAR *szConnStrOut, - SQLSMALLINT cbConnStrOutMax, - SQLSMALLINT *pcbConnStrOut, - SQLUSMALLINT fDriverCompletion) -{ - SQLRETURN r; - r = doSQLDriverConnect(hdbc, hwnd, szConnStrIn, cbConnStrIn, szConnStrOut, cbConnStrOutMax, pcbConnStrOut, fDriverCompletion); - return r; -} - -static SQLRETURN doSQLSetConnectAttr(SQLHDBC ConnectionHandle, - SQLINTEGER Attribute, SQLPOINTER Value, - SQLINTEGER StringLength) -{ - conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_INVALID_HANDLE; - - if (Attribute != SQL_ATTR_AUTOCOMMIT) { - SET_ERROR(conn, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "Attribute other than SQL_ATTR_AUTOCOMMIT not supported yet"); - return SQL_ERROR; - } - if (Value != (SQLPOINTER)SQL_AUTOCOMMIT_ON) { - SET_ERROR(conn, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "Attribute Value other than SQL_AUTOCOMMIT_ON not supported yet[%p]", Value); - return SQL_ERROR; - } - - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLSetConnectAttr(SQLHDBC ConnectionHandle, - SQLINTEGER Attribute, SQLPOINTER Value, - SQLINTEGER StringLength) -{ - SQLRETURN r; - r = doSQLSetConnectAttr(ConnectionHandle, Attribute, Value, StringLength); - return r; -} - -static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLCHAR *ColumnName, - SQLSMALLINT BufferLength, SQLSMALLINT *NameLength, - SQLSMALLINT *DataType, SQLULEN *ColumnSize, - SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable) -{ - sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_INVALID_HANDLE; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - if (!sql->rs) { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NO_RESULT, ""); - return SQL_ERROR; - } - - int nfields = taos_field_count(sql->rs); - TAOS_FIELD *fields = taos_fetch_fields(sql->rs); - - if (ColumnNumber<=0 || ColumnNumber>nfields) { - SET_ERROR(sql, "07009", TSDB_CODE_ODBC_OUT_OF_RANGE, "invalid column number [%d]", ColumnNumber); - return SQL_ERROR; - } - if (BufferLength<0) { - SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - - TAOS_FIELD *field = fields + ColumnNumber - 1; - if (ColumnName) { - size_t n = sizeof(field->name); - if (n>BufferLength) n = (size_t)BufferLength; - strncpy((char*)ColumnName, field->name, n); - } - if (NameLength) { - *NameLength = (SQLSMALLINT)strnlen(field->name, sizeof(field->name)); - } - if (ColumnSize) *ColumnSize = (SQLULEN)field->bytes; - if (DecimalDigits) *DecimalDigits = 0; - - if (DataType) { - switch (field->type) { - case TSDB_DATA_TYPE_BOOL: { - *DataType = SQL_TINYINT; - } break; - - case TSDB_DATA_TYPE_TINYINT: { - *DataType = SQL_TINYINT; - } break; - - case TSDB_DATA_TYPE_SMALLINT: { - *DataType = SQL_SMALLINT; - } break; - - case TSDB_DATA_TYPE_INT: { - *DataType = SQL_INTEGER; - } break; - - case TSDB_DATA_TYPE_BIGINT: { - *DataType = SQL_BIGINT; - } break; - - case TSDB_DATA_TYPE_FLOAT: { - *DataType = SQL_FLOAT; - } break; - - case TSDB_DATA_TYPE_DOUBLE: { - *DataType = SQL_DOUBLE; - } break; - - case TSDB_DATA_TYPE_TIMESTAMP: { - *DataType = SQL_TIMESTAMP; - if (ColumnSize) *ColumnSize = sizeof(SQL_TIMESTAMP_STRUCT); - if (DecimalDigits) *DecimalDigits = 0; - } break; - - case TSDB_DATA_TYPE_NCHAR: { - *DataType = SQL_CHAR; // unicode ? - if (ColumnSize) *ColumnSize -= VARSTR_HEADER_SIZE; - } break; - - case TSDB_DATA_TYPE_BINARY: { - *DataType = SQL_CHAR; - if (ColumnSize) *ColumnSize -= VARSTR_HEADER_SIZE; - } break; - - default: - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, - "unknown [%s[%d/0x%x]]", taos_data_type(field->type), field->type, field->type); - return SQL_ERROR; - break; - } - } - if (Nullable) { - *Nullable = SQL_NULLABLE_UNKNOWN; - } - - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLDescribeCol(SQLHSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLCHAR *ColumnName, - SQLSMALLINT BufferLength, SQLSMALLINT *NameLength, - SQLSMALLINT *DataType, SQLULEN *ColumnSize, - SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable) -{ - SQLRETURN r; - r = doSQLDescribeCol(StatementHandle, ColumnNumber, ColumnName, - BufferLength, NameLength, - DataType, ColumnSize, - DecimalDigits, Nullable); - return r; -} - -static SQLRETURN doSQLNumParams(SQLHSTMT hstmt, SQLSMALLINT *pcpar) -{ - sql_t *sql = (sql_t*)hstmt; - if (!sql) return SQL_INVALID_HANDLE; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - if (!sql->stmt) { - SET_ERROR(sql, "HY010", TSDB_CODE_ODBC_STATEMENT_NOT_READY, ""); - return SQL_ERROR; - } - - int insert = 0; - int r = taos_stmt_is_insert(sql->stmt, &insert); - if (r) { - SET_ERROR(sql, "HY000", terrno, ""); - return SQL_ERROR; - } - // if (!insert) { - // SET_ERROR(sql, "HY000", terrno, "taos does not provide count of parameters for statement other than insert"); - // return SQL_ERROR; - // } - - int params = 0; - r = taos_stmt_num_params(sql->stmt, ¶ms); - if (r) { - SET_ERROR(sql, "HY000", terrno, "fetch num of statement params failed"); - return SQL_ERROR; - } - - if (pcpar) *pcpar = (SQLSMALLINT)params; - - return SQL_SUCCESS; -} - -SQLRETURN SQL_API SQLNumParams(SQLHSTMT hstmt, SQLSMALLINT *pcpar) -{ - SQLRETURN r; - r = doSQLNumParams(hstmt, pcpar); - return r; -} - -static SQLRETURN doSQLSetStmtAttr(SQLHSTMT StatementHandle, - SQLINTEGER Attribute, SQLPOINTER Value, - SQLINTEGER StringLength) -{ - sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_INVALID_HANDLE; - - CHK_CONN(sql); - CHK_CONN_TAOS(sql); - - if (!sql->stmt) { - SET_ERROR(sql, "HY010", TSDB_CODE_ODBC_STATEMENT_NOT_READY, ""); - return SQL_ERROR; - } - - if (sql->is_executed) { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, "change attr after executing statement not supported yet"); - return SQL_ERROR; - } - - switch (Attribute) { - case SQL_ATTR_PARAM_BIND_TYPE: { - SQLULEN val = (SQLULEN)Value; - if (val==SQL_BIND_BY_COLUMN) { - sql->rowlen = 0; - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, "SQL_ATTR_PARAM_BIND_TYPE/SQL_BIND_BY_COLUMN"); - return SQL_ERROR; - } - sql->rowlen = val; - return SQL_SUCCESS; - } break; - case SQL_ATTR_PARAMSET_SIZE: { - SQLULEN val = (SQLULEN)Value; - DASSERT(val>0); - sql->n_rows = val; - return SQL_SUCCESS; - } break; - case SQL_ATTR_PARAM_BIND_OFFSET_PTR: { - if (Value) { - SQLULEN val = *(SQLULEN*)Value; - sql->ptr_offset = val; - } else { - sql->ptr_offset = 0; - } - return SQL_SUCCESS; - } break; - default: { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, "Attribute:%d", Attribute); - } break; - } - return SQL_ERROR; -} - -SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle, - SQLINTEGER Attribute, SQLPOINTER Value, - SQLINTEGER StringLength) -{ - SQLRETURN r; - r = doSQLSetStmtAttr(StatementHandle, Attribute, Value, StringLength); - return r; -} - -#ifdef _MSC_VER - -#define POST_INSTALLER_ERROR(hwndParent, code, fmt, ...) \ -do { \ - char buf[4096]; \ - snprintf(buf, sizeof(buf), "%s[%d]%s():" fmt "", \ - basename((char*)__FILE__), __LINE__, __func__, \ - ##__VA_ARGS__); \ - SQLPostInstallerError(code, buf); \ - if (hwndParent) { \ - MessageBox(hwndParent, buf, "Error", MB_OK|MB_ICONEXCLAMATION); \ - } \ -} while (0) - -typedef struct kv_s kv_t; -struct kv_s { - char *line; - size_t val; -}; - -static BOOL get_driver_dll_path(HWND hwndParent, char *buf, size_t len) -{ - HMODULE hm = NULL; - - if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - (LPCSTR) &ConfigDSN, &hm) == 0) - { - int ret = GetLastError(); - POST_INSTALLER_ERROR(hwndParent, ODBC_ERROR_REQUEST_FAILED, "GetModuleHandle failed, error = %d\n", ret); - return FALSE; - } - if (GetModuleFileName(hm, buf, (DWORD)len) == 0) - { - int ret = GetLastError(); - POST_INSTALLER_ERROR(hwndParent, ODBC_ERROR_REQUEST_FAILED, "GetModuleFileName failed, error = %d\n", ret); - return FALSE; - } - return TRUE; -} - -static BOOL doDSNAdd(HWND hwndParent, LPCSTR lpszDriver, LPCSTR lpszAttributes) -{ - BOOL r = TRUE; - - kv_t *kvs = NULL; - - kv_t dsn = {0}; - char *line = NULL; - - do { - char driver_dll[MAX_PATH + 1]; - r = get_driver_dll_path(hwndParent, driver_dll, sizeof(driver_dll)); - if (!r) break; - - dsn.line = strdup("DSN=TAOS_DEMO"); - if (!dsn.line) { r = FALSE; break; } - - const char *p = lpszAttributes; - int ikvs = 0; - while (p && *p) { - line = strdup(p); - if (!line) { r = FALSE; break; } - char *v = strchr(line, '='); - if (!v) { r = FALSE; break; } - - if (strstr(line, "DSN")==line) { - if (dsn.line) { - free(dsn.line); - dsn.line = NULL; - dsn.val = 0; - } - dsn.line = line; - line = NULL; - } else { - kv_t *t = (kv_t*)realloc(kvs, (ikvs+1)*sizeof(*t)); - if (!t) { r = FALSE; free(line); break; } - t[ikvs].line = line; - *v = '\0'; - if (v) t[ikvs].val = v - line + 1; - line = NULL; - - kvs = t; - ++ikvs; - } - - p += strlen(p) + 1; - } - - if (hwndParent) { - MessageBox(hwndParent, "Please use odbcconf to add DSN for TAOS ODBC Driver", "Warning!", MB_OK|MB_ICONEXCLAMATION); - } - if (!r) break; - - char *v = NULL; - v = strchr(dsn.line, '='); - if (!v) { r = FALSE; break; } - *v = '\0'; - dsn.val = v - dsn.line + 1; - - if ((!dsn.line)) { - if (!r) POST_INSTALLER_ERROR(hwndParent, ODBC_ERROR_REQUEST_FAILED, "lack of either DSN or Driver"); - } else { - if (r) r = SQLWritePrivateProfileString("ODBC Data Sources", dsn.line+dsn.val, lpszDriver, "Odbc.ini"); - if (r) r = SQLWritePrivateProfileString(dsn.line+dsn.val, "Driver", driver_dll, "Odbc.ini"); - } - - for (int i=0; r && itype) { - case TSDB_DATA_TYPE_TINYINT: - return 5; - break; - - case TSDB_DATA_TYPE_SMALLINT: - return 7; - break; - - case TSDB_DATA_TYPE_INT: - return 12; - break; - - case TSDB_DATA_TYPE_BIGINT: - return 22; - break; - - case TSDB_DATA_TYPE_FLOAT: { - return 12; - } break; - - case TSDB_DATA_TYPE_DOUBLE: { - return 20; - } break; - - case TSDB_DATA_TYPE_BINARY: - case TSDB_DATA_TYPE_NCHAR: { - return 3*((size_t)field->bytes - VARSTR_HEADER_SIZE) + 2; - } break; - - case TSDB_DATA_TYPE_TIMESTAMP: - return 26; - break; - - case TSDB_DATA_TYPE_BOOL: - return 7; - default: - break; - } - - return 10; -} - - - diff --git a/src/connector/odbc/src/todbc.def b/src/connector/odbc/src/todbc.def index 1e080f01983ec2b38d657004291008f6da6198dc..2485e5df11490bafd5752e7fc3670ce09d47095a 100644 --- a/src/connector/odbc/src/todbc.def +++ b/src/connector/odbc/src/todbc.def @@ -3,13 +3,19 @@ SQLAllocEnv SQLFreeEnv SQLAllocConnect SQLFreeConnect +SQLGetEnvAttr +SQLSetEnvAttr +SQLGetConnectAttr +SQLGetConnectOption +SQLGetInfo SQLConnect SQLDisconnect SQLAllocStmt SQLAllocHandle +SQLFreeHandle SQLFreeStmt SQLExecDirect -SQLExecDirectW +;SQLExecDirectW SQLNumResultCols SQLRowCount SQLColAttribute @@ -17,14 +23,45 @@ SQLGetData SQLFetch SQLPrepare SQLExecute -SQLGetDiagField +SQLParamData +SQLPutData +;SQLGetDiagField SQLGetDiagRec SQLBindParameter +SQLDescribeParam SQLDriverConnect SQLSetConnectAttr SQLDescribeCol +SQLBindCol SQLNumParams SQLSetStmtAttr +SQLBindParam +SQLCancel +SQLCancelHandle +SQLCloseCursor +SQLColumns +SQLCopyDesc +SQLDataSources +SQLEndTran +;SQLError +SQLFetchScroll +SQLGetCursorName +SQLGetDescField +SQLGetDescRec +;SQLGetFunctions +SQLGetStmtAttr +SQLGetStmtOption +SQLGetTypeInfo +SQLSetConnectOption +SQLSetCursorName +SQLSetDescField +SQLSetDescRec +SQLSetParam +SQLSetStmtOption +SQLSpecialColumns +SQLStatistics +SQLTables +SQLTransact ConfigDSN ConfigTranslator ConfigDriver diff --git a/src/connector/odbc/src/todbc_buf.c b/src/connector/odbc/src/todbc_buf.c new file mode 100644 index 0000000000000000000000000000000000000000..1fce74299c53977359437dd1e43eba1f57eab936 --- /dev/null +++ b/src/connector/odbc/src/todbc_buf.c @@ -0,0 +1,410 @@ +/* + * 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 . + */ + +#include "todbc_buf.h" + +#include "todbc_list.h" +#include "todbc_log.h" +#include "todbc_tls.h" + +#include +#include + +#define BLOCK_SIZE (1024*16) + +// alignment for holding whatever struct would be +#define ALIGN(size) ((size==0?1:size) + sizeof(size_t) - 1) / sizeof(size_t) * sizeof(size_t); + +typedef struct buf_rec_s buf_rec_t; +typedef struct buf_block_s buf_block_t; + +struct buf_rec_s { + size_t size; // payload size couting from ptr[0] + buf_block_t *owner; + char ptr[0]; // place-holder +}; + +#define PTR_OFFSET() ((size_t)(((buf_rec_t*)0)->ptr)) + +struct buf_block_s { + todbc_buf_t *owner; + size_t cap; // total payload space available for allocation + size_t ptr; // beginning of free space + char base[0]; // place-holder +}; + +#define BASE_OFFSET() ((size_t)(((buf_block_t*)0)->base)) + +struct todbc_buf_s { + char buf[BLOCK_SIZE]; + buf_block_t *block; // mapped to &buf[0] + todbc_list_t *list; // dynamic allocated blocks list +}; + +#define BASE_STATIC(block) (block->owner->buf + BASE_OFFSET()==block->base) + + +typedef struct arg_s arg_t; +struct arg_s { + todbc_buf_t *buf; + + // input + char *arg_ptr; + size_t arg_size; + buf_rec_t *arg_rec; + size_t arg_align; + + // output + buf_rec_t *rec; +}; + +static buf_rec_t* ptr_rec(todbc_buf_t *buf, void *ptr) { + char *p = (char*)ptr; + char *begin = p-PTR_OFFSET(); + buf_rec_t *rec = (buf_rec_t*)begin; + OILE(rec, ""); + OILE(rec->size, ""); + OILE((rec->size)%sizeof(void*)==0, ""); + buf_block_t *block = rec->owner; + OILE(block, ""); + OILE(block->owner==buf, ""); + OILE(block->base, ""); + + char *end = begin + sizeof(buf_rec_t) + rec->size; + OILE(begin>=block->base, ""); + OILE(end<=block->base+block->ptr, ""); + + return rec; +} + +static buf_block_t* buf_block_create(size_t align); +static buf_rec_t* buf_block_realloc(buf_block_t *block, arg_t *arg); +static void buf_block_free(buf_block_t *block); +static void buf_block_reclaim(buf_block_t *block); + +#define ALLOC_LIST() do { \ + if (buf->list) break; \ + todbc_list_conf_t conf = {0}; \ + conf.arg = buf; \ + conf.val_free = do_free_buf_block; \ + buf->list = todbc_list_create(conf); \ +} while (0) + + +todbc_buf_t* todbc_buf_create(void) { + todbc_buf_t *buf = (todbc_buf_t*)calloc(1, sizeof(*buf)); + if (!buf) return NULL; + + buf_block_t *block = (buf_block_t*)(buf->buf); + + block->owner = buf; + block->cap = sizeof(buf->buf) - sizeof(buf_block_t); + block->ptr = 0; + + buf->block = block; + + OILE(BASE_STATIC(buf->block), ""); + + return buf; +} + +void todbc_buf_free(todbc_buf_t *buf) { + if (!buf) return; + + todbc_list_free(buf->list); + buf->list = NULL; + + free(buf); +} + +void* todbc_buf_alloc(todbc_buf_t *buf, size_t size) { + return todbc_buf_realloc(buf, NULL, size); +} + +void* todbc_buf_calloc(todbc_buf_t *buf, size_t count, size_t size) { + size_t align = ALIGN(size); + size_t total = count * align; + if (total > INT64_MAX) return NULL; + void *ptr = todbc_buf_realloc(buf, NULL, total); + if (!ptr) return NULL; + memset(ptr, 0, total); + return ptr; +} + +static void do_free_buf_block(todbc_list_t *list, void *val, void *arg); + +static int alloc_space_by(todbc_list_t *list, void *val, void *arg); + +void* todbc_buf_realloc(todbc_buf_t *buf, void *ptr, size_t size) { + OILE(buf, ""); + OILE(sizeof(buf_block_t)%sizeof(void*)==0, ""); + OILE(sizeof(buf_rec_t)%sizeof(void*)==0, ""); + + size_t align = ALIGN(size); + size_t req_size = align + sizeof(buf_rec_t); + + buf_rec_t *rec = NULL; + buf_block_t *block = NULL; + if (ptr) { + rec = ptr_rec(buf, ptr); + if (align<=rec->size) return ptr; + + block = rec->owner; + char *tail_rec = rec->ptr + rec->size; + char *tail_block = block->base + block->ptr; + if (tail_rec==tail_block) { + char *end_rec = rec->ptr + align; + char *end_block = block->base + block->cap; + if (end_rec<=end_block) { + rec->size = align; + block->ptr = (size_t)(end_rec - block->base); + return ptr; + } + } else { + size_t remain = block->cap - block->ptr; + if (req_size<=remain) { + char *new_ptr = block->base + block->ptr; + block->ptr += req_size; + buf_rec_t *new_rec = (buf_rec_t*)new_ptr; + new_rec->size = align; + new_rec->owner = block; + memcpy(new_rec->ptr, ptr, rec->size); + return new_rec->ptr; + } + } + } + + arg_t arg = {0}; + arg.buf = buf; + arg.arg_ptr = ptr; + arg.arg_size = size; + arg.arg_rec = rec; + arg.arg_align = align; + + if (block!=buf->block) { + buf_rec_t *new_rec = buf_block_realloc(buf->block, &arg); + if (new_rec) return new_rec->ptr; + } + + ALLOC_LIST(); + if (!buf->list) return NULL; + + int r = todbc_list_traverse(buf->list, alloc_space_by, &arg); + if (r) { + OILE(arg.rec, ""); + OILE(arg.rec->ptr, ""); + return arg.rec->ptr; + } + + block = buf_block_create(arg.arg_align); + if (!block) return NULL; + OILE(block->owner==NULL, ""); + r = todbc_list_pushfront(buf->list, block); + OILE(r==0, ""); + block->owner = buf; + buf_rec_t *p = buf_block_realloc(block, &arg); + OILE(p, ""); + + return p->ptr; +} + +static int do_reclaim(todbc_list_t *list, void *val, void *arg); + +void todbc_buf_reclaim(todbc_buf_t *buf) { + if (!buf) return; + + buf_block_reclaim(buf->block); + + if (!buf->list) return; + + todbc_list_traverse(buf->list, do_reclaim, buf); +} + +static int do_reclaim(todbc_list_t *list, void *val, void *arg) { + todbc_buf_t *buf = (todbc_buf_t*)arg; + buf_block_t *block = (buf_block_t*)val; + OILE(list, ""); + OILE(block, ""); + OILE(block->owner==buf, ""); + buf_block_reclaim(block); + return 0; +} + +static void buf_block_reclaim(buf_block_t *block) { + block->ptr = 0; +} + +static void buf_block_free(buf_block_t *block) { + if (!block) return; + + buf_block_reclaim(block); + + if (BASE_STATIC(block)) return; + + block->owner = NULL; + block->cap = 0; + block->ptr = 0; + + free(block); +} + +static void do_free_buf_block(todbc_list_t *list, void *val, void *arg) { + todbc_buf_t *buf = (todbc_buf_t*)arg; + OILE(buf && buf->list==list, ""); + buf_block_t *block = (buf_block_t*)val; + OILE(block, ""); + OILE(buf==block->owner, ""); + + buf_block_free(block); +} + +static int alloc_space_by(todbc_list_t *list, void *val, void *arg) { + buf_block_t *block = (buf_block_t*)val; + arg_t *targ = (arg_t*)arg; + + buf_rec_t *rec = targ->arg_rec; + if (rec && rec->owner == block) return 0; + + buf_rec_t *new_rec = buf_block_realloc(block, targ); + if (!new_rec) return 0; + return 1; +} + +static buf_block_t* buf_block_create(size_t size) { + size_t align = ALIGN(size); + size_t req_size = sizeof(buf_block_t) + sizeof(buf_rec_t) + align; + req_size = (req_size + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE; + + buf_block_t *block = (buf_block_t*)malloc(req_size); + if (!block) return NULL; + + block->owner = NULL; + block->cap = req_size - sizeof(buf_block_t); + block->ptr = 0; + + return block; +} + +static buf_rec_t* buf_block_realloc(buf_block_t *block, arg_t *arg) { + OILE(block, ""); + OILE(arg, ""); + OILE(block->base, ""); + OILE(block->cap >= block->ptr, ""); + + char *ptr = arg->arg_ptr; + buf_rec_t *rec = arg->arg_rec; + OILE(rec==NULL || rec->owner!=block, ""); + + size_t align = arg->arg_align; + size_t req_size = sizeof(buf_rec_t) + align; + + OILE(req_size>0, ""); + + size_t remain = block->cap - block->ptr; + if (req_size > remain) { + return NULL; + } + + char *p = block->base + block->ptr; + buf_rec_t *new_rec = (buf_rec_t*)p; + new_rec->size = align; + new_rec->owner = block; + + block->ptr += req_size; + + if (ptr) { + memcpy(new_rec->ptr, ptr, arg->arg_rec->size); + } + + arg->rec = new_rec; + + return new_rec; +} + + + + + + +// test + +void todbc_buf_test_random(size_t iterates, size_t size, int raw) { + size_t n_reallocs = 0; + todbc_buf_t *cache = NULL; + OD("use %s", raw ? "realloc" : "todbc_buf_t"); + if (!raw) { + cache = todbc_buf_create(); + OILE(cache, ""); + } + srand((unsigned)time(0)); + char *buf = NULL; + size_t blen = 0; + while (iterates-- > 0) { + char *p = NULL; + size_t i = 0; + size_t len = (size_t)rand()%size; + if (raw) { + p = realloc(buf, len); + } else { + p = todbc_buf_realloc(cache, buf, len); + } + OILE(p, ""); + for (i=blen; i 0) { + size_t i = 0; + char *buf = NULL; + while (i + * + * 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 . + */ + +#ifndef _todbc_buf_h_ +#define _todbc_buf_h_ + +#include +#include + +// non-thread-safe +typedef struct todbc_buf_s todbc_buf_t; + +todbc_buf_t* todbc_buf_create(void); +void todbc_buf_free(todbc_buf_t *buf); + +void* todbc_buf_alloc(todbc_buf_t *buf, size_t size); +void* todbc_buf_calloc(todbc_buf_t *buf, size_t count, size_t size); +void* todbc_buf_realloc(todbc_buf_t *buf, void *ptr, size_t size); +char* todbc_buf_strdup(todbc_buf_t *buf, const char *str); +void todbc_buf_reclaim(todbc_buf_t *buf); + +void todbc_buf_test_random(size_t iterates, size_t size, int raw); +void todbc_buf_test(size_t iterates, size_t size, int raw); + +#endif // _todbc_buf_h_ + diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c deleted file mode 100644 index 9c0f19764c2b456c63b6d0a01402e37868a0a366..0000000000000000000000000000000000000000 --- a/src/connector/odbc/src/todbc_conv.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * 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 . - */ - -#include "todbc_conv.h" - -#include "todbc_log.h" - -#include -#include -#include -#include -#include - -const char* tsdb_conv_code_str(TSDB_CONV_CODE code) { - switch (code) { - case TSDB_CONV_OK: return "TSDB_CONV_OK"; - case TSDB_CONV_NOT_AVAIL: return "TSDB_CONV_NOT_AVAIL"; - case TSDB_CONV_OOM: return "TSDB_CONV_OOM"; - case TSDB_CONV_OOR: return "TSDB_CONV_OOR"; - case TSDB_CONV_TRUNC_FRACTION: return "TSDB_CONV_TRUNC_FRACTION"; - case TSDB_CONV_TRUNC: return "TSDB_CONV_TRUNC"; - case TSDB_CONV_CHAR_NOT_NUM: return "TSDB_CONV_CHAR_NOT_NUM"; - case TSDB_CONV_CHAR_NOT_TS: return "TSDB_CONV_CHAR_NOT_TS"; - case TSDB_CONV_NOT_VALID_TS: return "TSDB_CONV_NOT_VALID_TS"; - case TSDB_CONV_GENERAL: return "TSDB_CONV_GENERAL"; - case TSDB_CONV_SRC_TOO_LARGE: return "TSDB_CONV_SRC_TOO_LARGE"; - case TSDB_CONV_SRC_BAD_SEQ: return "TSDB_CONV_SRC_BAD_SEQ"; - case TSDB_CONV_SRC_INCOMPLETE: return "TSDB_CONV_SRC_INCOMPLETE"; - case TSDB_CONV_SRC_GENERAL: return "TSDB_CONV_SRC_GENERAL"; - case TSDB_CONV_BAD_CHAR: return "TSDB_CONV_BAD_CHAR"; - default: return "UNKNOWN"; - }; -} - -// src: int -TSDB_CONV_CODE tsdb_int64_to_bit(int64_t src, int8_t *dst) { - *dst = (int8_t)src; - if (src==0 || src==1) return TSDB_CONV_OK; - return TSDB_CONV_OOR; -} - -TSDB_CONV_CODE tsdb_int64_to_tinyint(int64_t src, int8_t *dst) { - *dst = (int8_t)src; - if (src == *dst) return TSDB_CONV_OK; - return TSDB_CONV_OOR; -} - -TSDB_CONV_CODE tsdb_int64_to_smallint(int64_t src, int16_t *dst) { - *dst = (int16_t)src; - if (src == *dst) return TSDB_CONV_OK; - return TSDB_CONV_OOR; -} - -TSDB_CONV_CODE tsdb_int64_to_int(int64_t src, int32_t *dst) { - *dst = (int32_t)src; - if (src == *dst) return TSDB_CONV_OK; - return TSDB_CONV_OOR; -} - -TSDB_CONV_CODE tsdb_int64_to_bigint(int64_t src, int64_t *dst) { - *dst = src; - return TSDB_CONV_OK; -} - -TSDB_CONV_CODE tsdb_int64_to_ts(int64_t src, int64_t *dst) { - *dst = src; - - time_t t = (time_t)(src / 1000); - struct tm tm = {0}; - if (localtime_r(&t, &tm)) return TSDB_CONV_OK; - - return TSDB_CONV_OOR; -} - -TSDB_CONV_CODE tsdb_int64_to_float(int64_t src, float *dst) { - *dst = (float)src; - - int64_t v = (int64_t)*dst; - if (v==src) return TSDB_CONV_OK; - - return TSDB_CONV_OOR; -} - -TSDB_CONV_CODE tsdb_int64_to_double(int64_t src, double *dst) { - *dst = (double)src; - - int64_t v = (int64_t)*dst; - if (v==src) return TSDB_CONV_OK; - - return TSDB_CONV_OOR; -} - -TSDB_CONV_CODE tsdb_int64_to_char(int64_t src, char *dst, size_t dlen) { - int n = snprintf(dst, dlen, "%" PRId64 "", src); - DASSERT(n>=0); - - if (n=2) return TSDB_CONV_OOR; - if (src == *dst) return TSDB_CONV_OK; - - int64_t v = (int64_t)src; - if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; - - return TSDB_CONV_TRUNC; -} - -TSDB_CONV_CODE tsdb_double_to_tinyint(double src, int8_t *dst) { - *dst = (int8_t)src; - - if (srcSCHAR_MAX) return TSDB_CONV_OOR; - if (src == *dst) return TSDB_CONV_OK; - - int64_t v = (int64_t)src; - if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; - - return TSDB_CONV_TRUNC; -} - -TSDB_CONV_CODE tsdb_double_to_smallint(double src, int16_t *dst) { - *dst = (int16_t)src; - - if (srcSHRT_MAX) return TSDB_CONV_OOR; - if (src == *dst) return TSDB_CONV_OK; - - int64_t v = (int64_t)src; - if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; - - return TSDB_CONV_TRUNC; -} - -TSDB_CONV_CODE tsdb_double_to_int(double src, int32_t *dst) { - *dst = (int32_t)src; - - if (srcLONG_MAX) return TSDB_CONV_OOR; - if (src == *dst) return TSDB_CONV_OK; - - int64_t v = (int64_t)src; - if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; - - return TSDB_CONV_TRUNC; -} - -TSDB_CONV_CODE tsdb_double_to_bigint(double src, int64_t *dst) { - *dst = (int64_t)src; - - if (srcLLONG_MAX) return TSDB_CONV_OOR; - if (src == *dst) return TSDB_CONV_OK; - - int64_t v = (int64_t)src; - if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; - - return TSDB_CONV_TRUNC; -} - -TSDB_CONV_CODE tsdb_double_to_ts(double src, int64_t *dst) { - TSDB_CONV_CODE code = tsdb_double_to_bigint(src, dst); - - if (code==TSDB_CONV_OK || code==TSDB_CONV_TRUNC_FRACTION) { - int64_t v = (int64_t)src; - time_t t = (time_t)(v / 1000); - struct tm tm = {0}; - if (localtime_r(&t, &tm)) return TSDB_CONV_OK; - - return TSDB_CONV_OOR; - } - - return code; -} - -TSDB_CONV_CODE tsdb_double_to_char(double src, char *dst, size_t dlen) { - int n = snprintf(dst, dlen, "%lg", src); - DASSERT(n>=0); - - if (n=0); - if (n=19) return TSDB_CONV_TRUNC_FRACTION; - - return TSDB_CONV_TRUNC; -} - -// src: chars -TSDB_CONV_CODE tsdb_chars_to_bit(const char *src, size_t smax, int8_t *dst) { - if (strcmp(src, "0")==0) { - *dst = 0; - return TSDB_CONV_OK; - } - - if (strcmp(src, "1")==0) { - *dst = 1; - return TSDB_CONV_OK; - } - - double v; - int bytes; - int n = sscanf(src, "%lg%n", &v, &bytes); - - if (n!=1) return TSDB_CONV_CHAR_NOT_NUM; - if (bytes!=strlen(src)) return TSDB_CONV_CHAR_NOT_NUM; - - if (v<0 || v>=2) return TSDB_CONV_OOR; - - return TSDB_CONV_TRUNC_FRACTION; -} - -TSDB_CONV_CODE tsdb_chars_to_tinyint(const char *src, size_t smax, int8_t *dst) { - int64_t v; - TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v); - if (code!=TSDB_CONV_OK) return code; - - *dst = (int8_t)v; - - if (v==*dst) return TSDB_CONV_OK; - - return TSDB_CONV_OOR; -} - -TSDB_CONV_CODE tsdb_chars_to_smallint(const char *src, size_t smax, int16_t *dst) { - int64_t v; - TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v); - if (code!=TSDB_CONV_OK) return code; - - *dst = (int16_t)v; - - if (v==*dst) return TSDB_CONV_OK; - - return TSDB_CONV_OOR; -} - -TSDB_CONV_CODE tsdb_chars_to_int(const char *src, size_t smax, int32_t *dst) { - int64_t v; - TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v); - if (code!=TSDB_CONV_OK) return code; - - *dst = (int32_t)v; - - if (v==*dst) return TSDB_CONV_OK; - - return TSDB_CONV_OOR; -} - -TSDB_CONV_CODE tsdb_chars_to_bigint(const char *src, size_t smax, int64_t *dst) { - int bytes; - int n = sscanf(src, "%" PRId64 "%n", dst, &bytes); - - if (n!=1) return TSDB_CONV_CHAR_NOT_NUM; - if (bytes==strlen(src)) { - return TSDB_CONV_OK; - } - - double v; - n = sscanf(src, "%lg%n", &v, &bytes); - if (n!=1) return TSDB_CONV_CHAR_NOT_NUM; - if (bytes==strlen(src)) { - return TSDB_CONV_TRUNC_FRACTION; - } - - return TSDB_CONV_OK; -} - -TSDB_CONV_CODE tsdb_chars_to_ts(const char *src, size_t smax, int64_t *dst) { - int64_t v; - TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v); - if (code!=TSDB_CONV_OK) return code; - - *dst = v; - - if (v==*dst) { - time_t t = (time_t)(v / 1000); - struct tm tm = {0}; - if (localtime_r(&t, &tm)) return TSDB_CONV_OK; - } - - return TSDB_CONV_OOR; -} - -TSDB_CONV_CODE tsdb_chars_to_float(const char *src, size_t smax, float *dst) { - int bytes; - int n = sscanf(src, "%g%n", dst, &bytes); - - if (n==1 && bytes==strlen(src)) { - return TSDB_CONV_OK; - } - - return TSDB_CONV_CHAR_NOT_NUM; -} - -TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst) { - int bytes; - int n = sscanf(src, "%lg%n", dst, &bytes); - - if (n==1 && bytes==strlen(src)) { - return TSDB_CONV_OK; - } - - return TSDB_CONV_CHAR_NOT_NUM; -} - -TSDB_CONV_CODE tsdb_chars_to_timestamp(const char *src, size_t smax, SQL_TIMESTAMP_STRUCT *dst) { - int64_t v = 0; - // why cast to 'char*' ? - int r = taosParseTime((char*)src, &v, (int32_t)smax, TSDB_TIME_PRECISION_MILLI, 0); - - if (r) { - return TSDB_CONV_CHAR_NOT_TS; - } - - time_t t = v/1000; - struct tm vtm = {0}; - localtime_r(&t, &vtm); - dst->year = (SQLSMALLINT)(vtm.tm_year + 1900); - dst->month = (SQLUSMALLINT)(vtm.tm_mon + 1); - dst->day = (SQLUSMALLINT)(vtm.tm_mday); - dst->hour = (SQLUSMALLINT)(vtm.tm_hour); - dst->minute = (SQLUSMALLINT)(vtm.tm_min); - dst->second = (SQLUSMALLINT)(vtm.tm_sec); - dst->fraction = (SQLUINTEGER)(v%1000 * 1000000); - - return TSDB_CONV_OK; -} - -TSDB_CONV_CODE tsdb_chars_to_timestamp_ts(const char *src, size_t smax, int64_t *dst) { - // why cast to 'char*' ? - int r = taosParseTime((char*)src, dst, (int32_t)smax, TSDB_TIME_PRECISION_MILLI, 0); - - if (r) { - return TSDB_CONV_CHAR_NOT_TS; - } - - return TSDB_CONV_OK; -} - -TSDB_CONV_CODE tsdb_chars_to_char(const char *src, size_t smax, char *dst, size_t dmax) { - int n = snprintf(dst, dmax, "%s", src); - DASSERT(n>=0); - if (nnext + bytes; - if (next>sizeof(buffer->buf)) return NULL; - - char *p = buffer->buf + buffer->next; - buffer->next = next; - return p; -} - -int is_owned_by_stack_buffer(stack_buffer_t *buffer, const char *ptr) { - if (!buffer) return 0; - if (ptr>=buffer->buf && ptrbuf+buffer->next) return 1; - return 0; -} - - -struct tsdb_conv_s { - iconv_t cnv; - unsigned int direct:1; -}; - -static tsdb_conv_t no_conversion = {0}; -static pthread_once_t once = PTHREAD_ONCE_INIT; -static void once_init(void) { - no_conversion.cnv = (iconv_t)-1; - no_conversion.direct = 1; -} - -tsdb_conv_t* tsdb_conv_direct() { // get a non-conversion-converter - pthread_once(&once, once_init); - return &no_conversion; -} - -tsdb_conv_t* tsdb_conv_open(const char *from_enc, const char *to_enc) { - pthread_once(&once, once_init); - tsdb_conv_t *cnv = (tsdb_conv_t*)calloc(1, sizeof(*cnv)); - if (!cnv) return NULL; - if (strcmp(from_enc, to_enc)==0 && 0) { - cnv->cnv = (iconv_t)-1; - cnv->direct = 1; - return cnv; - } - cnv->cnv = iconv_open(to_enc, from_enc); - if (cnv->cnv == (iconv_t)-1) { - free(cnv); - return NULL; - } - cnv->direct = 0; - return cnv; -} - -void tsdb_conv_close(tsdb_conv_t *cnv) { - if (!cnv) return; - if (cnv == &no_conversion) return; - if (!cnv->direct) { - if (cnv->cnv != (iconv_t)-1) { - iconv_close(cnv->cnv); - } - } - cnv->cnv = (iconv_t)-1; - cnv->direct = 0; - free(cnv); -} - -TSDB_CONV_CODE tsdb_conv_write(tsdb_conv_t *cnv, const char *src, size_t *slen, char *dst, size_t *dlen) { - if (!cnv) return TSDB_CONV_NOT_AVAIL; - if (cnv->direct) { - size_t n = (*slen > *dlen) ? *dlen : *slen; - memcpy(dst, src, n); - *slen -= n; - *dlen -= n; - if (*dlen) dst[n] = '\0'; - return TSDB_CONV_OK; - } - if (!cnv->cnv) return TSDB_CONV_NOT_AVAIL; - size_t r = iconv(cnv->cnv, (char**)&src, slen, &dst, dlen); - if (r==(size_t)-1) return TSDB_CONV_BAD_CHAR; - if (*slen) return TSDB_CONV_TRUNC; - if (*dlen) *dst = '\0'; - return TSDB_CONV_OK; -} - -TSDB_CONV_CODE tsdb_conv_write_int64(tsdb_conv_t *cnv, int64_t val, char *dst, size_t *dlen) { - char utf8[64]; - int n = snprintf(utf8, sizeof(utf8), "%" PRId64 "", val); - DASSERT(n>=0); - DASSERT(n=0); - DASSERT(n=0); - DASSERT(ndirect) { - if (src[slen]=='\0') { // access violation? - *dst = src; - if (dlen) *dlen = slen; - return TSDB_CONV_OK; - } - blen = slen + 1; - } else { - blen = (slen + 1) * 4; - } - - buf = stack_buffer_alloc(buffer, blen); - if (!buf) { - buf = (char*)malloc(blen); - if (!buf) return TSDB_CONV_OOM; - } - - if (cnv->direct) { - size_t n = slen; - DASSERT(blen > n); - memcpy(buf, src, n); - buf[n] = '\0'; - *dst = buf; - if (dlen) *dlen = n; - return TSDB_CONV_OK; - } - - const char *orig_s = src; - char *orig_d = buf; - size_t orig_blen = blen; - - TSDB_CONV_CODE code; - size_t r = iconv(cnv->cnv, (char**)&src, &slen, &buf, &blen); - do { - if (r==(size_t)-1) { - switch(errno) { - case E2BIG: { - code = TSDB_CONV_SRC_TOO_LARGE; - } break; - case EILSEQ: { - code = TSDB_CONV_SRC_BAD_SEQ; - } break; - case EINVAL: { - code = TSDB_CONV_SRC_INCOMPLETE; - } break; - default: { - code = TSDB_CONV_SRC_GENERAL; - } break; - } - break; - } - if (slen) { - code = TSDB_CONV_TRUNC; - break; - } - DASSERT(blen); - *buf = '\0'; - *dst = orig_d; - if (dlen) *dlen = orig_blen - blen; - return TSDB_CONV_OK; - } while (0); - - if (orig_d!=(char*)orig_s && !is_owned_by_stack_buffer(buffer, orig_d)) free(orig_d); - return code; -} - -void tsdb_conv_free(tsdb_conv_t *cnv, const char *ptr, stack_buffer_t *buffer, const char *src) { - if (ptr!=src && !is_owned_by_stack_buffer(buffer, ptr)) free((char*)ptr); -} - diff --git a/src/connector/odbc/src/todbc_conv.h b/src/connector/odbc/src/todbc_conv.h deleted file mode 100644 index 2941f3e4961d38ed1e72bfd3d1184d1ea8de251b..0000000000000000000000000000000000000000 --- a/src/connector/odbc/src/todbc_conv.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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 . - */ - -#ifndef _todbc_conv_h_ -#define _todbc_conv_h_ - -#include "os.h" -#include -#include - - -typedef enum { - TSDB_CONV_OK = 0, - TSDB_CONV_NOT_AVAIL, - TSDB_CONV_OOM, - TSDB_CONV_OOR, - TSDB_CONV_TRUNC_FRACTION, - TSDB_CONV_TRUNC, - TSDB_CONV_CHAR_NOT_NUM, - TSDB_CONV_CHAR_NOT_TS, - TSDB_CONV_NOT_VALID_TS, - TSDB_CONV_GENERAL, - TSDB_CONV_BAD_CHAR, - TSDB_CONV_SRC_TOO_LARGE, - TSDB_CONV_SRC_BAD_SEQ, - TSDB_CONV_SRC_INCOMPLETE, - TSDB_CONV_SRC_GENERAL, -} TSDB_CONV_CODE; - -const char* tsdb_conv_code_str(TSDB_CONV_CODE code); - -typedef struct stack_buffer_s stack_buffer_t; -struct stack_buffer_s { - char buf[1024*16]; - size_t next; -}; - -char* stack_buffer_alloc(stack_buffer_t *buffer, size_t bytes); -int is_owned_by_stack_buffer(stack_buffer_t *buffer, const char *ptr); - -typedef struct tsdb_conv_s tsdb_conv_t; -tsdb_conv_t* tsdb_conv_direct(); // get a non-conversion-converter -tsdb_conv_t* tsdb_conv_open(const char *from_enc, const char *to_enc); -void tsdb_conv_close(tsdb_conv_t *cnv); - -TSDB_CONV_CODE tsdb_conv_write(tsdb_conv_t *cnv, const char *src, size_t *slen, char *dst, size_t *dlen); -TSDB_CONV_CODE tsdb_conv_write_int64(tsdb_conv_t *cnv, int64_t val, char *dst, size_t *dlen); -TSDB_CONV_CODE tsdb_conv_write_double(tsdb_conv_t *cnv, double val, char *dst, size_t *dlen); -TSDB_CONV_CODE tsdb_conv_write_timestamp(tsdb_conv_t *cnv, SQL_TIMESTAMP_STRUCT val, char *dst, size_t *dlen); - -TSDB_CONV_CODE tsdb_conv_chars_to_bit(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int8_t *dst); -TSDB_CONV_CODE tsdb_conv_chars_to_tinyint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int8_t *dst); -TSDB_CONV_CODE tsdb_conv_chars_to_smallint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int16_t *dst); -TSDB_CONV_CODE tsdb_conv_chars_to_int(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int32_t *dst); -TSDB_CONV_CODE tsdb_conv_chars_to_bigint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst); -TSDB_CONV_CODE tsdb_conv_chars_to_ts(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst); -TSDB_CONV_CODE tsdb_conv_chars_to_float(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, float *dst); -TSDB_CONV_CODE tsdb_conv_chars_to_double(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, double *dst); -TSDB_CONV_CODE tsdb_conv_chars_to_timestamp(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, SQL_TIMESTAMP_STRUCT *dst); -TSDB_CONV_CODE tsdb_conv_chars_to_timestamp_ts(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst); -TSDB_CONV_CODE tsdb_conv(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, const char **dst, size_t *dlen); -void tsdb_conv_free(tsdb_conv_t *cnv, const char *ptr, stack_buffer_t *buffer, const char *src); - - -TSDB_CONV_CODE tsdb_int64_to_bit(int64_t src, int8_t *dst); -TSDB_CONV_CODE tsdb_int64_to_tinyint(int64_t src, int8_t *dst); -TSDB_CONV_CODE tsdb_int64_to_smallint(int64_t src, int16_t *dst); -TSDB_CONV_CODE tsdb_int64_to_int(int64_t src, int32_t *dst); -TSDB_CONV_CODE tsdb_int64_to_bigint(int64_t src, int64_t *dst); -TSDB_CONV_CODE tsdb_int64_to_ts(int64_t src, int64_t *dst); -TSDB_CONV_CODE tsdb_int64_to_float(int64_t src, float *dst); -TSDB_CONV_CODE tsdb_int64_to_double(int64_t src, double *dst); -TSDB_CONV_CODE tsdb_int64_to_char(int64_t src, char *dst, size_t dlen); - -TSDB_CONV_CODE tsdb_double_to_bit(double src, int8_t *dst); -TSDB_CONV_CODE tsdb_double_to_tinyint(double src, int8_t *dst); -TSDB_CONV_CODE tsdb_double_to_smallint(double src, int16_t *dst); -TSDB_CONV_CODE tsdb_double_to_int(double src, int32_t *dst); -TSDB_CONV_CODE tsdb_double_to_bigint(double src, int64_t *dst); -TSDB_CONV_CODE tsdb_double_to_ts(double src, int64_t *dst); -TSDB_CONV_CODE tsdb_double_to_char(double src, char *dst, size_t dlen); - -TSDB_CONV_CODE tsdb_timestamp_to_char(SQL_TIMESTAMP_STRUCT src, char *dst, size_t dlen); - -TSDB_CONV_CODE tsdb_chars_to_bit(const char *src, size_t smax, int8_t *dst); -TSDB_CONV_CODE tsdb_chars_to_tinyint(const char *src, size_t smax, int8_t *dst); -TSDB_CONV_CODE tsdb_chars_to_smallint(const char *src, size_t smax, int16_t *dst); -TSDB_CONV_CODE tsdb_chars_to_int(const char *src, size_t smax, int32_t *dst); -TSDB_CONV_CODE tsdb_chars_to_bigint(const char *src, size_t smax, int64_t *dst); -TSDB_CONV_CODE tsdb_chars_to_ts(const char *src, size_t smax, int64_t *dst); -TSDB_CONV_CODE tsdb_chars_to_float(const char *src, size_t smax, float *dst); -TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst); -TSDB_CONV_CODE tsdb_chars_to_timestamp(const char *src, size_t smax, SQL_TIMESTAMP_STRUCT *dst); -TSDB_CONV_CODE tsdb_chars_to_char(const char *src, size_t smax, char *dst, size_t dmax); - -#endif // _todbc_conv_h_ - diff --git a/src/connector/odbc/src/todbc_flex.h b/src/connector/odbc/src/todbc_flex.h index a13f1f4d2ebd8bbca73d9ff224bb3ed20ed43174..762ffba0bec7bcfd47f45ad4475d08f20dc2375a 100644 --- a/src/connector/odbc/src/todbc_flex.h +++ b/src/connector/odbc/src/todbc_flex.h @@ -16,16 +16,40 @@ #ifndef _TODBC_FLEX_H_ #define _TODBC_FLEX_H_ +#include +#include + +// TSDB predefined field types +// TINYINT SMALLINT INT BIGINT FLOAT DOUBLE BOOL TIMESTAMP BINARY NCHAR + +typedef struct map_tsdb_type_s map_tsdb_type_t; +struct map_tsdb_type_s { + SQLSMALLINT tsdb_tinyint; + SQLSMALLINT tsdb_smallint; + SQLSMALLINT tsdb_int; + SQLSMALLINT tsdb_bigint; + SQLULEN tsdb_bigint_size; + SQLSMALLINT tsdb_float; + SQLSMALLINT tsdb_double; + SQLSMALLINT tsdb_bool; + SQLSMALLINT tsdb_timestamp; + SQLSMALLINT tsdb_binary; + SQLSMALLINT tsdb_nchar; +}; + typedef struct conn_val_s conn_val_t; struct conn_val_s { - char *key; - char *dsn; - char *uid; - char *pwd; - char *db; - char *server; - char *svr_enc; - char *cli_enc; + char *dsn; + char *uid; + char *pwd; + char *db; + char *server; + char *enc_local; + char *enc_char; + char *enc_wchar; + char *enc_db; + + map_tsdb_type_t tsdb_map; }; diff --git a/src/connector/odbc/src/todbc_hash.c b/src/connector/odbc/src/todbc_hash.c new file mode 100644 index 0000000000000000000000000000000000000000..1f64a490fd2adf5688e320c14d22db8c279c9f98 --- /dev/null +++ b/src/connector/odbc/src/todbc_hash.c @@ -0,0 +1,195 @@ +/* + * 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 . + */ + +#include "todbc_hash.h" + +#include "todbc_list.h" +#include "todbc_log.h" + +#include + +typedef struct todbc_hash_slot_s todbc_hash_slot_t; + +struct todbc_hash_s { + todbc_hash_conf_t conf; + + todbc_hash_slot_t *slots; + size_t n_slots; +}; + +struct todbc_hash_slot_s { + todbc_list_t *list; +}; + +todbc_hash_t* todbc_hash_create(todbc_hash_conf_t conf) { + if (!conf.key_hash) return NULL; + if (!conf.key_comp) return NULL; + if (!conf.val_free) return NULL; + + todbc_hash_t *hash = (todbc_hash_t*)calloc(1, sizeof(*hash)); + if (!hash) return NULL; + + hash->conf = conf; + if (hash->conf.slots==0) { + hash->conf.slots = 33; + } + + hash->slots = (todbc_hash_slot_t*)calloc(hash->conf.slots, sizeof(*hash->slots)); + do { + if (!hash->slots) break; + hash->n_slots = hash->conf.slots; + return hash; + } while (0); + + todbc_hash_free(hash); + return NULL; +} + +void todbc_hash_free(todbc_hash_t *hash) { + if (!hash) return; + for (int i=0; in_slots; ++i) { + todbc_hash_slot_t *slot = hash->slots + i; + if (!slot->list) continue; + todbc_list_free(slot->list); + slot->list = NULL; + } + free(hash->slots); + hash->n_slots = 0; +} + +typedef struct kv_s kv_t; +struct kv_s { + todbc_hash_t *hash; + void *key; + void *val; +}; + +static void do_val_free(todbc_list_t *list, void *val, void *arg) { + todbc_hash_t *hash = (todbc_hash_t*)arg; + DASSERT(list); + DASSERT(hash); + DASSERT(hash->conf.val_free); + hash->conf.val_free(hash, val, hash->conf.arg); +} + +int todbc_hash_put(todbc_hash_t *hash, void *key, void *val) { + if (!hash) return -1; + if (!hash->slots) return -1; + if (!key) return -1; + if (!val) return -1; + + void *old = NULL; + int found = 0; + int r = todbc_hash_get(hash, key, &old, &found); + if (r) return r; + if (found) return -1; + + unsigned long hash_val = hash->conf.key_hash(hash, key); + todbc_hash_slot_t *slot = hash->slots + (hash_val % hash->n_slots); + if (!slot->list) { + todbc_list_conf_t conf = {0}; + conf.arg = hash; + conf.val_free = do_val_free; + + slot->list = todbc_list_create(conf); + if (!slot->list) return -1; + } + + r = todbc_list_pushback(slot->list, val); + + return r; +} + +static int do_comp(todbc_list_t *list, void *old, void *val, void *arg) { + kv_t *kv = (kv_t*)arg; + DASSERT(kv); + DASSERT(kv->hash); + DASSERT(kv->key); + DASSERT(kv->hash->conf.key_comp); + DASSERT(kv->key == val); + int r = kv->hash->conf.key_comp(kv->hash, kv->key, old); + if (r==0) { + kv->val = old; + } + return r; +} + +int todbc_hash_get(todbc_hash_t *hash, void *key, void **val, int *found) { + if (!hash) return -1; + if (!hash->slots) return -1; + if (!key) return -1; + if (!val) return -1; + if (!found) return -1; + + *found = 0; + + unsigned long hash_val = hash->conf.key_hash(hash, key); + todbc_hash_slot_t *slot = hash->slots + (hash_val % hash->n_slots); + if (slot->list) { + kv_t kv = {0}; + kv.hash = hash; + kv.key = key; + kv.val = NULL; + int r = todbc_list_find(slot->list, key, found, do_comp, &kv); + if (*found) { + DASSERT(r==0); + DASSERT(kv.val); + *val = kv.val; + } + return r; + } + + return 0; +} + +int todbc_hash_del(todbc_hash_t *hash, void *key) { + return -1; +} + +typedef struct arg_s arg_t; +struct arg_s { + todbc_hash_t *hash; + void *arg; + int (*iterate)(todbc_hash_t *hash, void *val, void *arg); +}; + +static int do_iterate(todbc_list_t *list, void *val, void *arg); + +int todbc_hash_traverse(todbc_hash_t *hash, int (*iterate)(todbc_hash_t *hash, void *val, void *arg), void *arg) { + if (!hash) return -1; + if (!iterate) return -1; + + for (int i=0; in_slots; ++i) { + todbc_hash_slot_t *slot = hash->slots + i; + if (!slot->list) continue; + arg_t targ = {0}; + targ.hash = hash; + targ.arg = arg; + targ.iterate = iterate; + int r = todbc_list_traverse(slot->list, do_iterate, &targ); + if (r) return r; + } + + return 0; +} + +static int do_iterate(todbc_list_t *list, void *val, void *arg) { + arg_t *targ = (arg_t*)arg; + DASSERT(targ); + DASSERT(targ->iterate); + DASSERT(targ->hash); + return targ->iterate(targ->hash, val, targ->arg); +} + diff --git a/src/connector/odbc/src/todbc_hash.h b/src/connector/odbc/src/todbc_hash.h new file mode 100644 index 0000000000000000000000000000000000000000..9172c8b7f9c79b84f643d25bb317593675e15521 --- /dev/null +++ b/src/connector/odbc/src/todbc_hash.h @@ -0,0 +1,53 @@ +/* + * 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 . + */ + +#ifndef _todbc_hash_h_ +#define _todbc_hash_h_ + + +#include +#include + +// non-thread-safe + +typedef struct todbc_hash_conf_s todbc_hash_conf_t; +typedef struct todbc_hash_s todbc_hash_t; + +typedef void (*hash_val_free_f)(todbc_hash_t *hash, void *val, void *arg); +typedef unsigned long (*hash_key_hash_f)(todbc_hash_t *hash, void *key); +typedef int (*hash_key_comp_f)(todbc_hash_t *hash, void *key, void *val); + +struct todbc_hash_conf_s { + void *arg; + hash_val_free_f val_free; + + hash_key_hash_f key_hash; + hash_key_comp_f key_comp; + + size_t slots; +}; + +todbc_hash_t* todbc_hash_create(todbc_hash_conf_t conf); +void todbc_hash_free(todbc_hash_t *hash); + +// fail if key exists +int todbc_hash_put(todbc_hash_t *hash, void *key, void *val); +int todbc_hash_get(todbc_hash_t *hash, void *key, void **val, int *found); +int todbc_hash_del(todbc_hash_t *hash, void *key); +typedef int (*hash_iterate_f)(todbc_hash_t *hash, void *val, void *arg); +int todbc_hash_traverse(todbc_hash_t *hash, hash_iterate_f iterate, void *arg); + +#endif // _todbc_hash_h_ + diff --git a/src/connector/odbc/src/todbc_iconv.c b/src/connector/odbc/src/todbc_iconv.c new file mode 100644 index 0000000000000000000000000000000000000000..968cc870f81d420484de3361a54e8185901c3f14 --- /dev/null +++ b/src/connector/odbc/src/todbc_iconv.c @@ -0,0 +1,682 @@ +/* + * 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 . + */ + +#include "todbc_iconv.h" + +#include "todbc_hash.h" +#include "todbc_log.h" +#include "todbc_string.h" +#include "todbc_tls.h" + +#define invalid_iconv() ((iconv_t)-1) + +struct todbc_iconvset_s { + todbc_hash_t *iconv_hash; + + todbc_hash_t *enc_hash; +}; + +typedef struct todbc_iconv_key_s todbc_iconv_key_t; +struct todbc_iconv_key_s { + const char *enc_to; + const char *enc_from; +}; + +struct todbc_iconv_s { + char enc_to[64]; + char enc_from[64]; + todbc_iconv_key_t key; + iconv_t cnv; + + todbc_enc_t from; + todbc_enc_t to; + + unsigned int direct:1; +}; + +static void todbc_iconv_free(todbc_iconv_t *val); + +todbc_iconvset_t* todbc_iconvset_create(void) { + todbc_iconvset_t *cnvset = (todbc_iconvset_t*)calloc(1, sizeof(*cnvset)); + if (!cnvset) return NULL; + + return cnvset; +} + +void todbc_iconvset_free(todbc_iconvset_t *cnvset) { + if (!cnvset) return; + if (cnvset->iconv_hash) { + todbc_hash_free(cnvset->iconv_hash); + cnvset->iconv_hash = NULL; + } + if (cnvset->enc_hash) { + todbc_hash_free(cnvset->enc_hash); + cnvset->enc_hash = NULL; + } + free(cnvset); +} + +static void do_iconv_hash_val_free(todbc_hash_t *hash, void *val, void *arg); +static unsigned long do_iconv_hash_key_hash(todbc_hash_t *hash, void *key); +static int do_iconv_hash_key_comp(todbc_hash_t *hash, void *key, void *val); + +static void do_enc_hash_val_free(todbc_hash_t *hash, void *val, void *arg); +static unsigned long do_enc_hash_key_hash(todbc_hash_t *hash, void *key); +static int do_enc_hash_key_comp(todbc_hash_t *hash, void *key, void *val); + +#define CHK(x, y, n) if (strcasecmp(x, y)==0) return n + +#define SET_SIZES(cs, enc, a,b) do { \ + if (strcasecmp(enc->enc, cs)==0) { \ + enc->char_size = a; \ + enc->variable_char_size = b; \ + return; \ + } \ +} while (0) + +static void do_set_sizes(todbc_enc_t *enc) { + if (!enc) return; + + SET_SIZES("ISO-10646-UCS-2", enc, 2, -1); + SET_SIZES("UCS-2", enc, 2, -1); + SET_SIZES("CSUNICODE", enc, 2, -1); + SET_SIZES("UCS-2BE", enc, 2, -1); + SET_SIZES("UNICODE-1-1", enc, 2, -1); + SET_SIZES("UNICODEBIG", enc, 2, -1); + SET_SIZES("CSUNICODE11", enc, 2, -1); + SET_SIZES("UCS-2LE", enc, 2, -1); + SET_SIZES("UNICODELITTLE", enc, 2, -1); + SET_SIZES("UTF-16", enc, 2, -1); + SET_SIZES("UTF-16BE", enc, 2, -1); + SET_SIZES("UTF-16LE", enc, 2, -1); + SET_SIZES("UCS-2-INTERNAL", enc, 2, -1); + SET_SIZES("UCS-2-SWAPPED", enc, 2, -1); + SET_SIZES("ISO-10646-UCS-4", enc, 4, -1); + SET_SIZES("UCS-4", enc, 4, -1); + SET_SIZES("CSUCS4", enc, 4, -1); + SET_SIZES("UCS-4BE", enc, 4, -1); + SET_SIZES("UCS-4LE", enc, 4, -1); + SET_SIZES("UTF-32", enc, 4, -1); + SET_SIZES("UTF-32BE", enc, 4, -1); + SET_SIZES("UTF-32LE", enc, 4, -1); + SET_SIZES("UCS-4-INTERNAL", enc, 4, -1); + SET_SIZES("UCS-4-SWAPPED", enc, 4, -1); + + SET_SIZES("UTF-8", enc, -1, 3); + SET_SIZES("UTF8", enc, -1, 3); + SET_SIZES("UTF-8-MAC", enc, -1, 3); + SET_SIZES("UTF8-MAC", enc, -1, 3); + + SET_SIZES("CN-GB", enc, 2, -1); + SET_SIZES("EUC-CN", enc, 2, -1); + SET_SIZES("EUCCN", enc, 2, -1); + SET_SIZES("GB2312", enc, 2, -1); + SET_SIZES("CSGB2312", enc, 2, -1); + SET_SIZES("GBK", enc, 2, -1); + SET_SIZES("CP936", enc, 2, -1); + SET_SIZES("MS936", enc, 2, -1); + SET_SIZES("WINDOWS-936", enc, 2, -1); + SET_SIZES("GB18030", enc, 2, -1); + + // add more setup here after + + enc->char_size = -1; + enc->variable_char_size = -1; +} + +static int do_get_null_size(const char *enc, int *null_size); + +// static int do_get_unicode_char_size(const char *enc) { +// if (!enc) return -1; +// +// CHK("ISO-10646-UCS-2", enc, 2); +// CHK("UCS-2", enc, 2); +// CHK("CSUNICODE", enc, 2); +// CHK("UCS-2BE", enc, 2); +// CHK("UNICODE-1-1", enc, 2); +// CHK("UNICODEBIG", enc, 2); +// CHK("CSUNICODE11", enc, 2); +// CHK("UCS-2LE", enc, 2); +// CHK("UNICODELITTLE", enc, 2); +// CHK("UTF-16", enc, 2); +// CHK("UTF-16BE", enc, 2); +// CHK("UTF-16LE", enc, 2); +// CHK("UCS-2-INTERNAL", enc, 2); +// CHK("UCS-2-SWAPPED", enc, 2); +// CHK("ISO-10646-UCS-4", enc, 4); +// CHK("UCS-4", enc, 4); +// CHK("CSUCS4", enc, 4); +// CHK("UCS-4BE", enc, 4); +// CHK("UCS-4LE", enc, 4); +// CHK("UTF-32", enc, 4); +// CHK("UTF-32BE", enc, 4); +// CHK("UTF-32LE", enc, 4); +// CHK("UCS-4-INTERNAL", enc, 4); +// CHK("UCS-4-SWAPPED", enc, 4); +// +// return -1; +// } + +todbc_enc_t todbc_iconvset_enc(todbc_iconvset_t *cnvset, const char *enc) { + do { + if (!cnvset) break; + if (!enc) break; + + if (!cnvset->enc_hash) { + todbc_hash_conf_t conf = {0}; + conf.arg = cnvset; + conf.val_free = do_enc_hash_val_free; + conf.key_hash = do_enc_hash_key_hash; + conf.key_comp = do_enc_hash_key_comp; + conf.slots = 7; + cnvset->enc_hash = todbc_hash_create(conf); + if (!cnvset->enc_hash) break; + } + + void *old = NULL; + int found = 0; + int r = todbc_hash_get(cnvset->enc_hash, (void*)enc, &old, &found); + if (r) { + DASSERT(found==0); + DASSERT(old==NULL); + break; + } + + if (found) { + DASSERT(old); + todbc_enc_t *val = (todbc_enc_t*)old; + return *val; + } + + todbc_enc_t *val = (todbc_enc_t*)calloc(1, sizeof(*val)); + if (!val) break; + do { + if (snprintf(val->enc, sizeof(val->enc), "%s", enc)>=sizeof(val->enc)) { + break; + } + do_set_sizes(val); + + if (do_get_null_size(val->enc, &val->null_size)) break; + + return *val; + } while (0); + + free(val); + } while (0); + + todbc_enc_t v = {0}; + v.char_size = -1; + v.null_size = -1; + + return v; +} + +todbc_iconv_t* todbc_iconvset_get(todbc_iconvset_t *cnvset, const char *enc_to, const char *enc_from) { + if (!cnvset) return NULL; + if (!enc_to) return NULL; + if (!enc_from) return NULL; + todbc_iconv_key_t key; + key.enc_to = enc_to; + key.enc_from = enc_from; + + if (!cnvset->iconv_hash) { + todbc_hash_conf_t conf = {0}; + conf.arg = cnvset; + conf.val_free = do_iconv_hash_val_free; + conf.key_hash = do_iconv_hash_key_hash; + conf.key_comp = do_iconv_hash_key_comp; + conf.slots = 7; + cnvset->iconv_hash = todbc_hash_create(conf); + if (!cnvset->iconv_hash) return NULL; + } + + void *old = NULL; + int found = 0; + int r = todbc_hash_get(cnvset->iconv_hash, &key, &old, &found); + if (r) { + DASSERT(found==0); + DASSERT(old==NULL); + return NULL; + } + + if (found) { + DASSERT(old); + todbc_iconv_t *val = (todbc_iconv_t*)old; + // D("found [%p] for [%s->%s]", val, enc_from, enc_to); + return val; + } + + todbc_iconv_t *val = (todbc_iconv_t*)calloc(1, sizeof(*val)); + if (!val) return NULL; + do { + if (snprintf(val->enc_to, sizeof(val->enc_to), "%s", enc_to)>=sizeof(val->enc_to)) { + break; + } + if (snprintf(val->enc_from, sizeof(val->enc_from), "%s", enc_from)>=sizeof(val->enc_from)) { + break; + } + val->key.enc_to = val->enc_to; + val->key.enc_from = val->enc_from; + if (strcasecmp(enc_to, enc_from)==0) { + val->direct = 1; + } + + val->from = todbc_tls_iconv_enc(enc_from); + val->to = todbc_tls_iconv_enc(enc_to); + + val->cnv = iconv_open(enc_to, enc_from); + if (val->cnv==invalid_iconv()) break; + + r = todbc_hash_put(cnvset->iconv_hash, &key, val); + + if (r) break; + + // D("created [%p] for [%s->%s]", val, enc_from, enc_to); + return val; + } while (0); + + todbc_iconv_free(val); + return NULL; +} + +iconv_t todbc_iconv_get(todbc_iconv_t *cnv) { + if (!cnv) return invalid_iconv(); + return cnv->cnv; +} + +// static int todbc_legal_chars_by_cnv(iconv_t cnv, const unsigned char *str, todbc_bytes_t *bc); + +int todbc_iconv_get_legal_chars(todbc_iconv_t *cnv, const unsigned char *str, todbc_bytes_t *bc) { + DASSERT(0); + // if (!cnv) return -1; + // if (bc->inbytes==0 || bc->inbytes > INT64_MAX) { + // DASSERT(bc->chars<=INT64_MAX); + // if (bc->chars > 0) { + // DASSERT(cnv->from_char_size==2 || cnv->from_char_size==4); + // bc->inbytes = ((size_t)cnv->from_char_size) * bc->chars; + // bc->chars = 0; + // } + // } else { + // DASSERT(bc->chars==0); + // } + // return todbc_legal_chars_by_cnv(todbc_iconv_get(cnv), str, bc); +} + +// static int todbc_legal_chars_by_block(iconv_t cnv, const unsigned char *str, todbc_bytes_t *bc); + +// static int todbc_legal_chars_by_cnv(iconv_t cnv, const unsigned char *str, todbc_bytes_t *bc) { +// size_t max_bytes = bc->inbytes; +// if (max_bytes > INT64_MAX) max_bytes = (size_t)-1; +// +// if (max_bytes != (size_t)-1) { +// return todbc_legal_chars_by_block(cnv, str, bc); +// } +// +// memset(bc, 0, sizeof(*bc)); +// +// size_t nbytes = 0; +// size_t ch_bytes = 0; +// +// char buf[16]; +// char *inbuf = (char*)str; +// char *outbuf; +// size_t outbytes; +// size_t inbytes; +// +// size_t n = 0; +// +// int r = 0; +// inbytes = 1; +// while (1) { +// if (nbytes==max_bytes) break; +// outbytes = sizeof(buf); +// outbuf = buf; +// +// ch_bytes = inbytes; +// n = iconv(cnv, &inbuf, &inbytes, &outbuf, &outbytes); +// nbytes += 1; +// if (n==(size_t)-1) { +// int err = errno; +// if (err!=EINVAL) { +// E("......."); +// r = -1; +// break; +// } +// inbytes = ch_bytes + 1; +// continue; +// } +// DASSERT(inbytes==0); +// n = sizeof(buf) - outbytes; +// +// DASSERT(n==2); +// if (buf[0]=='\0' && buf[1]=='\0') { +// ch_bytes = 0; +// break; +// } +// +// bc->inbytes += ch_bytes; +// bc->chars += 1; +// bc->outbytes += 2; +// +// ch_bytes = 0; +// inbytes = 1; +// } +// +// outbytes = sizeof(buf); +// outbuf = buf; +// n = iconv(cnv, NULL, NULL, &outbuf, &outbytes); +// +// if (r) return -1; +// if (n==(size_t)-1) return -1; +// if (outbytes!=sizeof(buf)) return -1; +// if (outbuf!=buf) return -1; +// if (ch_bytes) return -1; +// return 0; +// } + +unsigned char* todbc_iconv_conv(todbc_iconv_t *cnv, todbc_buf_t *buf, const unsigned char *src, todbc_bytes_t *bc) { + if (!buf) { + buf = todbc_tls_buf(); + if (!buf) return NULL; + } + if (bc==NULL) { + todbc_bytes_t x = {0}; + x.inbytes = (size_t)-1; + return todbc_iconv_conv(cnv, buf, src, &x); + } + + DASSERT(buf); + DASSERT(cnv); + DASSERT(src); + + todbc_string_t s = todbc_string_init(cnv->from.enc, src, bc->inbytes); + // D("total_bytes/bytes: %d/%zu/%zu", s.total_bytes, s.bytes); + DASSERT(s.buf==src); + todbc_string_t t = todbc_string_conv_to(&s, cnv->to.enc, NULL); + DASSERT(t.buf); + // bc->outbytes not counting size of null-terminator + bc->outbytes = t.bytes; + return (unsigned char*)t.buf; +} + +size_t todbc_iconv_est_bytes(todbc_iconv_t *cnv, size_t inbytes) { + DASSERT(cnv); + DASSERT(inbytes<=INT64_MAX); + const todbc_enc_t *from = &cnv->from; + const todbc_enc_t *to = &cnv->to; + + size_t outbytes = inbytes; + do { + if (from == to) break; + + size_t inchars = inbytes; + if (from->char_size > 1) { + inchars = (inbytes + (size_t)from->char_size - 1) / (size_t)from->char_size; + } + outbytes = inchars; + size_t char_size = MAX_CHARACTER_SIZE; + if (to->char_size > 0) { + char_size = (size_t)to->char_size; + } else if (to->variable_char_size > 0) { + char_size = (size_t)to->variable_char_size; + } + outbytes *= char_size; + } while (0); + + size_t nullbytes = MAX_CHARACTER_SIZE; + if (to->null_size > 0) { + nullbytes = (size_t)to->null_size; + } + // D("%s->%s: %zu->%zu", from->enc, to->enc, inbytes, outbytes); + outbytes += nullbytes; + // D("%s->%s: %zu->%zu", from->enc, to->enc, inbytes, outbytes); + + return outbytes; +} + +size_t todbc_iconv_bytes(todbc_iconv_t *cnv, size_t inchars) { + DASSERT(cnv); + if (inchars >= INT64_MAX) return (size_t)-1; + const todbc_enc_t *from = &cnv->from; + if (from->char_size > 0) { + return inchars * (size_t)from->char_size; + } + return (size_t)-1; +} + +todbc_enc_t todbc_iconv_from(todbc_iconv_t *cnv) { + DASSERT(cnv); + return cnv->from; +} + +todbc_enc_t todbc_iconv_to(todbc_iconv_t *cnv) { + DASSERT(cnv); + return cnv->to; +} + +int todbc_iconv_raw(todbc_iconv_t *cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen) { + DASSERT(cnv); + DASSERT(src && dst); + DASSERT(slen && *slen < INT64_MAX); + DASSERT(dlen && *dlen < INT64_MAX); + + const int null_bytes = todbc_iconv_to(cnv).null_size; + + if (*dlen<=null_bytes) { + D("target buffer too small to hold even null-terminator"); + *dlen = 0; // while slen does not change + return -1; + } + + char *inbuf = (char*)src; + size_t inbytes = *slen; + char *outbuf = (char*)dst; + size_t outbytes = *dlen; + + size_t n = iconv(cnv->cnv, &inbuf, &inbytes, &outbuf, &outbytes); + int e = 0; + if (n==(size_t)-1) { + e = errno; + D("iconv failed: [%s->%s]:[%d]%s", cnv->from.enc, cnv->to.enc, e, strerror(e)); + } else { + DASSERT(n==0); + } + + const size_t inremain = inbytes; + const size_t outremain = outbytes; + *slen = inremain; + *dlen = outremain; + + // writing null-terminator to make dest a real string + DASSERT(outbytes <= INT64_MAX); + if (outbytes < null_bytes) { + D("target buffer too small to hold null-terminator"); + return -1; + } else { + for (int i=0; icnv, NULL, NULL, NULL, NULL); + + return 0; +} + +todbc_string_t todbc_iconv_conv2(todbc_iconv_t *cnv, todbc_buf_t *buf, const unsigned char *src, size_t *slen) { + const todbc_string_t nul = {0}; + if (!buf) { + buf = todbc_tls_buf(); + if (!buf) return nul; + } + DASSERT(cnv); + DASSERT(src); + + size_t inbytes = (size_t)-1; + if (slen && *slen <= INT64_MAX) inbytes = *slen; + + todbc_string_t in = todbc_string_init(todbc_iconv_from(cnv).enc, src, inbytes); + if (in.buf!=src) return nul; + if (in.bytes > INT64_MAX) return nul; + inbytes = in.bytes; + + size_t outblock = todbc_iconv_est_bytes(cnv, in.bytes); + if (outblock > INT64_MAX) return nul; + + unsigned char *out = todbc_buf_alloc(buf, outblock); + if (!out) return nul; + + const unsigned char *inbuf = src; + unsigned char *outbuf = out; + + + size_t outbytes = outblock; + int r = todbc_iconv_raw(cnv, inbuf, &inbytes, outbuf, &outbytes); + if (slen) *slen = inbytes; + if (r) return nul; + todbc_string_t s = {0}; + s.buf = outbuf; + s.bytes = outblock - outbytes; + s.total_bytes = s.bytes; + return s; +} + +// static int todbc_legal_chars_by_block(iconv_t cnv, const unsigned char *str, todbc_bytes_t *bc) { +// int r = 0; +// size_t max_bytes = bc->inbytes; +// char buf[1024*16]; +// memset(bc, 0, sizeof(*bc)); +// char *inbuf = (char*)str; +// while (bc->inbytesinbytes; +// size_t outbytes = sizeof(buf); +// char *outbuf = buf; +// size_t n = iconv(cnv, &inbuf, &inbytes, &outbuf, &outbytes); +// int err = 0; +// if (n==(size_t)-1) { +// err = errno; +// if (err!=E2BIG && err!=EINVAL) r = -1; +// } else { +// DASSERT(n==0); +// } +// if (inbytes == max_bytes - bc->inbytes) { +// r = -1; +// } +// bc->inbytes += max_bytes - bc->inbytes - inbytes; +// bc->outbytes += sizeof(buf) - outbytes; +// if (r) break; +// } +// bc->chars = bc->outbytes / 2; +// iconv(cnv, NULL, NULL, NULL, NULL); +// return r ? -1 : 0; +// } + +static void todbc_iconv_free(todbc_iconv_t *val) { + if (!val) return; + if (val->cnv!=invalid_iconv()) { + iconv_close(val->cnv); + val->cnv = invalid_iconv(); + } + free(val); +} + +// http://www.cse.yorku.ca/~oz/hash.html +static const unsigned long hash_seed = 5381; +static unsigned long hashing(unsigned long hash, const unsigned char *str); + +static void do_enc_hash_val_free(todbc_hash_t *hash, void *val, void *arg) { + todbc_iconvset_t *cnv = (todbc_iconvset_t*)arg; + todbc_enc_t *v = (todbc_enc_t*)val; + DASSERT(hash); + DASSERT(cnv); + DASSERT(v); + free(v); +} + +static unsigned long do_enc_hash_key_hash(todbc_hash_t *hash, void *key) { + const char *k = (const char*)key; + DASSERT(k); + unsigned long h = hash_seed; + h = hashing(h, (const unsigned char*)k); + return h; +} + +static int do_enc_hash_key_comp(todbc_hash_t *hash, void *key, void *val) { + const char *k = (const char*)key; + todbc_enc_t *v = (todbc_enc_t*)val; + if (strcasecmp(k, v->enc)) return 1; + return 0; +} + +static int do_get_null_size(const char *enc, int *null_size) { + iconv_t cnv = iconv_open(enc, UTF8_ENC); + if (cnv==(iconv_t)-1) return -1; + + char src[] = ""; + char dst[64]; + + char *inbuf = src; + size_t inbytes = 1; + char *outbuf = dst; + size_t outbytes = sizeof(dst); + + size_t n = iconv(cnv, &inbuf, &inbytes, &outbuf, &outbytes); + DASSERT(n==0); + DASSERT(inbytes==0); + + int size = (int)(sizeof(dst) - outbytes); + + iconv_close(cnv); + + if (null_size) *null_size = size; + + return 0; +} + +static void do_iconv_hash_val_free(todbc_hash_t *hash, void *val, void *arg) { + todbc_iconvset_t *cnv = (todbc_iconvset_t*)arg; + todbc_iconv_t *v = (todbc_iconv_t*)val; + DASSERT(hash); + DASSERT(cnv); + DASSERT(v); + todbc_iconv_free(v); +} + +static unsigned long do_iconv_hash_key_hash(todbc_hash_t *hash, void *key) { + todbc_iconv_key_t *k = (todbc_iconv_key_t*)key; + DASSERT(k); + unsigned long h = hash_seed; + h = hashing(h, (const unsigned char*)k->enc_to); + h = hashing(h, (const unsigned char*)k->enc_from); + return h; +} + +static int do_iconv_hash_key_comp(todbc_hash_t *hash, void *key, void *val) { + todbc_iconv_key_t *k = (todbc_iconv_key_t*)key; + todbc_iconv_t *v = (todbc_iconv_t*)val; + if (strcasecmp(k->enc_to, v->key.enc_to)) return 1; + if (strcasecmp(k->enc_from, v->key.enc_from)) return 1; + return 0; +} + +static unsigned long hashing(unsigned long hash, const unsigned char *str) { + unsigned long c; + while ((c = *str++)!=0) { + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + } + + return hash; +} + diff --git a/src/connector/odbc/src/todbc_iconv.h b/src/connector/odbc/src/todbc_iconv.h new file mode 100644 index 0000000000000000000000000000000000000000..269900f8f1fc77da2bdf6dd4e298ed765e5e7e9e --- /dev/null +++ b/src/connector/odbc/src/todbc_iconv.h @@ -0,0 +1,114 @@ +/* + * 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 . + */ + +#ifndef _todbc_iconv_h_ +#define _todbc_iconv_h_ + +#include "todbc_buf.h" +#include "todbc_string.h" + +#include + +// non-thread-safe + +#define ASCII_ENC "ASCII" +#define UTF8_ENC "UTF-8" +#define UTF16_ENC "UCS-2LE" +#define UNICODE_ENC "UCS-4LE" +#define GB18030_ENC "GB18030" + +#define MAX_CHARACTER_SIZE 6 + +typedef enum { + TSDB_CONV_OK = 0, + TSDB_CONV_NOT_AVAIL, + TSDB_CONV_OOM, + TSDB_CONV_OOR, + TSDB_CONV_TRUNC_FRACTION, + TSDB_CONV_TRUNC, + TSDB_CONV_CHAR_NOT_NUM, + TSDB_CONV_CHAR_NOT_TS, + TSDB_CONV_NOT_VALID_TS, + TSDB_CONV_GENERAL, + TSDB_CONV_BAD_CHAR, + TSDB_CONV_SRC_TOO_LARGE, + TSDB_CONV_SRC_BAD_SEQ, + TSDB_CONV_SRC_INCOMPLETE, + TSDB_CONV_SRC_GENERAL, +} TSDB_CONV_CODE; + +typedef struct todbc_iconvset_s todbc_iconvset_t; +typedef struct todbc_iconv_s todbc_iconv_t; +typedef struct todbc_enc_s todbc_enc_t; +struct todbc_enc_s { + int char_size; // character size at most + int null_size; // size for null terminator + int variable_char_size; // such as 3 for UTF8 + char enc[64]; // move here to satisfy todbc_enc_t enc = {0}; +}; + +todbc_iconvset_t* todbc_iconvset_create(void); +void todbc_iconvset_free(todbc_iconvset_t *cnvset); +todbc_iconv_t* todbc_iconvset_get(todbc_iconvset_t *cnvset, const char *enc_to, const char *enc_from); +todbc_enc_t todbc_iconvset_enc(todbc_iconvset_t *cnvset, const char *enc); + +typedef struct todbc_bytes_s todbc_bytes_t; +typedef struct todbc_err_s todbc_err_t; + +struct todbc_err_s { + unsigned int einval:1; // EINVAL + unsigned int eilseq:1; // EILSEQ + unsigned int etoobig:1; // E2BIG + unsigned int eoom:1; // ENOMEM +}; + +struct todbc_bytes_s { + size_t inbytes, outbytes; + size_t chars; + + todbc_err_t err; +}; + +typedef struct todbc_iconv_arg_s todbc_iconv_arg_t; +struct todbc_iconv_arg_s { + const unsigned char *inbuf; + size_t inbytes; // -1: not set + unsigned char *outbuf; + size_t outbytes; // -1: not set + + size_t chars; // -1: not set +}; + +iconv_t todbc_iconv_get(todbc_iconv_t *cnv); +int todbc_iconv_get_legal_chars(todbc_iconv_t *cnv, const unsigned char *str, todbc_bytes_t *bc); +// non-thread-safe +// use todbc_buf_t as mem-allocator, if NULL, fall-back to thread-local version +unsigned char* todbc_iconv_conv(todbc_iconv_t *cnv, todbc_buf_t *buf, const unsigned char *src, todbc_bytes_t *bc); +// null-terminator-inclusive +size_t todbc_iconv_est_bytes(todbc_iconv_t *cnv, size_t inbytes); +// if inchars>=0 && enc_from has fixed-char-size, returns inchars * char_size +// otherwise -1 +size_t todbc_iconv_bytes(todbc_iconv_t *cnv, size_t inchars); +todbc_enc_t todbc_iconv_from(todbc_iconv_t *cnv); +todbc_enc_t todbc_iconv_to(todbc_iconv_t *cnv); + +// at return, *slen/*dlen stores the remaining # +int todbc_iconv_raw(todbc_iconv_t *cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen); +// use todbc_buf_t as mem-allocator, if NULL, fall-back to thread-local version +// at return, *slen stores the remaining # +todbc_string_t todbc_iconv_conv2(todbc_iconv_t *cnv, todbc_buf_t *buf, const unsigned char *src, size_t *slen); + +#endif // _todbc_iconv_h_ + diff --git a/src/connector/odbc/src/todbc_list.c b/src/connector/odbc/src/todbc_list.c new file mode 100644 index 0000000000000000000000000000000000000000..447ce4826c4d6417af3c7d983a9278c8c6adf32c --- /dev/null +++ b/src/connector/odbc/src/todbc_list.c @@ -0,0 +1,256 @@ +/* + * 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 . + */ + +#include "todbc_list.h" + +#include "todbc_log.h" + +#include + +struct todbc_list_s { + todbc_list_conf_t conf; + + todbc_list_node_t *head; + todbc_list_node_t *tail; + size_t count; +}; + +struct todbc_list_node_s { + void *val; + + todbc_list_t *list; + todbc_list_node_t *next; + todbc_list_node_t *prev; +}; + +static void do_remove(todbc_list_t *list, todbc_list_node_t *node); + +static void do_pushback(todbc_list_t *list, todbc_list_node_t *node); +static void do_pushfront(todbc_list_t *list, todbc_list_node_t *node); + +todbc_list_t* todbc_list_create(todbc_list_conf_t conf) { + todbc_list_t *list = (todbc_list_t*)calloc(1, sizeof(*list)); + if (!list) return NULL; + + list->conf = conf; + + return list; +} + +void todbc_list_free(todbc_list_t *list) { + if (!list) return; + + while (list->head) { + void *val = list->head->val; + do_remove(list, list->head); + if (!list->conf.val_free) continue; + list->conf.val_free(list, val, list->conf.arg); + } + + DASSERT(list->count == 0); +} + +size_t todbc_list_count(todbc_list_t *list) { + if (!list) return 0; + return list->count; +} + +int todbc_list_pushback(todbc_list_t *list, void *val) { + if (!list) return -1; + + todbc_list_node_t *node = (todbc_list_node_t*)calloc(1, sizeof(*node)); + if (!node) return -1; + node->val = val; + + do_pushback(list, node); + + return 0; +} + +int todbc_list_pushfront(todbc_list_t *list, void *val) { + if (!list) return -1; + + todbc_list_node_t *node = (todbc_list_node_t*)calloc(1, sizeof(*node)); + if (!node) return -1; + node->val = val; + + do_pushfront(list, node); + + return 0; +} + +int todbc_list_popback(todbc_list_t *list, void **val, int *found) { + if (!list) return -1; + if (!found) return -1; + + *found = 0; + + todbc_list_node_t *node = list->tail; + if (!node) return 0; + + if (val) *val = node->val; + do_remove(list, node); + + *found = 1; + + return 0; +} + +int todbc_list_popfront(todbc_list_t *list, void **val, int *found) { + if (!list) return -1; + if (!found) return -1; + + *found = 0; + + todbc_list_node_t *node = list->head; + if (!node) return 0; + + if (val) *val = node->val; + do_remove(list, node); + + *found = 1; + + return 0; +} + +int todbc_list_pop(todbc_list_t *list, void *val, int *found) { + if (!list) return -1; + if (!found) return -1; + + *found = 0; + + todbc_list_node_t *node = list->head; + while (node) { + if (node->val == val) break; + node = node->next; + } + + if (!node) return 0; + + do_remove(list, node); + + *found = 1; + + return 0; +} + +int todbc_list_traverse(todbc_list_t *list, list_iterate_f iterate, void *arg) { + if (!list) return -1; + if (!iterate) return -1; + + todbc_list_node_t *node = list->head; + while (node) { + int r = iterate(list, node->val, arg); + if (r) return r; + node = node->next; + } + + return 0; +} + +typedef struct comp_s comp_t; +struct comp_s { + list_comp_f comp; + void *arg; + int found; + void *val; +}; + +static int do_comp(todbc_list_t *list, void *val, void *arg); + +int todbc_list_find(todbc_list_t *list, void *val, int *found, list_comp_f comp, void *arg) { + if (!list) return -1; + if (!found) return -1; + if (!comp) return -1; + + *found = 0; + + comp_t sarg = {0}; + sarg.comp = comp; + sarg.arg = arg; + sarg.val = val; + todbc_list_traverse(list, do_comp, &sarg); + if (sarg.found) { + *found = 1; + } + return 0; +} + +static int do_comp(todbc_list_t *list, void *val, void *arg) { + comp_t *sarg = (comp_t*)arg; + + int r = sarg->comp(list, val, sarg->val, sarg->arg); + if (r==0) { + sarg->found = 1; + } + + return r; +} + +static void do_remove(todbc_list_t *list, todbc_list_node_t *node) { + DASSERT(node); + DASSERT(list); + DASSERT(list == node->list); + + todbc_list_node_t *prev = node->prev; + todbc_list_node_t *next = node->next; + if (prev) prev->next = next; + else list->head = next; + if (next) next->prev = prev; + else list->tail = prev; + node->prev = NULL; + node->next = NULL; + node->list = NULL; + node->val = NULL; + + list->count -= 1; + DASSERT(list->count <= INT64_MAX); + + free(node); +} + +static void do_pushback(todbc_list_t *list, todbc_list_node_t *node) { + DASSERT(list); + DASSERT(node); + DASSERT(node->list == NULL); + DASSERT(node->prev == NULL); + DASSERT(node->next == NULL); + + node->list = list; + node->prev = list->tail; + if (list->tail) list->tail->next = node; + else list->head = node; + list->tail = node; + + list->count += 1; + DASSERT(list->count > 0); +} + +static void do_pushfront(todbc_list_t *list, todbc_list_node_t *node) { + DASSERT(node); + DASSERT(node->list == NULL); + DASSERT(node->prev == NULL); + DASSERT(node->next == NULL); + + node->list = list; + node->next = list->head; + if (list->head) list->head->prev = node; + else list->tail = node; + list->head = node; + + list->count += 1; + DASSERT(list->count > 0); +} + diff --git a/src/connector/odbc/src/todbc_list.h b/src/connector/odbc/src/todbc_list.h new file mode 100644 index 0000000000000000000000000000000000000000..d84ffd88a0e8d06cea2b7382da8cba5b881813a1 --- /dev/null +++ b/src/connector/odbc/src/todbc_list.h @@ -0,0 +1,53 @@ +/* + * 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 . + */ + +#ifndef _todbc_list_h_ +#define _todbc_list_h_ + +#include +#include + +// non-thread-safe + +typedef struct todbc_list_s todbc_list_t; +typedef struct todbc_list_node_s todbc_list_node_t; + +typedef struct todbc_list_conf_s todbc_list_conf_t; + +typedef void (*list_val_free_f)(todbc_list_t *list, void *val, void *arg); + +struct todbc_list_conf_s { + void *arg; + list_val_free_f val_free; +}; + +todbc_list_t* todbc_list_create(todbc_list_conf_t conf); +void todbc_list_free(todbc_list_t *list); + +size_t todbc_list_count(todbc_list_t *list); + +int todbc_list_pushback(todbc_list_t *list, void *val); +int todbc_list_pushfront(todbc_list_t *list, void *val); +int todbc_list_popback(todbc_list_t *list, void **val, int *found); +int todbc_list_popfront(todbc_list_t *list, void **val, int *found); +int todbc_list_pop(todbc_list_t *list, void *val, int *found); +typedef int (*list_iterate_f)(todbc_list_t *list, void *val, void *arg); +int todbc_list_traverse(todbc_list_t *list, list_iterate_f iterate, void *arg); +typedef int (*list_comp_f)(todbc_list_t *list, void *old, void *val, void *arg); +int todbc_list_find(todbc_list_t *list, void *val, int *found, list_comp_f comp, void *arg); + + +#endif // _todbc_list_h_ + diff --git a/src/connector/odbc/src/todbc_log.c b/src/connector/odbc/src/todbc_log.c new file mode 100644 index 0000000000000000000000000000000000000000..c83ad2d62df3ce08cb70bd035898ec9e33b893fe --- /dev/null +++ b/src/connector/odbc/src/todbc_log.c @@ -0,0 +1,94 @@ +/* + * 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 . + */ + +#include "todbc_log.h" + +uint64_t todbc_get_threadid(void) { + uint64_t tid = 0; +#ifdef __APPLE__ + pthread_threadid_np(NULL, &tid); +#elif defined(__linux__) + tid = (uint64_t)syscall(__NR_gettid); +#elif defined(_MSC_VER) + tid = GetCurrentThreadId(); +#else +#error you have to check the target API for thread id +#endif + return tid; +} + +#ifdef _MSC_VER +static __declspec(thread) uint64_t thread_id = 0; +#else +static __thread uint64_t thread_id = 0; +#endif + +#ifdef __GNUC__ + __attribute__((format(printf, 6, 7))) +#endif +void todbc_log(const char *file, int line, const char *func, const char tag, int err, const char *fmt, ...) { + struct tm stm = {0}; + struct timeval tv; + + if (thread_id==0) { + thread_id = todbc_get_threadid(); + } + + gettimeofday(&tv, NULL); + time_t tt = tv.tv_sec; + localtime_r(&tt, &stm); + + char buf[4096]; + size_t bytes = sizeof(buf); + + char *p = buf; + int n = 0; + + n = snprintf(p, bytes, "%C%02d:%02d:%02d.%06d[%" PRIx64 "]%s[%d]%s()", + tag, stm.tm_hour, stm.tm_min, stm.tm_sec, (int)tv.tv_usec, + thread_id, basename((char*)file), line, func); + if (n>0) { + bytes -= (size_t)n; + p += n; + } + + if (bytes>0) { + if (tag=='E' && err) { + n = snprintf(p, bytes, "[%d]%s", err, strerror(err)); + if (n>0) { + bytes -= (size_t)n; + p += n; + } + } + } + + if (bytes>0) { + n = snprintf(p, bytes, ": "); + if (n>0) { + bytes -= (size_t)n; + p += n; + } + } + + if (bytes>0) { + va_list ap; + va_start(ap, fmt); + n = vsnprintf(p, bytes, fmt, ap); + va_end(ap); + } + + fprintf(stderr, "%s\n", buf); +} + diff --git a/src/connector/odbc/src/todbc_log.h b/src/connector/odbc/src/todbc_log.h index 391a690cccb0954736cac76af3354cc8a39754a8..30ef8436e1e02535f9a7a3eaefc456a792bd1744 100644 --- a/src/connector/odbc/src/todbc_log.h +++ b/src/connector/odbc/src/todbc_log.h @@ -18,25 +18,35 @@ #include "os.h" -#define D(fmt, ...) \ - fprintf(stderr, \ - "%s[%d]:%s() " fmt "\n", \ - basename((char*)__FILE__), __LINE__, __func__, \ - ##__VA_ARGS__) - -#define DASSERT(statement) \ -do { \ - if (statement) break; \ - D("Assertion failure: %s", #statement); \ - abort(); \ -} while (0) +#ifdef __GNUC__ + __attribute__((format(printf, 6, 7))) +#endif +void todbc_log(const char *file, int line, const char *func, const char tag, int err, const char *fmt, ...); -#define DASSERTX(statement, fmt, ...) \ -do { \ - if (statement) break; \ - D("Assertion failure: %s, " fmt "", #statement, ##__VA_ARGS__); \ - abort(); \ +#define OL(tag, err, fmt, ...) todbc_log(__FILE__, __LINE__, __func__, tag, err, "%s" fmt "", "", ##__VA_ARGS__) +#define OD(fmt, ...) OL('D', 0, fmt, ##__VA_ARGS__) +#define OE(fmt, ...) OL('E', errno, fmt, ##__VA_ARGS__) +#define OW(fmt, ...) OL('W', 0, fmt, ##__VA_ARGS__) +#define OI(fmt, ...) OL('I', 0, fmt, ##__VA_ARGS__) +#define OV(fmt, ...) OL('V', 0, fmt, ##__VA_ARGS__) +#define OA(statement, fmt, ...) do { \ + if (statement) break; \ + OL('A', 0, "Assertion failure:[%s]; " fmt "", #statement, ##__VA_ARGS__); \ + abort(); \ } while (0) +#define OILE(statement, fmt, ...) OA(statement, "internal logic error: [" fmt "]", ##__VA_ARGS__) +#define ONIY(statement, fmt, ...) OA(statement, "not implemented yet: [" fmt "]", ##__VA_ARGS__) +#define ONSP(statement, fmt, ...) OA(statement, "not support yet: [" fmt "]", ##__VA_ARGS__) + +#define D(fmt, ...) OD(fmt, ##__VA_ARGS__) +#define E(fmt, ...) OE(fmt, ##__VA_ARGS__) +#define DASSERT(statement) OA(statement, "") +#define DASSERTX(statement, fmt, ...) OA(statement, fmt, ##__VA_ARGS__) + + +uint64_t todbc_get_threadid(void); + + #endif // _todbc_log_h_ diff --git a/src/connector/odbc/src/todbc_scanner.l b/src/connector/odbc/src/todbc_scanner.l index f8c6a15d92442ee7f7b9041f017b41a4ed590314..b36c894f73cd7d8eb3b1642eb8b9c3bb433f2a5b 100644 --- a/src/connector/odbc/src/todbc_scanner.l +++ b/src/connector/odbc/src/todbc_scanner.l @@ -1,11 +1,18 @@ %{ +#ifdef _MSC_VER +#include +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#define basename PathFindFileNameA +#else +#include +#endif + #include "todbc_flex.h" #include +#include -#ifdef _MSC_VER -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#endif +static int process_map(const char *cfg, map_tsdb_type_t *tsdb_map, int type); #define PUSH_STATE(state) yy_push_state(state, yyscanner) #define POP_STATE() yy_pop_state(yyscanner) @@ -28,50 +35,73 @@ do { \ while (yyleng) unput(yytext[yyleng-1]); \ } while (0) -#define set_key() \ -do { \ - free(yyextra->key); \ - yyextra->key = strdup(yytext); \ +#define set_val() \ +do { \ + int r = 0; \ + int curr; TOP_STATE(curr); \ + POP_STATE(); \ + int state; TOP_STATE(state); \ + switch(state) { \ + case DSN: { \ + free(yyextra->dsn); \ + yyextra->dsn = strdup(yytext); \ + } break; \ + case UID: { \ + free(yyextra->uid); \ + yyextra->uid = strdup(yytext); \ + } break; \ + case PWD: { \ + free(yyextra->pwd); \ + yyextra->pwd = strdup(yytext); \ + } break; \ + case SERVER: { \ + free(yyextra->server); \ + yyextra->server = strdup(yytext); \ + } break; \ + case DB: { \ + free(yyextra->db); \ + yyextra->db = strdup(yytext); \ + } break; \ + case ENC_CHAR: { \ + free(yyextra->enc_char); \ + yyextra->enc_char = strdup(yytext); \ + } break; \ + case ENC_WCHAR: { \ + free(yyextra->enc_wchar); \ + yyextra->enc_wchar = strdup(yytext); \ + } break; \ + case ENC_DB: { \ + free(yyextra->enc_db); \ + yyextra->enc_db = strdup(yytext); \ + } break; \ + case ENC_LOCAL: { \ + free(yyextra->enc_local); \ + yyextra->enc_local = strdup(yytext); \ + } break; \ + case TSDB_FLOAT: { \ + if (process_map(yytext, &yyextra->tsdb_map, TSDB_FLOAT)) { \ + r = -1; \ + } \ + } break; \ + case TSDB_BIGINT: { \ + if (process_map(yytext, &yyextra->tsdb_map, TSDB_BIGINT)) { \ + r = -1; \ + } \ + } break; \ + case KEY: { \ + } break; \ + default: { \ + r = -1; \ + } break; \ + } \ + PUSH_STATE(curr); \ + if (r) return r; \ } while (0) -#define set_val() \ -do { \ - if (!yyextra->key) break; \ - if (strcasecmp(yyextra->key, "DSN")==0) { \ - free(yyextra->dsn); \ - yyextra->dsn = strdup(yytext); \ - break; \ - } \ - if (strcasecmp(yyextra->key, "UID")==0) { \ - free(yyextra->uid); \ - yyextra->uid = strdup(yytext); \ - break; \ - } \ - if (strcasecmp(yyextra->key, "PWD")==0) { \ - free(yyextra->pwd); \ - yyextra->pwd = strdup(yytext); \ - break; \ - } \ - if (strcasecmp(yyextra->key, "DB")==0) { \ - free(yyextra->db); \ - yyextra->pwd = strdup(yytext); \ - break; \ - } \ - if (strcasecmp(yyextra->key, "Server")==0) { \ - free(yyextra->server); \ - yyextra->server = strdup(yytext); \ - break; \ - } \ - if (strcasecmp(yyextra->key, "SERVER_ENC")==0) { \ - free(yyextra->svr_enc); \ - yyextra->svr_enc = strdup(yytext); \ - break; \ - } \ - if (strcasecmp(yyextra->key, "CLIENT_ENC")==0) { \ - free(yyextra->cli_enc); \ - yyextra->cli_enc = strdup(yytext); \ - break; \ - } \ +#define FAIL() \ +do { \ + /*fprintf(stderr, "==%s[%d]%s()==\n", basename(__FILE__), __LINE__, __func__);*/ \ + return -1; \ } while (0) %} @@ -89,57 +119,85 @@ do { \ %option warn %option perf-report %option 8bit +%option case-insensitive +%x DSN UID PWD SERVER DB +%x ENC_CHAR ENC_WCHAR ENC_DB ENC_LOCAL +%x TSDB_FLOAT TSDB_BIGINT %x KEY EQ BRACE1 BRACE2 VAL %% <> { int state; TOP_STATE(state); if (state == INITIAL) yyterminate(); if (state == VAL) yyterminate(); - return -1; } + FAIL(); } [[:space:]]+ { } -[[:alnum:]_]+ { set_key(); PUSH_STATE(KEY); } -.|\n { return -1; } +"DSN" { PUSH_STATE(DSN); } +"UID" { PUSH_STATE(UID); } +"PWD" { PUSH_STATE(PWD); } +"Server" { PUSH_STATE(SERVER); } +"DB" { PUSH_STATE(DB); } +"ENC_CHAR" { PUSH_STATE(ENC_CHAR); } +"ENC_WCHAR" { PUSH_STATE(ENC_WCHAR); } +"ENC_DB" { PUSH_STATE(ENC_DB); } +"ENC_LOCAL" { PUSH_STATE(ENC_LOCAL); } +"map.float" { PUSH_STATE(TSDB_FLOAT); } +"map.bigint" { PUSH_STATE(TSDB_BIGINT); } +[[:alnum:]_]+ { PUSH_STATE(KEY); } +.|\n { FAIL(); } -[[:space:]]+ { } -[=] { CHG_STATE(EQ); } -.|\n { return -1; } +[[:space:]]+ { } +[=] { PUSH_STATE(EQ); } +.|\n { FAIL(); } [[:space:]]+ { } -[^][{}(),;?*=!@/\\\n[:space:]]+ { set_val(); CHG_STATE(VAL); } [{] { CHG_STATE(BRACE1); } -.|\n { return -1; } +[^][{}(),;?*=!@/\\\n[:space:]]+ { set_val(); POP_STATE(); CHG_STATE(VAL); } +.|\n { FAIL(); } [^{}\n]+ { set_val(); CHG_STATE(BRACE2); } -.|\n { return -1; } +.|\n { FAIL(); } [[:space:]]+ { } -[}] { CHG_STATE(VAL); } -.|\n { return -1; } +[}] { POP_STATE(); CHG_STATE(VAL); } +.|\n { FAIL(); } [;] { POP_STATE(); } -.|\n { return -1; } +.|\n { FAIL(); } %% +static char* get_val_by_key_from_odbc_ini(const char *dsn, const char *key); + +static void conn_val_init(conn_val_t *val); + int todbc_parse_conn_string(const char *conn, conn_val_t *val) { yyscan_t arg = {0}; yylex_init(&arg); yyset_debug(0, arg); yyset_extra(val, arg); + + conn_val_init(val); + yy_scan_string(conn, arg); int ret =yylex(arg); yylex_destroy(arg); - if (val->key) free(val->key); val->key = NULL; - if (ret) { + if (ret || !val->dsn) { conn_val_reset(val); + } else { + if (!val->uid) { + val->uid = get_val_by_key_from_odbc_ini(val->dsn, "UID"); + } + if (!val->pwd) { + val->pwd = get_val_by_key_from_odbc_ini(val->dsn, "PWD"); + } + if (!val->server) { + val->server = get_val_by_key_from_odbc_ini(val->dsn, "Server"); + } } return ret ? -1 : 0; } void conn_val_reset(conn_val_t *val) { - if (val->key) { - free(val->key); val->key = NULL; - } if (val->dsn) { free(val->dsn); val->dsn = NULL; } @@ -155,11 +213,68 @@ void conn_val_reset(conn_val_t *val) { if (val->server) { free(val->server); val->server = NULL; } - if (val->svr_enc) { - free(val->svr_enc); val->svr_enc = NULL; + if (val->enc_local) { + free(val->enc_local); val->enc_local = NULL; + } + if (val->enc_db) { + free(val->enc_db); val->enc_db = NULL; + } + if (val->enc_char) { + free(val->enc_char); val->enc_char = NULL; } - if (val->cli_enc) { - free(val->cli_enc); val->cli_enc = NULL; + if (val->enc_wchar) { + free(val->enc_wchar); val->enc_wchar = NULL; + } +} + +static char* get_val_by_key_from_odbc_ini(const char *dsn, const char *key) { + char Val[4096]; + Val[0] = '\0'; + int n = SQLGetPrivateProfileString(dsn, key, "", Val, sizeof(Val), "odbc.ini"); + if (n<=0) return NULL; + if (Val[0]=='\0') return NULL; + return strdup(Val); +} + +static int process_map(const char *cfg, map_tsdb_type_t *tsdb_map, int type) { + switch (type) { + case TSDB_FLOAT: { + if (strcmp(cfg, "SQL_DOUBLE")==0) { + tsdb_map->tsdb_float = SQL_DOUBLE; + return 0; + } + } break; + case TSDB_BIGINT: { + if (strcmp(cfg, "SQL_C_SBIGINT")==0) { + tsdb_map->tsdb_bigint = SQL_C_SBIGINT; + return 0; + } + if (strcmp(cfg, "SQL_C_UBIGINT")==0) { + tsdb_map->tsdb_bigint = SQL_C_UBIGINT; + return 0; + } + if (strcmp(cfg, "SQL_CHAR")==0) { + tsdb_map->tsdb_bigint = SQL_CHAR; + return 0; + } + } break; + default: { + } break; } + return -1; +} + +static void conn_val_init(conn_val_t *val) { + if (!val) return; + val->tsdb_map.tsdb_tinyint = SQL_TINYINT; + val->tsdb_map.tsdb_smallint = SQL_SMALLINT; + val->tsdb_map.tsdb_int = SQL_INTEGER; + val->tsdb_map.tsdb_bigint = SQL_BIGINT; + val->tsdb_map.tsdb_float = SQL_REAL; + val->tsdb_map.tsdb_double = SQL_DOUBLE; + val->tsdb_map.tsdb_bool = SQL_TINYINT; + val->tsdb_map.tsdb_timestamp = SQL_CHAR; + val->tsdb_map.tsdb_binary = SQL_BINARY; + val->tsdb_map.tsdb_nchar = SQL_WCHAR; } diff --git a/src/connector/odbc/src/todbc_string.c b/src/connector/odbc/src/todbc_string.c new file mode 100644 index 0000000000000000000000000000000000000000..96e9a6d8c3658b08e9e57071aaf4d573e3ca81cb --- /dev/null +++ b/src/connector/odbc/src/todbc_string.c @@ -0,0 +1,218 @@ +/* + * 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 . + */ + +#include "todbc_string.h" + +#include "todbc_log.h" +#include "todbc_tls.h" + +#include + +static int do_calc_bytes(todbc_string_t *str); + +todbc_string_t todbc_string_init(const char *enc, const unsigned char *src, const size_t bytes) { + DASSERT(enc); + DASSERT(src); + + todbc_string_t s = {0}; + todbc_string_t *str = &s; + + todbc_iconv_t *cnv = todbc_tls_iconv_get(enc, UTF8_ENC); + if (!cnv) return s; + + if (snprintf(str->enc, sizeof(str->enc), "%s", enc)>=sizeof(str->enc)) { + return s; + } + str->buf = src; + str->total_bytes = bytes; // need to recalc + str->bytes = 0; + + if (do_calc_bytes(str)) { + str->buf = NULL; + str->total_bytes = 0; + str->bytes = 0; + } + + return s; +} + +todbc_string_t todbc_string_copy(todbc_string_t *str, const char *enc, unsigned char *dst, const size_t target_bytes) { + todbc_string_t val = {0}; + DASSERT(str); + DASSERT(dst); + DASSERT(str->buf); + DASSERT(str->bytes<=INT64_MAX); + DASSERT(str->total_bytes<=INT64_MAX); + + if (snprintf(val.enc, sizeof(val.enc), "%s", enc)>=sizeof(val.enc)) { + return val; + } + + todbc_iconv_t *icnv = todbc_tls_iconv_get(enc, str->enc); + if (!icnv) return val; + iconv_t cnv = todbc_iconv_get(icnv); + if (cnv==(iconv_t)-1) return val; + + val.buf = dst; + val.total_bytes = target_bytes; + + const int null_bytes = todbc_iconv_to(icnv).null_size; + + if (target_bytes<=null_bytes) return val; + size_t estsize = todbc_iconv_est_bytes(icnv, str->bytes); + if (estsize>INT64_MAX) return val; + + // smaller is better!!! + const size_t outblock = (estsize > target_bytes) ? estsize = target_bytes : estsize; + + char *inbuf = (char*)str->buf; + size_t inbytes = str->bytes; // not counting null-terminator + char *outbuf = (char*)dst; + size_t outbytes = outblock; + + int r = todbc_iconv_raw(icnv, (const unsigned char*)inbuf, &inbytes, (unsigned char*)outbuf, &outbytes); + if (r) { + DASSERT(outbytes > 0); + val.bytes = outblock - outbytes; + val.total_bytes = outblock; + return val; + } else { + val.bytes = outblock - outbytes; + val.total_bytes = val.bytes; + if (inbytes > 0) { + val.total_bytes += 1; // to indicate truncation + } + return val; + } +} + +todbc_string_t todbc_copy(const char *from_enc, const unsigned char *src, size_t *inbytes, const char *to_enc, unsigned char *dst, const size_t dlen) { + DASSERT(from_enc); + DASSERT(src); + DASSERT(inbytes); + DASSERT(to_enc); + DASSERT(dst); + DASSERT(dlen <= INT64_MAX); + + todbc_string_t s_from = todbc_string_init(from_enc, src, *inbytes); + DASSERT(s_from.buf == src); + + return todbc_string_copy(&s_from, to_enc, dst, dlen); +} + +todbc_string_t todbc_string_conv_to(todbc_string_t *str, const char *enc, todbc_buf_t *buf) { + DASSERT(str); + DASSERT(str->buf); + DASSERT(str->bytes<=INT64_MAX); + DASSERT(str->total_bytes<=INT64_MAX); + + todbc_string_t nul = {0}; + + todbc_iconv_t *icnv = todbc_tls_iconv_get(enc, str->enc); + if (!icnv) return nul; + + size_t estsize = todbc_iconv_est_bytes(icnv, str->bytes); + if (estsize>INT64_MAX) return nul; + char *out = NULL; + if (!buf) out = (char*)todbc_tls_buf_alloc(estsize); + else out = (char*)todbc_buf_alloc(buf, estsize); + if (!out) return nul; + + return todbc_string_copy(str, enc, (unsigned char*)out, estsize); +} + +static int do_calc_bytes(todbc_string_t *str) { + iconv_t cnv = todbc_tls_iconv(UTF8_ENC, str->enc); + if (cnv == (iconv_t)-1) return -1; + + size_t total_bytes = 0; + + char buf[1024*16]; + + char *inbuf = (char*)str->buf; + + while (1) { + size_t outblock = sizeof(buf); + + size_t inblock = outblock; + size_t remain = (size_t)-1; + if (str->total_bytes <= INT64_MAX) { + remain = str->total_bytes - total_bytes; + if (remain==0) break; + if (inblock > remain) inblock = remain; + } + + size_t inbytes = inblock; + char *outbuf = buf; + size_t outbytes = outblock; + + size_t n = iconv(cnv, &inbuf, &inbytes, &outbuf, &outbytes); + total_bytes += inblock - inbytes; + + int e = 0; + if (n==(size_t)-1) { + e = errno; + if (str->total_bytes<=INT64_MAX) { + D("iconv failed @[%zu], inbytes[%zd->%zd], outbytes[%zd->%zd]: [%d]%s", + (inblock-inbytes), inblock, inbytes, outblock, outbytes, e, strerror(e)); + } + DASSERT(e==EILSEQ || e==E2BIG || e==EINVAL); + } + if (n>0 && n<=INT64_MAX) { + D("iconv found non-reversible seq"); + } + + size_t outlen = outblock - outbytes; + size_t utf8len = strnlen(buf, outlen); + if (utf8len < outlen) { + // null-terminator found + // revert + inbuf -= inblock - inbytes; + total_bytes -= inblock - inbytes; + + if (utf8len==0) break; + + inbytes = inblock; + outbuf = buf; + outbytes = utf8len; + + n = iconv(cnv, &inbuf, &inbytes, &outbuf, &outbytes); + total_bytes += inblock - inbytes; + DASSERT(n==(size_t)-1); + e = errno; + DASSERT(e==E2BIG); + + break; + } + + if (e==EILSEQ) break; + if (e==EINVAL) { + if (inbytes == remain) { + // this is the last stuff + break; + } + } + } + + if (str->total_bytes > INT64_MAX) { + str->total_bytes = total_bytes; + } + str->bytes = total_bytes; + + iconv(cnv, NULL, NULL, NULL, NULL); + + return 0; +} + diff --git a/src/connector/odbc/src/todbc_string.h b/src/connector/odbc/src/todbc_string.h new file mode 100644 index 0000000000000000000000000000000000000000..eed3356847a16ab383da63eaa8c503312273136a --- /dev/null +++ b/src/connector/odbc/src/todbc_string.h @@ -0,0 +1,54 @@ +/* + * 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 . + */ + +#ifndef _todbc_string_h_ +#define _todbc_string_h_ + +#include +#include + +#include "todbc_buf.h" + +// non-thread-safe + +typedef struct todbc_string_s todbc_string_t; +struct todbc_string_s { + // null if init failed because of internal resources shortage + const unsigned char *buf; // null-terminator inclusive + size_t total_bytes; // not counting null-terminator + + // <= total_bytes + // truncated if < total_bytes + size_t bytes; // not counting null-terminator + + // move here to satisfy todbc_string_t dummy = {0}; + char enc[64]; +}; + + +// does not copy internally +// bytes: not characters, <0 means bytes unknown +todbc_string_t todbc_string_init(const char *enc, const unsigned char *src, const size_t bytes); +// conv and copy to dst not more than target_bytes (null-terminator-inclusive) +// return'd val->buf == dst, total_bytes + * + * 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 . + */ + +#include "todbc_tls.h" + +#include "todbc_buf.h" +#include "todbc_iconv.h" +#include "todbc_log.h" + + +typedef struct todbc_tls_s todbc_tls_t; + +struct todbc_tls_s { + todbc_buf_t *buf; + todbc_iconvset_t *cnvset; +}; + + +static void todbc_tls_free(todbc_tls_t *value); + +static pthread_key_t key_this; +static pthread_once_t key_once = PTHREAD_ONCE_INIT; +static int key_err = 0; + + +static void key_init(void); +static void key_destructor(void *arg); + + +static void key_init(void) { + key_err = pthread_key_create(&key_this, key_destructor); + if (key_err) { + D("thread local initialization failed: [%d]%s", key_err, strerror(key_err)); + } +} + +static todbc_tls_t* todbc_tls_create(void); + +static todbc_tls_t* key_value(void) { + pthread_once(&key_once, key_init); + if (key_err) return NULL; + + int err = 0; + + todbc_tls_t *value = pthread_getspecific(key_this); + if (value) return value; + + value = todbc_tls_create(); + if (!value) return NULL; + + do { + err = pthread_setspecific(key_this, value); + if (err) { + D("thread local setup failed: [%d]%s", err, strerror(err)); + break; + } + + return value; + } while (0); + + todbc_tls_free(value); + + return NULL; +} + +static void key_destructor(void *arg) { + todbc_tls_t *value = (todbc_tls_t*)arg; + todbc_tls_free(value); +} + +static todbc_tls_t* todbc_tls_create(void) { + int err = 0; + todbc_tls_t *value = (todbc_tls_t*)calloc(1, sizeof(*value)); + if (!value) { + err = errno; + D("thread local creation failed: [%d]%s", err, strerror(err)); + return NULL; + } + do { + return value; + } while (0); + + todbc_tls_free(value); + return NULL; +} + +static void todbc_tls_free(todbc_tls_t *value) { + if (value->cnvset) { + todbc_iconvset_free(value->cnvset); + value->cnvset = NULL; + } + + if (value->buf) { + todbc_buf_free(value->buf); + value->buf = NULL; + } + + free(value); +} + +static todbc_iconvset_t* do_get_iconvset(void); + +// iconv +int todbc_legal_chars(const char *enc, const unsigned char *str, todbc_bytes_t *bc) { + todbc_iconvset_t *icnv = do_get_iconvset(); + if (!icnv) return -1; + todbc_iconv_t *cnv = todbc_iconvset_get(icnv, UTF16_ENC, enc); + if (!cnv) return -1; + return todbc_iconv_get_legal_chars(cnv, str, bc); +} + +todbc_iconv_t* todbc_tls_iconv_get(const char *to_enc, const char *from_enc) { + todbc_iconvset_t *cnvset = do_get_iconvset(); + if (!cnvset) return NULL; + todbc_iconv_t *cnv = todbc_iconvset_get(cnvset, to_enc, from_enc); + return cnv; +} + +iconv_t todbc_tls_iconv(const char *to_enc, const char *from_enc) { + todbc_iconv_t *icnv = todbc_tls_iconv_get(to_enc, from_enc); + if (!icnv) return (iconv_t)-1; + return todbc_iconv_get(icnv); +} + +todbc_enc_t todbc_tls_iconv_enc(const char *enc) { + do { + todbc_iconvset_t *cnvset = do_get_iconvset(); + if (!cnvset) break; + return todbc_iconvset_enc(cnvset, enc); + } while (0); + + todbc_enc_t v = {0}; + v.char_size = -1; + v.null_size = -1; + + return v; +} + +todbc_string_t todbc_tls_conv(todbc_buf_t *buf, const char *enc_to, const char *enc_from, const unsigned char *src, size_t *slen) { + todbc_iconv_t *cnv = todbc_tls_iconv_get(enc_to, enc_from); + if (!cnv) { + todbc_string_t nul = {0}; + return nul; + } + return todbc_iconv_conv2(cnv, buf, src, slen); +} + +todbc_string_t todbc_tls_write(const char *enc_to, const char *enc_from, + const unsigned char *src, size_t *slen, unsigned char *dst, size_t dlen) +{ + todbc_iconv_t *cnv = todbc_tls_iconv_get(enc_to, enc_from); + if (!cnv) { + todbc_string_t nul = {0}; + return nul; + } + todbc_string_t s = {0}; + s.buf = dst; + s.total_bytes = dlen; + size_t inbytes = *slen; + size_t outbytes = dlen; + todbc_iconv_raw(cnv, src, &inbytes, dst, &outbytes); + s.bytes = dlen - outbytes; + s.total_bytes = s.bytes; + if (inbytes) { + s.total_bytes += 1; + } + *slen = inbytes; + + return s; +} + +char* todbc_tls_strndup(const char *src, size_t n) { + todbc_buf_t *buf = todbc_tls_buf(); + if (!buf) return NULL; + n = strnlen(src, n); + char *d = todbc_buf_alloc(buf, (n+1)); + if (!d) return NULL; + snprintf(d, n+1, "%s", src); + return d; +} + +static todbc_iconvset_t* do_get_iconvset(void) { + todbc_tls_t *tls = key_value(); + if (!tls) return NULL; + if (!tls->cnvset) { + tls->cnvset = todbc_iconvset_create(); + } + return tls->cnvset; +} + +// tls_buf +void* todbc_tls_buf_alloc(size_t size) { + todbc_tls_t *tls = key_value(); + if (!tls) return NULL; + if (!tls->buf) { + tls->buf = todbc_buf_create(); + if (!tls->buf) return NULL; + } + return todbc_buf_alloc(tls->buf, size); +} + +void* todbc_tls_buf_calloc(size_t count, size_t size) { + todbc_tls_t *tls = key_value(); + if (!tls) return NULL; + if (!tls->buf) { + tls->buf = todbc_buf_create(); + if (!tls->buf) return NULL; + } + return todbc_buf_calloc(tls->buf, count, size); +} + +void* todbc_tls_buf_realloc(void *ptr, size_t size) { + todbc_tls_t *tls = key_value(); + if (!tls) return NULL; + if (!tls->buf) { + tls->buf = todbc_buf_create(); + if (!tls->buf) return NULL; + } + return todbc_buf_realloc(tls->buf, ptr, size); +} + +void todbc_tls_buf_reclaim(void) { + todbc_tls_t *tls = key_value(); + if (!tls) return; + if (!tls->buf) return; + + todbc_buf_reclaim(tls->buf); +} + +todbc_buf_t* todbc_tls_buf(void) { + todbc_tls_t *tls = key_value(); + if (!tls) return NULL; + if (!tls->buf) { + tls->buf = todbc_buf_create(); + } + return tls->buf; +} + diff --git a/src/connector/odbc/src/todbc_tls.h b/src/connector/odbc/src/todbc_tls.h new file mode 100644 index 0000000000000000000000000000000000000000..e636f6ae6c9c9051fe4a77d5e9d1e082e2dcfdb0 --- /dev/null +++ b/src/connector/odbc/src/todbc_tls.h @@ -0,0 +1,56 @@ +/* + * 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 . + */ + +#ifndef _todbc_tls_h_ +#define _todbc_tls_h_ + +// !!! functions exported in this header file are all non-thread-safe !!! + +#include "taos.h" + +#include "todbc_buf.h" +#include "todbc_iconv.h" +#include "todbc_string.h" + +// thread local buffers +// non-thread-safe +// returned-buf are all thread-local-accessible until todbc_tls_buf_reclaim +void* todbc_tls_buf_alloc(size_t size); +void* todbc_tls_buf_calloc(size_t count, size_t size); +void* todbc_tls_buf_realloc(void *ptr, size_t size); +// reclaim all above thread-local-buf(s) +void todbc_tls_buf_reclaim(void); + +// return local-thread-buf +todbc_buf_t* todbc_tls_buf(void); + +// thread local iconv +// non-thread-safe +todbc_iconv_t* todbc_tls_iconv_get(const char *to_enc, const char *from_enc); +iconv_t todbc_tls_iconv(const char *to_enc, const char *from_enc); + +todbc_enc_t todbc_tls_iconv_enc(const char *enc); + +// non-thread-safe +int todbc_legal_chars(const char *enc, const unsigned char *str, todbc_bytes_t *bc); + +// at return, *slen stores the remaining # +todbc_string_t todbc_tls_conv(todbc_buf_t *buf, const char *enc_to, const char *enc_from, const unsigned char *src, size_t *slen); +todbc_string_t todbc_tls_write(const char *enc_to, const char *enc_from, const unsigned char *src, size_t *slen, unsigned char *dst, size_t dlen); + +char* todbc_tls_strndup(const char *src, size_t n); + +#endif // _todbc_tls_h_ + diff --git a/src/connector/odbc/src/todbc_util.c b/src/connector/odbc/src/todbc_util.c index 9c130b4f2f2e6d0f5d4a19e11ab323d42b800195..d0b5abe09321c0b65b711b4e45e23e038c3dff88 100644 --- a/src/connector/odbc/src/todbc_util.c +++ b/src/connector/odbc/src/todbc_util.c @@ -15,86 +15,576 @@ #include "todbc_util.h" #include "todbc_log.h" + #include #include +#define SQL_CASE(type) case type: return #type + const char* sql_sql_type(int type) { switch (type) { - case SQL_BIT: return "SQL_BIT"; - case SQL_TINYINT: return "SQL_TINYINT"; - case SQL_SMALLINT: return "SQL_SMALLINT"; - case SQL_INTEGER: return "SQL_INTEGER"; - case SQL_BIGINT: return "SQL_BIGINT"; - case SQL_FLOAT: return "SQL_FLOAT"; - case SQL_DOUBLE: return "SQL_DOUBLE"; - case SQL_DECIMAL: return "SQL_DECIMAL"; - case SQL_NUMERIC: return "SQL_NUMERIC"; - case SQL_REAL: return "SQL_REAL"; - case SQL_CHAR: return "SQL_CHAR"; - case SQL_VARCHAR: return "SQL_VARCHAR"; - case SQL_LONGVARCHAR: return "SQL_LONGVARCHAR"; - case SQL_WCHAR: return "SQL_WCHAR"; - case SQL_WVARCHAR: return "SQL_WVARCHAR"; - case SQL_WLONGVARCHAR: return "SQL_WLONGVARCHAR"; - case SQL_BINARY: return "SQL_BINARY"; - case SQL_VARBINARY: return "SQL_VARBINARY"; - case SQL_LONGVARBINARY: return "SQL_LONGVARBINARY"; - case SQL_DATE: return "SQL_DATE"; - case SQL_TIME: return "SQL_TIME"; - case SQL_TIMESTAMP: return "SQL_TIMESTAMP"; - case SQL_TYPE_DATE: return "SQL_TYPE_DATE"; - case SQL_TYPE_TIME: return "SQL_TYPE_TIME"; - case SQL_TYPE_TIMESTAMP: return "SQL_TYPE_TIMESTAMP"; - case SQL_INTERVAL_MONTH: return "SQL_INTERVAL_MONTH"; - case SQL_INTERVAL_YEAR: return "SQL_INTERVAL_YEAR"; - case SQL_INTERVAL_YEAR_TO_MONTH: return "SQL_INTERVAL_YEAR_TO_MONTH"; - case SQL_INTERVAL_DAY: return "SQL_INTERVAL_DAY"; - case SQL_INTERVAL_HOUR: return "SQL_INTERVAL_HOUR"; - case SQL_INTERVAL_MINUTE: return "SQL_INTERVAL_MINUTE"; - case SQL_INTERVAL_SECOND: return "SQL_INTERVAL_SECOND"; - case SQL_INTERVAL_DAY_TO_HOUR: return "SQL_INTERVAL_DAY_TO_HOUR"; - case SQL_INTERVAL_DAY_TO_MINUTE: return "SQL_INTERVAL_DAY_TO_MINUTE"; - case SQL_INTERVAL_DAY_TO_SECOND: return "SQL_INTERVAL_DAY_TO_SECOND"; - case SQL_INTERVAL_HOUR_TO_MINUTE: return "SQL_INTERVAL_HOUR_TO_MINUTE"; - case SQL_INTERVAL_HOUR_TO_SECOND: return "SQL_INTERVAL_HOUR_TO_SECOND"; - case SQL_INTERVAL_MINUTE_TO_SECOND: return "SQL_INTERVAL_MINUTE_TO_SECOND"; - case SQL_GUID: return "SQL_GUID"; + SQL_CASE(SQL_BIT); + SQL_CASE(SQL_TINYINT); + SQL_CASE(SQL_SMALLINT); + SQL_CASE(SQL_INTEGER); + SQL_CASE(SQL_BIGINT); + SQL_CASE(SQL_FLOAT); + SQL_CASE(SQL_DOUBLE); + SQL_CASE(SQL_DECIMAL); + SQL_CASE(SQL_NUMERIC); + SQL_CASE(SQL_REAL); + SQL_CASE(SQL_CHAR); + SQL_CASE(SQL_VARCHAR); + SQL_CASE(SQL_LONGVARCHAR); + SQL_CASE(SQL_WCHAR); + SQL_CASE(SQL_WVARCHAR); + SQL_CASE(SQL_WLONGVARCHAR); + SQL_CASE(SQL_BINARY); + SQL_CASE(SQL_VARBINARY); + SQL_CASE(SQL_LONGVARBINARY); + SQL_CASE(SQL_DATE); + SQL_CASE(SQL_TIME); + SQL_CASE(SQL_TIMESTAMP); + SQL_CASE(SQL_TYPE_DATE); + SQL_CASE(SQL_TYPE_TIME); + SQL_CASE(SQL_TYPE_TIMESTAMP); + SQL_CASE(SQL_INTERVAL_MONTH); + SQL_CASE(SQL_INTERVAL_YEAR); + SQL_CASE(SQL_INTERVAL_YEAR_TO_MONTH); + SQL_CASE(SQL_INTERVAL_DAY); + SQL_CASE(SQL_INTERVAL_HOUR); + SQL_CASE(SQL_INTERVAL_MINUTE); + SQL_CASE(SQL_INTERVAL_SECOND); + SQL_CASE(SQL_INTERVAL_DAY_TO_HOUR); + SQL_CASE(SQL_INTERVAL_DAY_TO_MINUTE); + SQL_CASE(SQL_INTERVAL_DAY_TO_SECOND); + SQL_CASE(SQL_INTERVAL_HOUR_TO_MINUTE); + SQL_CASE(SQL_INTERVAL_HOUR_TO_SECOND); + SQL_CASE(SQL_INTERVAL_MINUTE_TO_SECOND); + SQL_CASE(SQL_GUID); + SQL_CASE(SQL_ALL_TYPES); default: return "UNKNOWN"; } } const char* sql_c_type(int type) { switch (type) { - case SQL_C_CHAR: return "SQL_C_CHAR"; - case SQL_C_WCHAR: return "SQL_C_WCHAR"; - case SQL_C_SHORT: return "SQL_C_SHORT"; - case SQL_C_SSHORT: return "SQL_C_SSHORT"; - case SQL_C_USHORT: return "SQL_C_USHORT"; - case SQL_C_LONG: return "SQL_C_LONG"; - case SQL_C_SLONG: return "SQL_C_SLONG"; - case SQL_C_ULONG: return "SQL_C_ULONG"; - case SQL_C_FLOAT: return "SQL_C_FLOAT"; - case SQL_C_DOUBLE: return "SQL_C_DOUBLE"; - case SQL_C_BIT: return "SQL_C_BIT"; - case SQL_C_TINYINT: return "SQL_C_TINYINT"; - case SQL_C_STINYINT: return "SQL_C_STINYINT"; - case SQL_C_UTINYINT: return "SQL_C_UTINYINT"; - case SQL_C_SBIGINT: return "SQL_C_SBIGINT"; - case SQL_C_UBIGINT: return "SQL_C_UBIGINT"; - case SQL_C_BINARY: return "SQL_C_BINARY"; - case SQL_C_DATE: return "SQL_C_DATE"; - case SQL_C_TIME: return "SQL_C_TIME"; - case SQL_C_TIMESTAMP: return "SQL_C_TIMESTAMP"; - case SQL_C_TYPE_DATE: return "SQL_C_TYPE_DATE"; - case SQL_C_TYPE_TIME: return "SQL_C_TYPE_TIME"; - case SQL_C_TYPE_TIMESTAMP: return "SQL_C_TYPE_TIMESTAMP"; - case SQL_C_NUMERIC: return "SQL_C_NUMERIC"; - case SQL_C_GUID: return "SQL_C_GUID"; + SQL_CASE(SQL_C_CHAR); + SQL_CASE(SQL_C_WCHAR); + SQL_CASE(SQL_C_SHORT); + SQL_CASE(SQL_C_SSHORT); + SQL_CASE(SQL_C_USHORT); + SQL_CASE(SQL_C_LONG); + SQL_CASE(SQL_C_SLONG); + SQL_CASE(SQL_C_ULONG); + SQL_CASE(SQL_C_FLOAT); + SQL_CASE(SQL_C_DOUBLE); + SQL_CASE(SQL_C_BIT); + SQL_CASE(SQL_C_TINYINT); + SQL_CASE(SQL_C_STINYINT); + SQL_CASE(SQL_C_UTINYINT); + SQL_CASE(SQL_C_SBIGINT); + SQL_CASE(SQL_C_UBIGINT); + SQL_CASE(SQL_C_BINARY); + SQL_CASE(SQL_C_DATE); + SQL_CASE(SQL_C_TIME); + SQL_CASE(SQL_C_TIMESTAMP); + SQL_CASE(SQL_C_TYPE_DATE); + SQL_CASE(SQL_C_TYPE_TIME); + SQL_CASE(SQL_C_TYPE_TIMESTAMP); + SQL_CASE(SQL_C_NUMERIC); + SQL_CASE(SQL_C_GUID); + default: return "UNKNOWN"; + } +} + +// https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlgetdiagfield-function?view=sql-server-ver15 +const char* sql_diag_identifier(int type) { + switch (type) { + // header fields + SQL_CASE(SQL_DIAG_CURSOR_ROW_COUNT); + SQL_CASE(SQL_DIAG_DYNAMIC_FUNCTION); + SQL_CASE(SQL_DIAG_DYNAMIC_FUNCTION_CODE); + SQL_CASE(SQL_DIAG_NUMBER); + SQL_CASE(SQL_DIAG_RETURNCODE); + SQL_CASE(SQL_DIAG_ROW_COUNT); + // record fields + SQL_CASE(SQL_DIAG_CLASS_ORIGIN); + SQL_CASE(SQL_DIAG_COLUMN_NUMBER); + SQL_CASE(SQL_DIAG_CONNECTION_NAME); + SQL_CASE(SQL_DIAG_MESSAGE_TEXT); + SQL_CASE(SQL_DIAG_NATIVE); + SQL_CASE(SQL_DIAG_ROW_NUMBER); + SQL_CASE(SQL_DIAG_SERVER_NAME); + SQL_CASE(SQL_DIAG_SQLSTATE); + SQL_CASE(SQL_DIAG_SUBCLASS_ORIGIN); + default: return "UNKNOWN"; + } +} + +const char* sql_handle_type(int type) { + switch(type) { + SQL_CASE(SQL_HANDLE_ENV); + SQL_CASE(SQL_HANDLE_DBC); + SQL_CASE(SQL_HANDLE_STMT); + SQL_CASE(SQL_HANDLE_DESC); + // SQL_CASE(SQL_HANDLE_DBC_INFO_TOKEN); + default: return "UNKNOWN"; + } +} + +const char* sql_env_attr_type(int type) { + switch(type) { + SQL_CASE(SQL_ATTR_OUTPUT_NTS); + SQL_CASE(SQL_ATTR_ODBC_VERSION); + SQL_CASE(SQL_ATTR_CONNECTION_POOLING); + SQL_CASE(SQL_ATTR_CP_MATCH); + default: return "UNKNOWN"; + } +} + +// https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlsetconnectattr-function?view=sql-server-ver15 +const char* sql_conn_attr_type(int type) { + switch(type) { + SQL_CASE(SQL_ATTR_ACCESS_MODE); + // ODBC 3.8 + // SQL_CASE(SQL_ATTR_ASYNC_DBC_EVENT); + SQL_CASE(SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE); + // ODBC 3.8 + // SQL_CASE(SQL_ATTR_ASYNC_DBC_PCALLBACK); + // ODBC 3.8 + // SQL_CASE(SQL_ATTR_ASYNC_DBC_PCONTEXT); + SQL_CASE(SQL_ATTR_ASYNC_ENABLE); + SQL_CASE(SQL_ATTR_AUTO_IPD); + SQL_CASE(SQL_ATTR_AUTOCOMMIT); + SQL_CASE(SQL_ATTR_CONNECTION_DEAD); + SQL_CASE(SQL_ATTR_CONNECTION_TIMEOUT); + SQL_CASE(SQL_ATTR_CURRENT_CATALOG); + // ODBC 3.8 + // SQL_CASE(SQL_ATTR_DBC_INFO_TOKEN); + SQL_CASE(SQL_ATTR_ENLIST_IN_DTC); + SQL_CASE(SQL_ATTR_LOGIN_TIMEOUT); + SQL_CASE(SQL_ATTR_METADATA_ID); + SQL_CASE(SQL_ATTR_ODBC_CURSORS); + SQL_CASE(SQL_ATTR_PACKET_SIZE); + SQL_CASE(SQL_ATTR_QUIET_MODE); + SQL_CASE(SQL_ATTR_TRACE); + SQL_CASE(SQL_ATTR_TRACEFILE); + SQL_CASE(SQL_ATTR_TRANSLATE_LIB); + SQL_CASE(SQL_ATTR_TRANSLATE_OPTION); + SQL_CASE(SQL_ATTR_TXN_ISOLATION); + default: return "UNKNOWN"; + } +} + +// https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlgetinfo-function?view=sql-server-ver15 +const char* sql_info_type(int type) { + switch(type) { + SQL_CASE(SQL_ACTIVE_ENVIRONMENTS); + SQL_CASE(SQL_ASYNC_DBC_FUNCTIONS); + SQL_CASE(SQL_ASYNC_MODE); + SQL_CASE(SQL_ASYNC_NOTIFICATION); + SQL_CASE(SQL_BATCH_ROW_COUNT); + SQL_CASE(SQL_BATCH_SUPPORT); + SQL_CASE(SQL_DATA_SOURCE_NAME); + SQL_CASE(SQL_DRIVER_AWARE_POOLING_SUPPORTED); + SQL_CASE(SQL_DRIVER_HDBC); + SQL_CASE(SQL_DRIVER_HDESC); + SQL_CASE(SQL_DRIVER_HENV); + SQL_CASE(SQL_DRIVER_HLIB); + SQL_CASE(SQL_DRIVER_HSTMT); + SQL_CASE(SQL_DRIVER_NAME); + SQL_CASE(SQL_DRIVER_ODBC_VER); + SQL_CASE(SQL_DRIVER_VER); + SQL_CASE(SQL_DYNAMIC_CURSOR_ATTRIBUTES1); + SQL_CASE(SQL_DYNAMIC_CURSOR_ATTRIBUTES2); + SQL_CASE(SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1); + SQL_CASE(SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2); + SQL_CASE(SQL_FILE_USAGE); + SQL_CASE(SQL_GETDATA_EXTENSIONS); + SQL_CASE(SQL_INFO_SCHEMA_VIEWS); + SQL_CASE(SQL_KEYSET_CURSOR_ATTRIBUTES1); + SQL_CASE(SQL_KEYSET_CURSOR_ATTRIBUTES2); + SQL_CASE(SQL_MAX_ASYNC_CONCURRENT_STATEMENTS); + SQL_CASE(SQL_MAX_CONCURRENT_ACTIVITIES); + SQL_CASE(SQL_MAX_DRIVER_CONNECTIONS); + SQL_CASE(SQL_ODBC_INTERFACE_CONFORMANCE); + // SQL_CASE(SQL_ODBC_STANDARD_CLI_CONFORMANCE); + SQL_CASE(SQL_ODBC_VER); + SQL_CASE(SQL_PARAM_ARRAY_ROW_COUNTS); + SQL_CASE(SQL_PARAM_ARRAY_SELECTS); + SQL_CASE(SQL_ROW_UPDATES); + SQL_CASE(SQL_SEARCH_PATTERN_ESCAPE); + SQL_CASE(SQL_SERVER_NAME); + SQL_CASE(SQL_STATIC_CURSOR_ATTRIBUTES1); + SQL_CASE(SQL_STATIC_CURSOR_ATTRIBUTES2); + + SQL_CASE(SQL_DATABASE_NAME); + SQL_CASE(SQL_DBMS_NAME); + SQL_CASE(SQL_DBMS_VER); + + SQL_CASE(SQL_ACCESSIBLE_PROCEDURES); + SQL_CASE(SQL_ACCESSIBLE_TABLES); + SQL_CASE(SQL_BOOKMARK_PERSISTENCE); + SQL_CASE(SQL_CATALOG_TERM); + SQL_CASE(SQL_COLLATION_SEQ); + SQL_CASE(SQL_CONCAT_NULL_BEHAVIOR); + SQL_CASE(SQL_CURSOR_COMMIT_BEHAVIOR); + SQL_CASE(SQL_CURSOR_ROLLBACK_BEHAVIOR); + SQL_CASE(SQL_CURSOR_SENSITIVITY); + SQL_CASE(SQL_DATA_SOURCE_READ_ONLY); + SQL_CASE(SQL_DEFAULT_TXN_ISOLATION); + SQL_CASE(SQL_DESCRIBE_PARAMETER); + SQL_CASE(SQL_MULT_RESULT_SETS); + SQL_CASE(SQL_MULTIPLE_ACTIVE_TXN); + SQL_CASE(SQL_NEED_LONG_DATA_LEN); + SQL_CASE(SQL_NULL_COLLATION); + SQL_CASE(SQL_PROCEDURE_TERM); + SQL_CASE(SQL_SCHEMA_TERM); + SQL_CASE(SQL_SCROLL_OPTIONS); + SQL_CASE(SQL_TABLE_TERM); + SQL_CASE(SQL_TXN_CAPABLE); + SQL_CASE(SQL_TXN_ISOLATION_OPTION); + SQL_CASE(SQL_USER_NAME); + + SQL_CASE(SQL_AGGREGATE_FUNCTIONS); + SQL_CASE(SQL_ALTER_DOMAIN); + // SQL_CASE(SQL_ALTER_SCHEMA); + SQL_CASE(SQL_ALTER_TABLE); + // SQL_CASE(SQL_ANSI_SQL_DATETIME_LITERALS); + SQL_CASE(SQL_CATALOG_LOCATION); + SQL_CASE(SQL_CATALOG_NAME); + SQL_CASE(SQL_CATALOG_NAME_SEPARATOR); + SQL_CASE(SQL_CATALOG_USAGE); + SQL_CASE(SQL_COLUMN_ALIAS); + SQL_CASE(SQL_CORRELATION_NAME); + SQL_CASE(SQL_CREATE_ASSERTION); + SQL_CASE(SQL_CREATE_CHARACTER_SET); + SQL_CASE(SQL_CREATE_COLLATION); + SQL_CASE(SQL_CREATE_DOMAIN); + SQL_CASE(SQL_CREATE_SCHEMA); + SQL_CASE(SQL_CREATE_TABLE); + SQL_CASE(SQL_CREATE_TRANSLATION); + SQL_CASE(SQL_DDL_INDEX); + SQL_CASE(SQL_DROP_ASSERTION); + SQL_CASE(SQL_DROP_CHARACTER_SET); + SQL_CASE(SQL_DROP_COLLATION); + SQL_CASE(SQL_DROP_DOMAIN); + SQL_CASE(SQL_DROP_SCHEMA); + + SQL_CASE(SQL_DROP_TABLE); + SQL_CASE(SQL_DROP_TRANSLATION); + SQL_CASE(SQL_DROP_VIEW); + SQL_CASE(SQL_EXPRESSIONS_IN_ORDERBY); + SQL_CASE(SQL_GROUP_BY); + SQL_CASE(SQL_IDENTIFIER_CASE); + SQL_CASE(SQL_IDENTIFIER_QUOTE_CHAR); + SQL_CASE(SQL_INDEX_KEYWORDS); + SQL_CASE(SQL_INSERT_STATEMENT); + SQL_CASE(SQL_INTEGRITY); + SQL_CASE(SQL_KEYWORDS); + SQL_CASE(SQL_LIKE_ESCAPE_CLAUSE); + SQL_CASE(SQL_NON_NULLABLE_COLUMNS); + SQL_CASE(SQL_OJ_CAPABILITIES); + SQL_CASE(SQL_ORDER_BY_COLUMNS_IN_SELECT); + SQL_CASE(SQL_OUTER_JOINS); + SQL_CASE(SQL_PROCEDURES); + SQL_CASE(SQL_QUOTED_IDENTIFIER_CASE); + SQL_CASE(SQL_SCHEMA_USAGE); + SQL_CASE(SQL_SPECIAL_CHARACTERS); + SQL_CASE(SQL_SQL_CONFORMANCE); + SQL_CASE(SQL_SUBQUERIES); + SQL_CASE(SQL_UNION); + + SQL_CASE(SQL_MAX_BINARY_LITERAL_LEN); + SQL_CASE(SQL_MAX_CATALOG_NAME_LEN); + SQL_CASE(SQL_MAX_CHAR_LITERAL_LEN); + SQL_CASE(SQL_MAX_COLUMN_NAME_LEN); + SQL_CASE(SQL_MAX_COLUMNS_IN_GROUP_BY); + SQL_CASE(SQL_MAX_COLUMNS_IN_INDEX); + SQL_CASE(SQL_MAX_COLUMNS_IN_ORDER_BY); + SQL_CASE(SQL_MAX_COLUMNS_IN_SELECT); + SQL_CASE(SQL_MAX_COLUMNS_IN_TABLE); + SQL_CASE(SQL_MAX_CURSOR_NAME_LEN); + + SQL_CASE(SQL_MAX_IDENTIFIER_LEN); + SQL_CASE(SQL_MAX_INDEX_SIZE); + SQL_CASE(SQL_MAX_PROCEDURE_NAME_LEN); + SQL_CASE(SQL_MAX_ROW_SIZE); + SQL_CASE(SQL_MAX_ROW_SIZE_INCLUDES_LONG); + SQL_CASE(SQL_MAX_SCHEMA_NAME_LEN); + SQL_CASE(SQL_MAX_STATEMENT_LEN); + SQL_CASE(SQL_MAX_TABLE_NAME_LEN); + SQL_CASE(SQL_MAX_TABLES_IN_SELECT); + SQL_CASE(SQL_MAX_USER_NAME_LEN); + + SQL_CASE(SQL_CONVERT_FUNCTIONS); + SQL_CASE(SQL_NUMERIC_FUNCTIONS); + SQL_CASE(SQL_STRING_FUNCTIONS); + SQL_CASE(SQL_SYSTEM_FUNCTIONS); + + SQL_CASE(SQL_TIMEDATE_ADD_INTERVALS); + SQL_CASE(SQL_TIMEDATE_DIFF_INTERVALS); + SQL_CASE(SQL_TIMEDATE_FUNCTIONS); + + SQL_CASE(SQL_CONVERT_BIGINT); + SQL_CASE(SQL_CONVERT_BINARY); + SQL_CASE(SQL_CONVERT_BIT); + SQL_CASE(SQL_CONVERT_CHAR); + SQL_CASE(SQL_CONVERT_DATE); + SQL_CASE(SQL_CONVERT_DECIMAL); + SQL_CASE(SQL_CONVERT_DOUBLE); + SQL_CASE(SQL_CONVERT_FLOAT); + SQL_CASE(SQL_CONVERT_INTEGER); + SQL_CASE(SQL_CONVERT_INTERVAL_DAY_TIME); + SQL_CASE(SQL_CONVERT_INTERVAL_YEAR_MONTH); + + SQL_CASE(SQL_CONVERT_LONGVARBINARY); + SQL_CASE(SQL_CONVERT_LONGVARCHAR); + SQL_CASE(SQL_CONVERT_NUMERIC); + SQL_CASE(SQL_CONVERT_REAL); + SQL_CASE(SQL_CONVERT_SMALLINT); + SQL_CASE(SQL_CONVERT_TIME); + SQL_CASE(SQL_CONVERT_TIMESTAMP); + SQL_CASE(SQL_CONVERT_TINYINT); + SQL_CASE(SQL_CONVERT_VARBINARY); + SQL_CASE(SQL_CONVERT_VARCHAR); + + SQL_CASE(SQL_DM_VER); + + SQL_CASE(SQL_XOPEN_CLI_YEAR); + + SQL_CASE(SQL_DTC_TRANSITION_COST); + + default: return "UNKNOWN"; + } +} + +// https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlcolattribute-function?view=sql-server-ver15 +const char* sql_field_identifier(int type) { + switch (type) { + SQL_CASE(SQL_DESC_AUTO_UNIQUE_VALUE); + SQL_CASE(SQL_DESC_BASE_COLUMN_NAME); + SQL_CASE(SQL_DESC_BASE_TABLE_NAME); + SQL_CASE(SQL_DESC_CASE_SENSITIVE); + SQL_CASE(SQL_DESC_CATALOG_NAME); + SQL_CASE(SQL_DESC_CONCISE_TYPE); + SQL_CASE(SQL_DESC_COUNT); + SQL_CASE(SQL_DESC_DISPLAY_SIZE); + SQL_CASE(SQL_DESC_FIXED_PREC_SCALE); + SQL_CASE(SQL_DESC_LABEL); + SQL_CASE(SQL_DESC_LENGTH); + SQL_CASE(SQL_DESC_LITERAL_PREFIX); + SQL_CASE(SQL_DESC_LITERAL_SUFFIX); + SQL_CASE(SQL_DESC_LOCAL_TYPE_NAME); + SQL_CASE(SQL_DESC_NAME); + SQL_CASE(SQL_DESC_NULLABLE); + SQL_CASE(SQL_DESC_NUM_PREC_RADIX); + SQL_CASE(SQL_DESC_OCTET_LENGTH); + SQL_CASE(SQL_DESC_PRECISION); + SQL_CASE(SQL_DESC_SCALE); + SQL_CASE(SQL_DESC_SCHEMA_NAME); + SQL_CASE(SQL_DESC_SEARCHABLE); + SQL_CASE(SQL_DESC_TABLE_NAME); + SQL_CASE(SQL_DESC_TYPE); + SQL_CASE(SQL_DESC_TYPE_NAME); + SQL_CASE(SQL_DESC_UNNAMED); + SQL_CASE(SQL_DESC_UNSIGNED); + SQL_CASE(SQL_DESC_UPDATABLE); default: return "UNKNOWN"; } } +// https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlbindparameter-function?view=sql-server-ver15 +const char* sql_input_output_type(int type) { + switch (type) { + SQL_CASE(SQL_PARAM_INPUT); + SQL_CASE(SQL_PARAM_OUTPUT); + SQL_CASE(SQL_PARAM_OUTPUT_STREAM); + SQL_CASE(SQL_PARAM_INPUT_OUTPUT); + SQL_CASE(SQL_PARAM_INPUT_OUTPUT_STREAM); + default: return "UNKNOWN"; + } +} + +// https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlsetstmtattr-function?view=sql-server-ver15 +const char* sql_stmt_attr_type(int type) { + switch (type) { + SQL_CASE(SQL_ATTR_APP_PARAM_DESC); + SQL_CASE(SQL_ATTR_APP_ROW_DESC); + SQL_CASE(SQL_ATTR_ASYNC_ENABLE); + SQL_CASE(SQL_ATTR_ASYNC_STMT_EVENT); + // ODBC 3.8 + // SQL_CASE(SQL_ATTR_ASYNC_STMT_PCALLBACK); + // ODBC 3.8 + // SQL_CASE(SQL_ATTR_ASYNC_STMT_PCONTEXT); + SQL_CASE(SQL_ATTR_CONCURRENCY); + SQL_CASE(SQL_ATTR_CURSOR_SCROLLABLE); + SQL_CASE(SQL_ATTR_CURSOR_SENSITIVITY); + SQL_CASE(SQL_ATTR_CURSOR_TYPE); + SQL_CASE(SQL_ATTR_ENABLE_AUTO_IPD); + SQL_CASE(SQL_ATTR_FETCH_BOOKMARK_PTR); + SQL_CASE(SQL_ATTR_IMP_PARAM_DESC); + SQL_CASE(SQL_ATTR_IMP_ROW_DESC); + SQL_CASE(SQL_ATTR_KEYSET_SIZE); + SQL_CASE(SQL_ATTR_MAX_LENGTH); + SQL_CASE(SQL_ATTR_MAX_ROWS); + SQL_CASE(SQL_ATTR_METADATA_ID); + SQL_CASE(SQL_ATTR_NOSCAN); + SQL_CASE(SQL_ATTR_PARAM_BIND_OFFSET_PTR); + SQL_CASE(SQL_ATTR_PARAM_BIND_TYPE); + SQL_CASE(SQL_ATTR_PARAM_OPERATION_PTR); + SQL_CASE(SQL_ATTR_PARAM_STATUS_PTR); + SQL_CASE(SQL_ATTR_PARAMS_PROCESSED_PTR); + SQL_CASE(SQL_ATTR_PARAMSET_SIZE); + SQL_CASE(SQL_ATTR_QUERY_TIMEOUT); + SQL_CASE(SQL_ATTR_RETRIEVE_DATA); + SQL_CASE(SQL_ATTR_ROW_ARRAY_SIZE); + SQL_CASE(SQL_ATTR_ROW_BIND_OFFSET_PTR); + SQL_CASE(SQL_ATTR_ROW_BIND_TYPE); + SQL_CASE(SQL_ATTR_ROW_NUMBER); + SQL_CASE(SQL_ATTR_ROW_OPERATION_PTR); + SQL_CASE(SQL_ATTR_ROW_STATUS_PTR); + SQL_CASE(SQL_ATTR_ROWS_FETCHED_PTR); + SQL_CASE(SQL_ATTR_SIMULATE_CURSOR); + SQL_CASE(SQL_ATTR_USE_BOOKMARKS); + default: return "UNKNOWN"; + } +} + +const char* sql_function_type(int type) { + switch (type) { + // + SQL_CASE(SQL_API_ALL_FUNCTIONS); + SQL_CASE(SQL_API_ODBC3_ALL_FUNCTIONS); + + // ISO 92 standards-compliance + SQL_CASE(SQL_API_SQLALLOCHANDLE); + SQL_CASE(SQL_API_SQLGETDESCFIELD); + SQL_CASE(SQL_API_SQLBINDCOL); + SQL_CASE(SQL_API_SQLGETDESCREC); + SQL_CASE(SQL_API_SQLCANCEL); + SQL_CASE(SQL_API_SQLGETDIAGFIELD); + SQL_CASE(SQL_API_SQLCLOSECURSOR); + SQL_CASE(SQL_API_SQLGETDIAGREC); + SQL_CASE(SQL_API_SQLCOLATTRIBUTE); + SQL_CASE(SQL_API_SQLGETENVATTR); + SQL_CASE(SQL_API_SQLCONNECT); + SQL_CASE(SQL_API_SQLGETFUNCTIONS); + SQL_CASE(SQL_API_SQLCOPYDESC); + SQL_CASE(SQL_API_SQLGETINFO); + SQL_CASE(SQL_API_SQLDATASOURCES); + SQL_CASE(SQL_API_SQLGETSTMTATTR); + SQL_CASE(SQL_API_SQLDESCRIBECOL); + SQL_CASE(SQL_API_SQLGETTYPEINFO); + SQL_CASE(SQL_API_SQLDISCONNECT); + SQL_CASE(SQL_API_SQLNUMRESULTCOLS); + SQL_CASE(SQL_API_SQLDRIVERS); + SQL_CASE(SQL_API_SQLPARAMDATA); + SQL_CASE(SQL_API_SQLENDTRAN); + SQL_CASE(SQL_API_SQLPREPARE); + SQL_CASE(SQL_API_SQLEXECDIRECT); + SQL_CASE(SQL_API_SQLPUTDATA); + SQL_CASE(SQL_API_SQLEXECUTE); + SQL_CASE(SQL_API_SQLROWCOUNT); + SQL_CASE(SQL_API_SQLFETCH); + SQL_CASE(SQL_API_SQLSETCONNECTATTR); + SQL_CASE(SQL_API_SQLFETCHSCROLL); + SQL_CASE(SQL_API_SQLSETCURSORNAME); + SQL_CASE(SQL_API_SQLFREEHANDLE); + SQL_CASE(SQL_API_SQLSETDESCFIELD); + SQL_CASE(SQL_API_SQLFREESTMT); + SQL_CASE(SQL_API_SQLSETDESCREC); + SQL_CASE(SQL_API_SQLGETCONNECTATTR); + SQL_CASE(SQL_API_SQLSETENVATTR); + SQL_CASE(SQL_API_SQLGETCURSORNAME); + SQL_CASE(SQL_API_SQLSETSTMTATTR); + SQL_CASE(SQL_API_SQLGETDATA); + + // Open Group standards-compliance); + SQL_CASE(SQL_API_SQLCOLUMNS); + SQL_CASE(SQL_API_SQLSTATISTICS); + SQL_CASE(SQL_API_SQLSPECIALCOLUMNS); + SQL_CASE(SQL_API_SQLTABLES); + + // ODBC standards-compliance); + SQL_CASE(SQL_API_SQLBINDPARAMETER); + SQL_CASE(SQL_API_SQLNATIVESQL); + SQL_CASE(SQL_API_SQLBROWSECONNECT); + SQL_CASE(SQL_API_SQLNUMPARAMS); + SQL_CASE(SQL_API_SQLBULKOPERATIONS); + SQL_CASE(SQL_API_SQLPRIMARYKEYS); + SQL_CASE(SQL_API_SQLCOLUMNPRIVILEGES); + SQL_CASE(SQL_API_SQLPROCEDURECOLUMNS); + SQL_CASE(SQL_API_SQLDESCRIBEPARAM); + SQL_CASE(SQL_API_SQLPROCEDURES); + SQL_CASE(SQL_API_SQLDRIVERCONNECT); + SQL_CASE(SQL_API_SQLSETPOS); + SQL_CASE(SQL_API_SQLFOREIGNKEYS); + SQL_CASE(SQL_API_SQLTABLEPRIVILEGES); + SQL_CASE(SQL_API_SQLMORERESULTS); + + SQL_CASE(SQL_API_SQLALLOCCONNECT); + SQL_CASE(SQL_API_SQLALLOCENV); + SQL_CASE(SQL_API_SQLALLOCSTMT); + SQL_CASE(SQL_API_SQLBINDPARAM); + SQL_CASE(SQL_API_SQLERROR); + SQL_CASE(SQL_API_SQLFREECONNECT); + SQL_CASE(SQL_API_SQLFREEENV); + SQL_CASE(SQL_API_SQLGETCONNECTOPTION); + SQL_CASE(SQL_API_SQLGETSTMTOPTION); + SQL_CASE(SQL_API_SQLSETCONNECTOPTION); + SQL_CASE(SQL_API_SQLSETPARAM); + SQL_CASE(SQL_API_SQLSETSTMTOPTION); + SQL_CASE(SQL_API_SQLTRANSACT); + SQL_CASE(SQL_API_SQLCANCELHANDLE); + + default: return "UNKNOWN"; + } +} + +const char* sql_freestmt_option_type(int type) { + switch (type) { + SQL_CASE(SQL_CLOSE); + SQL_CASE(SQL_DROP); + SQL_CASE(SQL_UNBIND); + SQL_CASE(SQL_RESET_PARAMS); + default: return "UNKNOWN"; + } +} + +const char* sql_soi_type(int soi) { + switch (soi) { + SQL_CASE(SQL_NTS); + SQL_CASE(SQL_NULL_DATA); + SQL_CASE(SQL_DEFAULT_PARAM); + SQL_CASE(SQL_DATA_AT_EXEC); + default: { + if (soi >= 0) return ""; + return "SQL_LEN_DATA_AT_EXEC(?)"; + } break; + } +} + +const char* sql_nullable_type(int type) { + switch (type) { + SQL_CASE(SQL_NO_NULLS); + SQL_CASE(SQL_NULLABLE); + SQL_CASE(SQL_NULLABLE_UNKNOWN); + default: { + return "UNKNOWN"; + } break; + } +} + + + + + + + + int is_valid_sql_c_type(int type) { const char *ctype = sql_c_type(type); if (strcmp(ctype, "UNKNOWN")==0) return 0; @@ -127,3 +617,46 @@ int utf8_chars(const char *src) return (int)chars; } +static int do_charset_chars(iconv_t cnv, const unsigned char *src) +{ + int chars = 0; + char *ps = (char*)src; + char buf[16]; + size_t sn = 1; + while (1) { + char *ds = buf; + size_t dn = sizeof(buf); + size_t n = iconv(cnv, &ps, &sn, &ds, &dn); + if (n==(size_t)-1) { + int e = errno; + switch (e) { + case EILSEQ: return -1; + case E2BIG: return -1; + case EINVAL: sn += 1; continue; + default: return -1; + } + } + if (sn) return -1; + if (n>0) return -1; + int i=0; + for (i=0; i<(sizeof(buf)-dn); ++i) { + if (buf[i]) break; + } + if (i>=(sizeof(buf)-dn)) break; + chars += (int)1; + sn = 1; + } + return chars; +} + +int charset_chars(const char *charset, const unsigned char *src) { + iconv_t cnv = iconv_open(charset, charset); + if (cnv==(iconv_t)-1) return -1; + + int chars = do_charset_chars(cnv, src); + + iconv_close(cnv); + + return chars; +} + diff --git a/src/connector/odbc/src/todbc_util.h b/src/connector/odbc/src/todbc_util.h index ead0d7348973409c85741cc4d676e40f6f140447..a340c32546e0b40ba05eda190c03944d1cea4d55 100644 --- a/src/connector/odbc/src/todbc_util.h +++ b/src/connector/odbc/src/todbc_util.h @@ -23,11 +23,24 @@ const char* sql_sql_type(int type); const char* sql_c_type(int type); +const char* sql_handle_type(int type); +const char* sql_env_attr_type(int type); +const char* sql_conn_attr_type(int type); +const char* sql_info_type(int type); +const char* sql_field_identifier(int type); +const char* sql_diag_identifier(int type); +const char* sql_input_output_type(int type); +const char* sql_stmt_attr_type(int type); +const char* sql_function_type(int type); +const char* sql_freestmt_option_type(int type); +const char* sql_soi_type(int soi); +const char* sql_nullable_type(int type); int is_valid_sql_c_type(int type); int is_valid_sql_sql_type(int type); int utf8_chars(const char *src); +int charset_chars(const char *charset, const unsigned char *src); #endif // _TODBC_UTIL_H_ diff --git a/src/connector/odbc/tests/CMakeLists.txt b/src/connector/odbc/tests/CMakeLists.txt deleted file mode 100644 index 1cc6acaf4bf34aa2158cc1f4fa0836d6e51f3a41..0000000000000000000000000000000000000000 --- a/src/connector/odbc/tests/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -PROJECT(TDengine) - -IF (TD_LINUX) - # AUX_SOURCE_DIRECTORY(. SRC) - ADD_EXECUTABLE(tcodbc main.c) - TARGET_LINK_LIBRARIES(tcodbc odbc) - ADD_EXECUTABLE(tconv tconv.c) -ENDIF () - -IF (TD_WINDOWS_64) - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /GL") - SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") - # AUX_SOURCE_DIRECTORY(. SRC) - ADD_EXECUTABLE(tcodbc main.c) - TARGET_LINK_LIBRARIES(tcodbc odbc32 odbccp32 user32 legacy_stdio_definitions os) - ADD_EXECUTABLE(tconv tconv.c) - TARGET_LINK_LIBRARIES(tconv tutil) -ENDIF () diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c deleted file mode 100644 index 417de00d55f64249a9194b77fecbeb458c560cc7..0000000000000000000000000000000000000000 --- a/src/connector/odbc/tests/main.c +++ /dev/null @@ -1,673 +0,0 @@ -#include "../src/todbc_log.h" - -#ifdef _MSC_VER -#include -#include -#include "os.h" -#endif -#include -#include -#include - -#include -#include - -#define CHK_TEST(statement) \ -do { \ - D("testing: %s", #statement); \ - int r = (statement); \ - if (r) { \ - D("testing failed: %s", #statement); \ - return 1; \ - } \ -} while (0); - -typedef struct db_column_s db_column_t; -struct db_column_s { - SQLSMALLINT nameLength; - char name[4096]; // seems enough - SQLSMALLINT dataType; - SQLULEN columnSize; - SQLSMALLINT decimalDigits; - SQLSMALLINT nullable; -}; - -static db_column_t *columns = NULL; - -typedef struct data_s data_t; -struct data_s { - int64_t ts; - int8_t b; - int8_t v1; - int16_t v2; - int32_t v4; - int64_t v8; - float f4; - double f8; - char bin[40+1]; - char blob[40+1]; // why 80? ref: tests/examples/c/apitest.c -}; - -static const char *pre_stmts[] = { - "create database db", - "use db", - "create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), blob nchar(10))" -}; - -static const char *pro_stmts[] = { - // "insert into t values ('2019-07-15 00:00:00', 1)", - // "insert into t values ('2019-07-15 01:00:00', 2)", - "select * from t" - // "drop database db" -}; - -#define CHK_RESULT(r, ht, h, fmt, ...) \ -do { \ - if (r==0) break; \ - SQLCHAR ss[10]; \ - SQLINTEGER ne = 0; \ - SQLCHAR es[4096]; \ - SQLSMALLINT n = 0; \ - ss[0] = '\0'; \ - es[0] = '\0'; \ - SQLRETURN ret = SQLGetDiagRec(ht, h, 1, ss, &ne, es, sizeof(es), &n); \ - if (ret) break; \ - D("[%s]%s: " fmt "", ss, es, ##__VA_ARGS__); \ -} while (0) - -static int open_connect(const char *dsn, const char *uid, const char *pwd, SQLHENV *pEnv, SQLHDBC *pConn) { - SQLRETURN r; - SQLHENV env = {0}; - SQLHDBC conn = {0}; - r = SQLAllocEnv(&env); - if (r!=SQL_SUCCESS) return 1; - do { - r = SQLAllocConnect(env, &conn); - CHK_RESULT(r, SQL_HANDLE_ENV, env, ""); - if (r!=SQL_SUCCESS) break; - do { - r = SQLConnect(conn, (SQLCHAR*)dsn, (SQLSMALLINT)(dsn ? strlen(dsn) : 0), - (SQLCHAR*)uid, (SQLSMALLINT)(uid ? strlen(uid) : 0), - (SQLCHAR*)pwd, (SQLSMALLINT)(pwd ? strlen(pwd) : 0)); - CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); - if (r==SQL_SUCCESS) { - *pEnv = env; - *pConn = conn; - return 0; - } - } while (0); - SQLFreeConnect(conn); - } while (0); - SQLFreeEnv(env); - - return 1; -} - -static int open_driver_connect(const char *connstr, SQLHENV *pEnv, SQLHDBC *pConn) { - SQLRETURN r; - SQLHENV env = {0}; - SQLHDBC conn = {0}; - r = SQLAllocEnv(&env); - if (r!=SQL_SUCCESS) return 1; - do { - r = SQLAllocConnect(env, &conn); - CHK_RESULT(r, SQL_HANDLE_ENV, env, ""); - if (r!=SQL_SUCCESS) break; - do { - SQLCHAR buf[4096]; - SQLSMALLINT blen = 0; - SQLHDBC ConnectionHandle = conn; - SQLHWND WindowHandle = NULL; - SQLCHAR * InConnectionString = (SQLCHAR*)connstr; - SQLSMALLINT StringLength1 = (SQLSMALLINT)(connstr ? strlen(connstr) : 0); - SQLCHAR * OutConnectionString = buf; - SQLSMALLINT BufferLength = sizeof(buf); - SQLSMALLINT * StringLength2Ptr = &blen; - SQLUSMALLINT DriverCompletion = SQL_DRIVER_NOPROMPT; - r = SQLDriverConnect(ConnectionHandle, WindowHandle, InConnectionString, - StringLength1, OutConnectionString, BufferLength, - StringLength2Ptr, DriverCompletion); - CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); - if (r==SQL_SUCCESS) { - *pEnv = env; - *pConn = conn; - return 0; - } - } while (0); - SQLFreeConnect(conn); - } while (0); - SQLFreeEnv(env); - - return 1; -} - -static SQLRETURN traverse_cols(SQLHSTMT stmt, SQLSMALLINT cols) { - SQLRETURN r = SQL_ERROR; - for (SQLSMALLINT i=0; i0) fprintf(stdout, "\n"); - return r; - } - } - if (soi==SQL_NULL_DATA) { - fprintf(stdout, "%snull", i==0?"":","); - } else { - fprintf(stdout, "%s\"%s\"", i==0?"":",", buf); - } - } - fprintf(stdout, "\n"); - } - - // r = SQLFetch(stmt); - // if (r==SQL_NO_DATA) { - // D(".........."); - // r = SQL_SUCCESS; - // break; - // } - // CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); - // if (r) break; - // r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement)); - // CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); - // if (r) break; - // r = SQLExecute(stmt); - // CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - // if (r) break; - } while (0); - return r; -} - -static int do_insert(SQLHSTMT stmt, data_t data) { - SQLRETURN r = 0; - SQLLEN lbin; - SQLLEN lblob; - - const char *statement = "insert into t values (?, ?, ?, ?, ?, ?, ?, ?, ?,?)"; - #define ignored 0 - - do { - r = SQLPrepare(stmt, (SQLCHAR*)statement, (SQLINTEGER)strlen(statement)); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - if (r) break; - - r = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_TIMESTAMP, ignored, ignored, &data.ts, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - if (r) break; - - r = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, ignored, ignored, &data.b, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - if (r) break; - - r = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_TINYINT, ignored, ignored, &data.v1, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - if (r) break; - - r = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_SMALLINT, ignored, ignored, &data.v2, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - if (r) break; - - r = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, ignored, ignored, &data.v4, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - if (r) break; - - r = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, ignored, ignored, &data.v8, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - if (r) break; - - r = SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, ignored, ignored, &data.f4, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - if (r) break; - - r = SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, ignored, ignored, &data.f8, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - if (r) break; - - lbin = SQL_NTS; - r = SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, sizeof(data.bin)-1, ignored, &data.bin, ignored, &lbin); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - if (r) break; - - lblob = SQL_NTS; - r = SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(data.blob)-1, ignored, &data.blob, ignored, &lblob); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - if (r) break; - - r = SQLExecute(stmt); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); - if (r) break; - - // ts += 1; - // v = 2; - // r = SQLExecute(stmt); - // if (r) break; - } while (0); - - #undef ignored - return r; -} - -static int test1(const char *dsn, const char *uid, const char *pwd) { - SQLHENV env = {0}; - SQLHDBC conn = {0}; - int n = open_connect(dsn, uid, pwd, &env, &conn); - if (n) return 1; - - int ok = 0; - do { - SQLRETURN r = SQL_SUCCESS; - SQLHSTMT stmt = {0}; - r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt); - if (r!=SQL_SUCCESS) break; - do { - if (do_statement(stmt, "drop database if exists db")) { - break; - } - for (size_t i=0; i0 && line[n-1] == '\n') line[n-1]='\0'; - if (n>0 && line[n-1] == '\r') line[n-1]='\0'; - if (n>1 && line[n-2] == '\r') line[n-2]='\0'; - p = line; - while (isspace(*p)) ++p; - - if (*p==0) break; - - int positive = 1; - if (strncmp(p, "N:", 2)==0) { - positive = 0; - p += 2; - } else if (strncmp(p, "P:", 2)==0) { - p += 2; - } - - D("statement: [%s]", p); - r = do_statement(stmt, p); - - if (positive && r==0) break; - if (!positive && r) { r = 0; break; } - if (positive) return r; - D("expecting negative result, but got positive"); - return -1; - } while (0); - - free(line); - - if (r) break; - } - - fclose(f); - return r ? 1 : 0; -} - -int test_sqls_in_conn(SQLHENV env, SQLHDBC conn, const char *sqls) { - SQLHSTMT stmt = {0}; - CHK_TEST(create_statement(env, conn, &stmt)); - int r = test_sqls_in_stmt(env, conn, stmt, sqls); - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - return r ? 1 : 0; -} - -int test_sqls(const char *dsn, const char *uid, const char *pwd, const char *connstr, const char *sqls) { - int r = 0; - SQLHENV env = {0}; - SQLHDBC conn = {0}; - if (dsn) { - CHK_TEST(open_connect(dsn, uid, pwd, &env, &conn)); - } else { - CHK_TEST(open_driver_connect(connstr, &env, &conn)); - } - if (sqls) { - r = test_sqls_in_conn(env, conn, sqls); - } - SQLDisconnect(conn); - SQLFreeConnect(conn); - SQLFreeEnv(env); - return r ? 1 : 0; -} - -void usage(const char *arg0) { - fprintf(stdout, "%s usage:\n", arg0); - fprintf(stdout, "%s [--dsn ] [--uid ] [--pwd ] [--dcs ] [--sts ]\n", arg0); - fprintf(stdout, " --dsn : DSN\n"); - fprintf(stdout, " --uid : UID\n"); - fprintf(stdout, " --pwd : PWD\n"); - fprintf(stdout, " --dcs : driver connection string\n"); - fprintf(stdout, " --sts : file where statements store\n"); -} - -int main(int argc, char *argv[]) { - // if (argc==1) { - // CHK_TEST(test_env()); - // CHK_TEST(test1("TAOS_DSN", "root", "taoxsdata")); - // D("Done!"); - // return 0; - // } - - const char *dsn = NULL; - const char *uid = NULL; - const char *pwd = NULL; - const char *dcs = NULL; // driver connection string - const char *sts = NULL; // statements file - for (size_t i=1; i=argc) { - D(" expected but got nothing"); - return 1; - } - if (dcs) { - D("--dcs has already been specified"); - return 1; - } - dsn = argv[i]; - continue; - } - if (strcmp(arg, "--uid")==0) { - ++i; - if (i>=argc) { - D(" expected but got nothing"); - return 1; - } - uid = argv[i]; - continue; - } - if (strcmp(arg, "--pwd")==0) { - ++i; - if (i>=argc) { - D(" expected but got nothing"); - return 1; - } - pwd = argv[i]; - continue; - } - if (strcmp(arg, "--dcs")==0) { - ++i; - if (i>=argc) { - D(" expected but got nothing"); - return 1; - } - if (dsn || uid || pwd) { - D("either of --dsn/--uid/--pwd has already been specified"); - return 1; - } - dcs = argv[i]; - continue; - } - if (strcmp(arg, "--sts")==0) { - ++i; - if (i>=argc) { - D(" expected but got nothing"); - return 1; - } - sts = argv[i]; - continue; - } - } - CHK_TEST(test_sqls(dsn, uid, pwd, dcs, sts)); - D("Done!"); - return 0; - - if (0) { - const char *dsn = (argc>1) ? argv[1] : NULL; - const char *uid = (argc>2) ? argv[2] : NULL; - const char *pwd = (argc>3) ? argv[3] : NULL; - const char *connstr = (argc>4) ? argv[4] : NULL; - const char *sqls = (argc>5) ? argv[5] : NULL; - - dsn = NULL; - uid = NULL; - pwd = NULL; - connstr = argv[1]; - sqls = argv[2]; - if (0) { - CHK_TEST(test_env()); - - CHK_TEST(test1(dsn, uid, pwd)); - - const char *statements[] = { - "drop database if exists m", - "create database m", - "use m", - "drop database m", - NULL - }; - CHK_TEST(test_statements(dsn, uid, pwd, statements)); - - if (connstr) - CHK_TEST(test_driver_connect(connstr)); - - if (connstr) { - SQLHENV env = {0}; - SQLHDBC conn = {0}; - CHK_TEST(open_driver_connect(connstr, &env, &conn)); - int r = tests(env, conn); - SQLDisconnect(conn); - SQLFreeConnect(conn); - SQLFreeEnv(env); - if (r) return 1; - } - } - - if ((dsn || connstr) && 1) { - CHK_TEST(test_sqls(dsn, uid, pwd, connstr, sqls)); - } - - D("Done!"); - return 0; - } -} - diff --git a/src/connector/odbc/tests/odbc.py b/src/connector/odbc/tests/odbc.py deleted file mode 100644 index c137905775e567f6163846690886850cb77a684a..0000000000000000000000000000000000000000 --- a/src/connector/odbc/tests/odbc.py +++ /dev/null @@ -1,131 +0,0 @@ -import pyodbc -# cnxn = pyodbc.connect('DSN={TAOS_DSN};UID={ root };PWD={ taosdata };HOST={ localhost:6030 }', autocommit=True) -cnxn = pyodbc.connect('DSN={TAOS_DSN}; UID=root;PWD=taosdata; HOST=localhost:6030', autocommit=True) -cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8') -#cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8') -#cnxn.setencoding(encoding='utf-8') - -#cursor = cnxn.cursor() -#cursor.execute("SELECT * from db.t") -#row = cursor.fetchone() -#while row: -# print(row) -# row = cursor.fetchone() -#cursor.close() - -#cursor = cnxn.cursor() -#cursor.execute(""" -#INSERT INTO db.t values (?,?,?,?,?,?,?,?,?,?) -#""", -#"2020-12-12 00:00:00", -#1, -#27, -#32767, -#147483647, -#223372036854775807, -#23.456, -#899.999999, -#"foo", -#"bar") - -cursor = cnxn.cursor() -cursor.execute("drop database if exists db"); -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("create database db"); -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("create table db.mt (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), blob nchar(10))"); -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("insert into db.mt values('2020-10-13 06:44:00', 1, 127, 32767, 32768, 32769, 123.456, 789.987, 'hello', 'world')") -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("insert into db.mt values(?,?,?,?,?,?,?,?,?,?)", "2020-10-13 07:06:00", 0, 127, 32767, 32768, 32769, 123.456, 789.987, "hel后lo", "wo哈rld"); -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("SELECT * from db.mt") -row = cursor.fetchone() -while row: - print(row) - row = cursor.fetchone() -cursor.close() - -#cursor = cnxn.cursor() -#cursor.execute("drop database if exists db"); -#cursor.close() -# -#cursor = cnxn.cursor() -#cursor.execute("create database db"); -#cursor.close() - -cursor = cnxn.cursor() -cursor.execute("create table db.t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(4), blob nchar(4))"); -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("insert into db.t values('2020-10-13 06:44:00', 1, 127, 32767, 32768, 32769, 123.456, 789.987, 'hell', 'worl')") -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("SELECT * from db.t") -row = cursor.fetchone() -while row: - print(row) - row = cursor.fetchone() -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("create table db.v (ts timestamp, v1 tinyint)") -cursor.close() - -params = [ ('A', 1), ('B', 2), ('C', 3) ] -params = [ ('A', 1), ('B', 2), ('C', 3) ] -params = [ ('2020-10-16 00:00:00', 1), - ('2020-10-16 00:00:01', 4), - ('2020-10-16 00:00:02', 5), - ('2020-10-16 00:00:03.009', 6) ] -cursor = cnxn.cursor() -cursor.fast_executemany = True -cursor.executemany("insert into db.v values (?, ?)", params) -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("SELECT * from db.v") -row = cursor.fetchone() -while row: - print(row) - row = cursor.fetchone() -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("SELECT * from db.v where v1 > ?", 4) -row = cursor.fetchone() -while row: - print(row) - row = cursor.fetchone() -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("SELECT * from db.v where v1 > ?", '5') -row = cursor.fetchone() -while row: - print(row) - row = cursor.fetchone() -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("create table db.f (ts timestamp, v1 float)") -cursor.close() - -params = [ ('2020-10-20 00:00:10', '123.3') ] -cursor = cnxn.cursor() -cursor.fast_executemany = True -cursor.executemany("insert into db.f values (?, ?)", params) -cursor.close() - diff --git a/src/connector/odbc/tools/CMakeLists.txt b/src/connector/odbc/tools/CMakeLists.txt index a0aafb1f3ca36bb0b6fb108e1948214b2dd14a6f..e543d245c8c3ef19f541832b3f2c8889860db2f9 100644 --- a/src/connector/odbc/tools/CMakeLists.txt +++ b/src/connector/odbc/tools/CMakeLists.txt @@ -1,12 +1,23 @@ PROJECT(TDengine) -IF (TD_LINUX) - ADD_EXECUTABLE(todbcinst main.c) +ADD_EXECUTABLE(todbcinst main.c) +ADD_EXECUTABLE(tconv tconv.c) + +IF (TD_LINUX OR TD_DARWIN) TARGET_LINK_LIBRARIES(todbcinst odbc odbcinst) ENDIF () +IF (TD_DARWIN) + target_include_directories(todbcinst PRIVATE /usr/local/include) + target_link_directories(todbcinst PUBLIC /usr/local/lib) + target_include_directories(tconv PRIVATE /usr/local/include) + target_link_directories(tconv PUBLIC /usr/local/lib) + TARGET_LINK_LIBRARIES(tconv iconv) +ENDIF () + IF (TD_WINDOWS_64) - ADD_EXECUTABLE(todbcinst main.c) TARGET_LINK_LIBRARIES(todbcinst odbc32 odbccp32 user32 legacy_stdio_definitions os) + TARGET_LINK_LIBRARIES(tconv taos) INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/todbcinst.exe DESTINATION .) ENDIF () + diff --git a/src/connector/odbc/tests/tconv.c b/src/connector/odbc/tools/tconv.c similarity index 100% rename from src/connector/odbc/tests/tconv.c rename to src/connector/odbc/tools/tconv.c diff --git a/src/dnode/src/dnodeVWrite.c b/src/dnode/src/dnodeVWrite.c index a3ff459396a974eae26be3561e418b5836b90f4b..87b31e4604882d750e4a43fde4a6d818cc862e98 100644 --- a/src/dnode/src/dnodeVWrite.c +++ b/src/dnode/src/dnodeVWrite.c @@ -222,7 +222,7 @@ static void *dnodeProcessVWriteQueue(void *wparam) { dnodeSendRpcVWriteRsp(pVnode, pWrite, pWrite->code); } else { if (qtype == TAOS_QTYPE_FWD) { - vnodeConfirmForward(pVnode, pWrite->pHead.version, 0); + vnodeConfirmForward(pVnode, pWrite->pHead.version, 0, pWrite->pHead.msgType != TSDB_MSG_TYPE_SUBMIT); } if (pWrite->rspRet.rsp) { rpcFreeCont(pWrite->rspRet.rsp); diff --git a/src/inc/taosdef.h b/src/inc/taosdef.h index 6e56e5059a99504b3492a619dd4590152f538632..9276b2291a66c6d4597930f89edcdb93deab7267 100644 --- a/src/inc/taosdef.h +++ b/src/inc/taosdef.h @@ -332,6 +332,10 @@ do { \ #define TSDB_QUERY_TYPE_NON_TYPE 0x00u // none type #define TSDB_QUERY_TYPE_FREE_RESOURCE 0x01u // free qhandle at vnode +#define TSDB_UDF_TYPE_SCALAR 1 +#define TSDB_UDF_TYPE_AGGREGATE 2 + + /* * 1. ordinary sub query for select * from super_table * 2. all sqlobj generated by createSubqueryObj with this flag diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index 2576285ae0ce10cfd60fc9563ae9e8856933242f..3be97b10f46be4d27aeb40f29913b9a5ab34ce59 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -194,6 +194,8 @@ int32_t* taosGetErrno(); #define TSDB_CODE_MND_INVALID_TOPIC TAOS_DEF_ERROR_CODE(0, 0x0392) //"Invalid topic name) #define TSDB_CODE_MND_INVALID_TOPIC_OPTION TAOS_DEF_ERROR_CODE(0, 0x0393) //"Invalid topic option) +#define TSDB_CODE_MND_INVALID_TOPIC_PARTITONS TAOS_DEF_ERROR_CODE(0, 0x0394) //"Invalid topic partitons num, valid range: [1, 1000]) +#define TSDB_CODE_MND_TOPIC_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0395) //"Topic already exists) // dnode #define TSDB_CODE_DND_MSG_NOT_PROCESSED TAOS_DEF_ERROR_CODE(0, 0x0400) //"Message not processed") diff --git a/src/inc/taosmsg.h b/src/inc/taosmsg.h index 7e61010cd20791ed7d994b08fd08cbbe21c8f5fa..201b7865a2a7942120a029cae740d098e31159b9 100644 --- a/src/inc/taosmsg.h +++ b/src/inc/taosmsg.h @@ -580,6 +580,7 @@ typedef struct { typedef struct { char name[TSDB_FUNC_NAME_LEN]; char path[PATH_MAX]; + int32_t funcType; uint8_t outputType; int16_t outputLen; int32_t codeLen; @@ -593,6 +594,7 @@ typedef struct { typedef struct { char name[TSDB_FUNC_NAME_LEN]; + int32_t funcType; int8_t resType; int16_t resBytes; int32_t len; diff --git a/src/inc/tfs.h b/src/inc/tfs.h index 76e9b17a621f9842479396ada65bb10ac147366c..4ed21bc6e1ddb4d9011d701ad99e6f2a71f54b0e 100644 --- a/src/inc/tfs.h +++ b/src/inc/tfs.h @@ -35,6 +35,7 @@ typedef struct { // FS APIs ==================================== typedef struct { int64_t tsize; + int64_t used; int64_t avail; } SFSMeta; @@ -90,4 +91,4 @@ void tfsClosedir(TDIR *tdir); } #endif -#endif \ No newline at end of file +#endif diff --git a/src/inc/tp.h b/src/inc/tp.h index b0b787bf689dafb016416cb82c1ebeb049d7c104..1d6570898ebfcf0137fd2d502dc39de9378714b9 100644 --- a/src/inc/tp.h +++ b/src/inc/tp.h @@ -22,7 +22,7 @@ extern "C" { int32_t tpInit(); void tpCleanUp(); -void tpUpdateTs(int32_t *seq, void *pMsg); +void tpUpdateTs(int32_t vgId, int64_t *seq, void *pMsg); #ifdef __cplusplus } diff --git a/src/inc/tsdb.h b/src/inc/tsdb.h index 09444bb8e4b2c6cd45ce087a3444338d140a90ae..493bdbe5ded9f6235687d376625b8f6fc9861c8f 100644 --- a/src/inc/tsdb.h +++ b/src/inc/tsdb.h @@ -25,6 +25,8 @@ #include "tdataformat.h" #include "tname.h" #include "hash.h" +#include "tlockfree.h" +#include "tlist.h" #ifdef __cplusplus extern "C" { @@ -172,10 +174,32 @@ typedef struct STsdbQueryCond { int32_t type; // data block load type: } STsdbQueryCond; +typedef struct STableData STableData; +typedef struct { + T_REF_DECLARE() + SRWLatch latch; + TSKEY keyFirst; + TSKEY keyLast; + int64_t numOfRows; + int32_t maxTables; + STableData **tData; + SList * actList; + SList * extraBuffList; + SList * bufBlockList; + int64_t pointsAdd; // TODO + int64_t storageAdd; // TODO +} SMemTable; + +typedef struct { + SMemTable* mem; + SMemTable* imem; + SMemTable mtable; + SMemTable* omem; +} SMemSnapshot; + typedef struct SMemRef { - int32_t ref; - void * mem; - void * imem; + int32_t ref; + SMemSnapshot snapshot; } SMemRef; typedef struct SDataBlockInfo { diff --git a/src/inc/tsync.h b/src/inc/tsync.h index 379c877b266b6026ea9d9ee55f76ecb24fca1a44..99dfd3a6a30b1c7cf36e94a7d2485181f966f5fc 100644 --- a/src/inc/tsync.h +++ b/src/inc/tsync.h @@ -79,6 +79,9 @@ typedef void (*FStopSyncFile)(int32_t vgId, uint64_t fversion); // get file version typedef int32_t (*FGetVersion)(int32_t vgId, uint64_t *fver, uint64_t *vver); +// reset version +typedef int32_t (*FResetVersion)(int32_t vgId, uint64_t fver); + typedef int32_t (*FSendFile)(void *tsdb, SOCKET socketFd); typedef int32_t (*FRecvFile)(void *tsdb, SOCKET socketFd); @@ -96,6 +99,7 @@ typedef struct { FStartSyncFile startSyncFileFp; FStopSyncFile stopSyncFileFp; FGetVersion getVersionFp; + FResetVersion resetVersionFp; FSendFile sendFileFp; FRecvFile recvFileFp; } SSyncInfo; @@ -108,8 +112,8 @@ void syncCleanUp(); int64_t syncStart(const SSyncInfo *); void syncStop(int64_t rid); int32_t syncReconfig(int64_t rid, const SSyncCfg *); -int32_t syncForwardToPeer(int64_t rid, void *pHead, void *mhandle, int32_t qtype); -void syncConfirmForward(int64_t rid, uint64_t version, int32_t code); +int32_t syncForwardToPeer(int64_t rid, void *pHead, void *mhandle, int32_t qtype, bool force); +void syncConfirmForward(int64_t rid, uint64_t version, int32_t code, bool force); void syncRecover(int64_t rid); // recover from other nodes: int32_t syncGetNodesRole(int64_t rid, SNodesRole *); diff --git a/src/inc/ttokendef.h b/src/inc/ttokendef.h index b148d6bc759bfd727853728d0ec41aea8448a86e..6e845124b17bdcfc94077aa32e0450424472dff3 100644 --- a/src/inc/ttokendef.h +++ b/src/inc/ttokendef.h @@ -101,112 +101,111 @@ #define TK_EXISTS 82 #define TK_AS 83 #define TK_OUTPUTTYPE 84 -#define TK_PPS 85 -#define TK_TSERIES 86 -#define TK_DBS 87 -#define TK_STORAGE 88 -#define TK_QTIME 89 -#define TK_CONNS 90 -#define TK_STATE 91 -#define TK_KEEP 92 -#define TK_CACHE 93 -#define TK_REPLICA 94 -#define TK_QUORUM 95 -#define TK_DAYS 96 -#define TK_MINROWS 97 -#define TK_MAXROWS 98 -#define TK_BLOCKS 99 -#define TK_CTIME 100 -#define TK_WAL 101 -#define TK_FSYNC 102 -#define TK_COMP 103 -#define TK_PRECISION 104 -#define TK_UPDATE 105 -#define TK_CACHELAST 106 -#define TK_PARTITIONS 107 -#define TK_LP 108 -#define TK_RP 109 -#define TK_UNSIGNED 110 -#define TK_TAGS 111 -#define TK_USING 112 -#define TK_COMMA 113 -#define TK_NULL 114 -#define TK_SELECT 115 -#define TK_UNION 116 -#define TK_ALL 117 -#define TK_DISTINCT 118 -#define TK_FROM 119 -#define TK_VARIABLE 120 -#define TK_INTERVAL 121 -#define TK_SESSION 122 -#define TK_FILL 123 -#define TK_SLIDING 124 -#define TK_ORDER 125 -#define TK_BY 126 -#define TK_ASC 127 -#define TK_DESC 128 -#define TK_GROUP 129 -#define TK_HAVING 130 -#define TK_LIMIT 131 -#define TK_OFFSET 132 -#define TK_SLIMIT 133 -#define TK_SOFFSET 134 -#define TK_WHERE 135 -#define TK_NOW 136 -#define TK_RESET 137 -#define TK_QUERY 138 -#define TK_ADD 139 -#define TK_COLUMN 140 -#define TK_TAG 141 -#define TK_CHANGE 142 -#define TK_SET 143 -#define TK_KILL 144 -#define TK_CONNECTION 145 -#define TK_STREAM 146 -#define TK_COLON 147 -#define TK_ABORT 148 -#define TK_AFTER 149 -#define TK_ATTACH 150 -#define TK_BEFORE 151 -#define TK_BEGIN 152 -#define TK_CASCADE 153 -#define TK_CLUSTER 154 -#define TK_CONFLICT 155 -#define TK_COPY 156 -#define TK_DEFERRED 157 -#define TK_DELIMITERS 158 -#define TK_DETACH 159 -#define TK_EACH 160 -#define TK_END 161 -#define TK_EXPLAIN 162 -#define TK_FAIL 163 -#define TK_FOR 164 -#define TK_IGNORE 165 -#define TK_IMMEDIATE 166 -#define TK_INITIALLY 167 -#define TK_INSTEAD 168 -#define TK_MATCH 169 -#define TK_KEY 170 -#define TK_OF 171 -#define TK_RAISE 172 -#define TK_REPLACE 173 -#define TK_RESTRICT 174 -#define TK_ROW 175 -#define TK_STATEMENT 176 -#define TK_TRIGGER 177 -#define TK_VIEW 178 -#define TK_SEMI 179 -#define TK_NONE 180 -#define TK_PREV 181 -#define TK_LINEAR 182 -#define TK_IMPORT 183 -#define TK_METRIC 184 +#define TK_AGGREGATE 85 +#define TK_PPS 86 +#define TK_TSERIES 87 +#define TK_DBS 88 +#define TK_STORAGE 89 +#define TK_QTIME 90 +#define TK_CONNS 91 +#define TK_STATE 92 +#define TK_KEEP 93 +#define TK_CACHE 94 +#define TK_REPLICA 95 +#define TK_QUORUM 96 +#define TK_DAYS 97 +#define TK_MINROWS 98 +#define TK_MAXROWS 99 +#define TK_BLOCKS 100 +#define TK_CTIME 101 +#define TK_WAL 102 +#define TK_FSYNC 103 +#define TK_COMP 104 +#define TK_PRECISION 105 +#define TK_UPDATE 106 +#define TK_CACHELAST 107 +#define TK_PARTITIONS 108 +#define TK_LP 109 +#define TK_RP 110 +#define TK_UNSIGNED 111 +#define TK_TAGS 112 +#define TK_USING 113 +#define TK_COMMA 114 +#define TK_NULL 115 +#define TK_SELECT 116 +#define TK_UNION 117 +#define TK_ALL 118 +#define TK_DISTINCT 119 +#define TK_FROM 120 +#define TK_VARIABLE 121 +#define TK_INTERVAL 122 +#define TK_SESSION 123 +#define TK_FILL 124 +#define TK_SLIDING 125 +#define TK_ORDER 126 +#define TK_BY 127 +#define TK_ASC 128 +#define TK_DESC 129 +#define TK_GROUP 130 +#define TK_HAVING 131 +#define TK_LIMIT 132 +#define TK_OFFSET 133 +#define TK_SLIMIT 134 +#define TK_SOFFSET 135 +#define TK_WHERE 136 +#define TK_NOW 137 +#define TK_RESET 138 +#define TK_QUERY 139 +#define TK_ADD 140 +#define TK_COLUMN 141 +#define TK_TAG 142 +#define TK_CHANGE 143 +#define TK_SET 144 +#define TK_KILL 145 +#define TK_CONNECTION 146 +#define TK_STREAM 147 +#define TK_COLON 148 +#define TK_ABORT 149 +#define TK_AFTER 150 +#define TK_ATTACH 151 +#define TK_BEFORE 152 +#define TK_BEGIN 153 +#define TK_CASCADE 154 +#define TK_CLUSTER 155 +#define TK_CONFLICT 156 +#define TK_COPY 157 +#define TK_DEFERRED 158 +#define TK_DELIMITERS 159 +#define TK_DETACH 160 +#define TK_EACH 161 +#define TK_END 162 +#define TK_EXPLAIN 163 +#define TK_FAIL 164 +#define TK_FOR 165 +#define TK_IGNORE 166 +#define TK_IMMEDIATE 167 +#define TK_INITIALLY 168 +#define TK_INSTEAD 169 +#define TK_MATCH 170 +#define TK_KEY 171 +#define TK_OF 172 +#define TK_RAISE 173 +#define TK_REPLACE 174 +#define TK_RESTRICT 175 +#define TK_ROW 176 +#define TK_STATEMENT 177 +#define TK_TRIGGER 178 +#define TK_VIEW 179 +#define TK_SEMI 180 +#define TK_NONE 181 +#define TK_PREV 182 +#define TK_LINEAR 183 +#define TK_IMPORT 184 #define TK_TBNAME 185 #define TK_JOIN 186 -#define TK_METRICS 187 -#define TK_INSERT 188 -#define TK_INTO 189 -#define TK_VALUES 190 +#define TK_INSERT 187 +#define TK_INTO 188 +#define TK_VALUES 189 diff --git a/src/inc/twal.h b/src/inc/twal.h index 1645de77aacf020048dc21cd47907163089f269f..bce398d6f95518379c1cd4c0d95a4f6324aab4d7 100644 --- a/src/inc/twal.h +++ b/src/inc/twal.h @@ -65,6 +65,7 @@ void walFsync(twalh, bool forceFsync); int32_t walRestore(twalh, void *pVnode, FWalWrite writeFp); int32_t walGetWalFile(twalh, char *fileName, int64_t *fileId); uint64_t walGetVersion(twalh); +void walResetVersion(twalh, uint64_t newVer); #ifdef __cplusplus } diff --git a/src/inc/vnode.h b/src/inc/vnode.h index 7c9ebd8a0b9d96090134bd23c2061c857dfcd5f1..dddec83da87f6cf7f25212dd1aa39373e6b613f7 100644 --- a/src/inc/vnode.h +++ b/src/inc/vnode.h @@ -78,7 +78,7 @@ void vnodeFreeFromWQueue(void *pVnode, SVWriteMsg *pWrite); int32_t vnodeProcessWrite(void *pVnode, void *pHead, int32_t qtype, void *pRspRet); // vnodeSync -void vnodeConfirmForward(void *pVnode, uint64_t version, int32_t code); +void vnodeConfirmForward(void *pVnode, uint64_t version, int32_t code, bool force); // vnodeRead int32_t vnodeWriteToRQueue(void *pVnode, void *pCont, int32_t contLen, int8_t qtype, void *rparam); diff --git a/src/kit/shell/CMakeLists.txt b/src/kit/shell/CMakeLists.txt index b6babc5bc53aa254e0372dbbfd235bdd4cef878a..d36c1e3fccc4ee7c5eae359f975e2ac1faa6c135 100644 --- a/src/kit/shell/CMakeLists.txt +++ b/src/kit/shell/CMakeLists.txt @@ -36,6 +36,7 @@ ELSEIF (TD_DARWIN) LIST(APPEND SRC ./src/shellDarwin.c) LIST(APPEND SRC ./src/shellCommand.c) LIST(APPEND SRC ./src/shellImport.c) + LIST(APPEND SRC ./src/shellCheck.c) ADD_EXECUTABLE(shell ${SRC}) # linking with dylib TARGET_LINK_LIBRARIES(shell taos) diff --git a/src/kit/shell/inc/shell.h b/src/kit/shell/inc/shell.h index 50bceb1a7169373d1c832cadf03d6d601cace264..019f3e5d92d453a9df97ab0b4bb2c7614bf2210d 100644 --- a/src/kit/shell/inc/shell.h +++ b/src/kit/shell/inc/shell.h @@ -51,6 +51,7 @@ typedef struct SShellArguments { char file[TSDB_FILENAME_LEN]; char dir[TSDB_FILENAME_LEN]; int threadNum; + int check; char* commands; int abort; int port; @@ -71,6 +72,7 @@ void read_history(); void write_history(); void source_file(TAOS* con, char* fptr); void source_dir(TAOS* con, SShellArguments* args); +void shellCheck(TAOS* con, SShellArguments* args); void get_history_path(char* history); void cleanup_handler(void* arg); void exitShell(); diff --git a/src/kit/shell/src/shellCheck.c b/src/kit/shell/src/shellCheck.c new file mode 100644 index 0000000000000000000000000000000000000000..b88244ea018291fbdc98165a8665949f618e3291 --- /dev/null +++ b/src/kit/shell/src/shellCheck.c @@ -0,0 +1,199 @@ +/* + * 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 . + */ + +#define _GNU_SOURCE +#define _XOPEN_SOURCE +#define _DEFAULT_SOURCE + +#include "os.h" +#include "shell.h" +#include "shellCommand.h" +#include "tglobal.h" +#include "tutil.h" + +#define SHELL_SQL_LEN 1024 +static int32_t tbNum = 0; +static int32_t tbMallocNum = 0; +static char ** tbNames = NULL; +static int32_t checkedNum = 0; +static int32_t errorNum = 0; + +typedef struct { + pthread_t threadID; + int threadIndex; + int totalThreads; + void * taos; + char * db; +} ShellThreadObj; + +static int32_t shellUseDb(TAOS *con, char *db) { + if (db == NULL) { + fprintf(stdout, "no dbname input\n"); + return -1; + } + + char sql[SHELL_SQL_LEN] = {0}; + snprintf(sql, SHELL_SQL_LEN, "use %s", db); + + TAOS_RES *pSql = taos_query(con, sql); + int32_t code = taos_errno(pSql); + if (code != 0) { + fprintf(stdout, "failed to execute sql:%s since %s", sql, taos_errstr(pSql)); + } + + taos_free_result(pSql); + return code; +} + +static int32_t shellShowTables(TAOS *con, char *db) { + char sql[SHELL_SQL_LEN] = {0}; + snprintf(sql, SHELL_SQL_LEN, "show %s.tables", db); + + TAOS_RES *pSql = taos_query(con, sql); + int32_t code = taos_errno(pSql); + + if (code != 0) { + fprintf(stdout, "failed to execute sql:%s since %s\n", sql, taos_errstr(pSql)); + } else { + TAOS_ROW row; + while ((row = taos_fetch_row(pSql))) { + int32_t tbIndex = tbNum++; + if (tbMallocNum < tbNum) { + tbMallocNum = (tbMallocNum * 2 + 1); + tbNames = realloc(tbNames, tbMallocNum * sizeof(char *)); + if (tbNames == NULL) { + fprintf(stdout, "failed to malloc tablenames, num:%d\n", tbMallocNum); + code = TSDB_CODE_TSC_OUT_OF_MEMORY; + break; + } + } + + tbNames[tbIndex] = malloc(TSDB_TABLE_NAME_LEN); + strncpy(tbNames[tbIndex], (const char *)row[0], TSDB_TABLE_NAME_LEN); + if (tbIndex % 100000 == 0 && tbIndex != 0) { + fprintf(stdout, "%d tablenames fetched\n", tbIndex); + } + } + } + + taos_free_result(pSql); + + fprintf(stdout, "total %d tablenames fetched, over\n", tbNum); + return code; +} + +static void shellFreeTbnames() { + for (int32_t i = 0; i < tbNum; ++i) { + free(tbNames[i]); + } + free(tbNames); +} + +static void *shellCheckThreadFp(void *arg) { + ShellThreadObj *pThread = (ShellThreadObj *)arg; + + int32_t interval = tbNum / pThread->totalThreads + 1; + int32_t start = pThread->threadIndex * interval; + int32_t end = (pThread->threadIndex + 1) * interval; + + if (end > tbNum) end = tbNum + 1; + + char file[32] = {0}; + snprintf(file, 32, "tb%d.txt", pThread->threadIndex); + + FILE *fp = fopen(file, "w"); + if (!fp) { + fprintf(stdout, "failed to open %s, reason:%s", file, strerror(errno)); + return NULL; + } + + char sql[SHELL_SQL_LEN]; + for (int32_t t = start; t < end; ++t) { + char *tbname = tbNames[t]; + if (tbname == NULL) break; + + snprintf(sql, SHELL_SQL_LEN, "select * from %s limit 1", tbname); + + TAOS_RES *pSql = taos_query(pThread->taos, sql); + int32_t code = taos_errno(pSql); + if (code != 0) { + int32_t len = snprintf(sql, SHELL_SQL_LEN, "drop table %s.%s;\n", pThread->db, tbname); + fwrite(sql, 1, len, fp); + atomic_add_fetch_32(&errorNum, 1); + } + + int32_t cnum = atomic_add_fetch_32(&checkedNum, 1); + if (cnum % 5000 == 0 && cnum != 0) { + fprintf(stdout, "%d tables checked\n", cnum); + } + + taos_free_result(pSql); + } + + fsync(fileno(fp)); + fclose(fp); + + return NULL; +} + +static void shellRunCheckThreads(TAOS *con, SShellArguments *args) { + pthread_attr_t thattr; + ShellThreadObj *threadObj = (ShellThreadObj *)calloc(args->threadNum, sizeof(ShellThreadObj)); + for (int t = 0; t < args->threadNum; ++t) { + ShellThreadObj *pThread = threadObj + t; + pThread->threadIndex = t; + pThread->totalThreads = args->threadNum; + pThread->taos = con; + pThread->db = args->database; + + pthread_attr_init(&thattr); + pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); + + if (pthread_create(&(pThread->threadID), &thattr, shellCheckThreadFp, (void *)pThread) != 0) { + fprintf(stderr, "ERROR: thread:%d failed to start\n", pThread->threadIndex); + exit(0); + } + } + + for (int t = 0; t < args->threadNum; ++t) { + pthread_join(threadObj[t].threadID, NULL); + } + + for (int t = 0; t < args->threadNum; ++t) { + taos_close(threadObj[t].taos); + } + free(threadObj); +} + +void shellCheck(TAOS *con, SShellArguments *args) { + int64_t start = taosGetTimestampMs(); + + if (shellUseDb(con, args->database) != 0) { + shellFreeTbnames(); + return; + } + + if (shellShowTables(con, args->database) != 0) { + shellFreeTbnames(); + return; + } + + fprintf(stdout, "total %d tables will be checked by %d threads\n", tbNum, args->threadNum); + shellRunCheckThreads(con, args); + + int64_t end = taosGetTimestampMs(); + fprintf(stdout, "total %d tables checked, failed:%d, time spent %.2f seconds\n", checkedNum, errorNum, + (end - start) / 1000.0); +} diff --git a/src/kit/shell/src/shellEngine.c b/src/kit/shell/src/shellEngine.c index a6f5869936beb7e5d9a17d0ff9ecc9fbd499db2f..b9529aac8ec572083406f0d902d48f424ef4547b 100644 --- a/src/kit/shell/src/shellEngine.c +++ b/src/kit/shell/src/shellEngine.c @@ -121,6 +121,12 @@ TAOS *shellInit(SShellArguments *args) { taos_close(con); exit(EXIT_SUCCESS); } + + if (args->check != 0) { + shellCheck(con, args); + taos_close(con); + exit(EXIT_SUCCESS); + } #endif return con; @@ -412,7 +418,7 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) { #ifdef WINDOWS if (tt < 0) tt = 0; #endif - if (tt < 0 && ms != 0) { + if (tt <= 0 && ms < 0) { tt--; if (precision == TSDB_TIME_PRECISION_MICRO) { ms += 1000000; diff --git a/src/kit/shell/src/shellLinux.c b/src/kit/shell/src/shellLinux.c index 07b21531a7f1cf9fc6346a27373fe9de8895f2b2..3f6b3da9bf4b1f80f58a06613e8571ca16892c46 100644 --- a/src/kit/shell/src/shellLinux.c +++ b/src/kit/shell/src/shellLinux.c @@ -45,6 +45,7 @@ static struct argp_option options[] = { {"file", 'f', "FILE", 0, "Script to run without enter the shell."}, {"directory", 'D', "DIRECTORY", 0, "Use multi-thread to import all SQL files in the directory separately."}, {"thread", 'T', "THREADNUM", 0, "Number of threads when using multi-thread to import data."}, + {"check", 'k', "CHECK", 0, "Check tables."}, {"database", 'd', "DATABASE", 0, "Database to use when connecting to the server."}, {"timezone", 't', "TIMEZONE", 0, "Time zone of the shell, default is local."}, {"netrole", 'n', "NETROLE", 0, "Net role when network connectivity test, default is startup, options: client|server|rpc|startup|sync."}, @@ -130,6 +131,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { return -1; } break; + case 'k': + arguments->check = atoi(arg); + break; case 'd': arguments->database = arg; break; diff --git a/src/kit/taosdemo/insert-interlace.json b/src/kit/taosdemo/insert-interlace.json new file mode 100644 index 0000000000000000000000000000000000000000..0f54f008fb04d1873c5ee41d57a28e777d44ffea --- /dev/null +++ b/src/kit/taosdemo/insert-interlace.json @@ -0,0 +1,57 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 1000, + "num_of_records_per_req": 100, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "db", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 16, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb", + "child_table_exists":"no", + "childtable_count": 100, + "childtable_prefix": "stb_", + "auto_create_table": "no", + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 1000, + "multi_thread_write_one_tbl": "no", + "rows_per_tbl": 20, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}], + "tags": [{"type": "TINYINT", "count":1}] + }] + }] +} diff --git a/src/kit/taosdemo/insert.json b/src/kit/taosdemo/insert.json index 5ed744cde9b337e2a81d43c7c2022a6b180d0ce6..e6b1895043108dc1b36b504431da068ac7b302de 100644 --- a/src/kit/taosdemo/insert.json +++ b/src/kit/taosdemo/insert.json @@ -1,60 +1,57 @@ { - "filetype": "insert", - "cfgdir": "/etc/taos", - "host": "127.0.0.1", - "port": 6030, - "user": "root", - "password": "taosdata", - "thread_count": 4, - "thread_count_create_tbl": 4, - "result_file": "./insert_res.txt", + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", "confirm_parameter_prompt": "no", "insert_interval": 0, "num_of_records_per_req": 100, "max_sql_len": 1024000, - "databases": [{ - "dbinfo": { - "name": "db", - "drop": "yes", - "replica": 1, - "days": 10, - "cache": 16, - "blocks": 8, - "precision": "ms", - "keep": 365, - "minRows": 100, - "maxRows": 4096, - "comp":2, - "walLevel":1, - "cachelast":0, - "quorum":1, - "fsync":3000, - "update": 0 - }, - "super_tables": [{ - "name": "stb", + "databases": [{ + "dbinfo": { + "name": "db", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 16, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb", "child_table_exists":"no", - "childtable_count": 100, - "childtable_prefix": "stb_", - "auto_create_table": "no", - "data_source": "rand", - "insert_mode": "taosc", - "childtable_limit": 33, - "childtable_offset": 33, - "insert_rows": 1000, - "multi_thread_write_one_tbl": "no", - "number_of_tbl_in_one_sql": 0, - "rows_per_tbl": 100, - "max_sql_len": 1024000, - "disorder_ratio": 0, - "disorder_range": 1000, - "timestamp_step": 1, - "start_timestamp": "2020-10-01 00:00:00.000", - "sample_format": "csv", - "sample_file": "./sample.csv", - "tags_file": "", - "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":10}, {"type": "BINARY", "len": 16, "count":3}, {"type": "BINARY", "len": 32, "count":6}], - "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":5}] - }] - }] + "childtable_count": 10000, + "childtable_prefix": "stb_", + "auto_create_table": "no", + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 100000, + "multi_thread_write_one_tbl": "no", + "rows_per_tbl": 0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":10}, {"type": "BINARY", "len": 16, "count":3}, {"type": "BINARY", "len": 32, "count":6}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":5}] + }] + }] } diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index f561c1d610afc1cfea149c35591ea0f65b5f0843..b390ee76cd79d76b7a3edfb002cb27ca667cf02b 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -23,7 +23,6 @@ #ifdef LINUX #include - #include #include #ifndef _ALPINE #include @@ -39,11 +38,11 @@ #include #include #else - #include #include #include #endif +#include #include #include "cJSON.h" @@ -61,9 +60,12 @@ extern char configDir[]; #define QUERY_JSON_NAME "query.json" #define SUBSCRIBE_JSON_NAME "subscribe.json" -#define INSERT_MODE 0 -#define QUERY_MODE 1 -#define SUBSCRIBE_MODE 2 +enum TEST_MODE { + INSERT_TEST, // 0 + QUERY_TEST, // 1 + SUBSCRIBE_TEST, // 2 + INVAID_TEST +}; #define MAX_SQL_SIZE 65536 #define BUFFER_SIZE (65536*2) @@ -90,7 +92,7 @@ extern char configDir[]; #define MAX_DATABASE_COUNT 256 #define INPUT_BUF_LEN 256 -#define DEFAULT_TIMESTAMP_STEP 10 +#define DEFAULT_TIMESTAMP_STEP 1 typedef enum CREATE_SUB_TALBE_MOD_EN { PRE_CREATE_SUBTBL, @@ -99,8 +101,8 @@ typedef enum CREATE_SUB_TALBE_MOD_EN { } CREATE_SUB_TALBE_MOD_EN; typedef enum TALBE_EXISTS_EN { - TBL_ALREADY_EXISTS, TBL_NO_EXISTS, + TBL_ALREADY_EXISTS, TBL_EXISTS_BUTT } TALBE_EXISTS_EN; @@ -110,6 +112,12 @@ enum MODE { MODE_BUT }; +typedef enum enum_INSERT_MODE { + PROGRESSIVE_INSERT_MODE, + INTERLACE_INSERT_MODE, + INVALID_INSERT_MODE +} INSERT_MODE; + enum QUERY_TYPE { NO_INSERT_TYPE, INSERT_TYPE, @@ -149,7 +157,8 @@ enum _show_stables_index { TSDB_SHOW_STABLES_TID_INDEX, TSDB_SHOW_STABLES_VGID_INDEX, TSDB_MAX_SHOW_STABLES -}; +}; + enum _describe_table_index { TSDB_DESCRIBE_METRIC_FIELD_INDEX, TSDB_DESCRIBE_METRIC_TYPE_INDEX, @@ -182,6 +191,7 @@ typedef struct SArguments_S { bool answer_yes; bool debug_print; bool verbose_print; + bool performance_print; char * output_file; int mode; char * datatype[MAX_NUM_DATATYPE + 1]; @@ -189,6 +199,7 @@ typedef struct SArguments_S { int num_of_CPR; int num_of_threads; int insert_interval; + int rows_per_tbl; int num_of_RPR; int max_sql_len; int num_of_tables; @@ -198,6 +209,8 @@ typedef struct SArguments_S { int disorderRange; int method_of_delete; char ** arg_list; + int64_t totalInsertRows; + int64_t totalAffectedRows; } SArguments; typedef struct SColumn_S { @@ -221,7 +234,6 @@ typedef struct SSuperTable_S { int childTblOffset; int multiThreadWriteOneTbl; // 0: no, 1: yes - int numberOfTblInOneSql; // 0/1: one table, > 1: number of tbl int rowsPerTbl; // int disorderRatio; // 0: no disorder, >0: x% int disorderRange; // ms or us by database precision @@ -381,8 +393,9 @@ typedef struct SThreadInfo_S { char db_name[MAX_DB_NAME_SIZE+1]; char fp[4096]; char tb_prefix[MAX_TB_NAME_SIZE]; - int start_table_id; - int end_table_id; + int start_table_from; + int end_table_to; + int ntables; int data_of_rate; uint64_t start_time; char* cols; @@ -396,6 +409,8 @@ typedef struct SThreadInfo_S { uint64_t et; int64_t lastTs; + // sample data + int samplePos; // statistics int64_t totalInsertRows; int64_t totalAffectedRows; @@ -426,7 +441,7 @@ typedef unsigned __int32 uint32_t; static HANDLE g_stdoutHandle; static DWORD g_consoleMode; -void setupForAnsiEscape(void) { +static void setupForAnsiEscape(void) { DWORD mode = 0; g_stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); @@ -448,7 +463,7 @@ void setupForAnsiEscape(void) { } } -void resetAfterAnsiEscape(void) { +static void resetAfterAnsiEscape(void) { // Reset colors printf("\x1b[0m"); @@ -458,7 +473,7 @@ void resetAfterAnsiEscape(void) { } } -int taosRandom() +static int taosRandom() { int number; rand_s(&number); @@ -466,14 +481,14 @@ int taosRandom() return number; } #else -void setupForAnsiEscape(void) {} +static void setupForAnsiEscape(void) {} -void resetAfterAnsiEscape(void) { +static void resetAfterAnsiEscape(void) { // Reset colors printf("\x1b[0m"); } -int taosRandom() +static int taosRandom() { return random(); } @@ -512,6 +527,7 @@ SArguments g_args = { false, // insert_only false, // debug_print false, // verbose_print + false, // performance statistic print false, // answer_yes; "./output.txt", // output_file 0, // mode : sync or async @@ -531,6 +547,7 @@ SArguments g_args = { 10, // num_of_CPR 10, // num_of_connections/thread 0, // insert_interval + 0, // rows_per_tbl; 100, // num_of_RPR TSDB_PAYLOAD_SIZE, // max_sql_len 10000, // num_of_tables @@ -552,12 +569,24 @@ static FILE * g_fpOfInsertResult = NULL; #define debugPrint(fmt, ...) \ do { if (g_args.debug_print || g_args.verbose_print) \ fprintf(stderr, "DEBG: "fmt, __VA_ARGS__); } while(0) + #define verbosePrint(fmt, ...) \ - do { if (g_args.verbose_print) fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0) + do { if (g_args.verbose_print) \ + fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0) + +#define performancePrint(fmt, ...) \ + do { if (g_args.performance_print) \ + fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0) + +#define errorPrint(fmt, ...) \ + do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0) + /////////////////////////////////////////////////// -void printHelp() { +static void ERROR_EXIT(const char *msg) { perror(msg); exit(-1); } + +static void printHelp() { char indent[10] = " "; printf("%s%s%s%s\n", indent, "-f", indent, "The meta file to the execution procedure. Default is './meta.json'."); @@ -619,7 +648,7 @@ void printHelp() { */ } -void parse_args(int argc, char *argv[], SArguments *arguments) { +static void parse_args(int argc, char *argv[], SArguments *arguments) { char **sptr; wordexp_t full_path; @@ -629,7 +658,7 @@ void parse_args(int argc, char *argv[], SArguments *arguments) { } else if (strcmp(argv[i], "-c") == 0) { char *configPath = argv[++i]; if (wordexp(configPath, &full_path, 0) != 0) { - fprintf(stderr, "Invalid path %s\n", configPath); + errorPrint( "Invalid path %s\n", configPath); return; } taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]); @@ -652,6 +681,8 @@ void parse_args(int argc, char *argv[], SArguments *arguments) { arguments->num_of_threads = atoi(argv[++i]); } else if (strcmp(argv[i], "-i") == 0) { arguments->insert_interval = atoi(argv[++i]); + } else if (strcmp(argv[i], "-B") == 0) { + arguments->rows_per_tbl = atoi(argv[++i]); } else if (strcmp(argv[i], "-r") == 0) { arguments->num_of_RPR = atoi(argv[++i]); } else if (strcmp(argv[i], "-t") == 0) { @@ -676,8 +707,8 @@ void parse_args(int argc, char *argv[], SArguments *arguments) { && strcasecmp(argv[i], "DOUBLE") && strcasecmp(argv[i], "BINARY") && strcasecmp(argv[i], "NCHAR")) { - fprintf(stderr, "Invalid data_type!\n"); printHelp(); + ERROR_EXIT( "Invalid data_type!\n"); exit(EXIT_FAILURE); } sptr[0] = argv[i]; @@ -697,8 +728,8 @@ void parse_args(int argc, char *argv[], SArguments *arguments) { && strcasecmp(token, "DOUBLE") && strcasecmp(token, "BINARY") && strcasecmp(token, "NCHAR")) { - fprintf(stderr, "Invalid data_type!\n"); printHelp(); + ERROR_EXIT("Invalid data_type!\n"); exit(EXIT_FAILURE); } sptr[index++] = token; @@ -721,6 +752,8 @@ void parse_args(int argc, char *argv[], SArguments *arguments) { arguments->debug_print = true; } else if (strcmp(argv[i], "-gg") == 0) { arguments->verbose_print = true; + } else if (strcmp(argv[i], "-pp") == 0) { + arguments->performance_print = true; } else if (strcmp(argv[i], "-c") == 0) { strcpy(configDir, argv[++i]); } else if (strcmp(argv[i], "-O") == 0) { @@ -753,8 +786,8 @@ void parse_args(int argc, char *argv[], SArguments *arguments) { printHelp(); exit(0); } else { - fprintf(stderr, "wrong options\n"); printHelp(); + ERROR_EXIT("ERROR: wrong options\n"); exit(EXIT_FAILURE); } } @@ -808,13 +841,13 @@ static bool getInfoFromJsonFile(char* file); //static int generateOneRowDataForStb(SSuperTable* stbInfo); //static int getDataIntoMemForStb(SSuperTable* stbInfo); static void init_rand_data(); -void tmfclose(FILE *fp) { +static void tmfclose(FILE *fp) { if (NULL != fp) { fclose(fp); } } -void tmfree(char *buf) { +static void tmfree(char *buf) { if (NULL != buf) { free(buf); } @@ -840,7 +873,7 @@ static int queryDbExec(TAOS *taos, char *command, int type) { if (code != 0) { debugPrint("%s() LN%d - command: %s\n", __func__, __LINE__, command); - fprintf(stderr, "Failed to run %s, reason: %s\n", command, taos_errstr(res)); + errorPrint( "Failed to run %s, reason: %s\n", command, taos_errstr(res)); taos_free_result(res); //taos_close(taos); return -1; @@ -866,13 +899,13 @@ static void getResult(TAOS_RES *res, char* resultFileName) { if (resultFileName[0] != 0) { fp = fopen(resultFileName, "at"); if (fp == NULL) { - fprintf(stderr, "failed to open result file: %s, result will not save to file\n", resultFileName); + errorPrint("%s() LN%d, failed to open result file: %s, result will not save to file\n", __func__, __LINE__, resultFileName); } } char* databuf = (char*) calloc(1, 100*1024*1024); if (databuf == NULL) { - fprintf(stderr, "failed to malloc, warning: save result to file slowly!\n"); + errorPrint("%s() LN%d, failed to malloc, warning: save result to file slowly!\n", __func__, __LINE__); if (fp) fclose(fp); return ; @@ -913,7 +946,7 @@ static void selectAndGetResult(TAOS *taos, char *command, char* resultFileName) taos_free_result(res); } -double getCurrentTime() { +static double getCurrentTime() { struct timeval tv; if (gettimeofday(&tv, NULL) != 0) { perror("Failed to get current time in ms"); @@ -967,12 +1000,12 @@ static float rand_float(){ } static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; -void rand_string(char *str, int size) { +static void rand_string(char *str, int size) { str[0] = 0; if (size > 0) { //--size; int n; - for (n = 0; n < size; n++) { + for (n = 0; n < size - 1; n++) { int key = rand_tinyint() % (int)(sizeof(charset) - 1); str[n] = charset[key]; } @@ -1116,7 +1149,7 @@ static int printfInsertMeta() { if (g_Dbs.db[i].superTbls[j].childTblLimit > 0) { printf(" childTblLimit: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].childTblLimit); } - if (g_Dbs.db[i].superTbls[j].childTblOffset > 0) { + if (g_Dbs.db[i].superTbls[j].childTblOffset >= 0) { printf(" childTblOffset: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].childTblOffset); } printf(" insertRows: \033[33m%"PRId64"\033[0m\n", g_Dbs.db[i].superTbls[j].insertRows); @@ -1126,8 +1159,6 @@ static int printfInsertMeta() { }else { printf(" multiThreadWriteOneTbl: \033[33myes\033[0m\n"); } - printf(" numberOfTblInOneSql: \033[33m%d\033[0m\n", - g_Dbs.db[i].superTbls[j].numberOfTblInOneSql); printf(" rowsPerTbl: \033[33m%d\033[0m\n", g_Dbs.db[i].superTbls[j].rowsPerTbl); printf(" disorderRange: \033[33m%d\033[0m\n", @@ -1287,7 +1318,6 @@ static void printfInsertMetaToFile(FILE* fp) { }else { fprintf(fp, " multiThreadWriteOneTbl: yes\n"); } - fprintf(fp, " numberOfTblInOneSql: %d\n", g_Dbs.db[i].superTbls[j].numberOfTblInOneSql); fprintf(fp, " rowsPerTbl: %d\n", g_Dbs.db[i].superTbls[j].rowsPerTbl); fprintf(fp, " disorderRange: %d\n", g_Dbs.db[i].superTbls[j].disorderRange); fprintf(fp, " disorderRatio: %d\n", g_Dbs.db[i].superTbls[j].disorderRatio); @@ -1302,33 +1332,45 @@ static void printfInsertMetaToFile(FILE* fp) { fprintf(fp, " columnCount: %d\n ", g_Dbs.db[i].superTbls[j].columnCount); for (int k = 0; k < g_Dbs.db[i].superTbls[j].columnCount; k++) { //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen); - if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType, "binary", 6)) || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType, "nchar", 5))) { - fprintf(fp, "column[%d]:%s(%d) ", k, g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen); + if ((0 == strncasecmp( + g_Dbs.db[i].superTbls[j].columns[k].dataType, + "binary", strlen("binary"))) + || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType, + "nchar", strlen("nchar")))) { + fprintf(fp, "column[%d]:%s(%d) ", k, + g_Dbs.db[i].superTbls[j].columns[k].dataType, + g_Dbs.db[i].superTbls[j].columns[k].dataLen); } else { fprintf(fp, "column[%d]:%s ", k, g_Dbs.db[i].superTbls[j].columns[k].dataType); } } fprintf(fp, "\n"); - - fprintf(fp, " tagCount: %d\n ", g_Dbs.db[i].superTbls[j].tagCount); + + fprintf(fp, " tagCount: %d\n ", + g_Dbs.db[i].superTbls[j].tagCount); for (int k = 0; k < g_Dbs.db[i].superTbls[j].tagCount; k++) { //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].tags[k].dataType, g_Dbs.db[i].superTbls[j].tags[k].dataLen); - if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, "binary", 6)) || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, "nchar", 5))) { - fprintf(fp, "tag[%d]:%s(%d) ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType, g_Dbs.db[i].superTbls[j].tags[k].dataLen); + if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, + "binary", strlen("binary"))) + || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, + "nchar", strlen("nchar")))) { + fprintf(fp, "tag[%d]:%s(%d) ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType, + g_Dbs.db[i].superTbls[j].tags[k].dataLen); } else { fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType); - } + } } fprintf(fp, "\n"); } fprintf(fp, "\n"); } - SHOW_PARSE_RESULT_END_TO_FILE(fp); + SHOW_PARSE_RESULT_END_TO_FILE(fp); } static void printfQueryMeta() { - SHOW_PARSE_RESULT_START(); - printf("host: \033[33m%s:%u\033[0m\n", g_queryInfo.host, g_queryInfo.port); + SHOW_PARSE_RESULT_START(); + printf("host: \033[33m%s:%u\033[0m\n", + g_queryInfo.host, g_queryInfo.port); printf("user: \033[33m%s\033[0m\n", g_queryInfo.user); printf("password: \033[33m%s\033[0m\n", g_queryInfo.password); printf("database name: \033[33m%s\033[0m\n", g_queryInfo.dbName); @@ -1339,7 +1381,7 @@ static void printfQueryMeta() { printf("concurrent: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.concurrent); printf("sqlCount: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.sqlCount); - if (SUBSCRIBE_MODE == g_args.test_mode) { + if (SUBSCRIBE_TEST == g_args.test_mode) { printf("mod: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeMode); printf("interval: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeInterval); printf("restart: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeRestart); @@ -1356,7 +1398,7 @@ static void printfQueryMeta() { printf("childTblCount: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.childTblCount); printf("stable name: \033[33m%s\033[0m\n", g_queryInfo.subQueryInfo.sTblName); - if (SUBSCRIBE_MODE == g_args.test_mode) { + if (SUBSCRIBE_TEST == g_args.test_mode) { printf("mod: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeMode); printf("interval: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeInterval); printf("restart: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeRestart); @@ -1457,7 +1499,7 @@ static int xDumpResultToFile(const char* fname, TAOS_RES* tres) { FILE* fp = fopen(fname, "at"); if (fp == NULL) { - fprintf(stderr, "ERROR: failed to open file: %s\n", fname); + errorPrint("%s() LN%d, failed to open file: %s\n", __func__, __LINE__, fname); return -1; } @@ -1502,7 +1544,7 @@ static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) { int32_t code = taos_errno(res); if (code != 0) { - fprintf(stderr, "failed to run , reason: %s\n", taos_errstr(res)); + errorPrint( "failed to run , reason: %s\n", taos_errstr(res)); return -1; } @@ -1514,19 +1556,23 @@ static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) { dbInfos[count] = (SDbInfo *)calloc(1, sizeof(SDbInfo)); if (dbInfos[count] == NULL) { - fprintf(stderr, "failed to allocate memory for some dbInfo[%d]\n", count); + errorPrint( "failed to allocate memory for some dbInfo[%d]\n", count); return -1; } - tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX], fields[TSDB_SHOW_DB_NAME_INDEX].bytes); - xFormatTimestamp(dbInfos[count]->create_time, *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX], TSDB_TIME_PRECISION_MILLI); + tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX], + fields[TSDB_SHOW_DB_NAME_INDEX].bytes); + xFormatTimestamp(dbInfos[count]->create_time, + *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX], + TSDB_TIME_PRECISION_MILLI); dbInfos[count]->ntables = *((int32_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]); dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]); dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]); dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]); dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]); - tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX], fields[TSDB_SHOW_DB_KEEP_INDEX].bytes); + tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX], + fields[TSDB_SHOW_DB_KEEP_INDEX].bytes); dbInfos[count]->cache = *((int32_t *)row[TSDB_SHOW_DB_CACHE_INDEX]); dbInfos[count]->blocks = *((int32_t *)row[TSDB_SHOW_DB_BLOCKS_INDEX]); dbInfos[count]->minrows = *((int32_t *)row[TSDB_SHOW_DB_MINROWS_INDEX]); @@ -1540,11 +1586,12 @@ static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) { (char *)row[TSDB_SHOW_DB_PRECISION_INDEX], fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes); dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]); - tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX], fields[TSDB_SHOW_DB_STATUS_INDEX].bytes); - + tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX], + fields[TSDB_SHOW_DB_STATUS_INDEX].bytes); + count++; if (count > MAX_DATABASE_COUNT) { - fprintf(stderr, "The database count overflow than %d\n", MAX_DATABASE_COUNT); + errorPrint( "The database count overflow than %d\n", MAX_DATABASE_COUNT); break; } } @@ -1558,7 +1605,7 @@ static void printfDbInfoForQueryToFile(char* filename, SDbInfo* dbInfos, int ind FILE *fp = fopen(filename, "at"); if (fp == NULL) { - fprintf(stderr, "failed to open file: %s\n", filename); + errorPrint( "failed to open file: %s\n", filename); return; } @@ -1596,8 +1643,10 @@ static void printfQuerySystemInfo(TAOS * taos) { struct tm* lt; time(&t); lt = localtime(&t); - snprintf(filename, MAX_QUERY_SQL_LENGTH, "querySystemInfo-%d-%d-%d %d:%d:%d", lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec); - + snprintf(filename, MAX_QUERY_SQL_LENGTH, "querySystemInfo-%d-%d-%d %d:%d:%d", + lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min, + lt->tm_sec); + // show variables res = taos_query(taos, "show variables;"); //getResult(res, filename); @@ -1607,12 +1656,12 @@ static void printfQuerySystemInfo(TAOS * taos) { res = taos_query(taos, "show dnodes;"); xDumpResultToFile(filename, res); //getResult(res, filename); - + // show databases res = taos_query(taos, "show databases;"); SDbInfo** dbInfos = (SDbInfo **)calloc(MAX_DATABASE_COUNT, sizeof(SDbInfo *)); if (dbInfos == NULL) { - fprintf(stderr, "failed to allocate memory\n"); + errorPrint("%s() LN%d, failed to allocate memory\n", __func__, __LINE__); return; } int dbCount = getDbFromServer(taos, dbInfos); @@ -1624,7 +1673,7 @@ static void printfQuerySystemInfo(TAOS * taos) { for (int i = 0; i < dbCount; i++) { // printf database info printfDbInfoForQueryToFile(filename, dbInfos[i], i); - + // show db.vgroups snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.vgroups;", dbInfos[i]->name); res = taos_query(taos, buffer); @@ -1642,9 +1691,7 @@ static void printfQuerySystemInfo(TAOS * taos) { } -void ERROR_EXIT(const char *msg) { perror(msg); exit(-1); } - -int postProceSql(char* host, uint16_t port, char* sqlstr) +static int postProceSql(char* host, uint16_t port, char* sqlstr) { char *req_fmt = "POST %s HTTP/1.1\r\nHost: %s:%d\r\nAccept: */*\r\nAuthorization: Basic %s\r\nContent-Length: %d\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n%s"; @@ -1691,9 +1738,9 @@ int postProceSql(char* host, uint16_t port, char* sqlstr) sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { #ifdef WINDOWS - fprintf(stderr, "Could not create socket : %d" , WSAGetLastError()); + errorPrint( "Could not create socket : %d" , WSAGetLastError()); #endif - debugPrint("%s() LN%d sockfd=%d\n", __func__, __LINE__, sockfd); + debugPrint("%s() LN%d, sockfd=%d\n", __func__, __LINE__, sockfd); free(request_buf); ERROR_EXIT("ERROR opening socket"); } @@ -1813,7 +1860,7 @@ int postProceSql(char* host, uint16_t port, char* sqlstr) static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) { char* dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1); if (NULL == dataBuf) { - printf("calloc failed! size:%d\n", TSDB_MAX_SQL_LEN+1); + errorPrint("%s() LN%d, calloc failed! size:%d\n", __func__, __LINE__, TSDB_MAX_SQL_LEN+1); return NULL; } @@ -1997,7 +2044,7 @@ static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos, int childTblCount = (limit < 0)?10000:limit; int count = 0; - childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN); +// childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN); char* pTblName = childTblName; while ((row = taos_fetch_row(res)) != NULL) { int32_t* len = taos_fetch_lengths(res); @@ -2005,7 +2052,8 @@ static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos, //printf("==== sub table name: %s\n", pTblName); count++; if (count >= childTblCount - 1) { - char *tmp = realloc(childTblName, (size_t)childTblCount*1.5*TSDB_TABLE_NAME_LEN+1); + char *tmp = realloc(childTblName, + (size_t)childTblCount*1.5*TSDB_TABLE_NAME_LEN+1); if (tmp != NULL) { childTblName = tmp; childTblCount = (int)(childTblCount*1.5); @@ -2013,14 +2061,15 @@ static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos, (size_t)((childTblCount-count)*TSDB_TABLE_NAME_LEN)); } else { // exit, if allocate more memory failed - printf("realloc fail for save child table name of %s.%s\n", dbName, sTblName); + errorPrint("%s() LN%d, realloc fail for save child table name of %s.%s\n", + __func__, __LINE__, dbName, sTblName); tmfree(childTblName); taos_free_result(res); taos_close(taos); exit(-1); } } - pTblName = childTblName + count * TSDB_TABLE_NAME_LEN; + pTblName = childTblName + count * TSDB_TABLE_NAME_LEN; } *childTblCountOfSuperTbl = count; @@ -2101,13 +2150,21 @@ static int getSuperTableFromServer(TAOS * taos, char* dbName, calcRowLen(superTbls); +/* if (TBL_ALREADY_EXISTS == superTbls->childTblExists) { //get all child table name use cmd: select tbname from superTblName; + int childTblCount = 10000; + superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN); + if (superTbls->childTblName == NULL) { + errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__); + return -1; + } getAllChildNameOfSuperTable(taos, dbName, superTbls->sTblName, &superTbls->childTblName, &superTbls->childTblCount); } + */ return 0; } @@ -2239,7 +2296,7 @@ static int createSuperTable(TAOS * taos, char* dbName, SSuperTable* superTbls, verbosePrint("%s() LN%d: %s\n", __func__, __LINE__, command); if (0 != queryDbExec(taos, command, NO_INSERT_TYPE)) { - fprintf(stderr, "create supertable %s failed!\n\n", + errorPrint( "create supertable %s failed!\n\n", superTbls->sTblName); return -1; } @@ -2253,7 +2310,7 @@ static int createDatabases() { int ret = 0; taos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, NULL, g_Dbs.port); if (taos == NULL) { - fprintf(stderr, "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); + errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); return -1; } char command[BUFFER_SIZE] = "\0"; @@ -2329,7 +2386,8 @@ static int createDatabases() { " fsync %d", g_Dbs.db[i].dbCfg.fsync); } if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", strlen("ms"))) - || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", strlen("us")))) { + || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, + "us", strlen("us")))) { dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, " precision \'%s\';", g_Dbs.db[i].dbCfg.precision); } @@ -2337,22 +2395,29 @@ static int createDatabases() { debugPrint("%s() %d command: %s\n", __func__, __LINE__, command); if (0 != queryDbExec(taos, command, NO_INSERT_TYPE)) { taos_close(taos); - fprintf(stderr, "\ncreate database %s failed!\n\n", g_Dbs.db[i].dbName); + errorPrint( "\ncreate database %s failed!\n\n", g_Dbs.db[i].dbName); return -1; } printf("\ncreate database %s success!\n\n", g_Dbs.db[i].dbName); - debugPrint("%s() %d supertbl count:%d\n", __func__, __LINE__, g_Dbs.db[i].superTblCount); + debugPrint("%s() %d supertbl count:%d\n", + __func__, __LINE__, g_Dbs.db[i].superTblCount); for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { // describe super table, if exists - sprintf(command, "describe %s.%s;", g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].sTblName); + sprintf(command, "describe %s.%s;", g_Dbs.db[i].dbName, + g_Dbs.db[i].superTbls[j].sTblName); verbosePrint("%s() %d command: %s\n", __func__, __LINE__, command); if (0 != queryDbExec(taos, command, NO_INSERT_TYPE)) { g_Dbs.db[i].superTbls[j].superTblExists = TBL_NO_EXISTS; - ret = createSuperTable(taos, g_Dbs.db[i].dbName, &g_Dbs.db[i].superTbls[j], g_Dbs.use_metric); + ret = createSuperTable(taos, g_Dbs.db[i].dbName, + &g_Dbs.db[i].superTbls[j], g_Dbs.use_metric); } else { g_Dbs.db[i].superTbls[j].superTblExists = TBL_ALREADY_EXISTS; - ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName, &g_Dbs.db[i].superTbls[j]); + + if (g_Dbs.db[i].superTbls[j].childTblExists != TBL_ALREADY_EXISTS) { + ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName, + &g_Dbs.db[i].superTbls[j]); + } } if (0 != ret) { @@ -2382,14 +2447,18 @@ static void* createTable(void *sarg) char *buffer = calloc(buff_len, 1); if (buffer == NULL) { - fprintf(stderr, "Memory allocated failed!"); + errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__); exit(-1); } int len = 0; int batchNum = 0; - //printf("Creating table from %d to %d\n", winfo->start_table_id, winfo->end_table_id); - for (int i = winfo->start_table_id; i <= winfo->end_table_id; i++) { + + verbosePrint("%s() LN%d: Creating table from %d to %d\n", + __func__, __LINE__, + winfo->start_table_from, winfo->end_table_to); + + for (int i = winfo->start_table_from; i <= winfo->end_table_to; i++) { if (0 == g_Dbs.use_metric) { snprintf(buffer, buff_len, "create table if not exists %s.%s%d %s;", @@ -2436,7 +2505,7 @@ static void* createTable(void *sarg) len = 0; verbosePrint("%s() LN%d %s\n", __func__, __LINE__, buffer); if (0 != queryDbExec(winfo->taos, buffer, NO_INSERT_TYPE)){ - fprintf(stderr, "queryDbExec() failed. buffer:\n%s\n", buffer); + errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer); free(buffer); return NULL; } @@ -2444,7 +2513,7 @@ static void* createTable(void *sarg) int64_t currentPrintTime = taosGetTimestampMs(); if (currentPrintTime - lastPrintTime > 30*1000) { printf("thread[%d] already create %d - %d tables\n", - winfo->threadID, winfo->start_table_id, i); + winfo->threadID, winfo->start_table_from, i); lastPrintTime = currentPrintTime; } } @@ -2452,7 +2521,7 @@ static void* createTable(void *sarg) if (0 != len) { verbosePrint("%s() %d buffer: %s\n", __func__, __LINE__, buffer); if (0 != queryDbExec(winfo->taos, buffer, NO_INSERT_TYPE)) { - fprintf(stderr, "queryDbExec() failed. buffer:\n%s\n", buffer); + errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer); } } @@ -2460,7 +2529,7 @@ static void* createTable(void *sarg) return NULL; } -int startMultiThreadCreateChildTable( +static int startMultiThreadCreateChildTable( char* cols, int threads, int startFrom, int ntables, char* db_name, SSuperTable* superTblInfo) { pthread_t *pids = malloc(threads * sizeof(pthread_t)); @@ -2484,7 +2553,6 @@ int startMultiThreadCreateChildTable( int b = 0; b = ntables % threads; - int last = startFrom; for (int i = 0; i < threads; i++) { threadInfo *t_info = infos + i; t_info->threadID = i; @@ -2498,14 +2566,16 @@ int startMultiThreadCreateChildTable( db_name, g_Dbs.port); if (t_info->taos == NULL) { - fprintf(stderr, "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); + errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); free(pids); free(infos); return -1; } - t_info->start_table_id = last; - t_info->end_table_id = i < b ? last + a : last + a - 1; - last = t_info->end_table_id + 1; + + t_info->start_table_from = startFrom; + t_info->ntables = iend_table_to = i < b ? startFrom + a : startFrom + a - 1; + startFrom = t_info->end_table_to + 1; t_info->use_metric = 1; t_info->cols = cols; t_info->minDelay = INT16_MAX; @@ -2563,10 +2633,10 @@ static void createChildTables() { if ((strncasecmp(g_args.datatype[j], "BINARY", strlen("BINARY")) == 0) || (strncasecmp(g_args.datatype[j], "NCHAR", strlen("NCHAR")) == 0)) { - len = snprintf(tblColsBuf + len, MAX_SQL_SIZE, + len = snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ", COL%d %s(60)", j, g_args.datatype[j]); } else { - len = snprintf(tblColsBuf + len, MAX_SQL_SIZE, + len = snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ", COL%d %s", j, g_args.datatype[j]); } len = strlen(tblColsBuf); @@ -2592,7 +2662,7 @@ static void createChildTables() { /* Read 10000 lines at most. If more than 10000 lines, continue to read after using */ -int readTagFromCsvFileToMem(SSuperTable * superTblInfo) { +static int readTagFromCsvFileToMem(SSuperTable * superTblInfo) { size_t n = 0; ssize_t readLen = 0; char * line = NULL; @@ -2662,7 +2732,6 @@ int readSampleFromJsonFileToMem(SSuperTable * superTblInfo) { return 0; } - /* Read 10000 lines at most. If more than 10000 lines, continue to read after using */ @@ -2675,18 +2744,19 @@ static int readSampleFromCsvFileToMem( FILE* fp = fopen(superTblInfo->sampleFile, "r"); if (fp == NULL) { - fprintf(stderr, "Failed to open sample file: %s, reason:%s\n", + errorPrint( "Failed to open sample file: %s, reason:%s\n", superTblInfo->sampleFile, strerror(errno)); return -1; } + assert(superTblInfo->sampleDataBuf); memset(superTblInfo->sampleDataBuf, 0, MAX_SAMPLES_ONCE_FROM_FILE * superTblInfo->lenOfOneRow); while (1) { readLen = tgetline(&line, &n, fp); if (-1 == readLen) { if(0 != fseek(fp, 0, SEEK_SET)) { - fprintf(stderr, "Failed to fseek file: %s, reason:%s\n", + errorPrint( "Failed to fseek file: %s, reason:%s\n", superTblInfo->sampleFile, strerror(errno)); fclose(fp); return -1; @@ -2708,6 +2778,9 @@ static int readSampleFromCsvFileToMem( continue; } + verbosePrint("readLen=%ld stb->lenOfOneRow=%d getRows=%d\n", (long)readLen, + superTblInfo->lenOfOneRow, getRows); + memcpy(superTblInfo->sampleDataBuf + getRows * superTblInfo->lenOfOneRow, line, readLen); getRows++; @@ -2722,23 +2795,10 @@ static int readSampleFromCsvFileToMem( return 0; } -/* -void readSampleFromFileToMem(SSuperTable * supterTblInfo) { - int ret; - if (0 == strncasecmp(supterTblInfo->sampleFormat, "csv", 3)) { - ret = readSampleFromCsvFileToMem(supterTblInfo); - } else if (0 == strncasecmp(supterTblInfo->sampleFormat, "json", 4)) { - ret = readSampleFromJsonFileToMem(supterTblInfo); - } - - if (0 != ret) { - exit(-1); - } -} -*/ -static bool getColumnAndTagTypeFromInsertJsonFile(cJSON* stbInfo, SSuperTable* superTbls) { +static bool getColumnAndTagTypeFromInsertJsonFile( + cJSON* stbInfo, SSuperTable* superTbls) { bool ret = false; - + // columns cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns"); if (columns && columns->type != cJSON_Array) { @@ -2749,11 +2809,11 @@ static bool getColumnAndTagTypeFromInsertJsonFile(cJSON* stbInfo, SSuperTable* s superTbls->tagCount = 0; return true; } - + int columnSize = cJSON_GetArraySize(columns); if (columnSize > MAX_COLUMN_COUNT) { - printf("ERROR: failed to read json, column size overflow, max column size is %d\n", - MAX_COLUMN_COUNT); + errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n", + __func__, __LINE__, MAX_COLUMN_COUNT); goto PARSE_OVER; } @@ -2761,7 +2821,7 @@ static bool getColumnAndTagTypeFromInsertJsonFile(cJSON* stbInfo, SSuperTable* s int index = 0; StrColumn columnCase; - //superTbls->columnCount = columnSize; + //superTbls->columnCount = columnSize; for (int k = 0; k < columnSize; ++k) { cJSON* column = cJSON_GetArrayItem(columns, k); if (column == NULL) continue; @@ -2769,9 +2829,9 @@ static bool getColumnAndTagTypeFromInsertJsonFile(cJSON* stbInfo, SSuperTable* s count = 1; cJSON* countObj = cJSON_GetObjectItem(column, "count"); if (countObj && countObj->type == cJSON_Number) { - count = countObj->valueint; + count = countObj->valueint; } else if (countObj && countObj->type != cJSON_Number) { - printf("ERROR: failed to read json, column count not found\n"); + errorPrint("%s() LN%d, failed to read json, column count not found\n", __func__, __LINE__); goto PARSE_OVER; } else { count = 1; @@ -2781,54 +2841,55 @@ static bool getColumnAndTagTypeFromInsertJsonFile(cJSON* stbInfo, SSuperTable* s memset(&columnCase, 0, sizeof(StrColumn)); cJSON *dataType = cJSON_GetObjectItem(column, "type"); if (!dataType || dataType->type != cJSON_String || dataType->valuestring == NULL) { - printf("ERROR: failed to read json, column type not found\n"); + errorPrint("%s() LN%d: failed to read json, column type not found\n", __func__, __LINE__); goto PARSE_OVER; } //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, MAX_TB_NAME_SIZE); tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE); - + cJSON* dataLen = cJSON_GetObjectItem(column, "len"); if (dataLen && dataLen->type == cJSON_Number) { - columnCase.dataLen = dataLen->valueint; + columnCase.dataLen = dataLen->valueint; } else if (dataLen && dataLen->type != cJSON_Number) { - printf("ERROR: failed to read json, column len not found\n"); + debugPrint("%s() LN%d: failed to read json, column len not found\n", __func__, __LINE__); goto PARSE_OVER; } else { columnCase.dataLen = 8; } - + for (int n = 0; n < count; ++n) { - tstrncpy(superTbls->columns[index].dataType, columnCase.dataType, MAX_TB_NAME_SIZE); - superTbls->columns[index].dataLen = columnCase.dataLen; + tstrncpy(superTbls->columns[index].dataType, + columnCase.dataType, MAX_TB_NAME_SIZE); + superTbls->columns[index].dataLen = columnCase.dataLen; index++; } - } - superTbls->columnCount = index; - + } + superTbls->columnCount = index; + count = 1; index = 0; // tags cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags"); if (!tags || tags->type != cJSON_Array) { - printf("ERROR: failed to read json, tags not found\n"); + debugPrint("%s() LN%d, failed to read json, tags not found\n", __func__, __LINE__); goto PARSE_OVER; } int tagSize = cJSON_GetArraySize(tags); if (tagSize > MAX_TAG_COUNT) { - printf("ERROR: failed to read json, tags size overflow, max tag size is %d\n", MAX_TAG_COUNT); + debugPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n", __func__, __LINE__, MAX_TAG_COUNT); goto PARSE_OVER; } - - //superTbls->tagCount = tagSize; + + //superTbls->tagCount = tagSize; for (int k = 0; k < tagSize; ++k) { cJSON* tag = cJSON_GetArrayItem(tags, k); if (tag == NULL) continue; - + count = 1; cJSON* countObj = cJSON_GetObjectItem(tag, "count"); if (countObj && countObj->type == cJSON_Number) { - count = countObj->valueint; + count = countObj->valueint; } else if (countObj && countObj->type != cJSON_Number) { printf("ERROR: failed to read json, column count not found\n"); goto PARSE_OVER; @@ -2844,23 +2905,23 @@ static bool getColumnAndTagTypeFromInsertJsonFile(cJSON* stbInfo, SSuperTable* s goto PARSE_OVER; } tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE); - + cJSON* dataLen = cJSON_GetObjectItem(tag, "len"); if (dataLen && dataLen->type == cJSON_Number) { - columnCase.dataLen = dataLen->valueint; + columnCase.dataLen = dataLen->valueint; } else if (dataLen && dataLen->type != cJSON_Number) { printf("ERROR: failed to read json, column len not found\n"); goto PARSE_OVER; } else { columnCase.dataLen = 0; - } - + } + for (int n = 0; n < count; ++n) { tstrncpy(superTbls->tags[index].dataType, columnCase.dataType, MAX_TB_NAME_SIZE); - superTbls->tags[index].dataLen = columnCase.dataLen; + superTbls->tags[index].dataLen = columnCase.dataLen; index++; } - } + } superTbls->tagCount = index; ret = true; @@ -2938,37 +2999,47 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { goto PARSE_OVER; } - cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval"); - if (gInsertInterval && gInsertInterval->type == cJSON_Number) { - g_args.insert_interval = gInsertInterval->valueint; - } else if (!gInsertInterval) { - g_args.insert_interval = 0; - } else { - fprintf(stderr, "ERROR: failed to read json, insert_interval input mistake\n"); - goto PARSE_OVER; - } - - cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len"); - if (maxSqlLen && maxSqlLen->type == cJSON_Number) { - g_args.max_sql_len = maxSqlLen->valueint; - } else if (!maxSqlLen) { - g_args.max_sql_len = TSDB_PAYLOAD_SIZE; - } else { - fprintf(stderr, "ERROR: failed to read json, max_sql_len input mistake\n"); - goto PARSE_OVER; - } - + cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval"); + if (gInsertInterval && gInsertInterval->type == cJSON_Number) { + g_args.insert_interval = gInsertInterval->valueint; + } else if (!gInsertInterval) { + g_args.insert_interval = 0; + } else { + errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n", __func__, __LINE__); + goto PARSE_OVER; + } - cJSON* numRecPerReq = cJSON_GetObjectItem(root, "num_of_records_per_req"); - if (numRecPerReq && numRecPerReq->type == cJSON_Number) { - g_args.num_of_RPR = numRecPerReq->valueint; - } else if (!numRecPerReq) { - g_args.num_of_RPR = 100; - } else { - printf("ERROR: failed to read json, num_of_records_per_req not found\n"); - goto PARSE_OVER; - } + cJSON* rowsPerTbl = cJSON_GetObjectItem(root, "rows_per_tbl"); + if (rowsPerTbl && rowsPerTbl->type == cJSON_Number) { + g_args.rows_per_tbl = rowsPerTbl->valueint; + } else if (!rowsPerTbl) { + g_args.rows_per_tbl = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req + } else { + errorPrint("%s() LN%d, failed to read json, rows_per_tbl input mistake\n", __func__, __LINE__); + goto PARSE_OVER; + } + + cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len"); + if (maxSqlLen && maxSqlLen->type == cJSON_Number) { + g_args.max_sql_len = maxSqlLen->valueint; + } else if (!maxSqlLen) { + g_args.max_sql_len = TSDB_PAYLOAD_SIZE; + } else { + errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n", __func__, __LINE__); + goto PARSE_OVER; + } + + cJSON* numRecPerReq = cJSON_GetObjectItem(root, "num_of_records_per_req"); + if (numRecPerReq && numRecPerReq->type == cJSON_Number) { + g_args.num_of_RPR = numRecPerReq->valueint; + } else if (!numRecPerReq) { + g_args.num_of_RPR = 100; + } else { + errorPrint("%s() LN%d, failed to read json, num_of_records_per_req not found\n", __func__, __LINE__); + goto PARSE_OVER; + } + cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no, if (answerPrompt && answerPrompt->type == cJSON_String @@ -2995,7 +3066,9 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { int dbSize = cJSON_GetArraySize(dbs); if (dbSize > MAX_DB_COUNT) { - printf("ERROR: failed to read json, databases size overflow, max database is %d\n", MAX_DB_COUNT); + errorPrint( + "ERROR: failed to read json, databases size overflow, max database is %d\n", + MAX_DB_COUNT); goto PARSE_OVER; } @@ -3033,8 +3106,10 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } cJSON *precision = cJSON_GetObjectItem(dbinfo, "precision"); - if (precision && precision->type == cJSON_String && precision->valuestring != NULL) { - tstrncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring, MAX_DB_NAME_SIZE); + if (precision && precision->type == cJSON_String + && precision->valuestring != NULL) { + tstrncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring, + MAX_DB_NAME_SIZE); } else if (!precision) { //tstrncpy(g_Dbs.db[i].dbCfg.precision, "ms", MAX_DB_NAME_SIZE); memset(g_Dbs.db[i].dbCfg.precision, 0, MAX_DB_NAME_SIZE); @@ -3192,7 +3267,9 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { int stbSize = cJSON_GetArraySize(stables); if (stbSize > MAX_SUPER_TABLE_COUNT) { - printf("ERROR: failed to read json, databases size overflow, max database is %d\n", MAX_SUPER_TABLE_COUNT); + errorPrint( + "ERROR: failed to read json, databases size overflow, max database is %d\n", + MAX_SUPER_TABLE_COUNT); goto PARSE_OVER; } @@ -3258,13 +3335,13 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!childTblExists) { g_Dbs.db[i].superTbls[j].childTblExists = TBL_NO_EXISTS; } else { - printf("ERROR: failed to read json, child_table_exists not found\n"); + errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n", __func__, __LINE__); goto PARSE_OVER; } cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count"); if (!count || count->type != cJSON_Number || 0 >= count->valueint) { - printf("ERROR: failed to read json, childtable_count not found\n"); + errorPrint("%s() LN%d, failed to read json, childtable_count not found\n", __func__, __LINE__); goto PARSE_OVER; } g_Dbs.db[i].superTbls[j].childTblCount = count->valueint; @@ -3277,7 +3354,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!dataSource) { tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand", MAX_DB_NAME_SIZE); } else { - printf("ERROR: failed to read json, data_source not found\n"); + errorPrint("%s() LN%d, failed to read json, data_source not found\n", __func__, __LINE__); goto PARSE_OVER; } @@ -3317,9 +3394,11 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp"); if (ts && ts->type == cJSON_String && ts->valuestring != NULL) { - tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp, ts->valuestring, MAX_DB_NAME_SIZE); + tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp, + ts->valuestring, MAX_DB_NAME_SIZE); } else if (!ts) { - tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp, "now", MAX_DB_NAME_SIZE); + tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp, + "now", MAX_DB_NAME_SIZE); } else { printf("ERROR: failed to read json, start_timestamp not found\n"); goto PARSE_OVER; @@ -3420,23 +3499,13 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { goto PARSE_OVER; } - cJSON* numberOfTblInOneSql = cJSON_GetObjectItem(stbInfo, "number_of_tbl_in_one_sql"); - if (numberOfTblInOneSql && numberOfTblInOneSql->type == cJSON_Number) { - g_Dbs.db[i].superTbls[j].numberOfTblInOneSql = numberOfTblInOneSql->valueint; - } else if (!numberOfTblInOneSql) { - g_Dbs.db[i].superTbls[j].numberOfTblInOneSql = 0; - } else { - printf("ERROR: failed to read json, numberOfTblInOneSql not found\n"); - goto PARSE_OVER; - } - cJSON* rowsPerTbl = cJSON_GetObjectItem(stbInfo, "rows_per_tbl"); if (rowsPerTbl && rowsPerTbl->type == cJSON_Number) { g_Dbs.db[i].superTbls[j].rowsPerTbl = rowsPerTbl->valueint; } else if (!rowsPerTbl) { - g_Dbs.db[i].superTbls[j].rowsPerTbl = 1; + g_Dbs.db[i].superTbls[j].rowsPerTbl = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req } else { - printf("ERROR: failed to read json, rowsPerTbl not found\n"); + errorPrint("%s() LN%d, failed to read json, rowsPerTbl input mistake\n", __func__, __LINE__); goto PARSE_OVER; } @@ -3466,7 +3535,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!insertRows) { g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF; } else { - fprintf(stderr, "failed to read json, insert_rows input mistake"); + errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n", __func__, __LINE__); goto PARSE_OVER; } @@ -3478,16 +3547,18 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { __func__, __LINE__, g_args.insert_interval); g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval; } else { - fprintf(stderr, "failed to read json, insert_interval input mistake"); + errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n", __func__, __LINE__); goto PARSE_OVER; } - if (NO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable +/* CBD if (NO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) { continue; } + */ - int retVal = getColumnAndTagTypeFromInsertJsonFile(stbInfo, &g_Dbs.db[i].superTbls[j]); + int retVal = getColumnAndTagTypeFromInsertJsonFile( + stbInfo, &g_Dbs.db[i].superTbls[j]); if (false == retVal) { goto PARSE_OVER; } @@ -3769,7 +3840,9 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { } cJSON* subkeepProgress = cJSON_GetObjectItem(subQuery, "keepProgress"); - if (subkeepProgress && subkeepProgress->type == cJSON_String && subkeepProgress->valuestring != NULL) { + if (subkeepProgress && + subkeepProgress->type == cJSON_String + && subkeepProgress->valuestring != NULL) { if (0 == strcmp("yes", subkeepProgress->valuestring)) { g_queryInfo.subQueryInfo.subscribeKeepProgress = 1; } else if (0 == strcmp("no", subkeepProgress->valuestring)) { @@ -3860,30 +3933,30 @@ static bool getInfoFromJsonFile(char* file) { cJSON* filetype = cJSON_GetObjectItem(root, "filetype"); if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) { if (0 == strcasecmp("insert", filetype->valuestring)) { - g_args.test_mode = INSERT_MODE; + g_args.test_mode = INSERT_TEST; } else if (0 == strcasecmp("query", filetype->valuestring)) { - g_args.test_mode = QUERY_MODE; + g_args.test_mode = QUERY_TEST; } else if (0 == strcasecmp("subscribe", filetype->valuestring)) { - g_args.test_mode = SUBSCRIBE_MODE; + g_args.test_mode = SUBSCRIBE_TEST; } else { printf("ERROR: failed to read json, filetype not support\n"); goto PARSE_OVER; } } else if (!filetype) { - g_args.test_mode = INSERT_MODE; + g_args.test_mode = INSERT_TEST; } else { printf("ERROR: failed to read json, filetype not found\n"); goto PARSE_OVER; } - if (INSERT_MODE == g_args.test_mode) { + if (INSERT_TEST == g_args.test_mode) { ret = getMetaFromInsertJsonFile(root); - } else if (QUERY_MODE == g_args.test_mode) { + } else if (QUERY_TEST == g_args.test_mode) { ret = getMetaFromQueryJsonFile(root); - } else if (SUBSCRIBE_MODE == g_args.test_mode) { + } else if (SUBSCRIBE_TEST == g_args.test_mode) { ret = getMetaFromQueryJsonFile(root); } else { - printf("ERROR: input json file type error! please input correct file type: insert or query or subscribe\n"); + errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n", __func__, __LINE__); goto PARSE_OVER; } @@ -3894,13 +3967,9 @@ PARSE_OVER: return ret; } -void prepareSampleData() { +static void prepareSampleData() { for (int i = 0; i < g_Dbs.dbCount; i++) { for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { - //if (0 == strncasecmp(g_Dbs.db[i].superTbls[j].dataSource, "sample", 6)) { - // readSampleFromFileToMem(&g_Dbs.db[i].superTbls[j]); - //} - if (g_Dbs.db[i].superTbls[j].tagsFile[0] != 0) { (void)readTagFromCsvFileToMem(&g_Dbs.db[i].superTbls[j]); } @@ -3908,7 +3977,7 @@ void prepareSampleData() { } } -void postFreeResource() { +static void postFreeResource() { tmfclose(g_fpOfInsertResult); for (int i = 0; i < g_Dbs.dbCount; i++) { for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { @@ -3935,15 +4004,18 @@ void postFreeResource() { static int getRowDataFromSample(char* dataBuf, int maxLen, int64_t timestamp, SSuperTable* superTblInfo, int* sampleUsePos) { if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) { - int ret = readSampleFromCsvFileToMem(superTblInfo); +/* int ret = readSampleFromCsvFileToMem(superTblInfo); if (0 != ret) { tmfree(superTblInfo->sampleDataBuf); + superTblInfo->sampleDataBuf = NULL; return -1; } +*/ *sampleUsePos = 0; } int dataLen = 0; + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "(%" PRId64 ", ", timestamp); dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, @@ -3955,33 +4027,44 @@ static int getRowDataFromSample(char* dataBuf, int maxLen, int64_t timestamp, return dataLen; } -int generateRowData(char* dataBuf, int maxLen, int64_t timestamp, SSuperTable* stbInfo) { +static int generateRowData(char* dataBuf, int maxLen, int64_t timestamp, SSuperTable* stbInfo) { int dataLen = 0; dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "(%" PRId64 ", ", timestamp); for (int i = 0; i < stbInfo->columnCount; i++) { - if ((0 == strncasecmp(stbInfo->columns[i].dataType, "binary", 6)) || (0 == strncasecmp(stbInfo->columns[i].dataType, "nchar", 5))) { + if ((0 == strncasecmp(stbInfo->columns[i].dataType, "binary", 6)) + || (0 == strncasecmp(stbInfo->columns[i].dataType, "nchar", 5))) { if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) { - printf("binary or nchar length overflow, max size:%u\n", (uint32_t)TSDB_MAX_BINARY_LEN); + errorPrint( "binary or nchar length overflow, max size:%u\n", + (uint32_t)TSDB_MAX_BINARY_LEN); return (-1); } - + char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1); if (NULL == buf) { - printf("calloc failed! size:%d\n", stbInfo->columns[i].dataLen); + errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen); return (-1); } rand_string(buf, stbInfo->columns[i].dataLen); dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "\'%s\', ", buf); tmfree(buf); - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "int", 3)) { - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_int()); - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "bigint", 6)) { - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%"PRId64", ", rand_bigint()); - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "float", 5)) { - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%f, ", rand_float()); - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "double", 6)) { - dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%f, ", rand_double()); - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "smallint", 8)) { + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, + "int", 3)) { + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, + "%d, ", rand_int()); + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, + "bigint", 6)) { + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, + "%"PRId64", ", rand_bigint()); + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, + "float", 5)) { + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, + "%f, ", rand_float()); + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, + "double", 6)) { + dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, + "%f, ", rand_double()); + } else if (0 == strncasecmp(stbInfo->columns[i].dataType, + "smallint", 8)) { dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_smallint()); } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "tinyint", 7)) { dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_tinyint()); @@ -3990,7 +4073,7 @@ int generateRowData(char* dataBuf, int maxLen, int64_t timestamp, SSuperTable* } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "timestamp", 9)) { dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%"PRId64", ", rand_bigint()); } else { - printf("No support data type: %s\n", stbInfo->columns[i].dataType); + errorPrint( "No support data type: %s\n", stbInfo->columns[i].dataType); return (-1); } } @@ -4001,256 +4084,7 @@ int generateRowData(char* dataBuf, int maxLen, int64_t timestamp, SSuperTable* return dataLen; } -static void syncWriteForNumberOfTblInOneSql( - threadInfo *winfo, char* sampleDataBuf) { - SSuperTable* superTblInfo = winfo->superTblInfo; - - int samplePos = 0; - - //printf("========threadID[%d], table rang: %d - %d \n", winfo->threadID, winfo->start_table_id, winfo->end_table_id); - int64_t lastPrintTime = taosGetTimestampMs(); - - char* buffer = calloc(superTblInfo->maxSqlLen+1, 1); - if (NULL == buffer) { - printf("========calloc size[ %d ] fail!\n", superTblInfo->maxSqlLen); - return; - } - - int32_t numberOfTblInOneSql = superTblInfo->numberOfTblInOneSql; - int32_t tbls = winfo->end_table_id - winfo->start_table_id + 1; - if (numberOfTblInOneSql > tbls) { - numberOfTblInOneSql = tbls; - } - - uint64_t time_counter = winfo->start_time; - int sampleUsePos; - - int insert_interval = superTblInfo?superTblInfo->insertInterval:g_args.insert_interval; - int64_t st = 0; - int64_t et = 0xffffffff; - - int64_t insertRows = (superTblInfo)?superTblInfo->insertRows:g_args.num_of_DPT; - for (int i = 0; i < insertRows;) { - int32_t tbl_id = 0; - for (int tableSeq = winfo->start_table_id; tableSeq <= winfo->end_table_id; ) { - int64_t start_time = 0; - int inserted = i; - - for (int k = 0; k < g_args.num_of_RPR;) { - int len = 0; - memset(buffer, 0, superTblInfo->maxSqlLen); - char *pstr = buffer; - - int32_t end_tbl_id = tableSeq + numberOfTblInOneSql; - if (end_tbl_id > winfo->end_table_id) { - end_tbl_id = winfo->end_table_id+1; - } - - for (tbl_id = tableSeq ; tbl_id < end_tbl_id; tbl_id++) { - sampleUsePos = samplePos; - if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) { - char* tagsValBuf = NULL; - if (0 == superTblInfo->tagSource) { - tagsValBuf = generateTagVaulesForStb(superTblInfo); - } else { - tagsValBuf = getTagValueFromTagSample( - superTblInfo, tbl_id % superTblInfo->tagSampleCount); - } - if (NULL == tagsValBuf) { - goto free_and_statistics; - } - - if (0 == len) { - len += snprintf(pstr + len, - superTblInfo->maxSqlLen - len, - "insert into %s.%s%d using %s.%s tags %s values ", - winfo->db_name, - superTblInfo->childTblPrefix, - tbl_id, - winfo->db_name, - superTblInfo->sTblName, - tagsValBuf); - } else { - len += snprintf(pstr + len, - superTblInfo->maxSqlLen - len, - " %s.%s%d using %s.%s tags %s values ", - winfo->db_name, - superTblInfo->childTblPrefix, - tbl_id, - winfo->db_name, - superTblInfo->sTblName, - tagsValBuf); - } - tmfree(tagsValBuf); - } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) { - if (0 == len) { - len += snprintf(pstr + len, - superTblInfo->maxSqlLen - len, - "insert into %s.%s values ", - winfo->db_name, - superTblInfo->childTblName + tbl_id * TSDB_TABLE_NAME_LEN); - } else { - len += snprintf(pstr + len, - superTblInfo->maxSqlLen - len, - " %s.%s values ", - winfo->db_name, - superTblInfo->childTblName + tbl_id * TSDB_TABLE_NAME_LEN); - } - } else { // pre-create child table - if (0 == len) { - len += snprintf(pstr + len, - superTblInfo->maxSqlLen - len, - "insert into %s.%s%d values ", - winfo->db_name, - superTblInfo->childTblPrefix, - tbl_id); - } else { - len += snprintf(pstr + len, - superTblInfo->maxSqlLen - len, - " %s.%s%d values ", - winfo->db_name, - superTblInfo->childTblPrefix, - tbl_id); - } - } - - start_time = time_counter; - for (int j = 0; j < superTblInfo->rowsPerTbl;) { - int retLen = 0; - if (0 == strncasecmp(superTblInfo->dataSource, - "sample", strlen("sample"))) { - retLen = getRowDataFromSample(pstr + len, - superTblInfo->maxSqlLen - len, - start_time += superTblInfo->timeStampStep, - superTblInfo, - &sampleUsePos); - if (retLen < 0) { - goto free_and_statistics; - } - } else if (0 == strncasecmp( - superTblInfo->dataSource, "rand", strlen("rand"))) { - int rand_num = rand_tinyint() % 100; - if (0 != superTblInfo->disorderRatio - && rand_num < superTblInfo->disorderRatio) { - int64_t d = start_time - taosRandom() % superTblInfo->disorderRange; - retLen = generateRowData(pstr + len, - superTblInfo->maxSqlLen - len, - d, - superTblInfo); - } else { - retLen = generateRowData(pstr + len, - superTblInfo->maxSqlLen - len, - start_time += superTblInfo->timeStampStep, - superTblInfo); - } - if (retLen < 0) { - goto free_and_statistics; - } - } - len += retLen; - //inserted++; - j++; - winfo->totalInsertRows++; - - if (inserted >= superTblInfo->insertRows || - (superTblInfo->maxSqlLen - len) < (superTblInfo->lenOfOneRow + 128)) { - tableSeq = tbl_id + 1; - printf("config rowsPerTbl and numberOfTblInOneSql not match with max_sql_lenth, please reconfig![lenOfOneRow:%d]\n", - superTblInfo->lenOfOneRow); - goto send_to_server; - } - } - } - - tableSeq = tbl_id; - inserted += superTblInfo->rowsPerTbl; - -send_to_server: - if (insert_interval) { - st = taosGetTimestampUs(); - - if (insert_interval > ((et - st)/1000)) { - int sleep_time = insert_interval - (et -st); - printf("sleep: %d ms insert interval\n", sleep_time); - taosMsleep(sleep_time); // ms - } - } - - if (0 == strncasecmp(superTblInfo->insertMode, - "taosc", - strlen("taosc"))) { - //printf("multi table===== sql: %s \n\n", buffer); - //int64_t t1 = taosGetTimestampMs(); - int64_t startTs; - int64_t endTs; - startTs = taosGetTimestampUs(); - - debugPrint("%s() LN%d buff: %s\n", __func__, __LINE__, buffer); - int affectedRows = queryDbExec( - winfo->taos, buffer, INSERT_TYPE); - - if (0 < affectedRows) { - endTs = taosGetTimestampUs(); - int64_t delay = endTs - startTs; - if (delay > winfo->maxDelay) winfo->maxDelay = delay; - if (delay < winfo->minDelay) winfo->minDelay = delay; - winfo->cntDelay++; - winfo->totalDelay += delay; - winfo->avgDelay = (double)winfo->totalDelay / winfo->cntDelay; - winfo->totalAffectedRows += affectedRows; - } else { - fprintf(stderr, "queryDbExec() buffer:\n%s\naffected rows is %d", buffer, affectedRows); - goto free_and_statistics; - } - - int64_t currentPrintTime = taosGetTimestampMs(); - if (currentPrintTime - lastPrintTime > 30*1000) { - printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n", - winfo->threadID, - winfo->totalInsertRows, - winfo->totalAffectedRows); - lastPrintTime = currentPrintTime; - } - //int64_t t2 = taosGetTimestampMs(); - //printf("taosc insert sql return, Spent %.4f seconds \n", (double)(t2 - t1)/1000.0); - } else { - //int64_t t1 = taosGetTimestampMs(); - int retCode = postProceSql(g_Dbs.host, g_Dbs.port, buffer); - //int64_t t2 = taosGetTimestampMs(); - //printf("http insert sql return, Spent %ld ms \n", t2 - t1); - - if (0 != retCode) { - printf("========restful return fail, threadID[%d]\n", winfo->threadID); - goto free_and_statistics; - } - } - if (insert_interval) { - et = taosGetTimestampUs(); - } - - break; - } - - if (tableSeq > winfo->end_table_id) { - if (0 == strncasecmp(superTblInfo->dataSource, "sample", strlen("sample"))) { - samplePos = sampleUsePos; - } - i = inserted; - time_counter = start_time; - } - } - - //printf("========loop %d childTables duration:%"PRId64 "========inserted rows:%d\n", winfo->end_table_id - winfo->start_table_id, et - st, i); - } - -free_and_statistics: - tmfree(buffer); - printf("====thread[%d] completed total inserted rows: %"PRId64 ", affected rows: %"PRId64 "====\n", - winfo->threadID, winfo->totalInsertRows, winfo->totalAffectedRows); - return; -} - -int32_t generateData(char *res, char **data_type, +static int32_t generateData(char *res, char **data_type, int num_of_cols, int64_t timestamp, int lenOfBinary) { memset(res, 0, MAX_DATA_SIZE); char *pstr = res; @@ -4311,70 +4145,82 @@ int32_t generateData(char *res, char **data_type, static int prepareSampleDataForSTable(SSuperTable *superTblInfo) { char* sampleDataBuf = NULL; - // each thread read sample data from csv file - if (0 == strncasecmp(superTblInfo->dataSource, - "sample", - strlen("sample"))) { - sampleDataBuf = calloc( + sampleDataBuf = calloc( superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1); - if (sampleDataBuf == NULL) { - fprintf(stderr, "Failed to calloc %d Bytes, reason:%s\n", + if (sampleDataBuf == NULL) { + errorPrint("%s() LN%d, Failed to calloc %d Bytes, reason:%s\n", + __func__, __LINE__, superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, strerror(errno)); return -1; - } + } - int ret = readSampleFromCsvFileToMem(superTblInfo); - if (0 != ret) { + superTblInfo->sampleDataBuf = sampleDataBuf; + int ret = readSampleFromCsvFileToMem(superTblInfo); + + if (0 != ret) { + errorPrint("%s() LN%d, read sample from csv file failed.\n", __func__, __LINE__); tmfree(sampleDataBuf); + superTblInfo->sampleDataBuf = NULL; return -1; - } } - superTblInfo->sampleDataBuf = sampleDataBuf; - return 0; } -static int execInsert(threadInfo *winfo, char *buffer, int k) +static int execInsert(threadInfo *pThreadInfo, char *buffer, int k) { int affectedRows; - SSuperTable* superTblInfo = winfo->superTblInfo; + SSuperTable* superTblInfo = pThreadInfo->superTblInfo; + verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID, + __func__, __LINE__, buffer); if (superTblInfo) { if (0 == strncasecmp(superTblInfo->insertMode, "taosc", strlen("taosc"))) { - verbosePrint("%s() LN%d %s\n", __func__, __LINE__, buffer); - affectedRows = queryDbExec(winfo->taos, buffer, INSERT_TYPE); + affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE); } else { - verbosePrint("%s() LN%d %s\n", __func__, __LINE__, buffer); - int retCode = postProceSql(g_Dbs.host, g_Dbs.port, buffer); - - if (0 != retCode) { - affectedRows = -1; - printf("========restful return fail, threadID[%d]\n", winfo->threadID); - } else { - affectedRows = k; - } + if (0 != postProceSql(g_Dbs.host, g_Dbs.port, buffer)) { + affectedRows = -1; + printf("========restful return fail, threadID[%d]\n", pThreadInfo->threadID); + } else { + affectedRows = k; + } } } else { - verbosePrint("%s() LN%d %s\n", __func__, __LINE__, buffer); - affectedRows = queryDbExec(winfo->taos, buffer, 1); - } - - if (0 > affectedRows){ - return affectedRows; + affectedRows = queryDbExec(pThreadInfo->taos, buffer, 1); } return affectedRows; } -static int generateDataBuffer(int32_t tableSeq, - threadInfo *pThreadInfo, char *buffer, - int64_t insertRows, - int64_t startFrom, int64_t startTime, int *pSampleUsePos) +static void getTableName(char *pTblName, threadInfo* pThreadInfo, int tableSeq) { SSuperTable* superTblInfo = pThreadInfo->superTblInfo; + if (superTblInfo) { + if ((superTblInfo->childTblOffset >= 0) + && (superTblInfo->childTblLimit > 0)) { + snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s", + superTblInfo->childTblName + (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN); + } else { + + verbosePrint("[%d] %s() LN%d: from=%d count=%d seq=%d\n", + pThreadInfo->threadID, __func__, __LINE__, + pThreadInfo->start_table_from, + pThreadInfo->ntables, tableSeq); + snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s", + superTblInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN); + } + } else { + snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%d", + g_args.tb_prefix, tableSeq); + } +} +static int generateDataTail(char *tableName, int32_t tableSeq, + threadInfo* pThreadInfo, SSuperTable* superTblInfo, + int batch, char* buffer, int64_t insertRows, + int64_t startFrom, uint64_t startTime, int *pSamplePos, int *dataLen) { + int len = 0; int ncols_per_record = 1; // count first col ts if (superTblInfo == NULL) { @@ -4385,159 +4231,389 @@ static int generateDataBuffer(int32_t tableSeq, } } - assert(buffer != NULL); + verbosePrint("%s() LN%d batch=%d\n", __func__, __LINE__, batch); - char *pChildTblName; - int childTblCount; + int k = 0; + for (k = 0; k < batch;) { + if (superTblInfo) { + int retLen = 0; - if (superTblInfo && (superTblInfo->childTblOffset > 0)) { - // select tbname from stb limit 1 offset tableSeq - getChildNameOfSuperTableWithLimitAndOffset(pThreadInfo->taos, - pThreadInfo->db_name, superTblInfo->sTblName, - &pChildTblName, &childTblCount, - 1, tableSeq); - } else { - pChildTblName = calloc(TSDB_TABLE_NAME_LEN, 1); - if (NULL == pChildTblName) { - fprintf(stderr, "failed to alloc memory %d\n", TSDB_TABLE_NAME_LEN); - return -1; - } - snprintf(pChildTblName, TSDB_TABLE_NAME_LEN, "%s%d", - superTblInfo?superTblInfo->childTblPrefix:g_args.tb_prefix, tableSeq); - } + if (0 == strncasecmp(superTblInfo->dataSource, + "sample", strlen("sample"))) { + retLen = getRowDataFromSample( + buffer + len, + superTblInfo->maxSqlLen - len, + startTime + superTblInfo->timeStampStep * k, + superTblInfo, + pSamplePos); + } else if (0 == strncasecmp(superTblInfo->dataSource, + "rand", strlen("rand"))) { + int rand_num = rand_tinyint() % 100; + if (0 != superTblInfo->disorderRatio + && rand_num < superTblInfo->disorderRatio) { + int64_t d = startTime + + superTblInfo->timeStampStep * k + - taosRandom() % superTblInfo->disorderRange; + retLen = generateRowData( + buffer + len, + superTblInfo->maxSqlLen - len, + d, + superTblInfo); + } else { + retLen = generateRowData( + buffer + len, + superTblInfo->maxSqlLen - len, + startTime + superTblInfo->timeStampStep * k, + superTblInfo); + } + } - memset(buffer, 0, superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len); + if (retLen < 0) { + return -1; + } - char *pstr = buffer; + len += retLen; - if (superTblInfo) { - if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) { - char* tagsValBuf = NULL; - if (0 == superTblInfo->tagSource) { - tagsValBuf = generateTagVaulesForStb(superTblInfo); + if (len >= (superTblInfo->maxSqlLen - 256)) { // reserve for overwrite + k++; + break; + } + } else { + int rand_num = taosRandom() % 100; + char data[MAX_DATA_SIZE]; + char **data_type = g_args.datatype; + int lenOfBinary = g_args.len_of_binary; + + if ((g_args.disorderRatio != 0) + && (rand_num < g_args.disorderRange)) { + + int64_t d = startTime + DEFAULT_TIMESTAMP_STEP * k + - taosRandom() % 1000000 + rand_num; + len = generateData(data, data_type, + ncols_per_record, d, lenOfBinary); } else { - tagsValBuf = getTagValueFromTagSample( + len = generateData(data, data_type, + ncols_per_record, + startTime + DEFAULT_TIMESTAMP_STEP * k, + lenOfBinary); + } + + buffer += sprintf(buffer, " %s", data); + if (strlen(buffer) >= (g_args.max_sql_len - 256)) { // too long + k++; + break; + } + } + + verbosePrint("%s() LN%d len=%d k=%d \nbuffer=%s\n", + __func__, __LINE__, len, k, buffer); + + k++; + startFrom ++; + + if (startFrom >= insertRows) { + break; + } + } + + *dataLen = len; + return k; +} + +static int generateSQLHead(char *tableName, int32_t tableSeq, + threadInfo* pThreadInfo, SSuperTable* superTblInfo, char *buffer) +{ + int len; + if (superTblInfo) { + if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) { + char* tagsValBuf = NULL; + if (0 == superTblInfo->tagSource) { + tagsValBuf = generateTagVaulesForStb(superTblInfo); + } else { + tagsValBuf = getTagValueFromTagSample( superTblInfo, tableSeq % superTblInfo->tagSampleCount); } if (NULL == tagsValBuf) { - fprintf(stderr, "tag buf failed to allocate memory\n"); - free(pChildTblName); - return -1; + errorPrint("%s() LN%d, tag buf failed to allocate memory\n", __func__, __LINE__); + return -1; } - pstr += snprintf(pstr, + len = snprintf(buffer, superTblInfo->maxSqlLen, "insert into %s.%s using %s.%s tags %s values", pThreadInfo->db_name, - pChildTblName, + tableName, pThreadInfo->db_name, superTblInfo->sTblName, tagsValBuf); tmfree(tagsValBuf); } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) { - pstr += snprintf(pstr, + len = snprintf(buffer, superTblInfo->maxSqlLen, "insert into %s.%s values", pThreadInfo->db_name, - superTblInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN); + tableName); } else { - pstr += snprintf(pstr, - (superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len), + len = snprintf(buffer, + superTblInfo->maxSqlLen, "insert into %s.%s values", pThreadInfo->db_name, - pChildTblName); + tableName); } } else { - pstr += snprintf(pstr, + len = snprintf(buffer, g_args.max_sql_len, "insert into %s.%s values", pThreadInfo->db_name, - pChildTblName); + tableName); } + return len; +} + +static int generateDataBuffer(char *pTblName, + int32_t tableSeq, + threadInfo *pThreadInfo, char *buffer, + int64_t insertRows, + int64_t startFrom, int64_t startTime, int *pSamplePos) +{ + SSuperTable* superTblInfo = pThreadInfo->superTblInfo; + + int ncols_per_record = 1; // count first col ts + + if (superTblInfo == NULL) { + int datatypeSeq = 0; + while(g_args.datatype[datatypeSeq]) { + datatypeSeq ++; + ncols_per_record ++; + } + } + + assert(buffer != NULL); + + memset(buffer, 0, superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len); + + char *pstr = buffer; + + int headLen = generateSQLHead(pTblName, tableSeq, pThreadInfo, superTblInfo, + buffer); + pstr += headLen; + int k; - int len = 0; + int dataLen; + k = generateDataTail(pTblName, tableSeq, pThreadInfo, superTblInfo, + g_args.num_of_RPR, pstr, insertRows, startFrom, + startTime, + pSamplePos, &dataLen); + return k; +} - verbosePrint("%s() LN%d num_of_RPR=%d\n", __func__, __LINE__, g_args.num_of_RPR); - for (k = 0; k < g_args.num_of_RPR;) { - if (superTblInfo) { - int retLen = 0; +static void* syncWriteInterlace(threadInfo *pThreadInfo) { + debugPrint("[%d] %s() LN%d: ### interlace write\n", + pThreadInfo->threadID, __func__, __LINE__); - if (0 == strncasecmp(superTblInfo->dataSource, - "sample", strlen("sample"))) { - retLen = getRowDataFromSample( - pstr + len, - superTblInfo->maxSqlLen - len, - startTime + superTblInfo->timeStampStep * startFrom, - superTblInfo, - pSampleUsePos); - } else if (0 == strncasecmp(superTblInfo->dataSource, - "rand", strlen("rand"))) { - int rand_num = rand_tinyint() % 100; - if (0 != superTblInfo->disorderRatio - && rand_num < superTblInfo->disorderRatio) { - int64_t d = startTime - taosRandom() % superTblInfo->disorderRange; - retLen = generateRowData( - pstr + len, - superTblInfo->maxSqlLen - len, - d, - superTblInfo); - //printf("disorder rows, rand_num:%d, last ts:%"PRId64" current ts:%"PRId64"\n", rand_num, start_time, d); - } else { - retLen = generateRowData( - pstr + len, - superTblInfo->maxSqlLen - len, - startTime + superTblInfo->timeStampStep * startFrom, - superTblInfo); - } + SSuperTable* superTblInfo = pThreadInfo->superTblInfo; - if (retLen < 0) { - free(pChildTblName); - return -1; - } + char* buffer = calloc(superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len, 1); + if (NULL == buffer) { + errorPrint( "Failed to alloc %d Bytes, reason:%s\n", + superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len, + strerror(errno)); + return NULL; + } + + int insertMode; + char tableName[TSDB_TABLE_NAME_LEN]; - len += retLen; - } - } else { - int rand_num = taosRandom() % 100; - char data[MAX_DATA_SIZE]; - char **data_type = g_args.datatype; - int lenOfBinary = g_args.len_of_binary; + int rowsPerTbl = superTblInfo?superTblInfo->rowsPerTbl:g_args.rows_per_tbl; - if ((g_args.disorderRatio != 0) - && (rand_num < g_args.disorderRange)) { - - int64_t d = startTime - taosRandom() % 1000000 + rand_num; - len = generateData(data, data_type, - ncols_per_record, d, lenOfBinary); + if (rowsPerTbl > 0) { + insertMode = INTERLACE_INSERT_MODE; + } else { + insertMode = PROGRESSIVE_INSERT_MODE; + } + + // rows per table need be less than insert batch + if (rowsPerTbl > g_args.num_of_RPR) + rowsPerTbl = g_args.num_of_RPR; + + pThreadInfo->totalInsertRows = 0; + pThreadInfo->totalAffectedRows = 0; + + int64_t insertRows = (superTblInfo)?superTblInfo->insertRows:g_args.num_of_DPT; + int insert_interval = superTblInfo?superTblInfo->insertInterval:g_args.insert_interval; + uint64_t st = 0; + uint64_t et = 0xffffffff; + + int64_t lastPrintTime = taosGetTimestampMs(); + int64_t startTs = taosGetTimestampUs(); + int64_t endTs; + + int tableSeq = pThreadInfo->start_table_from; + + debugPrint("[%d] %s() LN%d: start_table_from=%d ntables=%d insertRows=%"PRId64"\n", + pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->start_table_from, + pThreadInfo->ntables, insertRows); + + int64_t startTime = pThreadInfo->start_time; + + int batchPerTblTimes; + int batchPerTbl; + + assert(pThreadInfo->ntables > 0); + + if (rowsPerTbl > g_args.num_of_RPR) + rowsPerTbl = g_args.num_of_RPR; + + batchPerTbl = rowsPerTbl; + if ((rowsPerTbl > 0) && (pThreadInfo->ntables > 1)) { + batchPerTblTimes = + (g_args.num_of_RPR / (rowsPerTbl * pThreadInfo->ntables)) + 1; + } else { + batchPerTblTimes = 1; + } + + int generatedRecPerTbl = 0; + bool flagSleep = true; + int sleepTimeTotal = 0; + while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) { + if ((flagSleep) && (insert_interval)) { + st = taosGetTimestampUs(); + flagSleep = false; + } + // generate data + memset(buffer, 0, superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len); + + char *pstr = buffer; + int recOfBatch = 0; + + for (int i = 0; i < batchPerTblTimes; i ++) { + getTableName(tableName, pThreadInfo, tableSeq); + + int headLen; + if (i == 0) { + headLen = generateSQLHead(tableName, tableSeq, pThreadInfo, + superTblInfo, pstr); } else { - len = generateData(data, data_type, - ncols_per_record, - startTime + DEFAULT_TIMESTAMP_STEP * startFrom, - lenOfBinary); + headLen = snprintf(pstr, TSDB_TABLE_NAME_LEN, "%s.%s values", + pThreadInfo->db_name, + tableName); } - //assert(len + pstr - buffer < BUFFER_SIZE); - if (len + pstr - buffer >= g_args.max_sql_len) { // too long - break; + // generate data buffer + verbosePrint("[%d] %s() LN%d i=%d buffer:\n%s\n", + pThreadInfo->threadID, __func__, __LINE__, i, buffer); + + pstr += headLen; + int dataLen = 0; + + verbosePrint("[%d] %s() LN%d i=%d batchPerTblTimes=%d batchPerTbl = %d\n", + pThreadInfo->threadID, __func__, __LINE__, + i, batchPerTblTimes, batchPerTbl); + generateDataTail( + tableName, tableSeq, pThreadInfo, superTblInfo, + batchPerTbl, pstr, insertRows, 0, + startTime, + &(pThreadInfo->samplePos), &dataLen); + + pstr += dataLen; + recOfBatch += batchPerTbl; + pThreadInfo->totalInsertRows += batchPerTbl; + + verbosePrint("[%d] %s() LN%d batchPerTbl=%d recOfBatch=%d\n", + pThreadInfo->threadID, __func__, __LINE__, + batchPerTbl, recOfBatch); + + tableSeq ++; + if (insertMode == INTERLACE_INSERT_MODE) { + if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) { + // turn to first table + startTime += batchPerTbl * superTblInfo->timeStampStep; + tableSeq = pThreadInfo->start_table_from; + generatedRecPerTbl += batchPerTbl; + flagSleep = true; + if (generatedRecPerTbl >= insertRows) + break; + + if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR) + break; + } } - pstr += sprintf(pstr, " %s", data); + int remainRows = insertRows - generatedRecPerTbl; + if ((remainRows > 0) && (batchPerTbl > remainRows)) + batchPerTbl = remainRows; + + verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%d insertRows=%"PRId64"\n", + pThreadInfo->threadID, __func__, __LINE__, + generatedRecPerTbl, insertRows); + + if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl) + break; } - verbosePrint("%s() LN%d len=%d k=%d \nbuffer=%s\n", __func__, __LINE__, len, k, buffer); + verbosePrint("[%d] %s() LN%d recOfBatch=%d totalInsertRows=%"PRId64"\n", + pThreadInfo->threadID, __func__, __LINE__, recOfBatch, + pThreadInfo->totalInsertRows); + verbosePrint("[%d] %s() LN%d, buffer=%s\n", + pThreadInfo->threadID, __func__, __LINE__, buffer); - k++; - startFrom ++; + startTs = taosGetTimestampUs(); - if (startFrom >= insertRows) - break; + int affectedRows = execInsert(pThreadInfo, buffer, recOfBatch); + + endTs = taosGetTimestampUs(); + int64_t delay = endTs - startTs; + performancePrint("%s() LN%d, insert execution time is %10.6fms\n", + __func__, __LINE__, delay/1000.0); + + if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay; + if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay; + pThreadInfo->cntDelay++; + pThreadInfo->totalDelay += delay; + + verbosePrint("[%d] %s() LN%d affectedRows=%d\n", pThreadInfo->threadID, + __func__, __LINE__, affectedRows); + if ((affectedRows < 0) || (recOfBatch != affectedRows)) { + errorPrint("[%d] %s() LN%d execInsert insert %d, affected rows: %d\n%s\n", + pThreadInfo->threadID, __func__, __LINE__, + recOfBatch, affectedRows, buffer); + goto free_and_statistics_interlace; + } + + pThreadInfo->totalAffectedRows += affectedRows; + + int64_t currentPrintTime = taosGetTimestampMs(); + if (currentPrintTime - lastPrintTime > 30*1000) { + printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n", + pThreadInfo->threadID, + pThreadInfo->totalInsertRows, + pThreadInfo->totalAffectedRows); + lastPrintTime = currentPrintTime; + } + + if ((insert_interval) && flagSleep) { + et = taosGetTimestampUs(); + + if (insert_interval > ((et - st)/1000) ) { + int sleepTime = insert_interval - (et -st)/1000; + performancePrint("%s() LN%d sleep: %d ms for insert interval\n", + __func__, __LINE__, sleepTime); + taosMsleep(sleepTime); // ms + sleepTimeTotal += insert_interval; + } + } } - free(pChildTblName); +free_and_statistics_interlace: + tmfree(buffer); - return k; + printf("====thread[%d] completed total inserted rows: %"PRId64 ", total affected rows: %"PRId64 "====\n", + pThreadInfo->threadID, + pThreadInfo->totalInsertRows, + pThreadInfo->totalAffectedRows); + return NULL; } // sync insertion @@ -4548,49 +4624,36 @@ static int generateDataBuffer(int32_t tableSeq, 2 taosinsertdata , 1 thread: 10 tables * 20000 rows/s */ -static void* syncWrite(void *sarg) { +static void* syncWriteProgressive(threadInfo *pThreadInfo) { + debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__); - threadInfo *winfo = (threadInfo *)sarg; - SSuperTable* superTblInfo = winfo->superTblInfo; + SSuperTable* superTblInfo = pThreadInfo->superTblInfo; char* buffer = calloc(superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len, 1); if (NULL == buffer) { - fprintf(stderr, "Failed to alloc %d Bytes, reason:%s\n", + errorPrint( "Failed to alloc %d Bytes, reason:%s\n", superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len, strerror(errno)); return NULL; } - - if (superTblInfo) { - if (0 != prepareSampleDataForSTable(superTblInfo)) - return NULL; - - if (superTblInfo->numberOfTblInOneSql > 0) { - syncWriteForNumberOfTblInOneSql(winfo, superTblInfo->sampleDataBuf); - tmfree(superTblInfo->sampleDataBuf); - return NULL; - } - } - int samplePos = 0; - int64_t lastPrintTime = taosGetTimestampMs(); int64_t startTs = taosGetTimestampUs(); int64_t endTs; - int insert_interval = superTblInfo?superTblInfo->insertInterval: - g_args.insert_interval; + int timeStampStep = superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP; + int insert_interval = superTblInfo?superTblInfo->insertInterval:g_args.insert_interval; uint64_t st = 0; uint64_t et = 0xffffffff; - winfo->totalInsertRows = 0; - winfo->totalAffectedRows = 0; + pThreadInfo->totalInsertRows = 0; + pThreadInfo->totalAffectedRows = 0; - int sampleUsePos; + pThreadInfo->samplePos = 0; - for (uint32_t tableSeq = winfo->start_table_id; tableSeq <= winfo->end_table_id; + for (uint32_t tableSeq = pThreadInfo->start_table_from; tableSeq <= pThreadInfo->end_table_to; tableSeq ++) { - int64_t start_time = winfo->start_time; + int64_t start_time = pThreadInfo->start_time; int64_t insertRows = (superTblInfo)?superTblInfo->insertRows:g_args.num_of_DPT; verbosePrint("%s() LN%d insertRows=%"PRId64"\n", __func__, __LINE__, insertRows); @@ -4600,35 +4663,49 @@ static void* syncWrite(void *sarg) { st = taosGetTimestampUs(); } - sampleUsePos = samplePos; + char tableName[TSDB_TABLE_NAME_LEN]; + getTableName(tableName, pThreadInfo, tableSeq); + verbosePrint("%s() LN%d: tid=%d seq=%d tableName=%s\n", + __func__, __LINE__, + pThreadInfo->threadID, tableSeq, tableName); - int generated = generateDataBuffer(tableSeq, winfo, buffer, insertRows, - i, start_time, &sampleUsePos); + int generated = generateDataBuffer( + tableName, tableSeq, pThreadInfo, buffer, insertRows, + i, start_time, + &(pThreadInfo->samplePos)); if (generated > 0) i += generated; else goto free_and_statistics_2; - int affectedRows = execInsert(winfo, buffer, generated); - if (affectedRows < 0) - goto free_and_statistics_2; + start_time += generated * timeStampStep; + pThreadInfo->totalInsertRows += generated; - winfo->totalInsertRows += generated; - winfo->totalAffectedRows += affectedRows; + startTs = taosGetTimestampUs(); + + int affectedRows = execInsert(pThreadInfo, buffer, generated); endTs = taosGetTimestampUs(); int64_t delay = endTs - startTs; - if (delay > winfo->maxDelay) winfo->maxDelay = delay; - if (delay < winfo->minDelay) winfo->minDelay = delay; - winfo->cntDelay++; - winfo->totalDelay += delay; + performancePrint("%s() LN%d, insert execution time is %10.6fms\n", + __func__, __LINE__, delay/1000.0); + + if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay; + if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay; + pThreadInfo->cntDelay++; + pThreadInfo->totalDelay += delay; + + if (affectedRows < 0) + goto free_and_statistics_2; + + pThreadInfo->totalAffectedRows += affectedRows; int64_t currentPrintTime = taosGetTimestampMs(); if (currentPrintTime - lastPrintTime > 30*1000) { printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n", - winfo->threadID, - winfo->totalInsertRows, - winfo->totalAffectedRows); + pThreadInfo->threadID, + pThreadInfo->totalInsertRows, + pThreadInfo->totalAffectedRows); lastPrintTime = currentPrintTime; } @@ -4640,32 +4717,48 @@ static void* syncWrite(void *sarg) { if (insert_interval > ((et - st)/1000) ) { int sleep_time = insert_interval - (et -st)/1000; - verbosePrint("%s() LN%d sleep: %d ms for insert interval\n", __func__, __LINE__, sleep_time); + performancePrint("%s() LN%d sleep: %d ms for insert interval\n", + __func__, __LINE__, sleep_time); taosMsleep(sleep_time); // ms } } } // num_of_DPT - if ((tableSeq == winfo->end_table_id) && superTblInfo && + if ((tableSeq == pThreadInfo->ntables - 1) && superTblInfo && (0 == strncasecmp( superTblInfo->dataSource, "sample", strlen("sample")))) { - samplePos = sampleUsePos; + printf("%s() LN%d samplePos=%d\n", + __func__, __LINE__, pThreadInfo->samplePos); } } // tableSeq free_and_statistics_2: tmfree(buffer); - if (superTblInfo) - tmfree(superTblInfo->sampleDataBuf); printf("====thread[%d] completed total inserted rows: %"PRId64 ", total affected rows: %"PRId64 "====\n", - winfo->threadID, - winfo->totalInsertRows, - winfo->totalAffectedRows); + pThreadInfo->threadID, + pThreadInfo->totalInsertRows, + pThreadInfo->totalAffectedRows); return NULL; } -void callBack(void *param, TAOS_RES *res, int code) { +static void* syncWrite(void *sarg) { + + threadInfo *winfo = (threadInfo *)sarg; + SSuperTable* superTblInfo = winfo->superTblInfo; + + int rowsPerTbl = superTblInfo?superTblInfo->rowsPerTbl:g_args.rows_per_tbl; + + if (rowsPerTbl > 0) { + // interlace mode + return syncWriteInterlace(winfo); + } else { + // progressive mode + return syncWriteProgressive(winfo); + } +} + +static void callBack(void *param, TAOS_RES *res, int code) { threadInfo* winfo = (threadInfo*)param; SSuperTable* superTblInfo = winfo->superTblInfo; @@ -4680,13 +4773,14 @@ void callBack(void *param, TAOS_RES *res, int code) { char *buffer = calloc(1, winfo->superTblInfo->maxSqlLen); char *data = calloc(1, MAX_DATA_SIZE); char *pstr = buffer; - pstr += sprintf(pstr, "insert into %s.%s%d values", winfo->db_name, winfo->tb_prefix, winfo->start_table_id); + pstr += sprintf(pstr, "insert into %s.%s%d values", winfo->db_name, winfo->tb_prefix, + winfo->start_table_from); // if (winfo->counter >= winfo->superTblInfo->insertRows) { if (winfo->counter >= g_args.num_of_RPR) { - winfo->start_table_id++; + winfo->start_table_from++; winfo->counter = 0; } - if (winfo->start_table_id > winfo->end_table_id) { + if (winfo->start_table_from > winfo->end_table_to) { tsem_post(&winfo->lock_sem); free(buffer); free(data); @@ -4712,7 +4806,7 @@ void callBack(void *param, TAOS_RES *res, int code) { break; } } - + if (insert_interval) { winfo->st = taosGetTimestampUs(); } @@ -4723,7 +4817,7 @@ void callBack(void *param, TAOS_RES *res, int code) { taos_free_result(res); } -void *asyncWrite(void *sarg) { +static void *asyncWrite(void *sarg) { threadInfo *winfo = (threadInfo *)sarg; SSuperTable* superTblInfo = winfo->superTblInfo; @@ -4755,13 +4849,18 @@ static void startMultiThreadInsertData(int threads, char* db_name, memset(infos, 0, threads * sizeof(threadInfo)); int ntables = 0; - if (superTblInfo) - if (superTblInfo->childTblOffset) + if (superTblInfo) { + + if ((superTblInfo->childTblOffset >= 0) + && (superTblInfo->childTblLimit > 0)) { + ntables = superTblInfo->childTblLimit; - else + } else { ntables = superTblInfo->childTblCount; - else + } + } else { ntables = g_args.num_of_tables; + } int a = ntables / threads; if (a < 1) { @@ -4790,7 +4889,7 @@ static void startMultiThreadInsertData(int threads, char* db_name, } else if (0 == strncasecmp(precision, "us", 2)) { timePrec = TSDB_TIME_PRECISION_MICRO; } else { - fprintf(stderr, "No support precision: %s\n", precision); + errorPrint( "No support precision: %s\n", precision); exit(-1); } } @@ -4800,14 +4899,13 @@ static void startMultiThreadInsertData(int threads, char* db_name, if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) { start_time = taosGetTimestamp(timePrec); } else { - if (TSDB_CODE_SUCCESS != taosParseTime( - superTblInfo->startTimestamp, - &start_time, - strlen(superTblInfo->startTimestamp), - timePrec, 0)) { - printf("ERROR to parse time!\n"); - exit(-1); - } + if (TSDB_CODE_SUCCESS != taosParseTime( + superTblInfo->startTimestamp, + &start_time, + strlen(superTblInfo->startTimestamp), + timePrec, 0)) { + ERROR_EXIT("failed to parse time!\n"); + } } } else { start_time = 1500000000000; @@ -4815,12 +4913,69 @@ static void startMultiThreadInsertData(int threads, char* db_name, double start = getCurrentTime(); - int last; + int startFrom; - if ((superTblInfo) && (superTblInfo->childTblOffset)) - last = superTblInfo->childTblOffset; + if ((superTblInfo) && (superTblInfo->childTblOffset >= 0)) + startFrom = superTblInfo->childTblOffset; else - last = 0; + startFrom = 0; + + // read sample data from file first + if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource, + "sample", strlen("sample")))) { + if (0 != prepareSampleDataForSTable(superTblInfo)) { + errorPrint("%s() LN%d, prepare sample data for stable failed!\n", __func__, __LINE__); + exit(-1); + } + } + + // read sample data from file first + if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource, + "sample", strlen("sample")))) { + if (0 != prepareSampleDataForSTable(superTblInfo)) { + errorPrint("%s() LN%d, prepare sample data for stable failed!\n", __func__, __LINE__); + exit(-1); + } + } + + TAOS* taos = taos_connect( + g_Dbs.host, g_Dbs.user, + g_Dbs.password, db_name, g_Dbs.port); + if (NULL == taos) { + errorPrint("%s() LN%d, connect to server fail , reason: %s\n", + __func__, __LINE__, taos_errstr(NULL)); + exit(-1); + } + + if (superTblInfo) { + + int limit, offset; + if (superTblInfo && (superTblInfo->childTblOffset >= 0) + && (superTblInfo->childTblLimit > 0)) { + limit = superTblInfo->childTblLimit; + offset = superTblInfo->childTblOffset; + } else { + limit = superTblInfo->childTblCount; + offset = 0; + } + + superTblInfo->childTblName = (char*)calloc(1, + limit * TSDB_TABLE_NAME_LEN); + if (superTblInfo->childTblName == NULL) { + errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__); + taos_close(taos); + exit(-1); + } + + int childTblCount; + getChildNameOfSuperTableWithLimitAndOffset( + taos, + db_name, superTblInfo->sTblName, + &superTblInfo->childTblName, &childTblCount, + limit, + offset); + } + taos_close(taos); for (int i = 0; i < threads; i++) { threadInfo *t_info = infos + i; @@ -4838,7 +4993,7 @@ static void startMultiThreadInsertData(int threads, char* db_name, g_Dbs.host, g_Dbs.user, g_Dbs.password, db_name, g_Dbs.port); if (NULL == t_info->taos) { - printf("connect to server fail from insert sub thread, reason: %s\n", + errorPrint( "connect to server fail from insert sub thread, reason: %s\n", taos_errstr(NULL)); exit(-1); } @@ -4848,12 +5003,13 @@ static void startMultiThreadInsertData(int threads, char* db_name, if ((NULL == superTblInfo) || (0 == superTblInfo->multiThreadWriteOneTbl)) { - t_info->start_table_id = last; - t_info->end_table_id = i < b ? last + a : last + a - 1; - last = t_info->end_table_id + 1; + t_info->start_table_from = startFrom; + t_info->ntables = iend_table_to = i < b ? startFrom + a : startFrom + a - 1; + startFrom = t_info->end_table_to + 1; } else { - t_info->start_table_id = 0; - t_info->end_table_id = superTblInfo->childTblCount - 1; + t_info->start_table_from = 0; + t_info->ntables = superTblInfo->childTblCount; t_info->start_time = t_info->start_time + rand_int() % 10000 - rand_tinyint(); } @@ -4881,9 +5037,16 @@ static void startMultiThreadInsertData(int threads, char* db_name, tsem_destroy(&(t_info->lock_sem)); taos_close(t_info->taos); + debugPrint("%s() LN%d, [%d] totalInsert=%"PRId64" totalAffected=%"PRId64"\n", + __func__, __LINE__, + t_info->threadID, t_info->totalInsertRows, + t_info->totalAffectedRows); if (superTblInfo) { superTblInfo->totalAffectedRows += t_info->totalAffectedRows; superTblInfo->totalInsertRows += t_info->totalInsertRows; + } else { + g_args.totalAffectedRows += t_info->totalAffectedRows; + g_args.totalInsertRows += t_info->totalInsertRows; } totalDelay += t_info->totalDelay; @@ -4911,6 +5074,18 @@ static void startMultiThreadInsertData(int threads, char* db_name, superTblInfo->totalAffectedRows, threads, db_name, superTblInfo->sTblName, superTblInfo->totalInsertRows/ t); + } else { + printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s %2.f records/second\n\n", + t, g_args.totalInsertRows, + g_args.totalAffectedRows, + threads, db_name, + g_args.totalInsertRows / t); + fprintf(g_fpOfInsertResult, + "Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s %2.f records/second\n\n", + t, g_args.totalInsertRows, + g_args.totalAffectedRows, + threads, db_name, + g_args.totalInsertRows / t); } printf("insert delay, avg: %10.6fms, max: %10.6fms, min: %10.6fms\n\n", @@ -4924,7 +5099,7 @@ static void startMultiThreadInsertData(int threads, char* db_name, free(infos); } -void *readTable(void *sarg) { +static void *readTable(void *sarg) { #if 1 threadInfo *rinfo = (threadInfo *)sarg; TAOS *taos = rinfo->taos; @@ -4933,7 +5108,7 @@ void *readTable(void *sarg) { char *tb_prefix = rinfo->tb_prefix; FILE *fp = fopen(rinfo->fp, "a"); if (NULL == fp) { - printf("fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno)); + errorPrint( "fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno)); return NULL; } @@ -4945,7 +5120,7 @@ void *readTable(void *sarg) { num_of_DPT = g_args.num_of_DPT; // } - int num_of_tables = rinfo->end_table_id - rinfo->start_table_id + 1; + int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1; int totalData = num_of_DPT * num_of_tables; bool do_aggreFunc = g_Dbs.do_aggreFunc; @@ -4967,7 +5142,7 @@ void *readTable(void *sarg) { int32_t code = taos_errno(pSql); if (code != 0) { - fprintf(stderr, "Failed to query:%s\n", taos_errstr(pSql)); + errorPrint( "Failed to query:%s\n", taos_errstr(pSql)); taos_free_result(pSql); taos_close(taos); fclose(fp); @@ -4995,7 +5170,7 @@ void *readTable(void *sarg) { return NULL; } -void *readMetric(void *sarg) { +static void *readMetric(void *sarg) { #if 1 threadInfo *rinfo = (threadInfo *)sarg; TAOS *taos = rinfo->taos; @@ -5007,7 +5182,7 @@ void *readMetric(void *sarg) { } int num_of_DPT = rinfo->superTblInfo->insertRows; - int num_of_tables = rinfo->end_table_id - rinfo->start_table_id + 1; + int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1; int totalData = num_of_DPT * num_of_tables; bool do_aggreFunc = g_Dbs.do_aggreFunc; @@ -5043,7 +5218,7 @@ void *readMetric(void *sarg) { int32_t code = taos_errno(pSql); if (code != 0) { - fprintf(stderr, "Failed to query:%s\n", taos_errstr(pSql)); + errorPrint( "Failed to query:%s\n", taos_errstr(pSql)); taos_free_result(pSql); taos_close(taos); fclose(fp); @@ -5055,7 +5230,8 @@ void *readMetric(void *sarg) { } t = getCurrentTime() - t; - fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n", num_of_tables * num_of_DPT / t, t * 1000); + fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n", + num_of_tables * num_of_DPT / t, t * 1000); printf("select %10s took %.6f second(s)\n\n", aggreFunc[j], t); taos_free_result(pSql); @@ -5080,7 +5256,7 @@ static int insertTestProcess() { debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile); g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a"); if (NULL == g_fpOfInsertResult) { - fprintf(stderr, "Failed to open %s for save result\n", g_Dbs.resultFile); + errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile); return -1; } @@ -5157,7 +5333,7 @@ static int insertTestProcess() { return 0; } -void *superQueryProcess(void *sarg) { +static void *superQueryProcess(void *sarg) { threadInfo *winfo = (threadInfo *)sarg; //char sqlStr[MAX_TB_NAME_SIZE*2]; @@ -5169,7 +5345,7 @@ void *superQueryProcess(void *sarg) { while (1) { if (g_queryInfo.superQueryInfo.rate && (et - st) < (int64_t)g_queryInfo.superQueryInfo.rate*1000) { taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms - //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_id, winfo->end_table_id); + //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to); } st = taosGetTimestampUs(); @@ -5233,13 +5409,14 @@ static void *subQueryProcess(void *sarg) { int64_t st = 0; int64_t et = (int64_t)g_queryInfo.subQueryInfo.rate*1000; while (1) { - if (g_queryInfo.subQueryInfo.rate && (et - st) < (int64_t)g_queryInfo.subQueryInfo.rate*1000) { + if (g_queryInfo.subQueryInfo.rate + && (et - st) < (int64_t)g_queryInfo.subQueryInfo.rate*1000) { taosMsleep(g_queryInfo.subQueryInfo.rate*1000 - (et - st)); // ms - //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_id, winfo->end_table_id); + //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to); } st = taosGetTimestampUs(); - for (int i = winfo->start_table_id; i <= winfo->end_table_id; i++) { + for (int i = winfo->start_table_from; i <= winfo->end_table_to; i++) { for (int j = 0; j < g_queryInfo.subQueryInfo.sqlCount; j++) { memset(sqlstr,0,sizeof(sqlstr)); replaceSubTblName(g_queryInfo.subQueryInfo.sql[j], sqlstr, i); @@ -5255,8 +5432,8 @@ static void *subQueryProcess(void *sarg) { et = taosGetTimestampUs(); printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%d - %d] once queries duration:%.4fs\n\n", taosGetSelfPthreadId(), - winfo->start_table_id, - winfo->end_table_id, + winfo->start_table_from, + winfo->end_table_to, (double)(et - st)/1000000.0); } return NULL; @@ -5270,7 +5447,7 @@ static int queryTestProcess() { NULL, g_queryInfo.port); if (taos == NULL) { - fprintf(stderr, "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); + errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); exit(-1); } @@ -5294,31 +5471,42 @@ static int queryTestProcess() { pthread_t *pids = NULL; threadInfo *infos = NULL; //==== create sub threads for query from specify table - if (g_queryInfo.superQueryInfo.sqlCount > 0 && g_queryInfo.superQueryInfo.concurrent > 0) { + if (g_queryInfo.superQueryInfo.sqlCount > 0 + && g_queryInfo.superQueryInfo.concurrent > 0) { pids = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(pthread_t)); + if (NULL == pids) { + taos_close(taos); + ERROR_EXIT("memory allocation failed\n"); + } infos = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(threadInfo)); - if ((NULL == pids) || (NULL == infos)) { - printf("malloc failed for create threads\n"); + if (NULL == infos) { taos_close(taos); - exit(-1); + free(pids); + ERROR_EXIT("memory allocation failed for create threads\n"); } for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) { threadInfo *t_info = infos + i; t_info->threadID = i; - + if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", 5)) { t_info->taos = taos; char sqlStr[MAX_TB_NAME_SIZE*2]; sprintf(sqlStr, "use %s", g_queryInfo.dbName); verbosePrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr); - (void)queryDbExec(t_info->taos, sqlStr, NO_INSERT_TYPE); + if (0 != queryDbExec(t_info->taos, sqlStr, NO_INSERT_TYPE)) { + free(infos); + free(pids); + errorPrint( "use database %s failed!\n\n", + g_queryInfo.dbName); + return -1; + } } else { t_info->taos = NULL; } - + pthread_create(pids + i, NULL, superQueryProcess, t_info); } }else { @@ -5331,11 +5519,21 @@ static int queryTestProcess() { if ((g_queryInfo.subQueryInfo.sqlCount > 0) && (g_queryInfo.subQueryInfo.threadCnt > 0)) { pidsOfSub = malloc(g_queryInfo.subQueryInfo.threadCnt * sizeof(pthread_t)); + if (NULL == pidsOfSub) { + taos_close(taos); + free(infos); + free(pids); + + ERROR_EXIT("memory allocation failed for create threads\n"); + } + infosOfSub = malloc(g_queryInfo.subQueryInfo.threadCnt * sizeof(threadInfo)); - if ((NULL == pidsOfSub) || (NULL == infosOfSub)) { - printf("malloc failed for create threads\n"); + if (NULL == infosOfSub) { taos_close(taos); - exit(-1); + free(pidsOfSub); + free(infos); + free(pids); + ERROR_EXIT("memory allocation failed for create threads\n"); } int ntables = g_queryInfo.subQueryInfo.childTblCount; @@ -5352,75 +5550,77 @@ static int queryTestProcess() { b = ntables % threads; } - int last = 0; + int startFrom = 0; for (int i = 0; i < threads; i++) { threadInfo *t_info = infosOfSub + i; t_info->threadID = i; - t_info->start_table_id = last; - t_info->end_table_id = i < b ? last + a : last + a - 1; - last = t_info->end_table_id + 1; + t_info->start_table_from = startFrom; + t_info->ntables = iend_table_to = i < b ? startFrom + a : startFrom + a - 1; + startFrom = t_info->end_table_to + 1; t_info->taos = taos; pthread_create(pidsOfSub + i, NULL, subQueryProcess, t_info); } g_queryInfo.subQueryInfo.threadCnt = threads; - }else { + } else { g_queryInfo.subQueryInfo.threadCnt = 0; } - + for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) { pthread_join(pids[i], NULL); } tmfree((char*)pids); - tmfree((char*)infos); - + tmfree((char*)infos); + for (int i = 0; i < g_queryInfo.subQueryInfo.threadCnt; i++) { pthread_join(pidsOfSub[i], NULL); } tmfree((char*)pidsOfSub); - tmfree((char*)infosOfSub); - + tmfree((char*)infosOfSub); + taos_close(taos); return 0; } -static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) { +static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) { if (res == NULL || taos_errno(res) != 0) { - printf("failed to subscribe result, code:%d, reason:%s\n", code, taos_errstr(res)); + errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n", + __func__, __LINE__, code, taos_errstr(res)); return; } - + getResult(res, (char*)param); taos_free_result(res); } static TAOS_SUB* subscribeImpl(TAOS *taos, char *sql, char* topic, char* resultFileName) { - TAOS_SUB* tsub = NULL; + TAOS_SUB* tsub = NULL; if (g_queryInfo.superQueryInfo.subscribeMode) { - tsub = taos_subscribe(taos, - g_queryInfo.superQueryInfo.subscribeRestart, - topic, sql, subscribe_callback, (void*)resultFileName, + tsub = taos_subscribe(taos, + g_queryInfo.superQueryInfo.subscribeRestart, + topic, sql, subscribe_callback, (void*)resultFileName, g_queryInfo.superQueryInfo.subscribeInterval); } else { - tsub = taos_subscribe(taos, - g_queryInfo.superQueryInfo.subscribeRestart, + tsub = taos_subscribe(taos, + g_queryInfo.superQueryInfo.subscribeRestart, topic, sql, NULL, NULL, 0); } if (tsub == NULL) { printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql); return NULL; - } + } return tsub; } -void *subSubscribeProcess(void *sarg) { - threadInfo *winfo = (threadInfo *)sarg; +static void *subSubscribeProcess(void *sarg) { + threadInfo *winfo = (threadInfo *)sarg; char subSqlstr[1024]; char sqlStr[MAX_TB_NAME_SIZE*2]; @@ -5429,13 +5629,13 @@ void *subSubscribeProcess(void *sarg) { if (0 != queryDbExec(winfo->taos, sqlStr, NO_INSERT_TYPE)){ return NULL; } - + //int64_t st = 0; //int64_t et = 0; do { //if (g_queryInfo.superQueryInfo.rate && (et - st) < g_queryInfo.superQueryInfo.rate*1000) { // taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms - // //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_id, winfo->end_table_id); + // //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to); //} //st = taosGetTimestampMs(); @@ -5464,13 +5664,13 @@ void *subSubscribeProcess(void *sarg) { if (1 == g_queryInfo.subQueryInfo.subscribeMode) { continue; } - + res = taos_consume(g_queryInfo.subQueryInfo.tsub[i]); if (res) { char tmpFile[MAX_FILE_NAME_LEN*2] = {0}; if (g_queryInfo.subQueryInfo.result[i][0] != 0) { - sprintf(tmpFile, "%s-%d", - g_queryInfo.subQueryInfo.result[i], + sprintf(tmpFile, "%s-%d", + g_queryInfo.subQueryInfo.result[i], winfo->threadID); } getResult(res, tmpFile); @@ -5478,16 +5678,16 @@ void *subSubscribeProcess(void *sarg) { } } taos_free_result(res); - + for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) { - taos_unsubscribe(g_queryInfo.subQueryInfo.tsub[i], + taos_unsubscribe(g_queryInfo.subQueryInfo.tsub[i], g_queryInfo.subQueryInfo.subscribeKeepProgress); } return NULL; } -void *superSubscribeProcess(void *sarg) { - threadInfo *winfo = (threadInfo *)sarg; +static void *superSubscribeProcess(void *sarg) { + threadInfo *winfo = (threadInfo *)sarg; char sqlStr[MAX_TB_NAME_SIZE*2]; sprintf(sqlStr, "use %s", g_queryInfo.dbName); @@ -5495,13 +5695,13 @@ void *superSubscribeProcess(void *sarg) { if (0 != queryDbExec(winfo->taos, sqlStr, NO_INSERT_TYPE)) { return NULL; } - + //int64_t st = 0; //int64_t et = 0; do { //if (g_queryInfo.superQueryInfo.rate && (et - st) < g_queryInfo.superQueryInfo.rate*1000) { // taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms - // //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_id, winfo->end_table_id); + // //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to); //} //st = taosGetTimestampMs(); @@ -5510,13 +5710,13 @@ void *superSubscribeProcess(void *sarg) { sprintf(topic, "taosdemo-subscribe-%d", i); char tmpFile[MAX_FILE_NAME_LEN*2] = {0}; if (g_queryInfo.subQueryInfo.result[i][0] != 0) { - sprintf(tmpFile, "%s-%d", + sprintf(tmpFile, "%s-%d", g_queryInfo.superQueryInfo.result[i], winfo->threadID); } - g_queryInfo.superQueryInfo.tsub[i] = - subscribeImpl(winfo->taos, - g_queryInfo.superQueryInfo.sql[i], - topic, tmpFile); + g_queryInfo.superQueryInfo.tsub[i] = + subscribeImpl(winfo->taos, + g_queryInfo.superQueryInfo.sql[i], + topic, tmpFile); if (NULL == g_queryInfo.superQueryInfo.tsub[i]) { return NULL; } @@ -5532,12 +5732,12 @@ void *superSubscribeProcess(void *sarg) { if (1 == g_queryInfo.superQueryInfo.subscribeMode) { continue; } - + res = taos_consume(g_queryInfo.superQueryInfo.tsub[i]); if (res) { char tmpFile[MAX_FILE_NAME_LEN*2] = {0}; if (g_queryInfo.superQueryInfo.result[i][0] != 0) { - sprintf(tmpFile, "%s-%d", + sprintf(tmpFile, "%s-%d", g_queryInfo.superQueryInfo.result[i], winfo->threadID); } getResult(res, tmpFile); @@ -5547,7 +5747,7 @@ void *superSubscribeProcess(void *sarg) { taos_free_result(res); for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) { - taos_unsubscribe(g_queryInfo.superQueryInfo.tsub[i], + taos_unsubscribe(g_queryInfo.superQueryInfo.tsub[i], g_queryInfo.superQueryInfo.subscribeKeepProgress); } return NULL; @@ -5568,7 +5768,7 @@ static int subscribeTestProcess() { g_queryInfo.dbName, g_queryInfo.port); if (taos == NULL) { - fprintf(stderr, "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); + errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); exit(-1); } @@ -5583,22 +5783,27 @@ static int subscribeTestProcess() { pthread_t *pids = NULL; threadInfo *infos = NULL; //==== create sub threads for query from super table - if (g_queryInfo.superQueryInfo.sqlCount > 0 - && g_queryInfo.superQueryInfo.concurrent > 0) { - pids = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(pthread_t)); - infos = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(threadInfo)); - if ((NULL == pids) || (NULL == infos)) { + if ((g_queryInfo.superQueryInfo.sqlCount <= 0) || + (g_queryInfo.superQueryInfo.concurrent <= 0)) { + errorPrint("%s() LN%d, query sqlCount %d or concurrent %d is not correct.\n", + __func__, __LINE__, g_queryInfo.superQueryInfo.sqlCount, + g_queryInfo.superQueryInfo.concurrent); + exit(-1); + } + + pids = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(pthread_t)); + infos = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(threadInfo)); + if ((NULL == pids) || (NULL == infos)) { printf("malloc failed for create threads\n"); taos_close(taos); exit(-1); - } + } - for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) { + for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) { threadInfo *t_info = infos + i; t_info->threadID = i; t_info->taos = taos; pthread_create(pids + i, NULL, superSubscribeProcess, t_info); - } } //==== create sub threads for query from sub table @@ -5630,13 +5835,15 @@ static int subscribeTestProcess() { b = ntables % threads; } - int last = 0; + int startFrom = 0; for (int i = 0; i < threads; i++) { threadInfo *t_info = infosOfSub + i; t_info->threadID = i; - t_info->start_table_id = last; - t_info->end_table_id = i < b ? last + a : last + a - 1; + t_info->start_table_from = startFrom; + t_info->ntables = iend_table_to = i < b ? startFrom + a : startFrom + a - 1; + startFrom = t_info->end_table_to + 1; t_info->taos = taos; pthread_create(pidsOfSub + i, NULL, subSubscribeProcess, t_info); } @@ -5660,7 +5867,7 @@ static int subscribeTestProcess() { return 0; } -void initOfInsertMeta() { +static void initOfInsertMeta() { memset(&g_Dbs, 0, sizeof(SDbs)); // set default values @@ -5672,7 +5879,7 @@ void initOfInsertMeta() { g_Dbs.use_metric = true; } -void initOfQueryMeta() { +static void initOfQueryMeta() { memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo)); // set default values @@ -5682,7 +5889,7 @@ void initOfQueryMeta() { tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_DB_NAME_SIZE); } -void setParaFromArg(){ +static void setParaFromArg(){ if (g_args.host) { strcpy(g_Dbs.host, g_args.host); } else { @@ -5823,7 +6030,7 @@ static int isCommentLine(char *line) { return regexMatch(line, "^\\s*#.*", REG_EXTENDED); } -void querySqlFile(TAOS* taos, char* sqlFile) +static void querySqlFile(TAOS* taos, char* sqlFile) { FILE *fp = fopen(sqlFile, "r"); if (fp == NULL) { @@ -5856,7 +6063,6 @@ void querySqlFile(TAOS* taos, char* sqlFile) memcpy(cmd + cmd_len, line, read_len); verbosePrint("%s() LN%d cmd: %s\n", __func__, __LINE__, cmd); - queryDbExec(taos, cmd, NO_INSERT_TYPE); if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE)) { printf("queryDbExec %s failed!\n", cmd); tmfree(cmd); @@ -5878,14 +6084,14 @@ void querySqlFile(TAOS* taos, char* sqlFile) } static void testMetaFile() { - if (INSERT_MODE == g_args.test_mode) { + if (INSERT_TEST == g_args.test_mode) { if (g_Dbs.cfgDir[0]) taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir); insertTestProcess(); - } else if (QUERY_MODE == g_args.test_mode) { + } else if (QUERY_TEST == g_args.test_mode) { if (g_queryInfo.cfgDir[0]) taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir); queryTestProcess(); - } else if (SUBSCRIBE_MODE == g_args.test_mode) { + } else if (SUBSCRIBE_TEST == g_args.test_mode) { if (g_queryInfo.cfgDir[0]) taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir); subscribeTestProcess(); @@ -5902,16 +6108,18 @@ static void queryResult() { pthread_t read_id; threadInfo *rInfo = malloc(sizeof(threadInfo)); rInfo->start_time = 1500000000000; // 2017-07-14 10:40:00.000 - rInfo->start_table_id = 0; + rInfo->start_table_from = 0; //rInfo->do_aggreFunc = g_Dbs.do_aggreFunc; if (g_args.use_metric) { - rInfo->end_table_id = g_Dbs.db[0].superTbls[0].childTblCount - 1; + rInfo->ntables = g_Dbs.db[0].superTbls[0].childTblCount; + rInfo->end_table_to = g_Dbs.db[0].superTbls[0].childTblCount - 1; rInfo->superTblInfo = &g_Dbs.db[0].superTbls[0]; strcpy(rInfo->tb_prefix, g_Dbs.db[0].superTbls[0].childTblPrefix); } else { - rInfo->end_table_id = g_args.num_of_tables -1; + rInfo->ntables = g_args.num_of_tables; + rInfo->end_table_to = g_args.num_of_tables -1; strcpy(rInfo->tb_prefix, g_args.tb_prefix); } @@ -5922,7 +6130,7 @@ static void queryResult() { g_Dbs.db[0].dbName, g_Dbs.port); if (rInfo->taos == NULL) { - fprintf(stderr, "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); + errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); free(rInfo); exit(-1); } @@ -5942,7 +6150,7 @@ static void queryResult() { static void testCmdLine() { - g_args.test_mode = INSERT_MODE; + g_args.test_mode = INSERT_TEST; insertTestProcess(); if (g_Dbs.insert_only) diff --git a/src/mnode/inc/mnodeDef.h b/src/mnode/inc/mnodeDef.h index 2a44d372d1366e4cd08ea4468ecb383115205a98..e77bf6dca0ee2d4a1a5ee7d2578806c7dc78b147 100644 --- a/src/mnode/inc/mnodeDef.h +++ b/src/mnode/inc/mnodeDef.h @@ -219,6 +219,7 @@ typedef struct SFuncObj { char path[128]; int32_t contLen; char cont[TSDB_FUNC_CODE_LEN]; + int32_t funcType; int64_t createdTime; uint8_t resType; int16_t resBytes; diff --git a/src/mnode/inc/mnodeFunc.h b/src/mnode/inc/mnodeFunc.h index 3bf8473e23607c9d59619d382140567d1968b80d..8c8187393252165448224c4a687015f1826a50ac 100644 --- a/src/mnode/inc/mnodeFunc.h +++ b/src/mnode/inc/mnodeFunc.h @@ -31,7 +31,7 @@ void mnodeCancelGetNextFunc(void *pIter); void mnodeIncFuncRef(SFuncObj *pFunc); void mnodeDecFuncRef(SFuncObj *pFunc); -int32_t mnodeCreateFunc(SAcctObj *pAcct, char *name, int32_t codeLen, char *code, char *path, uint8_t outputType, int16_t outputLen, SMnodeMsg *pMsg); +int32_t mnodeCreateFunc(SAcctObj *pAcct, char *name, int32_t codeLen, char *code, char *path, uint8_t outputType, int16_t outputLen, int32_t funcType, SMnodeMsg *pMsg); #ifdef __cplusplus } diff --git a/src/mnode/inc/mnodeVgroup.h b/src/mnode/inc/mnodeVgroup.h index 2067ad04ccf963701bffcf134c8ae478547f1abb..e052cdb83cbbffa0ceb1119bc49da52a23e02e2b 100644 --- a/src/mnode/inc/mnodeVgroup.h +++ b/src/mnode/inc/mnodeVgroup.h @@ -44,7 +44,7 @@ void mnodeDropVgroup(SVgObj *pVgroup, void *ahandle); void mnodeAlterVgroup(SVgObj *pVgroup, void *ahandle); int32_t mnodeGetAvailableVgroup(struct SMnodeMsg *pMsg, SVgObj **pVgroup, int32_t *sid); -void mnodeAddTableIntoVgroup(SVgObj *pVgroup, SCTableObj *pTable); +int32_t mnodeAddTableIntoVgroup(SVgObj *pVgroup, SCTableObj *pTable, bool needCheck); void mnodeRemoveTableFromVgroup(SVgObj *pVgroup, SCTableObj *pTable); void mnodeSendDropVnodeMsg(int32_t vgId, SRpcEpSet *epSet, void *ahandle); void mnodeSendCreateVgroupMsg(SVgObj *pVgroup, void *ahandle); diff --git a/src/mnode/src/mnodeDb.c b/src/mnode/src/mnodeDb.c index 0b97df2d380e98004894659028529954b6ab0059..2ca038a5a24708d23088c1191a668327d9e706d5 100644 --- a/src/mnode/src/mnodeDb.c +++ b/src/mnode/src/mnodeDb.c @@ -56,7 +56,7 @@ int32_t mnodeProcessAlterDbMsg(SMnodeMsg *pMsg); #ifndef _TOPIC int32_t tpInit() { return 0; } void tpCleanUp() {} -void tpUpdateTs(int32_t *seq, void *pMsg) {} +void tpUpdateTs(int32_t vgId, int64_t *seq, void *pMsg) {} #endif static void mnodeDestroyDb(SDbObj *pDb) { diff --git a/src/mnode/src/mnodeFunc.c b/src/mnode/src/mnodeFunc.c index 50bc6c7ae5fbd76ea58e084ce71f298dc5aa1c35..f363f9bee63c63f15941f7bd9811e2b145874d1b 100644 --- a/src/mnode/src/mnodeFunc.c +++ b/src/mnode/src/mnodeFunc.c @@ -190,7 +190,7 @@ static int32_t mnodeUpdateFunc(SFuncObj *pFunc, void *pMsg) { return code; } */ -int32_t mnodeCreateFunc(SAcctObj *pAcct, char *name, int32_t codeLen, char *codeScript, char *path, uint8_t outputType, int16_t outputLen, SMnodeMsg *pMsg) { +int32_t mnodeCreateFunc(SAcctObj *pAcct, char *name, int32_t codeLen, char *codeScript, char *path, uint8_t outputType, int16_t outputLen, int32_t funcType, SMnodeMsg *pMsg) { if (grantCheck(TSDB_GRANT_TIME) != TSDB_CODE_SUCCESS) { return TSDB_CODE_GRANT_EXPIRED; } @@ -236,6 +236,7 @@ int32_t mnodeCreateFunc(SAcctObj *pAcct, char *name, int32_t codeLen, char *code pFunc->createdTime = taosGetTimestampMs(); pFunc->resType = outputType; pFunc->resBytes = outputLen; + pFunc->funcType = funcType; pFunc->sig = 0; pFunc->type = 1; //lua script, refactor @@ -301,6 +302,12 @@ static int32_t mnodeGetFuncMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pCo pSchema[cols].bytes = htons(pShow->bytes[cols]); cols++; + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; + strcpy(pSchema[cols].name, "aggregate"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + pShow->bytes[cols] = TSDB_TYPE_STR_MAX_LEN + VARSTR_HEADER_SIZE; pSchema[cols].type = TSDB_DATA_TYPE_BINARY; strcpy(pSchema[cols].name, "outputtype"); @@ -381,6 +388,10 @@ static int32_t mnodeRetrieveFuncs(SShowObj *pShow, char *data, int32_t rows, voi STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pFunc->path, pShow->bytes[cols]); cols++; + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int32_t *)pWrite = pFunc->funcType == TSDB_UDF_TYPE_AGGREGATE ? 1 : 0; + cols++; + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; STR_WITH_MAXSIZE_TO_VARSTR(pWrite, mnodeGenTypeStr(buf, TSDB_TYPE_STR_MAX_LEN, pFunc->resType, pFunc->resBytes), pShow->bytes[cols]); cols++; @@ -410,8 +421,9 @@ static int32_t mnodeProcessCreateFuncMsg(SMnodeMsg *pMsg) { SCreateFuncMsg *pCreate = pMsg->rpcMsg.pCont; pCreate->codeLen = htonl(pCreate->codeLen); pCreate->outputLen = htons(pCreate->outputLen); + pCreate->funcType = htonl(pCreate->funcType); - return mnodeCreateFunc(pMsg->pUser->pAcct, pCreate->name, pCreate->codeLen, pCreate->code, pCreate->path, pCreate->outputType, pCreate->outputLen, pMsg); + return mnodeCreateFunc(pMsg->pUser->pAcct, pCreate->name, pCreate->codeLen, pCreate->code, pCreate->path, pCreate->outputType, pCreate->outputLen, pCreate->funcType, pMsg); } static int32_t mnodeProcessDropFuncMsg(SMnodeMsg *pMsg) { @@ -452,6 +464,7 @@ static int32_t mnodeProcessRetrieveFuncImplMsg(SMnodeMsg *pMsg) { pFuncInfo->len = htonl(pFuncObj->contLen); memcpy(pFuncInfo->content, pFuncObj->cont, pFuncObj->contLen); + pFuncInfo->funcType = htonl(pFuncObj->funcType); pFuncInfo->resType = pFuncObj->resType; pFuncInfo->resBytes = htons(pFuncObj->resBytes); pOutput += sizeof(SFunctionInfoMsg) + pFuncObj->contLen; diff --git a/src/mnode/src/mnodeSdb.c b/src/mnode/src/mnodeSdb.c index fe1f70cb50e4dd074962d42ea475095c37667c38..381cb11952dbdd639408bda1efdae258a9a94a30 100644 --- a/src/mnode/src/mnodeSdb.c +++ b/src/mnode/src/mnodeSdb.c @@ -35,7 +35,7 @@ #include "mnodeSdb.h" #define SDB_TABLE_LEN 12 -#define MAX_QUEUED_MSG_NUM 10000 +#define MAX_QUEUED_MSG_NUM 100000 typedef enum { SDB_ACTION_INSERT = 0, @@ -552,7 +552,7 @@ static int32_t sdbInsertHash(SSdbTable *pTable, SSdbRow *pRow) { int32_t code = (*pTable->fpInsert)(pRow); if (code != TSDB_CODE_SUCCESS) { - sdbError("vgId:1, sdb:%s, failed to insert key:%s to hash, remove it", pTable->name, + sdbError("vgId:1, sdb:%s, failed to perform insert action for key:%s, remove it", pTable->name, sdbGetRowStr(pTable, pRow->pObj)); sdbDeleteHash(pTable, pRow); } @@ -680,7 +680,7 @@ static int32_t sdbProcessWrite(void *wparam, void *hparam, int32_t qtype, void * if (pRow != NULL) { // forward to peers pRow->processedCount = 0; - int32_t syncCode = syncForwardToPeer(tsSdbMgmt.sync, pHead, pRow, TAOS_QTYPE_RPC); + int32_t syncCode = syncForwardToPeer(tsSdbMgmt.sync, pHead, pRow, TAOS_QTYPE_RPC, false); if (syncCode <= 0) pRow->processedCount = 1; if (syncCode < 0) { @@ -700,7 +700,7 @@ static int32_t sdbProcessWrite(void *wparam, void *hparam, int32_t qtype, void * actStr[action], sdbGetKeyStr(pTable, pHead->cont), pHead->version); // even it is WAL/FWD, it shall be called to update version in sync - syncForwardToPeer(tsSdbMgmt.sync, pHead, pRow, TAOS_QTYPE_RPC); + syncForwardToPeer(tsSdbMgmt.sync, pHead, pRow, TAOS_QTYPE_RPC, false); // from wal or forward msg, row not created, should add into hash if (action == SDB_ACTION_INSERT) { @@ -1119,7 +1119,7 @@ static void *sdbWorkerFp(void *pWorker) { sdbConfirmForward(1, pRow, pRow->code); } else { if (qtype == TAOS_QTYPE_FWD) { - syncConfirmForward(tsSdbMgmt.sync, pRow->pHead.version, pRow->code); + syncConfirmForward(tsSdbMgmt.sync, pRow->pHead.version, pRow->code, false); } sdbFreeFromQueue(pRow); } diff --git a/src/mnode/src/mnodeTable.c b/src/mnode/src/mnodeTable.c index 1378847d0b472bb65621fc88951d4fbd6e7d0790..39eca8819d8ace50b6fa82fadb1d4464247568d6 100644 --- a/src/mnode/src/mnodeTable.c +++ b/src/mnode/src/mnodeTable.c @@ -108,10 +108,12 @@ static int32_t mnodeChildTableActionDestroy(SSdbRow *pRow) { static int32_t mnodeChildTableActionInsert(SSdbRow *pRow) { SCTableObj *pTable = pRow->pObj; + int32_t code = 0; SVgObj *pVgroup = mnodeGetVgroup(pTable->vgId); if (pVgroup == NULL) { mError("ctable:%s, not in vgId:%d", pTable->info.tableId, pTable->vgId); + code = -1; } SDbObj *pDb = NULL; @@ -119,6 +121,7 @@ static int32_t mnodeChildTableActionInsert(SSdbRow *pRow) { pDb = mnodeGetDb(pVgroup->dbName); if (pDb == NULL) { mError("ctable:%s, vgId:%d not in db:%s", pTable->info.tableId, pVgroup->vgId, pVgroup->dbName); + code = -1; } } @@ -127,6 +130,7 @@ static int32_t mnodeChildTableActionInsert(SSdbRow *pRow) { pAcct = mnodeGetAcct(pDb->acct); if (pAcct == NULL) { mError("ctable:%s, acct:%s not exists", pTable->info.tableId, pDb->acct); + code = -1; } } @@ -139,6 +143,7 @@ static int32_t mnodeChildTableActionInsert(SSdbRow *pRow) { if (pAcct) pAcct->acctInfo.numOfTimeSeries += (pTable->superTable->numOfColumns - 1); } else { mError("table:%s:%p, correspond stable not found suid:%" PRIu64, pTable->info.tableId, pTable, pTable->suid); + code = -1; } } else { grantAdd(TSDB_GRANT_TIMESERIES, pTable->numOfColumns - 1); @@ -146,18 +151,31 @@ static int32_t mnodeChildTableActionInsert(SSdbRow *pRow) { } if (pDb) mnodeAddTableIntoDb(pDb); - if (pVgroup) mnodeAddTableIntoVgroup(pVgroup, pTable); + if (pVgroup) { + if (mnodeAddTableIntoVgroup(pVgroup, pTable, pRow->pMsg == NULL) != 0) { + mError("table:%s, vgId:%d tid:%d, failed to perform insert action, uid:%" PRIu64 " suid:%" PRIu64, + pTable->info.tableId, pTable->vgId, pTable->tid, pTable->uid, pTable->suid); + code = -1; + } + } mnodeDecVgroupRef(pVgroup); mnodeDecDbRef(pDb); mnodeDecAcctRef(pAcct); - return TSDB_CODE_SUCCESS; + if (code == 0) { + mTrace("table:%s, vgId:%d tid:%d, perform insert action, uid:%" PRIu64 " suid:%" PRIu64, pTable->info.tableId, + pTable->vgId, pTable->tid, pTable->uid, pTable->suid); + } + + return code; } static int32_t mnodeChildTableActionDelete(SSdbRow *pRow) { SCTableObj *pTable = pRow->pObj; if (pTable->vgId == 0) { + mError("table:%s, vgId:%d tid:%d, failed to perform delete action, uid:%" PRIu64 " suid:%" PRIu64, + pTable->info.tableId, pTable->vgId, pTable->tid, pTable->uid, pTable->suid); return TSDB_CODE_MND_VGROUP_NOT_EXIST; } @@ -188,6 +206,8 @@ static int32_t mnodeChildTableActionDelete(SSdbRow *pRow) { mnodeDecDbRef(pDb); mnodeDecAcctRef(pAcct); + mTrace("table:%s, vgId:%d tid:%d, perform delete action, uid:%" PRIu64 " suid:%" PRIu64, pTable->info.tableId, + pTable->vgId, pTable->tid, pTable->uid, pTable->suid); return TSDB_CODE_SUCCESS; } @@ -399,13 +419,13 @@ static void mnodeAddTableIntoStable(SSTableObj *pStable, SCTableObj *pCtable) { if (pStable->vgHash == NULL) { pStable->vgHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK); - mDebug("table:%s, create hash:%p", pStable->info.tableId, pStable->vgHash); + mDebug("stable:%s, create vgId hash:%p", pStable->info.tableId, pStable->vgHash); } if (pStable->vgHash != NULL) { if (taosHashGet(pStable->vgHash, &pCtable->vgId, sizeof(pCtable->vgId)) == NULL) { taosHashPut(pStable->vgHash, &pCtable->vgId, sizeof(pCtable->vgId), &pCtable->vgId, sizeof(pCtable->vgId)); - mDebug("table:%s, vgId:%d is put into stable hash:%p, sizeOfVgList:%d", pStable->info.tableId, pCtable->vgId, + mDebug("stable:%s, vgId:%d is put into stable vgId hash:%p, sizeOfVgList:%d", pStable->info.tableId, pCtable->vgId, pStable->vgHash, taosHashGetSize(pStable->vgHash)); } } @@ -443,19 +463,21 @@ static int32_t mnodeSuperTableActionDestroy(SSdbRow *pRow) { static int32_t mnodeSuperTableActionInsert(SSdbRow *pRow) { SSTableObj *pStable = pRow->pObj; - SDbObj *pDb = mnodeGetDbByTableName(pStable->info.tableId); + SDbObj * pDb = mnodeGetDbByTableName(pStable->info.tableId); if (pDb != NULL && pDb->status == TSDB_DB_STATUS_READY) { mnodeAddSuperTableIntoDb(pDb); } mnodeDecDbRef(pDb); taosHashPut(tsSTableUidHash, &pStable->uid, sizeof(int64_t), &pStable, sizeof(int64_t)); + + mTrace("stable:%s, perform insert action, uid:%" PRIu64, pStable->info.tableId, pStable->uid); return TSDB_CODE_SUCCESS; } static int32_t mnodeSuperTableActionDelete(SSdbRow *pRow) { SSTableObj *pStable = pRow->pObj; - SDbObj *pDb = mnodeGetDbByTableName(pStable->info.tableId); + SDbObj * pDb = mnodeGetDbByTableName(pStable->info.tableId); if (pDb != NULL) { mnodeRemoveSuperTableFromDb(pDb); mnodeDropAllChildTablesInStable((SSTableObj *)pStable); @@ -463,6 +485,8 @@ static int32_t mnodeSuperTableActionDelete(SSdbRow *pRow) { mnodeDecDbRef(pDb); taosHashRemove(tsSTableUidHash, &pStable->uid, sizeof(int64_t)); + + mTrace("stable:%s, perform delete action, uid:%" PRIu64, pStable->info.tableId, pStable->uid); return TSDB_CODE_SUCCESS; } @@ -1888,15 +1912,14 @@ static int32_t mnodeDoCreateChildTableCb(SMnodeMsg *pMsg, int32_t code) { pMsg->rpcMsg.handle); if (pMsg->pBatchMasterMsg) { - ++pMsg->pBatchMasterMsg->successed; - if (pMsg->pBatchMasterMsg->successed + pMsg->pBatchMasterMsg->received - >= pMsg->pBatchMasterMsg->expected) { - dnodeSendRpcMWriteRsp(pMsg->pBatchMasterMsg, code); - } + ++pMsg->pBatchMasterMsg->successed; + if (pMsg->pBatchMasterMsg->successed + pMsg->pBatchMasterMsg->received >= pMsg->pBatchMasterMsg->expected) { + dnodeSendRpcMWriteRsp(pMsg->pBatchMasterMsg, code); + } - mnodeDestroySubMsg(pMsg); + mnodeDestroySubMsg(pMsg); - return TSDB_CODE_MND_ACTION_IN_PROGRESS; + return TSDB_CODE_MND_ACTION_IN_PROGRESS; } dnodeSendRpcMWriteRsp(pMsg, TSDB_CODE_SUCCESS); @@ -1911,9 +1934,8 @@ static int32_t mnodeDoCreateChildTableCb(SMnodeMsg *pMsg, int32_t code) { if (pMsg->pBatchMasterMsg) { ++pMsg->pBatchMasterMsg->received; pMsg->pBatchMasterMsg->code = code; - if (pMsg->pBatchMasterMsg->successed + pMsg->pBatchMasterMsg->received - >= pMsg->pBatchMasterMsg->expected) { - dnodeSendRpcMWriteRsp(pMsg->pBatchMasterMsg, code); + if (pMsg->pBatchMasterMsg->successed + pMsg->pBatchMasterMsg->received >= pMsg->pBatchMasterMsg->expected) { + dnodeSendRpcMWriteRsp(pMsg->pBatchMasterMsg, code); } mnodeDestroySubMsg(pMsg); @@ -2662,9 +2684,8 @@ static void mnodeProcessCreateChildTableRsp(SRpcMsg *rpcMsg) { if (pMsg->pBatchMasterMsg) { ++pMsg->pBatchMasterMsg->successed; - if (pMsg->pBatchMasterMsg->successed + pMsg->pBatchMasterMsg->received - >= pMsg->pBatchMasterMsg->expected) { - dnodeSendRpcMWriteRsp(pMsg->pBatchMasterMsg, rpcMsg->code); + if (pMsg->pBatchMasterMsg->successed + pMsg->pBatchMasterMsg->received >= pMsg->pBatchMasterMsg->expected) { + dnodeSendRpcMWriteRsp(pMsg->pBatchMasterMsg, rpcMsg->code); } mnodeDestroySubMsg(pMsg); diff --git a/src/mnode/src/mnodeVgroup.c b/src/mnode/src/mnodeVgroup.c index 008a655597f0934a1281ca0e5ccedd84d33bc1f9..fdbf7ae398e10d754b82d01a002f79130071d3c7 100644 --- a/src/mnode/src/mnodeVgroup.c +++ b/src/mnode/src/mnodeVgroup.c @@ -443,6 +443,7 @@ int32_t mnodeGetAvailableVgroup(SMnodeMsg *pMsg, SVgObj **ppVgroup, int32_t *pSi mDebug("msg:%p, app:%p db:%s, no enough sid in vgId:%d", pMsg, pMsg->rpcMsg.ahandle, pDb->name, pVgroup->vgId); continue; } + mTrace("vgId:%d, alloc tid:%d", pVgroup->vgId, sid); *pSid = sid; *ppVgroup = pVgroup; @@ -507,6 +508,7 @@ int32_t mnodeGetAvailableVgroup(SMnodeMsg *pMsg, SVgObj **ppVgroup, int32_t *pSi pDb->vgListIndex = 0; pthread_mutex_unlock(&pDb->mutex); + mTrace("vgId:%d, alloc tid:%d", pVgroup->vgId, sid); return TSDB_CODE_SUCCESS; } @@ -832,26 +834,37 @@ static int32_t mnodeRetrieveVgroups(SShowObj *pShow, char *data, int32_t rows, v return numOfRows; } -void mnodeAddTableIntoVgroup(SVgObj *pVgroup, SCTableObj *pTable) { +int32_t mnodeAddTableIntoVgroup(SVgObj *pVgroup, SCTableObj *pTable, bool needCheck) { int32_t idPoolSize = taosIdPoolMaxSize(pVgroup->idPool); if (pTable->tid > idPoolSize) { mnodeAllocVgroupIdPool(pVgroup); } if (pTable->tid >= 1) { - taosIdPoolMarkStatus(pVgroup->idPool, pTable->tid); - pVgroup->numOfTables++; - // The create vgroup message may be received later than the create table message - // and the writing order in sdb is therefore uncertain - // which will cause the reference count of the vgroup to be incorrect when restarting - // mnodeIncVgroupRef(pVgroup); + if (taosIdPoolMarkStatus(pVgroup->idPool, pTable->tid) || !needCheck) { + pVgroup->numOfTables++; + mTrace("table:%s, vgId:%d tid:%d, mark tid used, uid:%" PRIu64, pTable->info.tableId, pTable->vgId, pTable->tid, + pTable->uid); + // The create vgroup message may be received later than the create table message + // and the writing order in sdb is therefore uncertain + // which will cause the reference count of the vgroup to be incorrect when restarting + // mnodeIncVgroupRef(pVgroup); + } else { + mError("table:%s, vgId:%d tid:%d, failed to mark tid, uid:%" PRIu64, pTable->info.tableId, pTable->vgId, + pTable->tid, pTable->uid); + return -1; + } } + + return 0; } void mnodeRemoveTableFromVgroup(SVgObj *pVgroup, SCTableObj *pTable) { if (pTable->tid >= 1) { taosFreeId(pVgroup->idPool, pTable->tid); pVgroup->numOfTables--; + mTrace("table:%s, vgId:%d tid:%d, put tid back uid:%" PRIu64, pTable->info.tableId, pTable->vgId, pTable->tid, + pTable->uid); // The create vgroup message may be received later than the create table message // and the writing order in sdb is therefore uncertain // which will cause the reference count of the vgroup to be incorrect when restarting diff --git a/src/os/inc/osSysinfo.h b/src/os/inc/osSysinfo.h index 25c9c97b1e888d9f4371eea67a16efea728294a4..895b5dd499196703f954c5621241cd2d1e2fabec 100644 --- a/src/os/inc/osSysinfo.h +++ b/src/os/inc/osSysinfo.h @@ -23,6 +23,7 @@ extern "C" { // TAOS_OS_FUNC_SYSINFO typedef struct { int64_t tsize; + int64_t used; int64_t avail; } SysDiskSize; diff --git a/src/os/src/darwin/darwinSysInfo.c b/src/os/src/darwin/darwinSysInfo.c index 6af6285f56aa33200379aa52f94e0ab39de80644..55c07766b307f57fbc8fd76798ac880efef8a4de 100644 --- a/src/os/src/darwin/darwinSysInfo.c +++ b/src/os/src/darwin/darwinSysInfo.c @@ -138,6 +138,8 @@ void taosPrintOsInfo() { // uInfo(" os streamMax: %" PRId64, tsStreamMax); uInfo(" os numOfCores: %d", tsNumOfCores); uInfo(" os totalDisk: %f(GB)", tsTotalDataDirGB); + uInfo(" os usedDisk: %f(GB)", tsUsedDataDirGB); + uInfo(" os availDisk: %f(GB)", tsAvailDataDirGB); uInfo(" os totalMemory: %d(MB)", tsTotalMemoryMB); struct utsname buf; @@ -222,6 +224,7 @@ int32_t taosGetDiskSize(char *dataDir, SysDiskSize *diskSize) { } else { diskSize->tsize = info.f_blocks * info.f_frsize; diskSize->avail = info.f_bavail * info.f_frsize; + diskSize->used = (info.f_blocks - info.f_bfree) * info.f_frsize; return 0; } } diff --git a/src/os/src/detail/osSysinfo.c b/src/os/src/detail/osSysinfo.c index f12ec93bf7725d013fa2f53d148de783e854d3bf..c0d46878a821db3490ccf54f8e303e37e52f84aa 100644 --- a/src/os/src/detail/osSysinfo.c +++ b/src/os/src/detail/osSysinfo.c @@ -326,6 +326,7 @@ int32_t taosGetDiskSize(char *dataDir, SysDiskSize *diskSize) { } else { diskSize->tsize = info.f_blocks * info.f_frsize; diskSize->avail = info.f_bavail * info.f_frsize; + diskSize->used = (info.f_blocks - info.f_bfree) * info.f_frsize; return 0; } } @@ -506,6 +507,8 @@ void taosPrintOsInfo() { uInfo(" os streamMax: %" PRId64, tsStreamMax); uInfo(" os numOfCores: %d", tsNumOfCores); uInfo(" os totalDisk: %f(GB)", tsTotalDataDirGB); + uInfo(" os usedDisk: %f(GB)", tsUsedDataDirGB); + uInfo(" os availDisk: %f(GB)", tsAvailDataDirGB); uInfo(" os totalMemory: %d(MB)", tsTotalMemoryMB); struct utsname buf; diff --git a/src/os/src/windows/wSysinfo.c b/src/os/src/windows/wSysinfo.c index 48fb3c13a8fe80332cfc26f893d6a21f1cdd902e..8a81e3079a17e013372ebd7de0facb6b49a99c7b 100644 --- a/src/os/src/windows/wSysinfo.c +++ b/src/os/src/windows/wSysinfo.c @@ -136,7 +136,8 @@ int32_t taosGetDiskSize(char *dataDir, SysDiskSize *diskSize) { (PULARGE_INTEGER)&i64FreeBytes); if (fResult) { diskSize->tsize = (int64_t)(i64TotalBytes); - diskSize->avail = (int64_t)(i64FreeBytes); + diskSize->avail = (int64_t)(i64FreeBytesToCaller); + diskSize->used = (int64_t)(i64TotalBytes - i64FreeBytes); return 0; } else { uError("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno)); @@ -205,6 +206,8 @@ void taosGetSystemInfo() { void taosPrintOsInfo() { uInfo(" os numOfCores: %d", tsNumOfCores); uInfo(" os totalDisk: %f(GB)", tsTotalDataDirGB); + uInfo(" os usedDisk: %f(GB)", tsUsedDataDirGB); + uInfo(" os availDisk: %f(GB)", tsAvailDataDirGB); uInfo(" os totalMemory: %d(MB)", tsTotalMemoryMB); uInfo("=================================="); } diff --git a/src/plugins/http/src/httpParser.c b/src/plugins/http/src/httpParser.c index 4ce54a8ee630579499fe498e5d8c155bb5916eea..18cea56cfe6e0d1e8a4f833a920e5473536e1c7e 100644 --- a/src/plugins/http/src/httpParser.c +++ b/src/plugins/http/src/httpParser.c @@ -110,7 +110,7 @@ static void httpCleanupString(HttpString *str) { static int32_t httpAppendString(HttpString *str, const char *s, int32_t len) { if (str->size == 0) { str->pos = 0; - str->size = 64; + str->size = len + 1; str->str = malloc(str->size); } else if (str->pos + len + 1 >= str->size) { str->size += len; @@ -715,10 +715,12 @@ static int32_t httpParserOnVersion(HttpParser *parser, HTTP_PARSER_STATE state, if (parser->method) { ok = httpOnRequestLine(parser, parser->method, parser->target, parser->version); + /* if (parser->target) { free(parser->target); parser->target = NULL; } + */ } httpClearString(&parser->str); diff --git a/src/plugins/monitor/src/monMain.c b/src/plugins/monitor/src/monMain.c index ac80ad62509a755b5b86b65593a90a2730120df8..94af8e3ecd6623f791f6ad797176a59ca2605c2b 100644 --- a/src/plugins/monitor/src/monMain.c +++ b/src/plugins/monitor/src/monMain.c @@ -292,7 +292,7 @@ static int32_t monBuildCpuSql(char *sql) { // unit is GB static int32_t monBuildDiskSql(char *sql) { - return sprintf(sql, ", %f, %d", (tsTotalDataDirGB - tsAvailDataDirGB), (int32_t)tsTotalDataDirGB); + return sprintf(sql, ", %f, %d", tsUsedDataDirGB, (int32_t)tsTotalDataDirGB); } // unit is Kb diff --git a/src/query/inc/qSqlparser.h b/src/query/inc/qSqlparser.h index 71c2d2e5cf063e542b5d93f30d015707596d0bdd..313e656cbd14b14f3eda42c8782ca0a8be34c566 100644 --- a/src/query/inc/qSqlparser.h +++ b/src/query/inc/qSqlparser.h @@ -27,6 +27,23 @@ extern "C" { #include "tvariant.h" #define ParseTOKENTYPE SStrToken + +#define NON_ARITHMEIC_EXPR 0 +#define NORMAL_ARITHMETIC 1 +#define AGG_ARIGHTMEIC 2 + +enum SQL_NODE_TYPE { + SQL_NODE_TABLE_COLUMN= 1, + SQL_NODE_SQLFUNCTION = 2, + SQL_NODE_VALUE = 3, + SQL_NODE_EXPR = 4, +}; + +enum SQL_NODE_FROM_TYPE { + SQL_NODE_FROM_SUBQUERY = 1, + SQL_NODE_FROM_NAMELIST = 2, +}; + extern char tTokenTypeSwitcher[13]; #define toTSDBType(x) \ @@ -38,140 +55,164 @@ extern char tTokenTypeSwitcher[13]; } \ } while (0) +#define TPARSER_HAS_TOKEN(_t) ((_t).n > 0) +#define TPARSER_SET_NONE_TOKEN(_t) ((_t).n = 0) + typedef struct SLimitVal { - int64_t limit; - int64_t offset; + int64_t limit; + int64_t offset; } SLimitVal; typedef struct SOrderVal { - uint32_t order; - int32_t orderColId; + uint32_t order; + int32_t orderColId; } SOrderVal; typedef struct tVariantListItem { - tVariant pVar; - uint8_t sortOrder; + tVariant pVar; + uint8_t sortOrder; } tVariantListItem; typedef struct SIntervalVal { - SStrToken interval; - SStrToken offset; + SStrToken interval; + SStrToken offset; } SIntervalVal; typedef struct SSessionWindowVal { - SStrToken col; - SStrToken gap; + SStrToken col; + SStrToken gap; } SSessionWindowVal; -typedef struct SQuerySQL { - struct tSQLExprList *pSelection; // select clause - SArray * from; // from clause SArray - struct tSQLExpr * pWhere; // where clause [optional] - SArray * pGroupby; // groupby clause, only for tags[optional], SArray - SArray * pSortOrder; // orderby [optional], SArray - SIntervalVal interval; // (interval, interval_offset) [optional] - SSessionWindowVal sessionVal; // session window [optional] - SStrToken sliding; // sliding window [optional] - SLimitVal limit; // limit offset [optional] - SLimitVal slimit; // group limit offset [optional] - SArray * fillType; // fill type[optional], SArray - SStrToken selectToken; // sql string -} SQuerySQL; +struct SFromInfo; + +typedef struct SQuerySqlNode { + struct SArray *pSelectList; // select clause + struct SFromInfo *from; // from clause SArray + struct tSqlExpr *pWhere; // where clause [optional] + SArray *pGroupby; // groupby clause, only for tags[optional], SArray + SArray *pSortOrder; // orderby [optional], SArray + SArray *fillType; // fill type[optional], SArray + SIntervalVal interval; // (interval, interval_offset) [optional] + SSessionWindowVal sessionVal; // session window [optional] + SStrToken sliding; // sliding window [optional] + SLimitVal limit; // limit offset [optional] + SLimitVal slimit; // group limit offset [optional] + SStrToken sqlstr; // sql string in select clause +} SQuerySqlNode; + +typedef struct STableNamePair { + SStrToken name; + SStrToken aliasName; +} STableNamePair; + +typedef struct SSubclauseInfo { // "UNION" multiple select sub-clause + SQuerySqlNode **pClause; + int32_t numOfClause; +} SSubclauseInfo; + +typedef struct SFromInfo { + int32_t type; // nested query|table name list + union { + SSubclauseInfo *pNode; + SArray *tableList; // SArray + }; +} SFromInfo; typedef struct SCreatedTableInfo { - SStrToken name; // table name token - SStrToken stableName; // super table name token , for using clause - SArray *pTagNames; // create by using super table, tag name - SArray *pTagVals; // create by using super table, tag value - char *fullname; // table full name - STagData tagdata; // true tag data, super table full name is in STagData - int8_t igExist; // ignore if exists + SStrToken name; // table name token + SStrToken stableName; // super table name token , for using clause + SArray *pTagNames; // create by using super table, tag name + SArray *pTagVals; // create by using super table, tag value + char *fullname; // table full name + STagData tagdata; // true tag data, super table full name is in STagData + int8_t igExist; // ignore if exists } SCreatedTableInfo; -typedef struct SCreateTableSQL { - SStrToken name; // table name, create table [name] xxx - int8_t type; // create normal table/from super table/ stream - bool existCheck; +typedef struct SCreateTableSql { + SStrToken name; // table name, create table [name] xxx + int8_t type; // create normal table/from super table/ stream + bool existCheck; struct { - SArray *pTagColumns; // SArray - SArray *pColumns; // SArray + SArray *pTagColumns; // SArray + SArray *pColumns; // SArray } colInfo; - SArray *childTableInfo; // SArray - SQuerySQL *pSelect; -} SCreateTableSQL; + SArray *childTableInfo; // SArray + SQuerySqlNode *pSelect; +} SCreateTableSql; typedef struct SAlterTableInfo { - SStrToken name; - int16_t tableType; - int16_t type; - STagData tagData; - SArray *pAddColumns; // SArray - SArray *varList; // set t=val or: change src dst, SArray + SStrToken name; + int16_t tableType; + int16_t type; + STagData tagData; + SArray *pAddColumns; // SArray + SArray *varList; // set t=val or: change src dst, SArray } SAlterTableInfo; typedef struct SCreateDbInfo { - SStrToken dbname; - int32_t replica; - int32_t cacheBlockSize; - int32_t maxTablesPerVnode; - int32_t numOfBlocks; - int32_t daysPerFile; - int32_t minRowsPerBlock; - int32_t maxRowsPerBlock; - int32_t fsyncPeriod; - int64_t commitTime; - int32_t walLevel; - int32_t quorum; - int32_t compressionLevel; - SStrToken precision; - bool ignoreExists; - int8_t update; - int8_t cachelast; - SArray *keep; - int8_t dbType; - int16_t partitions; + SStrToken dbname; + int32_t replica; + int32_t cacheBlockSize; + int32_t maxTablesPerVnode; + int32_t numOfBlocks; + int32_t daysPerFile; + int32_t minRowsPerBlock; + int32_t maxRowsPerBlock; + int32_t fsyncPeriod; + int64_t commitTime; + int32_t walLevel; + int32_t quorum; + int32_t compressionLevel; + SStrToken precision; + bool ignoreExists; + int8_t update; + int8_t cachelast; + SArray *keep; + int8_t dbType; + int16_t partitions; } SCreateDbInfo; typedef struct SCreateFuncInfo { SStrToken name; SStrToken path; + int32_t type; TAOS_FIELD output; } SCreateFuncInfo; typedef struct SCreateAcctInfo { - int32_t maxUsers; - int32_t maxDbs; - int32_t maxTimeSeries; - int32_t maxStreams; - int32_t maxPointsPerSecond; - int64_t maxStorage; - int64_t maxQueryTime; - int32_t maxConnections; - SStrToken stat; + int32_t maxUsers; + int32_t maxDbs; + int32_t maxTimeSeries; + int32_t maxStreams; + int32_t maxPointsPerSecond; + int64_t maxStorage; + int64_t maxQueryTime; + int32_t maxConnections; + SStrToken stat; } SCreateAcctInfo; typedef struct SShowInfo { - uint8_t showType; - SStrToken prefix; - SStrToken pattern; + uint8_t showType; + SStrToken prefix; + SStrToken pattern; } SShowInfo; typedef struct SUserInfo { - SStrToken user; - SStrToken passwd; - SStrToken privilege; - int16_t type; + SStrToken user; + SStrToken passwd; + SStrToken privilege; + int16_t type; } SUserInfo; typedef struct SMiscInfo { - SArray *a; // SArray - bool existsCheck; - int16_t dbType; - int16_t tableType; - SUserInfo user; + SArray *a; // SArray + bool existsCheck; + int16_t dbType; + int16_t tableType; + SUserInfo user; union { SCreateDbInfo dbOpt; SCreateAcctInfo acctOpt; @@ -181,110 +222,77 @@ typedef struct SMiscInfo { }; } SMiscInfo; -typedef struct SSubclauseInfo { // "UNION" multiple select sub-clause - SQuerySQL **pClause; - int32_t numOfClause; -} SSubclauseInfo; - typedef struct SSqlInfo { int32_t type; bool valid; SSubclauseInfo subclauseInfo; char msg[256]; union { - SCreateTableSQL *pCreateTableInfo; - SAlterTableInfo *pAlterInfo; - SMiscInfo *pMiscInfo; + SCreateTableSql *pCreateTableInfo; + SAlterTableInfo *pAlterInfo; + SMiscInfo *pMiscInfo; }; } SSqlInfo; -#define NON_ARITHMEIC_EXPR 0 -#define NORMAL_ARITHMETIC 1 -#define AGG_ARIGHTMEIC 2 - -enum SQL_NODE_TYPE { - SQL_NODE_TABLE_COLUMN= 1, - SQL_NODE_SQLFUNCTION = 2, - SQL_NODE_VALUE = 3, - SQL_NODE_EXPR = 4, -}; - -typedef struct tSQLExpr { - uint16_t type; // sql node type - uint32_t tokenId; // TK_FUNCTION: sql function, TK_LE: less than(binary expr) +typedef struct tSqlExpr { + uint16_t type; // sql node type + uint32_t tokenId; // TK_LE: less than(binary expr) // the whole string of the function(col, param), while the function name is kept in token - SStrToken operand; - int32_t functionId; // function id + SStrToken operand; + int32_t functionId; // function id - SStrToken colInfo; // table column info - tVariant value; // the use input value - SStrToken token; // original sql expr string + SStrToken colInfo; // table column info + tVariant value; // the use input value + SStrToken token; // original sql expr string - struct tSQLExpr *pLeft; // left child - struct tSQLExpr *pRight; // right child - struct tSQLExprList *pParam; // function parameters list -} tSQLExpr; + struct tSqlExpr *pLeft; // left child + struct tSqlExpr *pRight; // right child + struct SArray *pParam; // function parameters list +} tSqlExpr; -// used in select clause. select from xxx +// used in select clause. select from xxx typedef struct tSqlExprItem { - tSQLExpr *pNode; // The list of expressions - char * aliasName; // alias name, null-terminated string - bool distinct; + tSqlExpr *pNode; // The list of expressions + char *aliasName; // alias name, null-terminated string + bool distinct; } tSqlExprItem; -// todo refactor by using SArray -typedef struct tSQLExprList { - int32_t nExpr; /* Number of expressions on the list */ - int32_t nAlloc; /* Number of entries allocated below */ - tSqlExprItem *a; /* One entry for each expression */ -} tSQLExprList; - -/** - * - * @param yyp The parser - * @param yymajor The major token code number - * @param yyminor The value for the token - */ -void Parse(void *yyp, int yymajor, ParseTOKENTYPE yyminor, SSqlInfo *); - -/** - * - * @param p The parser to be deleted - * @param freeProc Function used to reclaim memory - */ -void ParseFree(void *p, void (*freeProc)(void *)); - SArray *tVariantListAppend(SArray *pList, tVariant *pVar, uint8_t sortOrder); SArray *tVariantListInsert(SArray *pList, tVariant *pVar, uint8_t sortOrder, int32_t index); SArray *tVariantListAppendToken(SArray *pList, SStrToken *pAliasToken, uint8_t sortOrder); -tSQLExpr *tSqlExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType); - -tSQLExpr *tSqlExprClone(tSQLExpr *pSrc); +SFromInfo *setTableNameList(SFromInfo* pFromInfo, SStrToken *pName, SStrToken* pAlias); +SFromInfo *setSubquery(SFromInfo* pFromInfo, SQuerySqlNode *pSqlNode); +void *destroyFromInfo(SFromInfo* pFromInfo); -void tSqlExprDestroy(tSQLExpr *pExpr); +// sql expr leaf node +tSqlExpr *tSqlExprCreateIdValue(SStrToken *pToken, int32_t optrType); +tSqlExpr *tSqlExprCreateFunction(SArray *pParam, SStrToken *pFuncToken, SStrToken *endToken, int32_t optType); -tSQLExprList *tSqlExprListAppend(tSQLExprList *pList, tSQLExpr *pNode, SStrToken *pDistinct, SStrToken *pToken); +tSqlExpr *tSqlExprCreate(tSqlExpr *pLeft, tSqlExpr *pRight, int32_t optrType); +tSqlExpr *tSqlExprClone(tSqlExpr *pSrc); +void tSqlExprCompact(tSqlExpr** pExpr); +bool tSqlExprIsLeaf(tSqlExpr* pExpr); +bool tSqlExprIsParentOfLeaf(tSqlExpr* pExpr); +void tSqlExprDestroy(tSqlExpr *pExpr); +SArray *tSqlExprListAppend(SArray *pList, tSqlExpr *pNode, SStrToken *pDistinct, SStrToken *pToken); +void tSqlExprListDestroy(SArray *pList); -void tSqlExprListDestroy(tSQLExprList *pList); +SQuerySqlNode *tSetQuerySqlNode(SStrToken *pSelectToken, SArray *pSelectList, SFromInfo *pFrom, tSqlExpr *pWhere, + SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval, SSessionWindowVal *ps, + SStrToken *pSliding, SArray *pFill, SLimitVal *pLimit, SLimitVal *pgLimit); -SQuerySQL *tSetQuerySqlNode(SStrToken *pSelectToken, tSQLExprList *pSelection, SArray *pFrom, tSQLExpr *pWhere, - SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval, SSessionWindowVal *pSession, - SStrToken *pSliding, SArray *pFill, SLimitVal *pLimit, SLimitVal *pGLimit); +SCreateTableSql *tSetCreateTableInfo(SArray *pCols, SArray *pTags, SQuerySqlNode *pSelect, int32_t type); -SCreateTableSQL *tSetCreateSqlElems(SArray *pCols, SArray *pTags, SQuerySQL *pSelect, int32_t type); - -void tSqlExprNodeDestroy(tSQLExpr *pExpr); - -SAlterTableInfo * tAlterTableSqlElems(SStrToken *pTableName, SArray *pCols, SArray *pVals, int32_t type, int16_t tableTable); +SAlterTableInfo *tSetAlterTableInfo(SStrToken *pTableName, SArray *pCols, SArray *pVals, int32_t type, int16_t tableTable); SCreatedTableInfo createNewChildTableInfo(SStrToken *pTableName, SArray *pTagNames, SArray *pTagVals, SStrToken *pToken, SStrToken* igExists); void destroyAllSelectClause(SSubclauseInfo *pSql); -void doDestroyQuerySql(SQuerySQL *pSql); +void destroyQuerySqlNode(SQuerySqlNode *pSql); void freeCreateTableInfo(void* p); -SSqlInfo * setSqlInfo(SSqlInfo *pInfo, void *pSqlExprInfo, SStrToken *pTableName, int32_t type); +SSqlInfo *setSqlInfo(SSqlInfo *pInfo, void *pSqlExprInfo, SStrToken *pTableName, int32_t type); SSubclauseInfo *setSubclause(SSubclauseInfo *pClause, void *pSqlExprInfo); SSubclauseInfo *appendSelectClause(SSubclauseInfo *pInfo, void *pSubclause); @@ -293,7 +301,7 @@ void setCreatedTableName(SSqlInfo *pInfo, SStrToken *pTableNameToken, SStrToken void SqlInfoDestroy(SSqlInfo *pInfo); -void setDCLSQLElems(SSqlInfo *pInfo, int32_t type, int32_t nParams, ...); +void setDCLSqlElems(SSqlInfo *pInfo, int32_t type, int32_t nParams, ...); void setDropDbTableInfo(SSqlInfo *pInfo, int32_t type, SStrToken* pToken, SStrToken* existsCheck,int16_t dbType,int16_t tableType); void setShowOptions(SSqlInfo *pInfo, int32_t type, SStrToken* prefix, SStrToken* pPatterns); @@ -308,19 +316,39 @@ void setDefaultCreateDbOption(SCreateDbInfo *pDBInfo); void setDefaultCreateTopicOption(SCreateDbInfo *pDBInfo); // prefix show db.tables; -void setDbName(SStrToken *pCpxName, SStrToken *pDb); +void tSetDbName(SStrToken *pCpxName, SStrToken *pDb); -tSQLExpr *tSqlExprIdValueCreate(SStrToken *pToken, int32_t optrType); +void tSetColumnInfo(TAOS_FIELD *pField, SStrToken *pName, TAOS_FIELD *pType); +void tSetColumnType(TAOS_FIELD *pField, SStrToken *type); -tSQLExpr *tSqlExprCreateFunction(tSQLExprList *pList, SStrToken *pFuncToken, SStrToken *endToken, int32_t optType); - -void tSqlSetColumnInfo(TAOS_FIELD *pField, SStrToken *pName, TAOS_FIELD *pType); +/** + * + * @param yyp The parser + * @param yymajor The major token code number + * @param yyminor The value for the token + */ +void Parse(void *yyp, int yymajor, ParseTOKENTYPE yyminor, SSqlInfo *); -void tSqlSetColumnType(TAOS_FIELD *pField, SStrToken *type); +/** + * + * @param p The parser to be deleted + * @param freeProc Function used to reclaim memory + */ +void ParseFree(void *p, void (*freeProc)(void *)); +/** + * + * @param mallocProc The parser allocator + * @return + */ void *ParseAlloc(void *(*mallocProc)(size_t)); -SSqlInfo qSQLParse(const char *str); +/** + * + * @param str sql string + * @return sql ast + */ +SSqlInfo qSqlParse(const char *str); #ifdef __cplusplus } diff --git a/src/query/inc/qUdf.h b/src/query/inc/qUdf.h index 7592d454196707dee87c66c4f9c31ccf7372637f..648f7047a9db74de61235fa5fb3bf4defcab6e85 100644 --- a/src/query/inc/qUdf.h +++ b/src/query/inc/qUdf.h @@ -16,7 +16,7 @@ #ifndef TDENGINE_QUDF_H #define TDENGINE_QUDF_H -enum { TSDB_UDF_FUNC_NORMAL = 0, TSDB_UDF_FUNC_INIT, TSDB_UDF_FUNC_AGG, TSDB_UDF_FUNC_MAX_NUM }; +enum { TSDB_UDF_FUNC_NORMAL = 0, TSDB_UDF_FUNC_INIT, TSDB_UDF_FUNC_FINALIZE, TSDB_UDF_FUNC_MAX_NUM }; @@ -31,7 +31,7 @@ typedef struct SUdfInit{ typedef struct SUdfInfo { int32_t functionId; // system assigned function id - int8_t funcType; // scalar function or aggregate function + int32_t funcType; // scalar function or aggregate function int8_t resType; // result type int16_t resBytes; // result byte int32_t contLen; // content length @@ -48,6 +48,8 @@ typedef struct SUdfInfo { typedef void (*udfNormalFunc)(char* data, int8_t type, int32_t numOfRows, int64_t* ts, char* dataOutput, char* tsOutput, int32_t* numOfOutput, char* buf); typedef void (*udfInitFunc)(SUdfInit* data); +typedef void (*udfFinalizeFunc)(char* data, int8_t type, int32_t numOfRows, int64_t* ts, char* dataOutput, char* tsOutput, + int32_t* numOfOutput, char* buf); #endif // TDENGINE_QUDF_H diff --git a/src/query/inc/sql.y b/src/query/inc/sql.y index 85e6017dc46882345b92d43c5a6c3b5d386d4886..71ca1f297098318fb8505b93230b7fef2404da5c 100644 --- a/src/query/inc/sql.y +++ b/src/query/inc/sql.y @@ -93,11 +93,11 @@ cpxName(A) ::= DOT ids(Y). {A = Y; A.n += 1; } cmd ::= SHOW CREATE TABLE ids(X) cpxName(Y). { X.n += Y.n; - setDCLSQLElems(pInfo, TSDB_SQL_SHOW_CREATE_TABLE, 1, &X); + setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_TABLE, 1, &X); } cmd ::= SHOW CREATE DATABASE ids(X). { - setDCLSQLElems(pInfo, TSDB_SQL_SHOW_CREATE_DATABASE, 1, &X); + setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_DATABASE, 1, &X); } cmd ::= SHOW dbPrefix(X) TABLES. { @@ -114,19 +114,19 @@ cmd ::= SHOW dbPrefix(X) STABLES. { cmd ::= SHOW dbPrefix(X) STABLES LIKE ids(Y). { SStrToken token; - setDbName(&token, &X); + tSetDbName(&token, &X); setShowOptions(pInfo, TSDB_MGMT_TABLE_METRIC, &token, &Y); } cmd ::= SHOW dbPrefix(X) VGROUPS. { SStrToken token; - setDbName(&token, &X); + tSetDbName(&token, &X); setShowOptions(pInfo, TSDB_MGMT_TABLE_VGROUP, &token, 0); } cmd ::= SHOW dbPrefix(X) VGROUPS ids(Y). { SStrToken token; - setDbName(&token, &X); + tSetDbName(&token, &X); setShowOptions(pInfo, TSDB_MGMT_TABLE_VGROUP, &token, &Y); } @@ -146,26 +146,26 @@ cmd ::= DROP DATABASE ifexists(Y) ids(X). { setDropDbTableInfo(pInfo, TSDB_SQ cmd ::= DROP TOPIC ifexists(Y) ids(X). { setDropDbTableInfo(pInfo, TSDB_SQL_DROP_DB, &X, &Y, TSDB_DB_TYPE_TOPIC, -1); } cmd ::= DROP FUNCTION ids(X). { setDropFuncInfo(pInfo, TSDB_SQL_DROP_FUNCTION, &X); } -cmd ::= DROP DNODE ids(X). { setDCLSQLElems(pInfo, TSDB_SQL_DROP_DNODE, 1, &X); } -cmd ::= DROP USER ids(X). { setDCLSQLElems(pInfo, TSDB_SQL_DROP_USER, 1, &X); } -cmd ::= DROP ACCOUNT ids(X). { setDCLSQLElems(pInfo, TSDB_SQL_DROP_ACCT, 1, &X); } +cmd ::= DROP DNODE ids(X). { setDCLSqlElems(pInfo, TSDB_SQL_DROP_DNODE, 1, &X); } +cmd ::= DROP USER ids(X). { setDCLSqlElems(pInfo, TSDB_SQL_DROP_USER, 1, &X); } +cmd ::= DROP ACCOUNT ids(X). { setDCLSqlElems(pInfo, TSDB_SQL_DROP_ACCT, 1, &X); } /////////////////////////////////THE USE STATEMENT////////////////////////////////////////// -cmd ::= USE ids(X). { setDCLSQLElems(pInfo, TSDB_SQL_USE_DB, 1, &X);} +cmd ::= USE ids(X). { setDCLSqlElems(pInfo, TSDB_SQL_USE_DB, 1, &X);} /////////////////////////////////THE DESCRIBE STATEMENT///////////////////////////////////// cmd ::= DESCRIBE ids(X) cpxName(Y). { X.n += Y.n; - setDCLSQLElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &X); + setDCLSqlElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &X); } /////////////////////////////////THE ALTER STATEMENT//////////////////////////////////////// cmd ::= ALTER USER ids(X) PASS ids(Y). { setAlterUserSql(pInfo, TSDB_ALTER_USER_PASSWD, &X, &Y, NULL); } cmd ::= ALTER USER ids(X) PRIVILEGE ids(Y). { setAlterUserSql(pInfo, TSDB_ALTER_USER_PRIVILEGES, &X, NULL, &Y);} -cmd ::= ALTER DNODE ids(X) ids(Y). { setDCLSQLElems(pInfo, TSDB_SQL_CFG_DNODE, 2, &X, &Y); } -cmd ::= ALTER DNODE ids(X) ids(Y) ids(Z). { setDCLSQLElems(pInfo, TSDB_SQL_CFG_DNODE, 3, &X, &Y, &Z); } -cmd ::= ALTER LOCAL ids(X). { setDCLSQLElems(pInfo, TSDB_SQL_CFG_LOCAL, 1, &X); } -cmd ::= ALTER LOCAL ids(X) ids(Y). { setDCLSQLElems(pInfo, TSDB_SQL_CFG_LOCAL, 2, &X, &Y); } +cmd ::= ALTER DNODE ids(X) ids(Y). { setDCLSqlElems(pInfo, TSDB_SQL_CFG_DNODE, 2, &X, &Y); } +cmd ::= ALTER DNODE ids(X) ids(Y) ids(Z). { setDCLSqlElems(pInfo, TSDB_SQL_CFG_DNODE, 3, &X, &Y, &Z); } +cmd ::= ALTER LOCAL ids(X). { setDCLSqlElems(pInfo, TSDB_SQL_CFG_LOCAL, 1, &X); } +cmd ::= ALTER LOCAL ids(X) ids(Y). { setDCLSqlElems(pInfo, TSDB_SQL_CFG_LOCAL, 2, &X, &Y); } cmd ::= ALTER DATABASE ids(X) alter_db_optr(Y). { SStrToken t = {0}; setCreateDbInfo(pInfo, TSDB_SQL_ALTER_DB, &X, &Y, &t);} cmd ::= ALTER TOPIC ids(X) alter_topic_optr(Y). { SStrToken t = {0}; setCreateDbInfo(pInfo, TSDB_SQL_ALTER_DB, &X, &Y, &t);} @@ -189,12 +189,13 @@ ifnotexists(X) ::= . { X.n = 0;} /////////////////////////////////THE CREATE STATEMENT/////////////////////////////////////// //create option for dnode/db/user/account -cmd ::= CREATE DNODE ids(X). { setDCLSQLElems(pInfo, TSDB_SQL_CREATE_DNODE, 1, &X);} +cmd ::= CREATE DNODE ids(X). { setDCLSqlElems(pInfo, TSDB_SQL_CREATE_DNODE, 1, &X);} cmd ::= CREATE ACCOUNT ids(X) PASS ids(Y) acct_optr(Z). { setCreateAcctSql(pInfo, TSDB_SQL_CREATE_ACCT, &X, &Y, &Z);} cmd ::= CREATE DATABASE ifnotexists(Z) ids(X) db_optr(Y). { setCreateDbInfo(pInfo, TSDB_SQL_CREATE_DB, &X, &Y, &Z);} cmd ::= CREATE TOPIC ifnotexists(Z) ids(X) topic_optr(Y). { setCreateDbInfo(pInfo, TSDB_SQL_CREATE_DB, &X, &Y, &Z);} -cmd ::= CREATE FUNCTION ids(X) AS ids(Y) OUTPUTTYPE typename(Z). { setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &X, &Y, &Z);} +cmd ::= CREATE FUNCTION ids(X) AS ids(Y) OUTPUTTYPE typename(Z). { setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &X, &Y, &Z, 1);} +cmd ::= CREATE AGGREGATE FUNCTION ids(X) AS ids(Y) OUTPUTTYPE typename(Z). { setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &X, &Y, &Z, 2);} cmd ::= CREATE USER ids(X) PASS ids(Y). { setCreateUserSql(pInfo, &X, &Y);} pps(Y) ::= . { Y.n = 0; } @@ -302,17 +303,17 @@ alter_topic_optr(Y) ::= alter_topic_optr(Z) partitions(X). { Y = Z; Y.parti %type typename {TAOS_FIELD} typename(A) ::= ids(X). { X.type = 0; - tSqlSetColumnType (&A, &X); + tSetColumnType (&A, &X); } //define binary type, e.g., binary(10), nchar(10) typename(A) ::= ids(X) LP signed(Y) RP. { if (Y <= 0) { X.type = 0; - tSqlSetColumnType(&A, &X); + tSetColumnType(&A, &X); } else { X.type = -Y; // negative value of name length - tSqlSetColumnType(&A, &X); + tSetColumnType(&A, &X); } } @@ -320,7 +321,7 @@ typename(A) ::= ids(X) LP signed(Y) RP. { typename(A) ::= ids(X) UNSIGNED(Z). { X.type = 0; X.n = ((Z.z + Z.n) - X.z); - tSqlSetColumnType (&A, &X); + tSetColumnType (&A, &X); } %type signed {int64_t} @@ -334,10 +335,10 @@ cmd ::= CREATE TABLE create_stable_args. {} cmd ::= CREATE STABLE create_stable_args. {} cmd ::= CREATE TABLE create_table_list(Z). { pInfo->type = TSDB_SQL_CREATE_TABLE; pInfo->pCreateTableInfo = Z;} -%type create_table_list{SCreateTableSQL*} +%type create_table_list{SCreateTableSql*} %destructor create_table_list{destroyCreateTableSql($$);} create_table_list(A) ::= create_from_stable(Z). { - SCreateTableSQL* pCreateTable = calloc(1, sizeof(SCreateTableSQL)); + SCreateTableSql* pCreateTable = calloc(1, sizeof(SCreateTableSql)); pCreateTable->childTableInfo = taosArrayInit(4, sizeof(SCreatedTableInfo)); taosArrayPush(pCreateTable->childTableInfo, &Z); @@ -350,9 +351,9 @@ create_table_list(A) ::= create_table_list(X) create_from_stable(Z). { A = X; } -%type create_table_args{SCreateTableSQL*} +%type create_table_args{SCreateTableSql*} create_table_args(A) ::= ifnotexists(U) ids(V) cpxName(Z) LP columnlist(X) RP. { - A = tSetCreateSqlElems(X, NULL, NULL, TSQL_CREATE_TABLE); + A = tSetCreateTableInfo(X, NULL, NULL, TSQL_CREATE_TABLE); setSqlInfo(pInfo, A, NULL, TSDB_SQL_CREATE_TABLE); V.n += Z.n; @@ -360,9 +361,9 @@ create_table_args(A) ::= ifnotexists(U) ids(V) cpxName(Z) LP columnlist(X) RP. { } // create super table -%type create_stable_args{SCreateTableSQL*} +%type create_stable_args{SCreateTableSql*} create_stable_args(A) ::= ifnotexists(U) ids(V) cpxName(Z) LP columnlist(X) RP TAGS LP columnlist(Y) RP. { - A = tSetCreateSqlElems(X, Y, NULL, TSQL_CREATE_STABLE); + A = tSetCreateTableInfo(X, Y, NULL, TSQL_CREATE_STABLE); setSqlInfo(pInfo, A, NULL, TSDB_SQL_CREATE_TABLE); V.n += Z.n; @@ -392,7 +393,7 @@ tagNamelist(A) ::= ids(X). {A = taosArrayInit(4, sizeof(SSt // create stream // create table table_name as select count(*) from super_table_name interval(time) create_table_args(A) ::= ifnotexists(U) ids(V) cpxName(Z) AS select(S). { - A = tSetCreateSqlElems(NULL, NULL, S, TSQL_CREATE_STREAM); + A = tSetCreateTableInfo(NULL, NULL, S, TSQL_CREATE_STREAM); setSqlInfo(pInfo, A, NULL, TSDB_SQL_CREATE_TABLE); V.n += Z.n; @@ -408,7 +409,7 @@ columnlist(A) ::= column(X). {A = taosArrayInit(4, sizeof(T // The information used for a column is the name and type of column: // tinyint smallint int bigint float double bool timestamp binary(x) nchar(x) column(A) ::= ids(X) typename(Y). { - tSqlSetColumnInfo(&A, &X, &Y); + tSetColumnInfo(&A, &X, &Y); } %type tagitemlist {SArray*} @@ -453,26 +454,26 @@ tagitem(A) ::= PLUS(X) FLOAT(Y). { } //////////////////////// The SELECT statement ///////////////////////////////// -%type select {SQuerySQL*} -%destructor select {doDestroyQuerySql($$);} +%type select {SQuerySqlNode*} +%destructor select {destroyQuerySqlNode($$);} select(A) ::= SELECT(T) selcollist(W) from(X) where_opt(Y) interval_opt(K) session_option(H) fill_opt(F) sliding_opt(S) groupby_opt(P) orderby_opt(Z) having_opt(N) slimit_opt(G) limit_opt(L). { A = tSetQuerySqlNode(&T, W, X, Y, P, Z, &K, &H, &S, F, &L, &G); } +select(A) ::= LP select(B) RP. {A = B;} + %type union {SSubclauseInfo*} %destructor union {destroyAllSelectClause($$);} - union(Y) ::= select(X). { Y = setSubclause(NULL, X); } -union(Y) ::= LP union(X) RP. { Y = X; } union(Y) ::= union(Z) UNION ALL select(X). { Y = appendSelectClause(Z, X); } -union(Y) ::= union(Z) UNION ALL LP select(X) RP. { Y = appendSelectClause(Z, X); } cmd ::= union(X). { setSqlInfo(pInfo, X, NULL, TSDB_SQL_SELECT); } // Support for the SQL exprssion without from & where subclauses, e.g., -// select current_database(), -// select server_version(), select client_version(), -// select server_state(); +// select current_database() +// select server_version() +// select client_version() +// select server_state() select(A) ::= SELECT(T) selcollist(W). { A = tSetQuerySqlNode(&T, W, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } @@ -480,10 +481,10 @@ select(A) ::= SELECT(T) selcollist(W). { // selcollist is a list of expressions that are to become the return // values of the SELECT statement. The "*" in statements like // "SELECT * FROM ..." is encoded as a special expression with an opcode of TK_ALL. -%type selcollist {tSQLExprList*} +%type selcollist {SArray*} %destructor selcollist {tSqlExprListDestroy($$);} -%type sclp {tSQLExprList*} +%type sclp {SArray*} %destructor sclp {tSqlExprListDestroy($$);} sclp(A) ::= selcollist(X) COMMA. {A = X;} sclp(A) ::= . {A = 0;} @@ -492,13 +493,12 @@ selcollist(A) ::= sclp(P) distinct(Z) expr(X) as(Y). { } selcollist(A) ::= sclp(P) STAR. { - tSQLExpr *pNode = tSqlExprIdValueCreate(NULL, TK_ALL); + tSqlExpr *pNode = tSqlExprCreateIdValue(NULL, TK_ALL); A = tSqlExprListAppend(P, pNode, 0, 0); } // An option "AS " phrase that can follow one of the expressions that // define the result set, or one of the tables in the FROM clause. -// %type as {SStrToken} as(X) ::= AS ids(Y). { X = Y; } as(X) ::= ids(Y). { X = Y; } @@ -509,39 +509,36 @@ distinct(X) ::= DISTINCT(Y). { X = Y; } distinct(X) ::= . { X.n = 0;} // A complete FROM clause. -%type from {SArray*} -// current not support query from no-table +%type from {SFromInfo*} from(A) ::= FROM tablelist(X). {A = X;} +from(A) ::= FROM LP union(Y) RP. {A = Y;} %type tablelist {SArray*} tablelist(A) ::= ids(X) cpxName(Y). { toTSDBType(X.type); X.n += Y.n; - A = tVariantListAppendToken(NULL, &X, -1); - A = tVariantListAppendToken(A, &X, -1); // table alias name + A = setTableNameList(NULL, &X, NULL); } tablelist(A) ::= ids(X) cpxName(Y) ids(Z). { toTSDBType(X.type); toTSDBType(Z.type); X.n += Y.n; - A = tVariantListAppendToken(NULL, &X, -1); - A = tVariantListAppendToken(A, &Z, -1); + A = setTableNameList(NULL, &X, &Z); } tablelist(A) ::= tablelist(Y) COMMA ids(X) cpxName(Z). { toTSDBType(X.type); X.n += Z.n; - A = tVariantListAppendToken(Y, &X, -1); - A = tVariantListAppendToken(A, &X, -1); + A = setTableNameList(Y, &X, NULL); } tablelist(A) ::= tablelist(Y) COMMA ids(X) cpxName(Z) ids(F). { toTSDBType(X.type); toTSDBType(F.type); X.n += Z.n; - A = tVariantListAppendToken(Y, &X, -1); - A = tVariantListAppendToken(A, &F, -1); + + A = setTableNameList(Y, &X, &F); } // The value of interval should be the form of "number+[a,s,m,h,d,n,y]" or "now" @@ -633,7 +630,7 @@ grouplist(A) ::= item(X). { } //having clause, ignore the input condition in having -%type having_opt {tSQLExpr*} +%type having_opt {tSqlExpr*} %destructor having_opt {tSqlExprDestroy($$);} having_opt(A) ::=. {A = 0;} having_opt(A) ::= HAVING expr(X). {A = X;} @@ -655,7 +652,7 @@ slimit_opt(A) ::= SLIMIT signed(X) SOFFSET signed(Y). slimit_opt(A) ::= SLIMIT signed(X) COMMA signed(Y). {A.limit = Y; A.offset = X;} -%type where_opt {tSQLExpr*} +%type where_opt {tSqlExpr*} %destructor where_opt {tSqlExprDestroy($$);} where_opt(A) ::= . {A = 0;} @@ -663,25 +660,25 @@ where_opt(A) ::= WHERE expr(X). {A = X;} /////////////////////////// Expression Processing ///////////////////////////// // -%type expr {tSQLExpr*} +%type expr {tSqlExpr*} %destructor expr {tSqlExprDestroy($$);} expr(A) ::= LP(X) expr(Y) RP(Z). {A = Y; A->token.z = X.z; A->token.n = (Z.z - X.z + 1);} -expr(A) ::= ID(X). { A = tSqlExprIdValueCreate(&X, TK_ID);} -expr(A) ::= ID(X) DOT ID(Y). { X.n += (1+Y.n); A = tSqlExprIdValueCreate(&X, TK_ID);} -expr(A) ::= ID(X) DOT STAR(Y). { X.n += (1+Y.n); A = tSqlExprIdValueCreate(&X, TK_ALL);} - -expr(A) ::= INTEGER(X). { A = tSqlExprIdValueCreate(&X, TK_INTEGER);} -expr(A) ::= MINUS(X) INTEGER(Y). { X.n += Y.n; X.type = TK_INTEGER; A = tSqlExprIdValueCreate(&X, TK_INTEGER);} -expr(A) ::= PLUS(X) INTEGER(Y). { X.n += Y.n; X.type = TK_INTEGER; A = tSqlExprIdValueCreate(&X, TK_INTEGER);} -expr(A) ::= FLOAT(X). { A = tSqlExprIdValueCreate(&X, TK_FLOAT);} -expr(A) ::= MINUS(X) FLOAT(Y). { X.n += Y.n; X.type = TK_FLOAT; A = tSqlExprIdValueCreate(&X, TK_FLOAT);} -expr(A) ::= PLUS(X) FLOAT(Y). { X.n += Y.n; X.type = TK_FLOAT; A = tSqlExprIdValueCreate(&X, TK_FLOAT);} -expr(A) ::= STRING(X). { A = tSqlExprIdValueCreate(&X, TK_STRING);} -expr(A) ::= NOW(X). { A = tSqlExprIdValueCreate(&X, TK_NOW); } -expr(A) ::= VARIABLE(X). { A = tSqlExprIdValueCreate(&X, TK_VARIABLE);} -expr(A) ::= BOOL(X). { A = tSqlExprIdValueCreate(&X, TK_BOOL);} +expr(A) ::= ID(X). { A = tSqlExprCreateIdValue(&X, TK_ID);} +expr(A) ::= ID(X) DOT ID(Y). { X.n += (1+Y.n); A = tSqlExprCreateIdValue(&X, TK_ID);} +expr(A) ::= ID(X) DOT STAR(Y). { X.n += (1+Y.n); A = tSqlExprCreateIdValue(&X, TK_ALL);} + +expr(A) ::= INTEGER(X). { A = tSqlExprCreateIdValue(&X, TK_INTEGER);} +expr(A) ::= MINUS(X) INTEGER(Y). { X.n += Y.n; X.type = TK_INTEGER; A = tSqlExprCreateIdValue(&X, TK_INTEGER);} +expr(A) ::= PLUS(X) INTEGER(Y). { X.n += Y.n; X.type = TK_INTEGER; A = tSqlExprCreateIdValue(&X, TK_INTEGER);} +expr(A) ::= FLOAT(X). { A = tSqlExprCreateIdValue(&X, TK_FLOAT);} +expr(A) ::= MINUS(X) FLOAT(Y). { X.n += Y.n; X.type = TK_FLOAT; A = tSqlExprCreateIdValue(&X, TK_FLOAT);} +expr(A) ::= PLUS(X) FLOAT(Y). { X.n += Y.n; X.type = TK_FLOAT; A = tSqlExprCreateIdValue(&X, TK_FLOAT);} +expr(A) ::= STRING(X). { A = tSqlExprCreateIdValue(&X, TK_STRING);} +expr(A) ::= NOW(X). { A = tSqlExprCreateIdValue(&X, TK_NOW); } +expr(A) ::= VARIABLE(X). { A = tSqlExprCreateIdValue(&X, TK_VARIABLE);} +expr(A) ::= BOOL(X). { A = tSqlExprCreateIdValue(&X, TK_BOOL);} // ordinary functions: min(x), max(x), top(k, 20) expr(A) ::= ID(X) LP exprlist(Y) RP(E). { A = tSqlExprCreateFunction(Y, &X, &E, X.type); } @@ -701,7 +698,7 @@ expr(A) ::= expr(X) GE expr(Y). {A = tSqlExprCreate(X, Y, TK_GE);} expr(A) ::= expr(X) NE expr(Y). {A = tSqlExprCreate(X, Y, TK_NE);} expr(A) ::= expr(X) EQ expr(Y). {A = tSqlExprCreate(X, Y, TK_EQ);} -expr(A) ::= expr(X) BETWEEN expr(Y) AND expr(Z). { tSQLExpr* X2 = tSqlExprClone(X); A = tSqlExprCreate(tSqlExprCreate(X, Y, TK_GE), tSqlExprCreate(X2, Z, TK_LE), TK_AND);} +expr(A) ::= expr(X) BETWEEN expr(Y) AND expr(Z). { tSqlExpr* X2 = tSqlExprClone(X); A = tSqlExprCreate(tSqlExprCreate(X, Y, TK_GE), tSqlExprCreate(X2, Z, TK_LE), TK_AND);} expr(A) ::= expr(X) AND expr(Y). {A = tSqlExprCreate(X, Y, TK_AND);} expr(A) ::= expr(X) OR expr(Y). {A = tSqlExprCreate(X, Y, TK_OR); } @@ -717,12 +714,12 @@ expr(A) ::= expr(X) REM expr(Y). {A = tSqlExprCreate(X, Y, TK_REM); } expr(A) ::= expr(X) LIKE expr(Y). {A = tSqlExprCreate(X, Y, TK_LIKE); } //in expression -expr(A) ::= expr(X) IN LP exprlist(Y) RP. {A = tSqlExprCreate(X, (tSQLExpr*)Y, TK_IN); } +expr(A) ::= expr(X) IN LP exprlist(Y) RP. {A = tSqlExprCreate(X, (tSqlExpr*)Y, TK_IN); } -%type exprlist {tSQLExprList*} +%type exprlist {SArray*} %destructor exprlist {tSqlExprListDestroy($$);} -%type expritem {tSQLExpr*} +%type expritem {tSqlExpr*} %destructor expritem {tSqlExprDestroy($$);} exprlist(A) ::= exprlist(X) COMMA expritem(Y). {A = tSqlExprListAppend(X,Y,0, 0);} @@ -731,12 +728,12 @@ expritem(A) ::= expr(X). {A = X;} expritem(A) ::= . {A = 0;} ///////////////////////////////////reset query cache////////////////////////////////////// -cmd ::= RESET QUERY CACHE. { setDCLSQLElems(pInfo, TSDB_SQL_RESET_CACHE, 0);} +cmd ::= RESET QUERY CACHE. { setDCLSqlElems(pInfo, TSDB_SQL_RESET_CACHE, 0);} ///////////////////////////////////ALTER TABLE statement////////////////////////////////// cmd ::= ALTER TABLE ids(X) cpxName(F) ADD COLUMN columnlist(A). { X.n += F.n; - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&X, A, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, A, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } @@ -746,14 +743,14 @@ cmd ::= ALTER TABLE ids(X) cpxName(F) DROP COLUMN ids(A). { toTSDBType(A.type); SArray* K = tVariantListAppendToken(NULL, &A, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&X, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } //////////////////////////////////ALTER TAGS statement///////////////////////////////////// cmd ::= ALTER TABLE ids(X) cpxName(Y) ADD TAG columnlist(A). { X.n += Y.n; - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&X, A, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, A, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } cmd ::= ALTER TABLE ids(X) cpxName(Z) DROP TAG ids(Y). { @@ -762,7 +759,7 @@ cmd ::= ALTER TABLE ids(X) cpxName(Z) DROP TAG ids(Y). { toTSDBType(Y.type); SArray* A = tVariantListAppendToken(NULL, &Y, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&X, NULL, A, TSDB_ALTER_TABLE_DROP_TAG_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, A, TSDB_ALTER_TABLE_DROP_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } @@ -775,7 +772,7 @@ cmd ::= ALTER TABLE ids(X) cpxName(F) CHANGE TAG ids(Y) ids(Z). { toTSDBType(Z.type); A = tVariantListAppendToken(A, &Z, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&X, NULL, A, TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, A, TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } @@ -786,7 +783,7 @@ cmd ::= ALTER TABLE ids(X) cpxName(F) SET TAG ids(Y) EQ tagitem(Z). { SArray* A = tVariantListAppendToken(NULL, &Y, -1); A = tVariantListAppend(A, &Z, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&X, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_VAL, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_VAL, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } @@ -794,7 +791,7 @@ cmd ::= ALTER TABLE ids(X) cpxName(F) SET TAG ids(Y) EQ tagitem(Z). { ///////////////////////////////////ALTER STABLE statement////////////////////////////////// cmd ::= ALTER STABLE ids(X) cpxName(F) ADD COLUMN columnlist(A). { X.n += F.n; - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&X, A, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, A, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } @@ -804,14 +801,14 @@ cmd ::= ALTER STABLE ids(X) cpxName(F) DROP COLUMN ids(A). { toTSDBType(A.type); SArray* K = tVariantListAppendToken(NULL, &A, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&X, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } //////////////////////////////////ALTER TAGS statement///////////////////////////////////// cmd ::= ALTER STABLE ids(X) cpxName(Y) ADD TAG columnlist(A). { X.n += Y.n; - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&X, A, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, A, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } cmd ::= ALTER STABLE ids(X) cpxName(Z) DROP TAG ids(Y). { @@ -820,7 +817,7 @@ cmd ::= ALTER STABLE ids(X) cpxName(Z) DROP TAG ids(Y). { toTSDBType(Y.type); SArray* A = tVariantListAppendToken(NULL, &Y, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&X, NULL, A, TSDB_ALTER_TABLE_DROP_TAG_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, A, TSDB_ALTER_TABLE_DROP_TAG_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } @@ -833,7 +830,7 @@ cmd ::= ALTER STABLE ids(X) cpxName(F) CHANGE TAG ids(Y) ids(Z). { toTSDBType(Z.type); A = tVariantListAppendToken(A, &Z, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&X, NULL, A, TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, A, TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } @@ -845,5 +842,4 @@ cmd ::= KILL QUERY INTEGER(X) COLON(Z) INTEGER(Y). {X.n += (Z.n + Y.n); s %fallback ID ABORT AFTER ASC ATTACH BEFORE BEGIN CASCADE CLUSTER CONFLICT COPY DATABASE DEFERRED DELIMITERS DESC DETACH EACH END EXPLAIN FAIL FOR GLOB IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH KEY OF OFFSET RAISE REPLACE RESTRICT ROW STATEMENT TRIGGER VIEW ALL - NOW IPTOKEN SEMI NONE PREV LINEAR IMPORT - METRIC TBNAME JOIN METRICS STABLE NULL INSERT INTO VALUES. + NOW IPTOKEN SEMI NONE PREV LINEAR IMPORT TBNAME JOIN STABLE NULL INSERT INTO VALUES. diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 2faaac2738f1ab24986bdca05eb3c961d170e9bd..a59f900459491e04f490897bd95250e442a3737c 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -156,7 +156,7 @@ static STableIdInfo createTableIdInfo(STableQueryInfo* pTableQueryInfo); static void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream); static int32_t getNumOfScanTimes(SQuery* pQuery); -static bool isFixedOutputQuery(SQuery* pQuery); +static bool isFixedOutputQuery(SQueryRuntimeEnv *pRuntimeEnv); static SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime); static SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime); @@ -472,22 +472,41 @@ static SResultRow *doPrepareResultRowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SRes return getResultRow(pResultRowInfo, pResultRowInfo->curIndex); } +static void getInitialStartTimeWindow(SQuery* pQuery, TSKEY ts, STimeWindow* w) { + if (QUERY_IS_ASC_QUERY(pQuery)) { + getAlignQueryTimeWindow(pQuery, ts, ts, pQuery->window.ekey, w); + } else { + // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp + getAlignQueryTimeWindow(pQuery, ts, pQuery->window.ekey, ts, w); + + int64_t key = w->skey; + while(key < ts) { // moving towards end + if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') { + key = taosTimeAdd(key, pQuery->interval.sliding, pQuery->interval.slidingUnit, pQuery->precision); + } else { + key += pQuery->interval.sliding; + } + + if (key >= ts) { + break; + } + + w->skey = key; + } + } +} + // get the correct time window according to the handled timestamp static STimeWindow getActiveTimeWindow(SResultRowInfo * pResultRowInfo, int64_t ts, SQuery *pQuery) { STimeWindow w = {0}; if (pResultRowInfo->curIndex == -1) { // the first window, from the previous stored value - if (pResultRowInfo->prevSKey == TSKEY_INITIAL_VAL) { - if (QUERY_IS_ASC_QUERY(pQuery)) { - getAlignQueryTimeWindow(pQuery, ts, ts, pQuery->window.ekey, &w); - } else { // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp - getAlignQueryTimeWindow(pQuery, ts, pQuery->window.ekey, ts, &w); - } - - pResultRowInfo->prevSKey = w.skey; - } else { - w.skey = pResultRowInfo->prevSKey; - } + if (pResultRowInfo->prevSKey == TSKEY_INITIAL_VAL) { + getInitialStartTimeWindow(pQuery, ts, &w); + pResultRowInfo->prevSKey = w.skey; + } else { + w.skey = pResultRowInfo->prevSKey; + } if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') { w.ekey = taosTimeAdd(w.skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1; @@ -1825,7 +1844,7 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf if (pQuery->pExpr2 != NULL) { pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2); } - } else if (isFixedOutputQuery(pQuery)) { + } else if (isFixedOutputQuery(pRuntimeEnv)) { if (pQuery->stableQuery && !isTsCompQuery(pQuery)) { pRuntimeEnv->proot = createMultiTableAggOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput); @@ -1880,7 +1899,7 @@ static void doFreeQueryHandle(SQueryRuntimeEnv* pRuntimeEnv) { pRuntimeEnv->pQueryHandle = NULL; SMemRef* pMemRef = &pQuery->memRef; - assert(pMemRef->ref == 0 && pMemRef->imem == NULL && pMemRef->mem == NULL); + assert(pMemRef->ref == 0 && pMemRef->snapshot.imem == NULL && pMemRef->snapshot.mem == NULL); } static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) { @@ -1947,11 +1966,17 @@ bool isQueryKilled(SQInfo *pQInfo) { void setQueryKilled(SQInfo *pQInfo) { pQInfo->code = TSDB_CODE_TSC_QUERY_CANCELLED;} -static bool isFixedOutputQuery(SQuery* pQuery) { +static bool isFixedOutputQuery(SQueryRuntimeEnv *pRuntimeEnv) { + SQuery* pQuery = pRuntimeEnv->pQuery; + if (QUERY_IS_INTERVAL_QUERY(pQuery)) { return false; } + if (pRuntimeEnv->pUdfInfo && pRuntimeEnv->pUdfInfo->funcType == TSDB_UDF_TYPE_AGGREGATE) { + return true; + } + // Note:top/bottom query is fixed output query if (pQuery->topBotQuery || pQuery->groupbyColumn || isTsCompQuery(pQuery)) { return true; @@ -2411,13 +2436,13 @@ static int32_t doTSJoinFilter(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key, bool asc } void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, - SSDataBlock* pBlock, STSBuf* pTsBuf, bool ascQuery) { + SSDataBlock* pBlock, bool ascQuery) { int32_t numOfRows = pBlock->info.rows; int8_t *p = calloc(numOfRows, sizeof(int8_t)); bool all = true; - if (pTsBuf != NULL) { + if (pRuntimeEnv->pTsBuf != NULL) { SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0); TSKEY* k = (TSKEY*) pColInfoData->pData; @@ -2438,6 +2463,9 @@ void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInf break; } } + + // save the cursor status + pRuntimeEnv->pQuery->current->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf); } else { for (int32_t i = 0; i < numOfRows; ++i) { bool qualified = false; @@ -2703,8 +2731,7 @@ int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTa doSetFilterColumnInfo(pQuery, pBlock); if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL) { - filterRowsInDataBlock(pRuntimeEnv, pQuery->pFilterInfo, pQuery->numOfFilterCols, pBlock, pRuntimeEnv->pTsBuf, - ascQuery); + filterRowsInDataBlock(pRuntimeEnv, pQuery->pFilterInfo, pQuery->numOfFilterCols, pBlock, ascQuery); } } @@ -2795,7 +2822,10 @@ static void doSetTagValueInParam(void* pTable, int32_t tagColId, tVariant *tag, } if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { - tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), type); + int32_t maxLen = bytes - VARSTR_HEADER_SIZE; + int32_t len = (varDataLen(val) > maxLen)? maxLen:varDataLen(val); + tVariantCreateFromBinary(tag, varDataVal(val), len, type); + //tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), type); } else { tVariantCreateFromBinary(tag, val, bytes, type); } @@ -3194,9 +3224,26 @@ void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResult setResultOutputBuf(pRuntimeEnv, buf, pCtx, numOfOutput, rowCellInfoOffset); for (int32_t j = 0; j < numOfOutput; ++j) { - aAggs[pCtx[j].functionId].xFinalize(&pCtx[j]); + if (pCtx[j].functionId < 0) { + int32_t output = 0; + char* buf = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo); + + if (pRuntimeEnv->pUdfInfo && pRuntimeEnv->pUdfInfo->funcs[TSDB_UDF_FUNC_FINALIZE]) { + (*(udfFinalizeFunc)pRuntimeEnv->pUdfInfo->funcs[TSDB_UDF_FUNC_FINALIZE])(pCtx[j].pInput, pCtx[j].inputType, pCtx[j].size, pCtx[j].ptsList, pCtx[j].pOutput, + pCtx[j].ptsOutputBuf, &output, buf); + } + + // set the output value exist + pCtx[j].resultInfo->numOfRes = output; + if (output > 0) { + pCtx[j].resultInfo->hasResult = DATA_SET_FLAG; + } + } else { + aAggs[pCtx[j].functionId].xFinalize(&pCtx[j]); + } } + /* * set the number of output results for group by normal columns, the number of output rows usually is 1 except * the top and bottom query @@ -3206,7 +3253,23 @@ void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResult } else { for (int32_t j = 0; j < numOfOutput; ++j) { - aAggs[pCtx[j].functionId].xFinalize(&pCtx[j]); + if (pCtx[j].functionId < 0) { + int32_t output = 0; + char* buf = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo); + + if (pRuntimeEnv->pUdfInfo && pRuntimeEnv->pUdfInfo->funcs[TSDB_UDF_FUNC_FINALIZE]) { + (*(udfFinalizeFunc)pRuntimeEnv->pUdfInfo->funcs[TSDB_UDF_FUNC_FINALIZE])(pCtx[j].pInput, pCtx[j].inputType, pCtx[j].size, pCtx[j].ptsList, pCtx[j].pOutput, + pCtx[j].ptsOutputBuf, &output, buf); + } + + // set the output value exist + pCtx[j].resultInfo->numOfRes = output; + if (output > 0) { + pCtx[j].resultInfo->hasResult = DATA_SET_FLAG; + } + } else { + aAggs[pCtx[j].functionId].xFinalize(&pCtx[j]); + } } } } @@ -3942,7 +4005,7 @@ static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) && (cond.order == TSDB_ORDER_ASC) && (!QUERY_IS_INTERVAL_QUERY(pQuery)) && (!isGroupbyColumn(pQuery->pGroupbyExpr)) - && (!isFixedOutputQuery(pQuery)) + && (!isFixedOutputQuery(pRuntimeEnv)) ) { SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0); STableQueryInfo* pCheckInfo = taosArrayGetP(pa, 0); @@ -4224,8 +4287,10 @@ static SSDataBlock* doTableScan(void* param) { assert(ret); } - pResultRowInfo->curIndex = 0; - pResultRowInfo->prevSKey = pResultRowInfo->pResult[0]->win.skey; + if (pResultRowInfo->size > 0) { + pResultRowInfo->curIndex = 0; + pResultRowInfo->prevSKey = pResultRowInfo->pResult[0]->win.skey; + } qDebug("QInfo:%p start to repeat scan data blocks due to query func required, qrange:%" PRId64 "-%" PRId64, pRuntimeEnv->qinfo, cond.twindow.skey, cond.twindow.ekey); @@ -4639,7 +4704,7 @@ static SSDataBlock* doOffset(void* param) { if (pRuntimeEnv->currentOffset == 0) { return pBlock; - } else if (pRuntimeEnv->currentOffset > pBlock->info.rows) { + } else if (pRuntimeEnv->currentOffset >= pBlock->info.rows) { pRuntimeEnv->currentOffset -= pBlock->info.rows; } else { int32_t remain = (int32_t)(pBlock->info.rows - pRuntimeEnv->currentOffset); @@ -5819,6 +5884,9 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { param->pUdfInfo->name = strndup(name->data, name->len); pMsg += varDataTLen(name); + param->pUdfInfo->funcType = htonl(*(int32_t*)pMsg); + pMsg += sizeof(int32_t); + param->pUdfInfo->content = malloc(pQueryMsg->udfContentLen); memcpy(param->pUdfInfo->content, pMsg, pQueryMsg->udfContentLen); @@ -5915,6 +5983,9 @@ static char* getUdfFuncName(char* name, int type) { case TSDB_UDF_FUNC_INIT: sprintf(funcname, "%s_init", name); break; + case TSDB_UDF_FUNC_FINALIZE: + sprintf(funcname, "%s_finalize", name); + break; default: assert(0); break; @@ -5952,6 +6023,10 @@ static int32_t flushUdfContentToDisk(SUdfInfo* pUdfInfo) { } pUdfInfo->funcs[TSDB_UDF_FUNC_INIT] = taosLoadSym(pUdfInfo->handle, getUdfFuncName(pUdfInfo->name, TSDB_UDF_FUNC_INIT)); + + if (pUdfInfo->funcType == TSDB_UDF_TYPE_AGGREGATE) { + pUdfInfo->funcs[TSDB_UDF_FUNC_FINALIZE] = taosLoadSym(pUdfInfo->handle, getUdfFuncName(pUdfInfo->name, TSDB_UDF_FUNC_FINALIZE)); + } return TSDB_CODE_SUCCESS; } @@ -6705,8 +6780,15 @@ static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type return; } - if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { - memcpy(output, val, varDataTLen(val)); + if (IS_VAR_DATA_TYPE(type)) { + // Binary data overflows for sort of unknown reasons. Let trim the overflow data + if (varDataTLen(val) > bytes) { + int32_t len = bytes - VARSTR_HEADER_SIZE; // remain available space + memcpy(varDataVal(output), varDataVal(val), len); + varDataSetLen(output, len); + } else { + varDataCopy(output, val); + } } else { memcpy(output, val, bytes); } diff --git a/src/query/src/qParserImpl.c b/src/query/src/qSqlParser.c similarity index 77% rename from src/query/src/qParserImpl.c rename to src/query/src/qSqlParser.c index 891084f642c4d18f27d3eebf5ac56b475dc460b5..ff2b3272af3b20a9d876a3f346ec95f46965d969 100644 --- a/src/query/src/qParserImpl.c +++ b/src/query/src/qSqlParser.c @@ -23,7 +23,7 @@ #include "ttokendef.h" #include "tutil.h" -SSqlInfo qSQLParse(const char *pStr) { +SSqlInfo qSqlParse(const char *pStr) { void *pParser = ParseAlloc(malloc); SSqlInfo sqlInfo = {0}; @@ -80,53 +80,48 @@ abort_parse: return sqlInfo; } -tSQLExprList *tSqlExprListAppend(tSQLExprList *pList, tSQLExpr *pNode, SStrToken *pDistinct, SStrToken *pToken) { +SArray *tSqlExprListAppend(SArray *pList, tSqlExpr *pNode, SStrToken *pDistinct, SStrToken *pToken) { if (pList == NULL) { - pList = calloc(1, sizeof(tSQLExprList)); + pList = taosArrayInit(4, sizeof(tSqlExprItem)); } - if (pList->nAlloc <= pList->nExpr) { - pList->nAlloc = (pList->nAlloc << 1u) + 4; - pList->a = realloc(pList->a, pList->nAlloc * sizeof(pList->a[0])); - if (pList->a == 0) { - pList->nExpr = pList->nAlloc = 0; - return pList; - } - } - assert(pList->a != 0); - if (pNode || pToken) { - struct tSqlExprItem *pItem = &pList->a[pList->nExpr++]; - memset(pItem, 0, sizeof(*pItem)); - pItem->pNode = pNode; + struct tSqlExprItem item = {0}; + + item.pNode = pNode; + item.distinct = (pDistinct != NULL); + if (pToken) { // set the as clause - pItem->aliasName = malloc(pToken->n + 1); - strncpy(pItem->aliasName, pToken->z, pToken->n); - pItem->aliasName[pToken->n] = 0; + item.aliasName = malloc(pToken->n + 1); + strncpy(item.aliasName, pToken->z, pToken->n); + item.aliasName[pToken->n] = 0; - strdequote(pItem->aliasName); + strdequote(item.aliasName); } - pItem->distinct = (pDistinct != NULL); + + taosArrayPush(pList, &item); } + return pList; } -void tSqlExprListDestroy(tSQLExprList *pList) { - if (pList == NULL) return; +static void freeExprElem(void* item) { + tSqlExprItem* exprItem = item; - for (int32_t i = 0; i < pList->nExpr; ++i) { - if (pList->a[i].aliasName != NULL) { - free(pList->a[i].aliasName); - } - tSqlExprDestroy(pList->a[i].pNode); + tfree(exprItem->aliasName); + tSqlExprDestroy(exprItem->pNode); +} + +void tSqlExprListDestroy(SArray *pList) { + if (pList == NULL) { + return; } - free(pList->a); - free(pList); + taosArrayDestroyEx(pList, freeExprElem); } -tSQLExpr *tSqlExprIdValueCreate(SStrToken *pToken, int32_t optrType) { - tSQLExpr *pSqlExpr = calloc(1, sizeof(tSQLExpr)); +tSqlExpr *tSqlExprCreateIdValue(SStrToken *pToken, int32_t optrType) { + tSqlExpr *pSqlExpr = calloc(1, sizeof(tSqlExpr)); if (pToken != NULL) { pSqlExpr->token = *pToken; @@ -171,15 +166,15 @@ tSQLExpr *tSqlExprIdValueCreate(SStrToken *pToken, int32_t optrType) { * pList is the parameters for function with id(optType) * function name is denoted by pFunctionToken */ -tSQLExpr *tSqlExprCreateFunction(tSQLExprList *pList, SStrToken *pFuncToken, SStrToken *endToken, int32_t optType) { +tSqlExpr *tSqlExprCreateFunction(SArray *pParam, SStrToken *pFuncToken, SStrToken *endToken, int32_t optType) { if (pFuncToken == NULL) { return NULL; } - tSQLExpr *pExpr = calloc(1, sizeof(tSQLExpr)); + tSqlExpr *pExpr = calloc(1, sizeof(tSqlExpr)); pExpr->tokenId = optType; pExpr->type = SQL_NODE_SQLFUNCTION; - pExpr->pParam = pList; + pExpr->pParam = pParam; int32_t len = (int32_t)((endToken->z + endToken->n) - pFuncToken->z); pExpr->operand = (*pFuncToken); @@ -193,14 +188,14 @@ tSQLExpr *tSqlExprCreateFunction(tSQLExprList *pList, SStrToken *pFuncToken, SSt /* * create binary expression in this procedure - * if the expr is arithmetic, calculate the result and set it to tSQLExpr Object + * if the expr is arithmetic, calculate the result and set it to tSqlExpr Object */ -tSQLExpr *tSqlExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType) { - tSQLExpr *pExpr = calloc(1, sizeof(tSQLExpr)); +tSqlExpr *tSqlExprCreate(tSqlExpr *pLeft, tSqlExpr *pRight, int32_t optrType) { + tSqlExpr *pExpr = calloc(1, sizeof(tSqlExpr)); pExpr->type = SQL_NODE_EXPR; if (pLeft != NULL && pRight != NULL && (optrType != TK_IN)) { - char* endPos = pRight->token.z + pRight->token.n; + char* endPos = pRight->token.z + pRight->token.n; pExpr->token.z = pLeft->token.z; pExpr->token.n = (uint32_t)(endPos - pExpr->token.z); pExpr->token.type = pLeft->token.type; @@ -291,9 +286,9 @@ tSQLExpr *tSqlExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType) { pExpr->tokenId = optrType; pExpr->pLeft = pLeft; - tSQLExpr *pRSub = calloc(1, sizeof(tSQLExpr)); + tSqlExpr *pRSub = calloc(1, sizeof(tSqlExpr)); pRSub->tokenId = TK_SET; // TODO refactor ..... - pRSub->pParam = (tSQLExprList *)pRight; + pRSub->pParam = (SArray *)pRight; pExpr->pRight = pRSub; } else { @@ -301,7 +296,7 @@ tSQLExpr *tSqlExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType) { pExpr->pLeft = pLeft; if (pLeft != NULL && pRight == NULL) { - pRight = calloc(1, sizeof(tSQLExpr)); + pRight = calloc(1, sizeof(tSqlExpr)); } pExpr->pRight = pRight; @@ -310,10 +305,8 @@ tSQLExpr *tSqlExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType) { return pExpr; } - - -tSQLExpr *tSqlExprClone(tSQLExpr *pSrc) { - tSQLExpr *pExpr = calloc(1, sizeof(tSQLExpr)); +tSqlExpr *tSqlExprClone(tSqlExpr *pSrc) { + tSqlExpr *pExpr = calloc(1, sizeof(tSqlExpr)); memcpy(pExpr, pSrc, sizeof(*pSrc)); @@ -327,12 +320,51 @@ tSQLExpr *tSqlExprClone(tSQLExpr *pSrc) { //we don't clone pParam now because clone is only used for between/and assert(pSrc->pParam == NULL); - return pExpr; } +void tSqlExprCompact(tSqlExpr** pExpr) { + if (*pExpr == NULL || tSqlExprIsParentOfLeaf(*pExpr)) { + return; + } + + if ((*pExpr)->pLeft) { + tSqlExprCompact(&(*pExpr)->pLeft); + } + + if ((*pExpr)->pRight) { + tSqlExprCompact(&(*pExpr)->pRight); + } -void tSqlExprNodeDestroy(tSQLExpr *pExpr) { + if ((*pExpr)->pLeft == NULL && (*pExpr)->pRight == NULL && ((*pExpr)->tokenId == TK_OR || (*pExpr)->tokenId == TK_AND)) { + tSqlExprDestroy(*pExpr); + *pExpr = NULL; + } else if ((*pExpr)->pLeft == NULL && (*pExpr)->pRight != NULL) { + tSqlExpr* tmpPtr = (*pExpr)->pRight; + (*pExpr)->pRight = NULL; + + tSqlExprDestroy(*pExpr); + (*pExpr) = tmpPtr; + } else if ((*pExpr)->pRight == NULL && (*pExpr)->pLeft != NULL) { + tSqlExpr* tmpPtr = (*pExpr)->pLeft; + (*pExpr)->pLeft = NULL; + + tSqlExprDestroy(*pExpr); + (*pExpr) = tmpPtr; + } +} + +bool tSqlExprIsLeaf(tSqlExpr* pExpr) { + return (pExpr->pRight == NULL && pExpr->pLeft == NULL) && + (pExpr->tokenId == 0 || pExpr->tokenId == TK_ID || (pExpr->tokenId >= TK_BOOL && pExpr->tokenId <= TK_NCHAR) || pExpr->tokenId == TK_SET); +} + +bool tSqlExprIsParentOfLeaf(tSqlExpr* pExpr) { + return (pExpr->pLeft != NULL && pExpr->pRight != NULL) && + (tSqlExprIsLeaf(pExpr->pLeft) && tSqlExprIsLeaf(pExpr->pRight)); +} + +static void doDestroySqlExprNode(tSqlExpr *pExpr) { if (pExpr == NULL) { return; } @@ -342,11 +374,10 @@ void tSqlExprNodeDestroy(tSQLExpr *pExpr) { } tSqlExprListDestroy(pExpr->pParam); - free(pExpr); } -void tSqlExprDestroy(tSQLExpr *pExpr) { +void tSqlExprDestroy(tSqlExpr *pExpr) { if (pExpr == NULL) { return; } @@ -355,7 +386,8 @@ void tSqlExprDestroy(tSQLExpr *pExpr) { pExpr->pLeft = NULL; tSqlExprDestroy(pExpr->pRight); pExpr->pRight = NULL; - tSqlExprNodeDestroy(pExpr); + + doDestroySqlExprNode(pExpr); } SArray *tVariantListAppendToken(SArray *pList, SStrToken *pToken, uint8_t order) { @@ -411,13 +443,59 @@ SArray *tVariantListInsert(SArray *pList, tVariant *pVar, uint8_t sortOrder, int return pList; } -void setDbName(SStrToken *pCpxName, SStrToken *pDb) { +SFromInfo *setTableNameList(SFromInfo* pFromInfo, SStrToken *pName, SStrToken* pAlias) { + if (pFromInfo == NULL) { + pFromInfo = calloc(1, sizeof(SFromInfo)); + pFromInfo->tableList = taosArrayInit(4, sizeof(STableNamePair)); + } + + pFromInfo->type = SQL_NODE_FROM_NAMELIST; + STableNamePair p = {.name = *pName}; + if (pAlias != NULL) { + p.aliasName = *pAlias; + } else { + TPARSER_SET_NONE_TOKEN(p.aliasName); + } + + taosArrayPush(pFromInfo->tableList, &p); + + return pFromInfo; +} + +SFromInfo *setSubquery(SFromInfo* pFromInfo, SQuerySqlNode* pSqlNode) { + if (pFromInfo == NULL) { + pFromInfo = calloc(1, sizeof(SFromInfo)); + } + + pFromInfo->type = SQL_NODE_FROM_SUBQUERY; + pFromInfo->pNode->pClause[pFromInfo->pNode->numOfClause - 1] = pSqlNode; + + return pFromInfo; +} + +void* destroyFromInfo(SFromInfo* pFromInfo) { + if (pFromInfo == NULL) { + return NULL; + } + + if (pFromInfo->type == SQL_NODE_FROM_NAMELIST) { + taosArrayDestroy(pFromInfo->tableList); + } else { + destroyAllSelectClause(pFromInfo->pNode); + } + + tfree(pFromInfo); + return NULL; +} + + +void tSetDbName(SStrToken *pCpxName, SStrToken *pDb) { pCpxName->type = pDb->type; pCpxName->z = pDb->z; pCpxName->n = pDb->n; } -void tSqlSetColumnInfo(TAOS_FIELD *pField, SStrToken *pName, TAOS_FIELD *pType) { +void tSetColumnInfo(TAOS_FIELD *pField, SStrToken *pName, TAOS_FIELD *pType) { int32_t maxLen = sizeof(pField->name) / sizeof(pField->name[0]); // truncate the column name @@ -485,7 +563,7 @@ static int32_t tryParseNameTwoParts(SStrToken *type) { } } -void tSqlSetColumnType(TAOS_FIELD *pField, SStrToken *type) { +void tSetColumnType(TAOS_FIELD *pField, SStrToken *type) { // set the field type invalid pField->type = -1; pField->name[0] = 0; @@ -550,43 +628,60 @@ void tSqlSetColumnType(TAOS_FIELD *pField, SStrToken *type) { /* * extract the select info out of sql string */ -SQuerySQL *tSetQuerySqlNode(SStrToken *pSelectToken, tSQLExprList *pSelection, SArray *pFrom, tSQLExpr *pWhere, - SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval, SSessionWindowVal *pSession, - SStrToken *pSliding, SArray *pFill, SLimitVal *pLimit, SLimitVal *pGLimit) { - assert(pSelection != NULL); +SQuerySqlNode *tSetQuerySqlNode(SStrToken *pSelectToken, SArray *pSelectList, SFromInfo *pFrom, tSqlExpr *pWhere, + SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval, + SSessionWindowVal *pSession, SStrToken *pSliding, SArray *pFill, SLimitVal *pLimit, + SLimitVal *psLimit) { + assert(pSelectList != NULL); + + SQuerySqlNode *pSqlNode = calloc(1, sizeof(SQuerySqlNode)); - SQuerySQL *pQuery = calloc(1, sizeof(SQuerySQL)); - pQuery->selectToken = *pSelectToken; - pQuery->selectToken.n = (uint32_t)strlen(pQuery->selectToken.z); // all later sql string are belonged to the stream sql + // all later sql string are belonged to the stream sql + pSqlNode->sqlstr = *pSelectToken; + pSqlNode->sqlstr.n = (uint32_t)strlen(pSqlNode->sqlstr.z); - pQuery->pSelection = pSelection; - pQuery->from = pFrom; - pQuery->pGroupby = pGroupby; - pQuery->pSortOrder = pSortOrder; - pQuery->pWhere = pWhere; + pSqlNode->pSelectList = pSelectList; + pSqlNode->from = pFrom; + pSqlNode->pGroupby = pGroupby; + pSqlNode->pSortOrder = pSortOrder; + pSqlNode->pWhere = pWhere; + pSqlNode->fillType = pFill; if (pLimit != NULL) { - pQuery->limit = *pLimit; + pSqlNode->limit = *pLimit; + } else { + pSqlNode->limit.limit = -1; + pSqlNode->limit.offset = 0; } - if (pGLimit != NULL) { - pQuery->slimit = *pGLimit; + if (psLimit != NULL) { + pSqlNode->slimit = *psLimit; + } else { + pSqlNode->slimit.limit = -1; + pSqlNode->slimit.offset = 0; } if (pInterval != NULL) { - pQuery->interval = *pInterval; + pSqlNode->interval = *pInterval; + } else { + TPARSER_SET_NONE_TOKEN(pSqlNode->interval.interval); + TPARSER_SET_NONE_TOKEN(pSqlNode->interval.offset); } if (pSliding != NULL) { - pQuery->sliding = *pSliding; + pSqlNode->sliding = *pSliding; + } else { + TPARSER_SET_NONE_TOKEN(pSqlNode->sliding); } if (pSession != NULL) { - pQuery->sessionVal = *pSession; + pSqlNode->sessionVal = *pSession; + } else { + TPARSER_SET_NONE_TOKEN(pSqlNode->sessionVal.gap); + TPARSER_SET_NONE_TOKEN(pSqlNode->sessionVal.col); } - pQuery->fillType = pFill; - return pQuery; + return pSqlNode; } static void freeVariant(void *pItem) { @@ -602,14 +697,14 @@ void freeCreateTableInfo(void* p) { tfree(pInfo->tagdata.data); } -void doDestroyQuerySql(SQuerySQL *pQuerySql) { +void destroyQuerySqlNode(SQuerySqlNode *pQuerySql) { if (pQuerySql == NULL) { return; } - tSqlExprListDestroy(pQuerySql->pSelection); + tSqlExprListDestroy(pQuerySql->pSelectList); - pQuerySql->pSelection = NULL; + pQuerySql->pSelectList = NULL; tSqlExprDestroy(pQuerySql->pWhere); pQuerySql->pWhere = NULL; @@ -620,8 +715,7 @@ void doDestroyQuerySql(SQuerySQL *pQuerySql) { taosArrayDestroyEx(pQuerySql->pGroupby, freeVariant); pQuerySql->pGroupby = NULL; - taosArrayDestroyEx(pQuerySql->from, freeVariant); - pQuerySql->from = NULL; + pQuerySql->from = destroyFromInfo(pQuerySql->from); taosArrayDestroyEx(pQuerySql->fillType, freeVariant); pQuerySql->fillType = NULL; @@ -635,15 +729,15 @@ void destroyAllSelectClause(SSubclauseInfo *pClause) { } for(int32_t i = 0; i < pClause->numOfClause; ++i) { - SQuerySQL *pQuerySql = pClause->pClause[i]; - doDestroyQuerySql(pQuerySql); + SQuerySqlNode *pQuerySql = pClause->pClause[i]; + destroyQuerySqlNode(pQuerySql); } tfree(pClause->pClause); } -SCreateTableSQL *tSetCreateSqlElems(SArray *pCols, SArray *pTags, SQuerySQL *pSelect, int32_t type) { - SCreateTableSQL *pCreate = calloc(1, sizeof(SCreateTableSQL)); +SCreateTableSql *tSetCreateTableInfo(SArray *pCols, SArray *pTags, SQuerySqlNode *pSelect, int32_t type) { + SCreateTableSql *pCreate = calloc(1, sizeof(SCreateTableSql)); switch (type) { case TSQL_CREATE_TABLE: { @@ -687,7 +781,7 @@ SCreatedTableInfo createNewChildTableInfo(SStrToken *pTableName, SArray *pTagNam return info; } -SAlterTableInfo *tAlterTableSqlElems(SStrToken *pTableName, SArray *pCols, SArray *pVals, int32_t type, int16_t tableType) { +SAlterTableInfo *tSetAlterTableInfo(SStrToken *pTableName, SArray *pCols, SArray *pVals, int32_t type, int16_t tableType) { SAlterTableInfo *pAlterTable = calloc(1, sizeof(SAlterTableInfo)); pAlterTable->name = *pTableName; @@ -709,8 +803,8 @@ SAlterTableInfo *tAlterTableSqlElems(SStrToken *pTableName, SArray *pCols, SArra return pAlterTable; } -void* destroyCreateTableSql(SCreateTableSQL* pCreate) { - doDestroyQuerySql(pCreate->pSelect); +void* destroyCreateTableSql(SCreateTableSql* pCreate) { + destroyQuerySqlNode(pCreate->pSelect); taosArrayDestroy(pCreate->colInfo.pColumns); taosArrayDestroy(pCreate->colInfo.pTagColumns); @@ -757,7 +851,7 @@ SSubclauseInfo* setSubclause(SSubclauseInfo* pSubclause, void *pSqlExprInfo) { return pSubclause; } - pSubclause->pClause = (SQuerySQL**) tmp; + pSubclause->pClause = (SQuerySqlNode**) tmp; pSubclause->pClause[newSize - 1] = pSqlExprInfo; pSubclause->numOfClause++; @@ -765,7 +859,7 @@ SSubclauseInfo* setSubclause(SSubclauseInfo* pSubclause, void *pSqlExprInfo) { return pSubclause; } -SSqlInfo*setSqlInfo(SSqlInfo *pInfo, void *pSqlExprInfo, SStrToken *pTableName, int32_t type) { +SSqlInfo* setSqlInfo(SSqlInfo *pInfo, void *pSqlExprInfo, SStrToken *pTableName, int32_t type) { pInfo->type = type; if (type == TSDB_SQL_SELECT) { @@ -788,7 +882,7 @@ SSubclauseInfo* appendSelectClause(SSubclauseInfo *pQueryInfo, void *pSubclause) return pQueryInfo; } - pQueryInfo->pClause = (SQuerySQL**) tmp; + pQueryInfo->pClause = (SQuerySqlNode**) tmp; pQueryInfo->pClause[pQueryInfo->numOfClause++] = pSubclause; return pQueryInfo; @@ -799,7 +893,7 @@ void setCreatedTableName(SSqlInfo *pInfo, SStrToken *pTableNameToken, SStrToken pInfo->pCreateTableInfo->existCheck = (pIfNotExists->n != 0); } -void setDCLSQLElems(SSqlInfo *pInfo, int32_t type, int32_t nParam, ...) { +void setDCLSqlElems(SSqlInfo *pInfo, int32_t type, int32_t nParam, ...) { pInfo->type = type; if (nParam == 0) { return; @@ -881,7 +975,7 @@ void setCreateDbInfo(SSqlInfo *pInfo, int32_t type, SStrToken *pToken, SCreateDb pInfo->pMiscInfo->dbOpt.ignoreExists = pIgExists->n; // sql.y has: ifnotexists(X) ::= IF NOT EXISTS. {X.n = 1;} } -void setCreateFuncInfo(SSqlInfo *pInfo, int32_t type, SStrToken *pName, SStrToken *pPath, TAOS_FIELD *output) { +void setCreateFuncInfo(SSqlInfo *pInfo, int32_t type, SStrToken *pName, SStrToken *pPath, TAOS_FIELD *output, int32_t funcType) { pInfo->type = type; if (pInfo->pMiscInfo == NULL) { pInfo->pMiscInfo = calloc(1, sizeof(SMiscInfo)); @@ -890,6 +984,7 @@ void setCreateFuncInfo(SSqlInfo *pInfo, int32_t type, SStrToken *pName, SStrToke pInfo->pMiscInfo->funcOpt.name = *pName; pInfo->pMiscInfo->funcOpt.path = *pPath; pInfo->pMiscInfo->funcOpt.output = *output; + pInfo->pMiscInfo->funcOpt.type = funcType; } diff --git a/src/query/src/qTokenizer.c b/src/query/src/qTokenizer.c index 4adb91326586c5fba713928511934ece9a04dbb3..eaaffec4de277270da3d8471f81568001dcd9a19 100644 --- a/src/query/src/qTokenizer.c +++ b/src/query/src/qTokenizer.c @@ -206,10 +206,8 @@ static SKeyword keywordTable[] = { {"PREV", TK_PREV}, {"LINEAR", TK_LINEAR}, {"IMPORT", TK_IMPORT}, - {"METRIC", TK_METRIC}, {"TBNAME", TK_TBNAME}, {"JOIN", TK_JOIN}, - {"METRICS", TK_METRICS}, {"STABLE", TK_STABLE}, {"FILE", TK_FILE}, {"VNODES", TK_VNODES}, @@ -221,7 +219,8 @@ static SKeyword keywordTable[] = { {"TOPICS", TK_TOPICS}, {"FUNCTION", TK_FUNCTION}, {"FUNCTIONS", TK_FUNCTIONS}, - {"OUTPUTTYPE", TK_OUTPUTTYPE} + {"OUTPUTTYPE", TK_OUTPUTTYPE}, + {"AGGREGATE", TK_AGGREGATE} }; static const char isIdChar[] = { diff --git a/src/query/src/queryMain.c b/src/query/src/queryMain.c index 677737250598f7e3d1e2bfb2adf32cc190bdeef8..337af94c213673638513da6df1ed8d460edb2b7b 100644 --- a/src/query/src/queryMain.c +++ b/src/query/src/queryMain.c @@ -433,7 +433,7 @@ void qQueryMgmtNotifyClosed(void* pQMgmt) { } SQueryMgmt* pQueryMgmt = pQMgmt; - qDebug("vgId:%d, set querymgmt closed, wait for all queries cancelled", pQueryMgmt->vgId); + qInfo("vgId:%d, set querymgmt closed, wait for all queries cancelled", pQueryMgmt->vgId); pthread_mutex_lock(&pQueryMgmt->lock); pQueryMgmt->closed = true; @@ -448,7 +448,7 @@ void qQueryMgmtReOpen(void *pQMgmt) { } SQueryMgmt *pQueryMgmt = pQMgmt; - qDebug("vgId:%d, set querymgmt reopen", pQueryMgmt->vgId); + qInfo("vgId:%d, set querymgmt reopen", pQueryMgmt->vgId); pthread_mutex_lock(&pQueryMgmt->lock); pQueryMgmt->closed = false; diff --git a/src/query/src/sql.c b/src/query/src/sql.c index e3290272cdd7aaa2f9abe0b95d20a48abcd35fd8..a9258f88adfee7d3c9b7918c1045c7bcae3db933 100644 --- a/src/query/src/sql.c +++ b/src/query/src/sql.c @@ -100,28 +100,28 @@ #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int -#define YYNOCODE 266 +#define YYNOCODE 265 #define YYACTIONTYPE unsigned short int #define ParseTOKENTYPE SStrToken typedef union { int yyinit; ParseTOKENTYPE yy0; - SSubclauseInfo* yy21; - TAOS_FIELD yy27; - SCreateDbInfo yy114; - tSQLExpr* yy134; - tSQLExprList* yy178; - SCreateAcctInfo yy183; - SCreateTableSQL* yy190; - SCreatedTableInfo yy192; - SArray* yy193; - SQuerySQL* yy288; - int yy312; - SIntervalVal yy392; - tVariant yy442; - SSessionWindowVal yy447; - int64_t yy473; - SLimitVal yy482; + SLimitVal yy74; + SQuerySqlNode* yy110; + SCreateDbInfo yy122; + SSessionWindowVal yy139; + TAOS_FIELD yy153; + SSubclauseInfo* yy154; + int64_t yy179; + SCreateAcctInfo yy211; + tVariant yy216; + SFromInfo* yy232; + SArray* yy291; + int yy382; + SIntervalVal yy400; + SCreateTableSql* yy412; + tSqlExpr* yy436; + SCreatedTableInfo yy446; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 @@ -137,18 +137,18 @@ typedef union { #define ParseCTX_FETCH #define ParseCTX_STORE #define YYFALLBACK 1 -#define YYNSTATE 319 -#define YYNRULE 268 -#define YYNRULE_WITH_ACTION 268 -#define YYNTOKEN 191 -#define YY_MAX_SHIFT 318 -#define YY_MIN_SHIFTREDUCE 511 -#define YY_MAX_SHIFTREDUCE 778 -#define YY_ERROR_ACTION 779 -#define YY_ACCEPT_ACTION 780 -#define YY_NO_ACTION 781 -#define YY_MIN_REDUCE 782 -#define YY_MAX_REDUCE 1049 +#define YYNSTATE 325 +#define YYNRULE 269 +#define YYNRULE_WITH_ACTION 269 +#define YYNTOKEN 190 +#define YY_MAX_SHIFT 324 +#define YY_MIN_SHIFTREDUCE 518 +#define YY_MAX_SHIFTREDUCE 786 +#define YY_ERROR_ACTION 787 +#define YY_ACCEPT_ACTION 788 +#define YY_NO_ACTION 789 +#define YY_MIN_REDUCE 790 +#define YY_MAX_REDUCE 1058 /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) @@ -215,260 +215,266 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (675) +#define YY_ACTTAB_COUNT (693) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 953, 560, 184, 560, 205, 316, 79, 17, 70, 561, - /* 10 */ 80, 561, 1031, 48, 49, 142, 52, 53, 135, 72, - /* 20 */ 217, 42, 184, 51, 264, 56, 54, 58, 55, 265, - /* 30 */ 31, 212, 1032, 47, 46, 182, 184, 45, 44, 43, - /* 40 */ 916, 914, 915, 29, 918, 211, 1032, 512, 513, 514, - /* 50 */ 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, - /* 60 */ 525, 317, 950, 209, 234, 48, 49, 31, 52, 53, - /* 70 */ 142, 207, 217, 42, 928, 51, 264, 56, 54, 58, - /* 80 */ 55, 249, 984, 71, 259, 47, 46, 917, 931, 45, - /* 90 */ 44, 43, 48, 49, 925, 52, 53, 31, 302, 217, - /* 100 */ 42, 560, 51, 264, 56, 54, 58, 55, 220, 561, - /* 110 */ 31, 928, 47, 46, 24, 229, 45, 44, 43, 48, - /* 120 */ 50, 37, 52, 53, 841, 222, 217, 42, 742, 51, - /* 130 */ 264, 56, 54, 58, 55, 261, 223, 77, 221, 47, - /* 140 */ 46, 928, 224, 45, 44, 43, 49, 282, 52, 53, - /* 150 */ 931, 285, 217, 42, 928, 51, 264, 56, 54, 58, - /* 160 */ 55, 726, 315, 314, 127, 47, 46, 931, 282, 45, - /* 170 */ 44, 43, 23, 280, 311, 310, 279, 278, 277, 309, - /* 180 */ 276, 308, 307, 306, 275, 305, 304, 891, 83, 879, - /* 190 */ 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, - /* 200 */ 890, 892, 893, 52, 53, 18, 188, 217, 42, 312, - /* 210 */ 51, 264, 56, 54, 58, 55, 1028, 228, 1, 157, - /* 220 */ 47, 46, 919, 192, 45, 44, 43, 216, 739, 194, - /* 230 */ 732, 730, 735, 733, 931, 736, 118, 117, 193, 899, - /* 240 */ 216, 739, 897, 898, 730, 31, 733, 900, 736, 902, - /* 250 */ 903, 901, 226, 904, 905, 45, 44, 43, 153, 213, - /* 260 */ 214, 47, 46, 263, 1027, 45, 44, 43, 23, 24, - /* 270 */ 311, 310, 213, 214, 1026, 309, 37, 308, 307, 306, - /* 280 */ 201, 305, 304, 12, 780, 318, 286, 82, 230, 928, - /* 290 */ 142, 289, 288, 237, 56, 54, 58, 55, 243, 942, - /* 300 */ 241, 240, 47, 46, 640, 200, 45, 44, 43, 202, - /* 310 */ 5, 159, 3, 170, 206, 142, 34, 158, 87, 92, - /* 320 */ 85, 91, 31, 227, 664, 680, 284, 661, 31, 662, - /* 330 */ 942, 663, 292, 291, 57, 105, 829, 707, 708, 229, - /* 340 */ 31, 169, 302, 103, 108, 244, 738, 57, 929, 97, - /* 350 */ 107, 133, 113, 116, 106, 231, 232, 983, 37, 738, - /* 360 */ 110, 677, 737, 290, 215, 728, 928, 25, 838, 294, - /* 370 */ 177, 173, 928, 169, 186, 737, 175, 172, 122, 121, - /* 380 */ 120, 119, 78, 247, 927, 830, 672, 32, 692, 62, - /* 390 */ 169, 698, 137, 246, 699, 61, 759, 65, 20, 740, - /* 400 */ 19, 729, 731, 19, 734, 650, 684, 96, 95, 32, - /* 410 */ 63, 6, 187, 267, 652, 269, 66, 32, 61, 81, - /* 420 */ 651, 68, 28, 639, 61, 270, 14, 13, 189, 102, - /* 430 */ 101, 16, 15, 668, 183, 669, 665, 666, 190, 667, - /* 440 */ 115, 114, 132, 130, 191, 197, 198, 196, 181, 195, - /* 450 */ 185, 1041, 930, 994, 993, 134, 944, 218, 952, 990, - /* 460 */ 989, 219, 293, 40, 959, 961, 136, 140, 976, 975, - /* 470 */ 37, 245, 154, 131, 152, 924, 104, 155, 691, 250, - /* 480 */ 208, 926, 303, 148, 146, 144, 156, 842, 272, 273, - /* 490 */ 59, 274, 38, 252, 179, 35, 283, 67, 257, 262, - /* 500 */ 941, 64, 837, 1046, 93, 143, 1045, 145, 258, 1043, - /* 510 */ 160, 287, 1040, 99, 1039, 1037, 260, 161, 860, 36, - /* 520 */ 33, 39, 180, 826, 109, 824, 111, 112, 822, 821, - /* 530 */ 233, 171, 819, 818, 817, 816, 815, 814, 813, 174, - /* 540 */ 176, 810, 808, 806, 804, 802, 178, 256, 248, 73, - /* 550 */ 251, 74, 253, 254, 977, 41, 295, 296, 297, 298, - /* 560 */ 299, 300, 203, 301, 313, 225, 271, 778, 235, 236, - /* 570 */ 777, 239, 204, 88, 238, 199, 89, 776, 764, 242, - /* 580 */ 246, 674, 69, 8, 138, 266, 820, 693, 164, 123, - /* 590 */ 861, 124, 162, 163, 812, 165, 166, 168, 167, 125, - /* 600 */ 811, 895, 126, 803, 4, 2, 150, 147, 75, 149, - /* 610 */ 696, 151, 139, 210, 9, 76, 255, 907, 700, 141, - /* 620 */ 10, 84, 741, 26, 7, 27, 11, 21, 743, 22, - /* 630 */ 30, 268, 86, 603, 82, 599, 597, 596, 595, 592, - /* 640 */ 564, 281, 32, 94, 60, 90, 642, 641, 638, 587, - /* 650 */ 585, 577, 583, 579, 581, 575, 98, 573, 100, 606, - /* 660 */ 605, 604, 602, 601, 600, 598, 594, 593, 61, 562, - /* 670 */ 529, 527, 128, 782, 129, + /* 0 */ 961, 567, 187, 567, 208, 322, 926, 17, 70, 568, + /* 10 */ 83, 568, 1040, 49, 50, 146, 53, 54, 139, 185, + /* 20 */ 220, 43, 187, 52, 267, 57, 55, 59, 56, 191, + /* 30 */ 32, 215, 1041, 48, 47, 1037, 187, 46, 45, 44, + /* 40 */ 925, 923, 924, 29, 927, 214, 1041, 519, 520, 521, + /* 50 */ 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, + /* 60 */ 532, 323, 958, 212, 237, 49, 50, 32, 53, 54, + /* 70 */ 146, 209, 220, 43, 937, 52, 267, 57, 55, 59, + /* 80 */ 56, 252, 993, 71, 262, 48, 47, 288, 940, 46, + /* 90 */ 45, 44, 49, 50, 288, 53, 54, 32, 82, 220, + /* 100 */ 43, 567, 52, 267, 57, 55, 59, 56, 223, 568, + /* 110 */ 32, 937, 48, 47, 75, 308, 46, 45, 44, 49, + /* 120 */ 51, 38, 53, 54, 12, 225, 220, 43, 85, 52, + /* 130 */ 267, 57, 55, 59, 56, 264, 227, 79, 224, 48, + /* 140 */ 47, 937, 318, 46, 45, 44, 50, 1036, 53, 54, + /* 150 */ 940, 291, 220, 43, 937, 52, 267, 57, 55, 59, + /* 160 */ 56, 940, 734, 837, 146, 48, 47, 940, 172, 46, + /* 170 */ 45, 44, 86, 23, 286, 317, 316, 285, 284, 283, + /* 180 */ 315, 282, 314, 313, 312, 281, 311, 310, 900, 32, + /* 190 */ 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, + /* 200 */ 898, 899, 901, 902, 53, 54, 928, 934, 220, 43, + /* 210 */ 146, 52, 267, 57, 55, 59, 56, 1035, 32, 18, + /* 220 */ 952, 48, 47, 1, 160, 46, 45, 44, 219, 747, + /* 230 */ 292, 992, 738, 937, 741, 210, 744, 195, 219, 747, + /* 240 */ 846, 204, 738, 197, 741, 172, 744, 5, 162, 226, + /* 250 */ 123, 122, 196, 35, 161, 92, 97, 88, 96, 296, + /* 260 */ 216, 217, 937, 229, 266, 23, 205, 317, 316, 278, + /* 270 */ 216, 217, 315, 567, 314, 313, 312, 80, 311, 310, + /* 280 */ 240, 568, 908, 1050, 75, 906, 907, 244, 243, 81, + /* 290 */ 909, 38, 911, 912, 910, 232, 913, 914, 57, 55, + /* 300 */ 59, 56, 72, 231, 850, 687, 48, 47, 108, 113, + /* 310 */ 46, 45, 44, 246, 102, 112, 32, 118, 121, 111, + /* 320 */ 203, 180, 176, 788, 324, 115, 268, 178, 175, 127, + /* 330 */ 126, 125, 124, 648, 672, 230, 58, 669, 290, 670, + /* 340 */ 189, 671, 321, 320, 132, 32, 58, 232, 746, 48, + /* 350 */ 47, 3, 173, 46, 45, 44, 849, 300, 746, 232, + /* 360 */ 937, 298, 297, 218, 745, 234, 235, 684, 938, 952, + /* 370 */ 46, 45, 44, 24, 745, 233, 248, 110, 295, 294, + /* 380 */ 33, 25, 736, 838, 247, 308, 694, 691, 172, 936, + /* 390 */ 715, 716, 700, 250, 63, 706, 141, 707, 767, 62, + /* 400 */ 748, 20, 19, 740, 19, 743, 739, 190, 742, 66, + /* 410 */ 658, 6, 192, 270, 33, 64, 660, 33, 737, 272, + /* 420 */ 62, 28, 186, 84, 273, 659, 750, 193, 67, 62, + /* 430 */ 101, 100, 14, 13, 107, 106, 69, 194, 647, 16, + /* 440 */ 15, 676, 674, 677, 675, 120, 119, 673, 137, 135, + /* 450 */ 200, 201, 199, 184, 198, 188, 939, 1003, 1002, 221, + /* 460 */ 999, 998, 222, 299, 138, 41, 985, 960, 968, 984, + /* 470 */ 136, 970, 953, 249, 251, 73, 140, 144, 935, 156, + /* 480 */ 76, 253, 211, 255, 904, 157, 699, 933, 148, 158, + /* 490 */ 159, 950, 147, 149, 851, 265, 150, 275, 276, 60, + /* 500 */ 277, 279, 68, 280, 260, 65, 39, 182, 263, 261, + /* 510 */ 36, 289, 845, 1055, 98, 1054, 1052, 163, 293, 1049, + /* 520 */ 259, 254, 104, 1048, 1046, 257, 42, 164, 869, 37, + /* 530 */ 34, 40, 183, 834, 114, 832, 116, 117, 830, 829, + /* 540 */ 236, 174, 827, 826, 825, 824, 823, 822, 821, 177, + /* 550 */ 179, 818, 816, 814, 812, 810, 181, 309, 256, 109, + /* 560 */ 986, 301, 302, 303, 304, 305, 306, 307, 319, 206, + /* 570 */ 228, 786, 238, 239, 274, 785, 241, 242, 784, 772, + /* 580 */ 207, 93, 94, 202, 245, 250, 77, 8, 269, 74, + /* 590 */ 213, 679, 701, 142, 751, 271, 704, 166, 870, 167, + /* 600 */ 168, 165, 170, 169, 171, 828, 2, 128, 129, 820, + /* 610 */ 4, 130, 819, 143, 131, 811, 153, 151, 152, 154, + /* 620 */ 155, 916, 78, 258, 9, 708, 145, 10, 87, 749, + /* 630 */ 26, 7, 27, 11, 21, 22, 85, 30, 89, 91, + /* 640 */ 90, 31, 611, 607, 605, 604, 603, 600, 99, 571, + /* 650 */ 287, 33, 95, 61, 103, 650, 649, 646, 595, 593, + /* 660 */ 585, 591, 105, 587, 589, 583, 581, 614, 613, 612, + /* 670 */ 610, 609, 608, 606, 602, 601, 62, 569, 133, 536, + /* 680 */ 534, 790, 789, 789, 789, 789, 789, 789, 789, 789, + /* 690 */ 789, 789, 134, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 194, 1, 255, 1, 193, 194, 240, 255, 200, 9, - /* 10 */ 200, 9, 265, 13, 14, 194, 16, 17, 194, 253, - /* 20 */ 20, 21, 255, 23, 24, 25, 26, 27, 28, 15, - /* 30 */ 194, 264, 265, 33, 34, 255, 255, 37, 38, 39, - /* 40 */ 232, 231, 232, 233, 234, 264, 265, 45, 46, 47, + /* 0 */ 193, 1, 254, 1, 192, 193, 0, 254, 199, 9, + /* 10 */ 199, 9, 264, 13, 14, 193, 16, 17, 193, 254, + /* 20 */ 20, 21, 254, 23, 24, 25, 26, 27, 28, 254, + /* 30 */ 193, 263, 264, 33, 34, 254, 254, 37, 38, 39, + /* 40 */ 231, 230, 231, 232, 233, 263, 264, 45, 46, 47, /* 50 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 60 */ 58, 59, 256, 214, 62, 13, 14, 194, 16, 17, - /* 70 */ 194, 235, 20, 21, 238, 23, 24, 25, 26, 27, - /* 80 */ 28, 257, 261, 83, 263, 33, 34, 0, 239, 37, - /* 90 */ 38, 39, 13, 14, 194, 16, 17, 194, 85, 20, - /* 100 */ 21, 1, 23, 24, 25, 26, 27, 28, 235, 9, - /* 110 */ 194, 238, 33, 34, 108, 194, 37, 38, 39, 13, - /* 120 */ 14, 115, 16, 17, 203, 214, 20, 21, 114, 23, - /* 130 */ 24, 25, 26, 27, 28, 259, 236, 261, 235, 33, - /* 140 */ 34, 238, 214, 37, 38, 39, 14, 81, 16, 17, - /* 150 */ 239, 235, 20, 21, 238, 23, 24, 25, 26, 27, - /* 160 */ 28, 109, 65, 66, 67, 33, 34, 239, 81, 37, - /* 170 */ 38, 39, 92, 93, 94, 95, 96, 97, 98, 99, - /* 180 */ 100, 101, 102, 103, 104, 105, 106, 213, 200, 215, - /* 190 */ 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - /* 200 */ 226, 227, 228, 16, 17, 44, 255, 20, 21, 214, - /* 210 */ 23, 24, 25, 26, 27, 28, 255, 68, 201, 202, - /* 220 */ 33, 34, 234, 62, 37, 38, 39, 1, 2, 68, - /* 230 */ 5, 5, 7, 7, 239, 9, 75, 76, 77, 213, - /* 240 */ 1, 2, 216, 217, 5, 194, 7, 221, 9, 223, - /* 250 */ 224, 225, 68, 227, 228, 37, 38, 39, 83, 33, - /* 260 */ 34, 33, 34, 37, 255, 37, 38, 39, 92, 108, - /* 270 */ 94, 95, 33, 34, 255, 99, 115, 101, 102, 103, - /* 280 */ 255, 105, 106, 108, 191, 192, 235, 112, 139, 238, - /* 290 */ 194, 142, 143, 138, 25, 26, 27, 28, 137, 237, - /* 300 */ 145, 146, 33, 34, 5, 144, 37, 38, 39, 255, - /* 310 */ 63, 64, 197, 198, 252, 194, 69, 70, 71, 72, - /* 320 */ 73, 74, 194, 139, 2, 37, 142, 5, 194, 7, - /* 330 */ 237, 9, 33, 34, 108, 78, 199, 127, 128, 194, - /* 340 */ 194, 204, 85, 63, 64, 252, 120, 108, 203, 69, - /* 350 */ 70, 108, 72, 73, 74, 33, 34, 261, 115, 120, - /* 360 */ 80, 113, 136, 235, 61, 1, 238, 119, 199, 235, - /* 370 */ 63, 64, 238, 204, 255, 136, 69, 70, 71, 72, - /* 380 */ 73, 74, 261, 109, 238, 199, 109, 113, 109, 113, - /* 390 */ 204, 109, 113, 116, 109, 113, 109, 113, 113, 109, - /* 400 */ 113, 37, 5, 113, 7, 109, 118, 140, 141, 113, - /* 410 */ 134, 108, 255, 109, 109, 109, 132, 113, 113, 113, - /* 420 */ 109, 108, 108, 110, 113, 111, 140, 141, 255, 140, - /* 430 */ 141, 140, 141, 5, 255, 7, 114, 5, 255, 7, - /* 440 */ 78, 79, 63, 64, 255, 255, 255, 255, 255, 255, - /* 450 */ 255, 239, 239, 230, 230, 194, 237, 230, 194, 230, - /* 460 */ 230, 230, 230, 254, 194, 194, 194, 194, 262, 262, - /* 470 */ 115, 237, 194, 61, 241, 194, 91, 194, 120, 258, - /* 480 */ 258, 237, 107, 245, 247, 249, 194, 194, 194, 194, - /* 490 */ 130, 194, 194, 258, 194, 194, 194, 131, 258, 125, - /* 500 */ 251, 133, 194, 194, 194, 250, 194, 248, 124, 194, - /* 510 */ 194, 194, 194, 194, 194, 194, 129, 194, 194, 194, - /* 520 */ 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, - /* 530 */ 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, - /* 540 */ 194, 194, 194, 194, 194, 194, 194, 123, 195, 195, - /* 550 */ 121, 195, 195, 122, 195, 135, 90, 51, 87, 89, - /* 560 */ 55, 88, 195, 86, 81, 195, 195, 5, 147, 5, - /* 570 */ 5, 5, 195, 200, 147, 195, 200, 5, 93, 138, - /* 580 */ 116, 109, 117, 108, 108, 111, 195, 109, 206, 196, - /* 590 */ 212, 196, 211, 210, 195, 209, 207, 205, 208, 196, - /* 600 */ 195, 229, 196, 195, 197, 201, 243, 246, 113, 244, - /* 610 */ 109, 242, 113, 1, 126, 108, 108, 229, 109, 108, - /* 620 */ 126, 78, 109, 113, 108, 113, 108, 108, 114, 108, - /* 630 */ 84, 111, 83, 9, 112, 5, 5, 5, 5, 5, - /* 640 */ 82, 15, 113, 141, 16, 78, 5, 5, 109, 5, - /* 650 */ 5, 5, 5, 5, 5, 5, 141, 5, 141, 5, - /* 660 */ 5, 5, 5, 5, 5, 5, 5, 5, 113, 82, - /* 670 */ 61, 60, 21, 0, 21, 266, 266, 266, 266, 266, - /* 680 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 690 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 700 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 710 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 720 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 730 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 740 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 750 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 760 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 770 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 780 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 790 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 800 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 810 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 820 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 830 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 840 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 850 */ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, - /* 860 */ 266, 266, 266, 266, 266, 266, + /* 60 */ 58, 59, 255, 213, 62, 13, 14, 193, 16, 17, + /* 70 */ 193, 234, 20, 21, 237, 23, 24, 25, 26, 27, + /* 80 */ 28, 256, 260, 83, 262, 33, 34, 81, 238, 37, + /* 90 */ 38, 39, 13, 14, 81, 16, 17, 193, 83, 20, + /* 100 */ 21, 1, 23, 24, 25, 26, 27, 28, 234, 9, + /* 110 */ 193, 237, 33, 34, 109, 86, 37, 38, 39, 13, + /* 120 */ 14, 116, 16, 17, 109, 213, 20, 21, 113, 23, + /* 130 */ 24, 25, 26, 27, 28, 258, 213, 260, 234, 33, + /* 140 */ 34, 237, 213, 37, 38, 39, 14, 254, 16, 17, + /* 150 */ 238, 234, 20, 21, 237, 23, 24, 25, 26, 27, + /* 160 */ 28, 238, 110, 198, 193, 33, 34, 238, 203, 37, + /* 170 */ 38, 39, 199, 93, 94, 95, 96, 97, 98, 99, + /* 180 */ 100, 101, 102, 103, 104, 105, 106, 107, 212, 193, + /* 190 */ 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + /* 200 */ 224, 225, 226, 227, 16, 17, 233, 193, 20, 21, + /* 210 */ 193, 23, 24, 25, 26, 27, 28, 254, 193, 44, + /* 220 */ 236, 33, 34, 200, 201, 37, 38, 39, 1, 2, + /* 230 */ 234, 260, 5, 237, 7, 251, 9, 62, 1, 2, + /* 240 */ 198, 254, 5, 68, 7, 203, 9, 63, 64, 235, + /* 250 */ 75, 76, 77, 69, 70, 71, 72, 73, 74, 234, + /* 260 */ 33, 34, 237, 68, 37, 93, 254, 95, 96, 85, + /* 270 */ 33, 34, 100, 1, 102, 103, 104, 260, 106, 107, + /* 280 */ 139, 9, 212, 238, 109, 215, 216, 146, 147, 239, + /* 290 */ 220, 116, 222, 223, 224, 193, 226, 227, 25, 26, + /* 300 */ 27, 28, 252, 68, 202, 37, 33, 34, 63, 64, + /* 310 */ 37, 38, 39, 138, 69, 70, 193, 72, 73, 74, + /* 320 */ 145, 63, 64, 190, 191, 80, 15, 69, 70, 71, + /* 330 */ 72, 73, 74, 5, 2, 140, 109, 5, 143, 7, + /* 340 */ 254, 9, 65, 66, 67, 193, 109, 193, 121, 33, + /* 350 */ 34, 196, 197, 37, 38, 39, 202, 234, 121, 193, + /* 360 */ 237, 33, 34, 61, 137, 33, 34, 114, 202, 236, + /* 370 */ 37, 38, 39, 120, 137, 140, 110, 78, 143, 144, + /* 380 */ 114, 109, 1, 198, 251, 86, 110, 119, 203, 237, + /* 390 */ 128, 129, 110, 117, 114, 110, 114, 110, 110, 114, + /* 400 */ 110, 114, 114, 5, 114, 7, 5, 254, 7, 114, + /* 410 */ 110, 109, 254, 110, 114, 135, 110, 114, 37, 110, + /* 420 */ 114, 109, 254, 114, 112, 110, 115, 254, 133, 114, + /* 430 */ 141, 142, 141, 142, 141, 142, 109, 254, 111, 141, + /* 440 */ 142, 5, 5, 7, 7, 78, 79, 115, 63, 64, + /* 450 */ 254, 254, 254, 254, 254, 254, 238, 229, 229, 229, + /* 460 */ 229, 229, 229, 229, 193, 253, 261, 193, 193, 261, + /* 470 */ 61, 193, 236, 194, 236, 194, 193, 193, 236, 240, + /* 480 */ 194, 257, 257, 257, 228, 193, 121, 193, 248, 193, + /* 490 */ 193, 250, 249, 247, 193, 126, 246, 193, 193, 131, + /* 500 */ 193, 193, 132, 193, 257, 134, 193, 193, 130, 125, + /* 510 */ 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + /* 520 */ 124, 122, 193, 193, 193, 123, 136, 193, 193, 193, + /* 530 */ 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + /* 540 */ 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + /* 550 */ 193, 193, 193, 193, 193, 193, 193, 108, 194, 92, + /* 560 */ 194, 91, 51, 88, 90, 55, 89, 87, 81, 194, + /* 570 */ 194, 5, 148, 5, 194, 5, 148, 5, 5, 94, + /* 580 */ 194, 199, 199, 194, 139, 117, 114, 109, 112, 118, + /* 590 */ 1, 110, 110, 109, 115, 112, 110, 209, 211, 205, + /* 600 */ 208, 210, 207, 206, 204, 194, 200, 195, 195, 194, + /* 610 */ 196, 195, 194, 114, 195, 194, 243, 245, 244, 242, + /* 620 */ 241, 228, 109, 109, 127, 110, 109, 127, 78, 110, + /* 630 */ 114, 109, 114, 109, 109, 109, 113, 84, 83, 83, + /* 640 */ 71, 84, 9, 5, 5, 5, 5, 5, 142, 82, + /* 650 */ 15, 114, 78, 16, 142, 5, 5, 110, 5, 5, + /* 660 */ 5, 5, 142, 5, 5, 5, 5, 5, 5, 5, + /* 670 */ 5, 5, 5, 5, 5, 5, 114, 82, 21, 61, + /* 680 */ 60, 0, 265, 265, 265, 265, 265, 265, 265, 265, + /* 690 */ 265, 265, 21, 265, 265, 265, 265, 265, 265, 265, + /* 700 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 710 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 720 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 730 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 740 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 750 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 760 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 770 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 780 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 790 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 800 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 810 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 820 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 830 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 840 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 850 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 860 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 870 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, + /* 880 */ 265, 265, 265, }; -#define YY_SHIFT_COUNT (318) +#define YY_SHIFT_COUNT (324) #define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (673) +#define YY_SHIFT_MAX (681) static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 161, 80, 80, 176, 176, 66, 226, 239, 100, 100, - /* 10 */ 100, 100, 100, 100, 100, 100, 100, 0, 2, 239, - /* 20 */ 322, 322, 322, 322, 6, 100, 100, 100, 100, 87, - /* 30 */ 100, 100, 100, 257, 66, 13, 13, 675, 675, 675, - /* 40 */ 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - /* 50 */ 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - /* 60 */ 322, 322, 299, 299, 299, 299, 299, 299, 299, 243, - /* 70 */ 100, 100, 288, 100, 100, 100, 100, 210, 210, 248, - /* 80 */ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + /* 0 */ 175, 80, 80, 172, 172, 13, 227, 237, 100, 100, + /* 10 */ 100, 100, 100, 100, 100, 100, 100, 0, 2, 237, + /* 20 */ 332, 332, 332, 332, 272, 5, 100, 100, 100, 6, + /* 30 */ 100, 100, 100, 100, 299, 13, 29, 29, 693, 693, + /* 40 */ 693, 237, 237, 237, 237, 237, 237, 237, 237, 237, + /* 50 */ 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, + /* 60 */ 237, 332, 332, 328, 328, 328, 328, 328, 328, 328, + /* 70 */ 100, 100, 268, 100, 5, 5, 100, 100, 100, 262, + /* 80 */ 262, 253, 5, 100, 100, 100, 100, 100, 100, 100, /* 90 */ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, /* 100 */ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, /* 110 */ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, /* 120 */ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - /* 130 */ 100, 100, 100, 355, 412, 412, 412, 358, 358, 358, - /* 140 */ 412, 358, 412, 366, 368, 360, 374, 387, 384, 424, - /* 150 */ 431, 429, 420, 355, 412, 412, 412, 375, 66, 66, - /* 160 */ 412, 412, 385, 466, 506, 471, 470, 505, 473, 477, - /* 170 */ 375, 412, 483, 483, 412, 483, 412, 483, 412, 675, - /* 180 */ 675, 52, 79, 106, 79, 79, 132, 187, 269, 269, - /* 190 */ 269, 269, 247, 280, 307, 228, 228, 228, 228, 149, - /* 200 */ 155, 218, 218, 175, 184, 97, 277, 274, 279, 282, - /* 210 */ 285, 287, 290, 225, 397, 364, 303, 14, 276, 284, - /* 220 */ 296, 304, 305, 306, 311, 314, 267, 286, 289, 313, - /* 230 */ 291, 428, 432, 362, 379, 562, 421, 564, 565, 427, - /* 240 */ 566, 572, 485, 441, 464, 472, 465, 474, 475, 495, - /* 250 */ 478, 476, 501, 499, 507, 612, 508, 509, 511, 510, - /* 260 */ 488, 512, 494, 513, 516, 514, 518, 474, 519, 520, - /* 270 */ 521, 522, 543, 546, 549, 624, 630, 631, 632, 633, - /* 280 */ 634, 558, 626, 567, 502, 529, 529, 628, 515, 517, - /* 290 */ 529, 641, 642, 539, 529, 644, 645, 646, 647, 648, - /* 300 */ 649, 650, 652, 654, 655, 656, 657, 658, 659, 660, - /* 310 */ 661, 662, 555, 587, 651, 653, 609, 611, 673, + /* 130 */ 100, 100, 100, 100, 100, 100, 100, 100, 409, 409, + /* 140 */ 409, 365, 365, 365, 409, 365, 409, 370, 371, 368, + /* 150 */ 369, 378, 384, 396, 402, 399, 390, 409, 409, 409, + /* 160 */ 449, 13, 13, 409, 409, 467, 470, 511, 475, 474, + /* 170 */ 510, 477, 480, 449, 409, 487, 487, 409, 487, 409, + /* 180 */ 487, 409, 693, 693, 52, 79, 106, 79, 79, 132, + /* 190 */ 188, 273, 273, 273, 273, 184, 245, 258, 316, 316, + /* 200 */ 316, 316, 235, 141, 333, 333, 15, 195, 277, 266, + /* 210 */ 276, 282, 285, 287, 288, 290, 398, 401, 381, 302, + /* 220 */ 311, 280, 295, 300, 303, 306, 309, 315, 312, 289, + /* 230 */ 291, 293, 327, 298, 436, 437, 367, 385, 566, 424, + /* 240 */ 568, 570, 428, 572, 573, 485, 445, 468, 476, 478, + /* 250 */ 471, 481, 472, 482, 484, 486, 499, 513, 589, 514, + /* 260 */ 515, 517, 516, 497, 518, 500, 519, 522, 479, 524, + /* 270 */ 476, 525, 483, 526, 523, 550, 553, 555, 569, 557, + /* 280 */ 556, 633, 638, 639, 640, 641, 642, 567, 635, 574, + /* 290 */ 506, 537, 537, 637, 512, 520, 537, 650, 651, 547, + /* 300 */ 537, 653, 654, 655, 656, 658, 659, 660, 661, 662, + /* 310 */ 663, 664, 665, 666, 667, 668, 669, 670, 562, 595, + /* 320 */ 657, 671, 618, 620, 681, }; -#define YY_REDUCE_COUNT (180) -#define YY_REDUCE_MIN (-253) -#define YY_REDUCE_MAX (408) +#define YY_REDUCE_COUNT (183) +#define YY_REDUCE_MIN (-252) +#define YY_REDUCE_MAX (421) static const short yy_reduce_ofst[] = { - /* 0 */ 93, -26, -26, 26, 26, -190, -233, -219, -164, -179, - /* 10 */ -124, -127, -97, -84, 51, 128, 134, -194, -189, -253, - /* 20 */ -151, -89, -72, -5, 62, -176, 96, 121, -100, -12, - /* 30 */ -79, 145, 146, 137, -192, 169, 186, -234, 17, 115, - /* 40 */ -248, -220, -49, -39, 9, 19, 25, 54, 119, 157, - /* 50 */ 173, 179, 183, 189, 190, 191, 192, 193, 194, 195, - /* 60 */ 212, 213, 223, 224, 227, 229, 230, 231, 232, 219, - /* 70 */ 261, 264, 209, 270, 271, 272, 273, 206, 207, 233, - /* 80 */ 278, 281, 283, 292, 293, 294, 295, 297, 298, 300, - /* 90 */ 301, 302, 308, 309, 310, 312, 315, 316, 317, 318, - /* 100 */ 319, 320, 321, 323, 324, 325, 326, 327, 328, 329, - /* 110 */ 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, - /* 120 */ 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, - /* 130 */ 350, 351, 352, 234, 353, 354, 356, 221, 222, 235, - /* 140 */ 357, 240, 359, 249, 255, 236, 259, 237, 361, 238, - /* 150 */ 365, 363, 369, 244, 367, 370, 371, 372, 373, 376, - /* 160 */ 377, 380, 378, 381, 383, 382, 386, 389, 390, 392, - /* 170 */ 388, 391, 393, 395, 399, 403, 405, 406, 408, 404, - /* 180 */ 407, + /* 0 */ 133, -24, -24, 70, 70, -189, -232, -218, -163, -178, + /* 10 */ -123, -126, -96, -83, -4, 25, 123, -193, -188, -252, + /* 20 */ -150, -88, -77, -71, -175, -16, -29, 17, 14, -27, + /* 30 */ 102, 154, 166, 152, -35, -191, 42, 185, 50, 23, + /* 40 */ 155, -247, -235, -225, -219, -107, -37, -13, 12, 86, + /* 50 */ 153, 158, 168, 173, 183, 196, 197, 198, 199, 200, + /* 60 */ 201, 45, 218, 228, 229, 230, 231, 232, 233, 234, + /* 70 */ 271, 274, 212, 275, 236, 238, 278, 283, 284, 205, + /* 80 */ 208, 239, 242, 292, 294, 296, 297, 301, 304, 305, + /* 90 */ 307, 308, 310, 313, 314, 317, 318, 319, 320, 321, + /* 100 */ 322, 323, 324, 325, 326, 329, 330, 331, 334, 335, + /* 110 */ 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, + /* 120 */ 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, + /* 130 */ 356, 357, 358, 359, 360, 361, 362, 363, 279, 281, + /* 140 */ 286, 224, 225, 226, 364, 247, 366, 241, 243, 240, + /* 150 */ 246, 250, 372, 374, 373, 377, 379, 375, 376, 380, + /* 160 */ 256, 382, 383, 386, 389, 387, 391, 388, 394, 392, + /* 170 */ 397, 395, 400, 393, 411, 412, 413, 415, 416, 418, + /* 180 */ 419, 421, 406, 414, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 779, 894, 839, 906, 827, 836, 1034, 1034, 779, 779, - /* 10 */ 779, 779, 779, 779, 779, 779, 779, 954, 799, 1034, - /* 20 */ 779, 779, 779, 779, 779, 779, 779, 779, 779, 836, - /* 30 */ 779, 779, 779, 843, 836, 843, 843, 949, 878, 896, - /* 40 */ 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, - /* 50 */ 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, - /* 60 */ 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, - /* 70 */ 779, 779, 956, 958, 960, 779, 779, 980, 980, 947, - /* 80 */ 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, - /* 90 */ 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, - /* 100 */ 779, 779, 779, 779, 779, 779, 779, 779, 779, 825, - /* 110 */ 779, 823, 779, 779, 779, 779, 779, 779, 779, 779, - /* 120 */ 779, 779, 779, 779, 779, 779, 779, 809, 779, 779, - /* 130 */ 779, 779, 779, 779, 801, 801, 801, 779, 779, 779, - /* 140 */ 801, 779, 801, 987, 991, 985, 973, 981, 972, 968, - /* 150 */ 966, 965, 995, 779, 801, 801, 801, 840, 836, 836, - /* 160 */ 801, 801, 859, 857, 855, 847, 853, 849, 851, 845, - /* 170 */ 828, 801, 834, 834, 801, 834, 801, 834, 801, 878, - /* 180 */ 896, 779, 996, 779, 1033, 986, 1023, 1022, 1029, 1021, - /* 190 */ 1020, 1019, 779, 779, 779, 1015, 1016, 1018, 1017, 779, - /* 200 */ 779, 1025, 1024, 779, 779, 779, 779, 779, 779, 779, - /* 210 */ 779, 779, 779, 779, 779, 779, 998, 779, 992, 988, - /* 220 */ 779, 779, 779, 779, 779, 779, 779, 779, 779, 908, - /* 230 */ 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, - /* 240 */ 779, 779, 779, 779, 946, 779, 779, 779, 779, 957, - /* 250 */ 779, 779, 779, 779, 779, 779, 779, 779, 779, 982, - /* 260 */ 779, 974, 779, 779, 779, 779, 779, 920, 779, 779, - /* 270 */ 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, - /* 280 */ 779, 779, 779, 779, 779, 1044, 1042, 779, 779, 779, - /* 290 */ 1038, 779, 779, 779, 1036, 779, 779, 779, 779, 779, - /* 300 */ 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, - /* 310 */ 779, 779, 862, 779, 807, 805, 779, 797, 779, + /* 0 */ 787, 903, 847, 915, 835, 844, 1043, 1043, 787, 787, + /* 10 */ 787, 787, 787, 787, 787, 787, 787, 962, 807, 1043, + /* 20 */ 787, 787, 787, 787, 787, 787, 787, 787, 787, 844, + /* 30 */ 787, 787, 787, 787, 852, 844, 852, 852, 957, 887, + /* 40 */ 905, 787, 787, 787, 787, 787, 787, 787, 787, 787, + /* 50 */ 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, + /* 60 */ 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, + /* 70 */ 787, 787, 964, 967, 787, 787, 969, 787, 787, 989, + /* 80 */ 989, 955, 787, 787, 787, 787, 787, 787, 787, 787, + /* 90 */ 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, + /* 100 */ 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, + /* 110 */ 787, 787, 787, 787, 833, 787, 831, 787, 787, 787, + /* 120 */ 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, + /* 130 */ 787, 787, 817, 787, 787, 787, 787, 787, 809, 809, + /* 140 */ 809, 787, 787, 787, 809, 787, 809, 996, 1000, 994, + /* 150 */ 982, 990, 981, 977, 975, 974, 1004, 809, 809, 809, + /* 160 */ 848, 844, 844, 809, 809, 868, 866, 864, 856, 862, + /* 170 */ 858, 860, 854, 836, 809, 842, 842, 809, 842, 809, + /* 180 */ 842, 809, 887, 905, 787, 1005, 787, 1042, 995, 1032, + /* 190 */ 1031, 1038, 1030, 1029, 1028, 787, 787, 787, 1024, 1025, + /* 200 */ 1027, 1026, 787, 787, 1034, 1033, 787, 787, 787, 787, + /* 210 */ 787, 787, 787, 787, 787, 787, 787, 787, 787, 1007, + /* 220 */ 787, 1001, 997, 787, 787, 787, 787, 787, 787, 787, + /* 230 */ 787, 787, 917, 787, 787, 787, 787, 787, 787, 787, + /* 240 */ 787, 787, 787, 787, 787, 787, 787, 954, 787, 787, + /* 250 */ 787, 787, 965, 787, 787, 787, 787, 787, 787, 787, + /* 260 */ 787, 787, 991, 787, 983, 787, 787, 787, 787, 787, + /* 270 */ 929, 787, 787, 787, 787, 787, 787, 787, 787, 787, + /* 280 */ 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, + /* 290 */ 787, 1053, 1051, 787, 787, 787, 1047, 787, 787, 787, + /* 300 */ 1045, 787, 787, 787, 787, 787, 787, 787, 787, 787, + /* 310 */ 787, 787, 787, 787, 787, 787, 787, 787, 871, 787, + /* 320 */ 815, 813, 787, 805, 787, }; /********** End of lemon-generated parsing tables *****************************/ @@ -573,6 +579,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* EXISTS => nothing */ 0, /* AS => nothing */ 0, /* OUTPUTTYPE => nothing */ + 0, /* AGGREGATE => nothing */ 0, /* PPS => nothing */ 0, /* TSERIES => nothing */ 0, /* DBS => nothing */ @@ -672,10 +679,8 @@ static const YYCODETYPE yyFallback[] = { 1, /* PREV => ID */ 1, /* LINEAR => ID */ 1, /* IMPORT => ID */ - 1, /* METRIC => ID */ 1, /* TBNAME => ID */ 1, /* JOIN => ID */ - 1, /* METRICS => ID */ 1, /* INSERT => ID */ 1, /* INTO => ID */ 1, /* VALUES => ID */ @@ -851,187 +856,186 @@ static const char *const yyTokenName[] = { /* 82 */ "EXISTS", /* 83 */ "AS", /* 84 */ "OUTPUTTYPE", - /* 85 */ "PPS", - /* 86 */ "TSERIES", - /* 87 */ "DBS", - /* 88 */ "STORAGE", - /* 89 */ "QTIME", - /* 90 */ "CONNS", - /* 91 */ "STATE", - /* 92 */ "KEEP", - /* 93 */ "CACHE", - /* 94 */ "REPLICA", - /* 95 */ "QUORUM", - /* 96 */ "DAYS", - /* 97 */ "MINROWS", - /* 98 */ "MAXROWS", - /* 99 */ "BLOCKS", - /* 100 */ "CTIME", - /* 101 */ "WAL", - /* 102 */ "FSYNC", - /* 103 */ "COMP", - /* 104 */ "PRECISION", - /* 105 */ "UPDATE", - /* 106 */ "CACHELAST", - /* 107 */ "PARTITIONS", - /* 108 */ "LP", - /* 109 */ "RP", - /* 110 */ "UNSIGNED", - /* 111 */ "TAGS", - /* 112 */ "USING", - /* 113 */ "COMMA", - /* 114 */ "NULL", - /* 115 */ "SELECT", - /* 116 */ "UNION", - /* 117 */ "ALL", - /* 118 */ "DISTINCT", - /* 119 */ "FROM", - /* 120 */ "VARIABLE", - /* 121 */ "INTERVAL", - /* 122 */ "SESSION", - /* 123 */ "FILL", - /* 124 */ "SLIDING", - /* 125 */ "ORDER", - /* 126 */ "BY", - /* 127 */ "ASC", - /* 128 */ "DESC", - /* 129 */ "GROUP", - /* 130 */ "HAVING", - /* 131 */ "LIMIT", - /* 132 */ "OFFSET", - /* 133 */ "SLIMIT", - /* 134 */ "SOFFSET", - /* 135 */ "WHERE", - /* 136 */ "NOW", - /* 137 */ "RESET", - /* 138 */ "QUERY", - /* 139 */ "ADD", - /* 140 */ "COLUMN", - /* 141 */ "TAG", - /* 142 */ "CHANGE", - /* 143 */ "SET", - /* 144 */ "KILL", - /* 145 */ "CONNECTION", - /* 146 */ "STREAM", - /* 147 */ "COLON", - /* 148 */ "ABORT", - /* 149 */ "AFTER", - /* 150 */ "ATTACH", - /* 151 */ "BEFORE", - /* 152 */ "BEGIN", - /* 153 */ "CASCADE", - /* 154 */ "CLUSTER", - /* 155 */ "CONFLICT", - /* 156 */ "COPY", - /* 157 */ "DEFERRED", - /* 158 */ "DELIMITERS", - /* 159 */ "DETACH", - /* 160 */ "EACH", - /* 161 */ "END", - /* 162 */ "EXPLAIN", - /* 163 */ "FAIL", - /* 164 */ "FOR", - /* 165 */ "IGNORE", - /* 166 */ "IMMEDIATE", - /* 167 */ "INITIALLY", - /* 168 */ "INSTEAD", - /* 169 */ "MATCH", - /* 170 */ "KEY", - /* 171 */ "OF", - /* 172 */ "RAISE", - /* 173 */ "REPLACE", - /* 174 */ "RESTRICT", - /* 175 */ "ROW", - /* 176 */ "STATEMENT", - /* 177 */ "TRIGGER", - /* 178 */ "VIEW", - /* 179 */ "SEMI", - /* 180 */ "NONE", - /* 181 */ "PREV", - /* 182 */ "LINEAR", - /* 183 */ "IMPORT", - /* 184 */ "METRIC", + /* 85 */ "AGGREGATE", + /* 86 */ "PPS", + /* 87 */ "TSERIES", + /* 88 */ "DBS", + /* 89 */ "STORAGE", + /* 90 */ "QTIME", + /* 91 */ "CONNS", + /* 92 */ "STATE", + /* 93 */ "KEEP", + /* 94 */ "CACHE", + /* 95 */ "REPLICA", + /* 96 */ "QUORUM", + /* 97 */ "DAYS", + /* 98 */ "MINROWS", + /* 99 */ "MAXROWS", + /* 100 */ "BLOCKS", + /* 101 */ "CTIME", + /* 102 */ "WAL", + /* 103 */ "FSYNC", + /* 104 */ "COMP", + /* 105 */ "PRECISION", + /* 106 */ "UPDATE", + /* 107 */ "CACHELAST", + /* 108 */ "PARTITIONS", + /* 109 */ "LP", + /* 110 */ "RP", + /* 111 */ "UNSIGNED", + /* 112 */ "TAGS", + /* 113 */ "USING", + /* 114 */ "COMMA", + /* 115 */ "NULL", + /* 116 */ "SELECT", + /* 117 */ "UNION", + /* 118 */ "ALL", + /* 119 */ "DISTINCT", + /* 120 */ "FROM", + /* 121 */ "VARIABLE", + /* 122 */ "INTERVAL", + /* 123 */ "SESSION", + /* 124 */ "FILL", + /* 125 */ "SLIDING", + /* 126 */ "ORDER", + /* 127 */ "BY", + /* 128 */ "ASC", + /* 129 */ "DESC", + /* 130 */ "GROUP", + /* 131 */ "HAVING", + /* 132 */ "LIMIT", + /* 133 */ "OFFSET", + /* 134 */ "SLIMIT", + /* 135 */ "SOFFSET", + /* 136 */ "WHERE", + /* 137 */ "NOW", + /* 138 */ "RESET", + /* 139 */ "QUERY", + /* 140 */ "ADD", + /* 141 */ "COLUMN", + /* 142 */ "TAG", + /* 143 */ "CHANGE", + /* 144 */ "SET", + /* 145 */ "KILL", + /* 146 */ "CONNECTION", + /* 147 */ "STREAM", + /* 148 */ "COLON", + /* 149 */ "ABORT", + /* 150 */ "AFTER", + /* 151 */ "ATTACH", + /* 152 */ "BEFORE", + /* 153 */ "BEGIN", + /* 154 */ "CASCADE", + /* 155 */ "CLUSTER", + /* 156 */ "CONFLICT", + /* 157 */ "COPY", + /* 158 */ "DEFERRED", + /* 159 */ "DELIMITERS", + /* 160 */ "DETACH", + /* 161 */ "EACH", + /* 162 */ "END", + /* 163 */ "EXPLAIN", + /* 164 */ "FAIL", + /* 165 */ "FOR", + /* 166 */ "IGNORE", + /* 167 */ "IMMEDIATE", + /* 168 */ "INITIALLY", + /* 169 */ "INSTEAD", + /* 170 */ "MATCH", + /* 171 */ "KEY", + /* 172 */ "OF", + /* 173 */ "RAISE", + /* 174 */ "REPLACE", + /* 175 */ "RESTRICT", + /* 176 */ "ROW", + /* 177 */ "STATEMENT", + /* 178 */ "TRIGGER", + /* 179 */ "VIEW", + /* 180 */ "SEMI", + /* 181 */ "NONE", + /* 182 */ "PREV", + /* 183 */ "LINEAR", + /* 184 */ "IMPORT", /* 185 */ "TBNAME", /* 186 */ "JOIN", - /* 187 */ "METRICS", - /* 188 */ "INSERT", - /* 189 */ "INTO", - /* 190 */ "VALUES", - /* 191 */ "program", - /* 192 */ "cmd", - /* 193 */ "dbPrefix", - /* 194 */ "ids", - /* 195 */ "cpxName", - /* 196 */ "ifexists", - /* 197 */ "alter_db_optr", - /* 198 */ "alter_topic_optr", - /* 199 */ "acct_optr", - /* 200 */ "ifnotexists", - /* 201 */ "db_optr", - /* 202 */ "topic_optr", - /* 203 */ "typename", - /* 204 */ "pps", - /* 205 */ "tseries", - /* 206 */ "dbs", - /* 207 */ "streams", - /* 208 */ "storage", - /* 209 */ "qtime", - /* 210 */ "users", - /* 211 */ "conns", - /* 212 */ "state", - /* 213 */ "keep", - /* 214 */ "tagitemlist", - /* 215 */ "cache", - /* 216 */ "replica", - /* 217 */ "quorum", - /* 218 */ "days", - /* 219 */ "minrows", - /* 220 */ "maxrows", - /* 221 */ "blocks", - /* 222 */ "ctime", - /* 223 */ "wal", - /* 224 */ "fsync", - /* 225 */ "comp", - /* 226 */ "prec", - /* 227 */ "update", - /* 228 */ "cachelast", - /* 229 */ "partitions", - /* 230 */ "signed", - /* 231 */ "create_table_args", - /* 232 */ "create_stable_args", - /* 233 */ "create_table_list", - /* 234 */ "create_from_stable", - /* 235 */ "columnlist", - /* 236 */ "tagNamelist", - /* 237 */ "select", - /* 238 */ "column", - /* 239 */ "tagitem", - /* 240 */ "selcollist", - /* 241 */ "from", - /* 242 */ "where_opt", - /* 243 */ "interval_opt", - /* 244 */ "session_option", - /* 245 */ "fill_opt", - /* 246 */ "sliding_opt", - /* 247 */ "groupby_opt", - /* 248 */ "orderby_opt", - /* 249 */ "having_opt", - /* 250 */ "slimit_opt", - /* 251 */ "limit_opt", - /* 252 */ "union", - /* 253 */ "sclp", - /* 254 */ "distinct", - /* 255 */ "expr", - /* 256 */ "as", - /* 257 */ "tablelist", - /* 258 */ "tmvar", - /* 259 */ "sortlist", - /* 260 */ "sortitem", - /* 261 */ "item", - /* 262 */ "sortorder", - /* 263 */ "grouplist", - /* 264 */ "exprlist", - /* 265 */ "expritem", + /* 187 */ "INSERT", + /* 188 */ "INTO", + /* 189 */ "VALUES", + /* 190 */ "program", + /* 191 */ "cmd", + /* 192 */ "dbPrefix", + /* 193 */ "ids", + /* 194 */ "cpxName", + /* 195 */ "ifexists", + /* 196 */ "alter_db_optr", + /* 197 */ "alter_topic_optr", + /* 198 */ "acct_optr", + /* 199 */ "ifnotexists", + /* 200 */ "db_optr", + /* 201 */ "topic_optr", + /* 202 */ "typename", + /* 203 */ "pps", + /* 204 */ "tseries", + /* 205 */ "dbs", + /* 206 */ "streams", + /* 207 */ "storage", + /* 208 */ "qtime", + /* 209 */ "users", + /* 210 */ "conns", + /* 211 */ "state", + /* 212 */ "keep", + /* 213 */ "tagitemlist", + /* 214 */ "cache", + /* 215 */ "replica", + /* 216 */ "quorum", + /* 217 */ "days", + /* 218 */ "minrows", + /* 219 */ "maxrows", + /* 220 */ "blocks", + /* 221 */ "ctime", + /* 222 */ "wal", + /* 223 */ "fsync", + /* 224 */ "comp", + /* 225 */ "prec", + /* 226 */ "update", + /* 227 */ "cachelast", + /* 228 */ "partitions", + /* 229 */ "signed", + /* 230 */ "create_table_args", + /* 231 */ "create_stable_args", + /* 232 */ "create_table_list", + /* 233 */ "create_from_stable", + /* 234 */ "columnlist", + /* 235 */ "tagNamelist", + /* 236 */ "select", + /* 237 */ "column", + /* 238 */ "tagitem", + /* 239 */ "selcollist", + /* 240 */ "from", + /* 241 */ "where_opt", + /* 242 */ "interval_opt", + /* 243 */ "session_option", + /* 244 */ "fill_opt", + /* 245 */ "sliding_opt", + /* 246 */ "groupby_opt", + /* 247 */ "orderby_opt", + /* 248 */ "having_opt", + /* 249 */ "slimit_opt", + /* 250 */ "limit_opt", + /* 251 */ "union", + /* 252 */ "sclp", + /* 253 */ "distinct", + /* 254 */ "expr", + /* 255 */ "as", + /* 256 */ "tablelist", + /* 257 */ "tmvar", + /* 258 */ "sortlist", + /* 259 */ "sortitem", + /* 260 */ "item", + /* 261 */ "sortorder", + /* 262 */ "grouplist", + /* 263 */ "exprlist", + /* 264 */ "expritem", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -1099,110 +1103,110 @@ static const char *const yyRuleName[] = { /* 57 */ "cmd ::= CREATE DATABASE ifnotexists ids db_optr", /* 58 */ "cmd ::= CREATE TOPIC ifnotexists ids topic_optr", /* 59 */ "cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename", - /* 60 */ "cmd ::= CREATE USER ids PASS ids", - /* 61 */ "pps ::=", - /* 62 */ "pps ::= PPS INTEGER", - /* 63 */ "tseries ::=", - /* 64 */ "tseries ::= TSERIES INTEGER", - /* 65 */ "dbs ::=", - /* 66 */ "dbs ::= DBS INTEGER", - /* 67 */ "streams ::=", - /* 68 */ "streams ::= STREAMS INTEGER", - /* 69 */ "storage ::=", - /* 70 */ "storage ::= STORAGE INTEGER", - /* 71 */ "qtime ::=", - /* 72 */ "qtime ::= QTIME INTEGER", - /* 73 */ "users ::=", - /* 74 */ "users ::= USERS INTEGER", - /* 75 */ "conns ::=", - /* 76 */ "conns ::= CONNS INTEGER", - /* 77 */ "state ::=", - /* 78 */ "state ::= STATE ids", - /* 79 */ "acct_optr ::= pps tseries storage streams qtime dbs users conns state", - /* 80 */ "keep ::= KEEP tagitemlist", - /* 81 */ "cache ::= CACHE INTEGER", - /* 82 */ "replica ::= REPLICA INTEGER", - /* 83 */ "quorum ::= QUORUM INTEGER", - /* 84 */ "days ::= DAYS INTEGER", - /* 85 */ "minrows ::= MINROWS INTEGER", - /* 86 */ "maxrows ::= MAXROWS INTEGER", - /* 87 */ "blocks ::= BLOCKS INTEGER", - /* 88 */ "ctime ::= CTIME INTEGER", - /* 89 */ "wal ::= WAL INTEGER", - /* 90 */ "fsync ::= FSYNC INTEGER", - /* 91 */ "comp ::= COMP INTEGER", - /* 92 */ "prec ::= PRECISION STRING", - /* 93 */ "update ::= UPDATE INTEGER", - /* 94 */ "cachelast ::= CACHELAST INTEGER", - /* 95 */ "partitions ::= PARTITIONS INTEGER", - /* 96 */ "db_optr ::=", - /* 97 */ "db_optr ::= db_optr cache", - /* 98 */ "db_optr ::= db_optr replica", - /* 99 */ "db_optr ::= db_optr quorum", - /* 100 */ "db_optr ::= db_optr days", - /* 101 */ "db_optr ::= db_optr minrows", - /* 102 */ "db_optr ::= db_optr maxrows", - /* 103 */ "db_optr ::= db_optr blocks", - /* 104 */ "db_optr ::= db_optr ctime", - /* 105 */ "db_optr ::= db_optr wal", - /* 106 */ "db_optr ::= db_optr fsync", - /* 107 */ "db_optr ::= db_optr comp", - /* 108 */ "db_optr ::= db_optr prec", - /* 109 */ "db_optr ::= db_optr keep", - /* 110 */ "db_optr ::= db_optr update", - /* 111 */ "db_optr ::= db_optr cachelast", - /* 112 */ "topic_optr ::= db_optr", - /* 113 */ "topic_optr ::= topic_optr partitions", - /* 114 */ "alter_db_optr ::=", - /* 115 */ "alter_db_optr ::= alter_db_optr replica", - /* 116 */ "alter_db_optr ::= alter_db_optr quorum", - /* 117 */ "alter_db_optr ::= alter_db_optr keep", - /* 118 */ "alter_db_optr ::= alter_db_optr blocks", - /* 119 */ "alter_db_optr ::= alter_db_optr comp", - /* 120 */ "alter_db_optr ::= alter_db_optr wal", - /* 121 */ "alter_db_optr ::= alter_db_optr fsync", - /* 122 */ "alter_db_optr ::= alter_db_optr update", - /* 123 */ "alter_db_optr ::= alter_db_optr cachelast", - /* 124 */ "alter_topic_optr ::= alter_db_optr", - /* 125 */ "alter_topic_optr ::= alter_topic_optr partitions", - /* 126 */ "typename ::= ids", - /* 127 */ "typename ::= ids LP signed RP", - /* 128 */ "typename ::= ids UNSIGNED", - /* 129 */ "signed ::= INTEGER", - /* 130 */ "signed ::= PLUS INTEGER", - /* 131 */ "signed ::= MINUS INTEGER", - /* 132 */ "cmd ::= CREATE TABLE create_table_args", - /* 133 */ "cmd ::= CREATE TABLE create_stable_args", - /* 134 */ "cmd ::= CREATE STABLE create_stable_args", - /* 135 */ "cmd ::= CREATE TABLE create_table_list", - /* 136 */ "create_table_list ::= create_from_stable", - /* 137 */ "create_table_list ::= create_table_list create_from_stable", - /* 138 */ "create_table_args ::= ifnotexists ids cpxName LP columnlist RP", - /* 139 */ "create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP", - /* 140 */ "create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP", - /* 141 */ "create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP", - /* 142 */ "tagNamelist ::= tagNamelist COMMA ids", - /* 143 */ "tagNamelist ::= ids", - /* 144 */ "create_table_args ::= ifnotexists ids cpxName AS select", - /* 145 */ "columnlist ::= columnlist COMMA column", - /* 146 */ "columnlist ::= column", - /* 147 */ "column ::= ids typename", - /* 148 */ "tagitemlist ::= tagitemlist COMMA tagitem", - /* 149 */ "tagitemlist ::= tagitem", - /* 150 */ "tagitem ::= INTEGER", - /* 151 */ "tagitem ::= FLOAT", - /* 152 */ "tagitem ::= STRING", - /* 153 */ "tagitem ::= BOOL", - /* 154 */ "tagitem ::= NULL", - /* 155 */ "tagitem ::= MINUS INTEGER", - /* 156 */ "tagitem ::= MINUS FLOAT", - /* 157 */ "tagitem ::= PLUS INTEGER", - /* 158 */ "tagitem ::= PLUS FLOAT", - /* 159 */ "select ::= SELECT selcollist from where_opt interval_opt session_option fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt", - /* 160 */ "union ::= select", - /* 161 */ "union ::= LP union RP", - /* 162 */ "union ::= union UNION ALL select", - /* 163 */ "union ::= union UNION ALL LP select RP", + /* 60 */ "cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename", + /* 61 */ "cmd ::= CREATE USER ids PASS ids", + /* 62 */ "pps ::=", + /* 63 */ "pps ::= PPS INTEGER", + /* 64 */ "tseries ::=", + /* 65 */ "tseries ::= TSERIES INTEGER", + /* 66 */ "dbs ::=", + /* 67 */ "dbs ::= DBS INTEGER", + /* 68 */ "streams ::=", + /* 69 */ "streams ::= STREAMS INTEGER", + /* 70 */ "storage ::=", + /* 71 */ "storage ::= STORAGE INTEGER", + /* 72 */ "qtime ::=", + /* 73 */ "qtime ::= QTIME INTEGER", + /* 74 */ "users ::=", + /* 75 */ "users ::= USERS INTEGER", + /* 76 */ "conns ::=", + /* 77 */ "conns ::= CONNS INTEGER", + /* 78 */ "state ::=", + /* 79 */ "state ::= STATE ids", + /* 80 */ "acct_optr ::= pps tseries storage streams qtime dbs users conns state", + /* 81 */ "keep ::= KEEP tagitemlist", + /* 82 */ "cache ::= CACHE INTEGER", + /* 83 */ "replica ::= REPLICA INTEGER", + /* 84 */ "quorum ::= QUORUM INTEGER", + /* 85 */ "days ::= DAYS INTEGER", + /* 86 */ "minrows ::= MINROWS INTEGER", + /* 87 */ "maxrows ::= MAXROWS INTEGER", + /* 88 */ "blocks ::= BLOCKS INTEGER", + /* 89 */ "ctime ::= CTIME INTEGER", + /* 90 */ "wal ::= WAL INTEGER", + /* 91 */ "fsync ::= FSYNC INTEGER", + /* 92 */ "comp ::= COMP INTEGER", + /* 93 */ "prec ::= PRECISION STRING", + /* 94 */ "update ::= UPDATE INTEGER", + /* 95 */ "cachelast ::= CACHELAST INTEGER", + /* 96 */ "partitions ::= PARTITIONS INTEGER", + /* 97 */ "db_optr ::=", + /* 98 */ "db_optr ::= db_optr cache", + /* 99 */ "db_optr ::= db_optr replica", + /* 100 */ "db_optr ::= db_optr quorum", + /* 101 */ "db_optr ::= db_optr days", + /* 102 */ "db_optr ::= db_optr minrows", + /* 103 */ "db_optr ::= db_optr maxrows", + /* 104 */ "db_optr ::= db_optr blocks", + /* 105 */ "db_optr ::= db_optr ctime", + /* 106 */ "db_optr ::= db_optr wal", + /* 107 */ "db_optr ::= db_optr fsync", + /* 108 */ "db_optr ::= db_optr comp", + /* 109 */ "db_optr ::= db_optr prec", + /* 110 */ "db_optr ::= db_optr keep", + /* 111 */ "db_optr ::= db_optr update", + /* 112 */ "db_optr ::= db_optr cachelast", + /* 113 */ "topic_optr ::= db_optr", + /* 114 */ "topic_optr ::= topic_optr partitions", + /* 115 */ "alter_db_optr ::=", + /* 116 */ "alter_db_optr ::= alter_db_optr replica", + /* 117 */ "alter_db_optr ::= alter_db_optr quorum", + /* 118 */ "alter_db_optr ::= alter_db_optr keep", + /* 119 */ "alter_db_optr ::= alter_db_optr blocks", + /* 120 */ "alter_db_optr ::= alter_db_optr comp", + /* 121 */ "alter_db_optr ::= alter_db_optr wal", + /* 122 */ "alter_db_optr ::= alter_db_optr fsync", + /* 123 */ "alter_db_optr ::= alter_db_optr update", + /* 124 */ "alter_db_optr ::= alter_db_optr cachelast", + /* 125 */ "alter_topic_optr ::= alter_db_optr", + /* 126 */ "alter_topic_optr ::= alter_topic_optr partitions", + /* 127 */ "typename ::= ids", + /* 128 */ "typename ::= ids LP signed RP", + /* 129 */ "typename ::= ids UNSIGNED", + /* 130 */ "signed ::= INTEGER", + /* 131 */ "signed ::= PLUS INTEGER", + /* 132 */ "signed ::= MINUS INTEGER", + /* 133 */ "cmd ::= CREATE TABLE create_table_args", + /* 134 */ "cmd ::= CREATE TABLE create_stable_args", + /* 135 */ "cmd ::= CREATE STABLE create_stable_args", + /* 136 */ "cmd ::= CREATE TABLE create_table_list", + /* 137 */ "create_table_list ::= create_from_stable", + /* 138 */ "create_table_list ::= create_table_list create_from_stable", + /* 139 */ "create_table_args ::= ifnotexists ids cpxName LP columnlist RP", + /* 140 */ "create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP", + /* 141 */ "create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP", + /* 142 */ "create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP", + /* 143 */ "tagNamelist ::= tagNamelist COMMA ids", + /* 144 */ "tagNamelist ::= ids", + /* 145 */ "create_table_args ::= ifnotexists ids cpxName AS select", + /* 146 */ "columnlist ::= columnlist COMMA column", + /* 147 */ "columnlist ::= column", + /* 148 */ "column ::= ids typename", + /* 149 */ "tagitemlist ::= tagitemlist COMMA tagitem", + /* 150 */ "tagitemlist ::= tagitem", + /* 151 */ "tagitem ::= INTEGER", + /* 152 */ "tagitem ::= FLOAT", + /* 153 */ "tagitem ::= STRING", + /* 154 */ "tagitem ::= BOOL", + /* 155 */ "tagitem ::= NULL", + /* 156 */ "tagitem ::= MINUS INTEGER", + /* 157 */ "tagitem ::= MINUS FLOAT", + /* 158 */ "tagitem ::= PLUS INTEGER", + /* 159 */ "tagitem ::= PLUS FLOAT", + /* 160 */ "select ::= SELECT selcollist from where_opt interval_opt session_option fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt", + /* 161 */ "select ::= LP select RP", + /* 162 */ "union ::= select", + /* 163 */ "union ::= union UNION ALL select", /* 164 */ "cmd ::= union", /* 165 */ "select ::= SELECT selcollist", /* 166 */ "sclp ::= selcollist COMMA", @@ -1215,98 +1219,99 @@ static const char *const yyRuleName[] = { /* 173 */ "distinct ::= DISTINCT", /* 174 */ "distinct ::=", /* 175 */ "from ::= FROM tablelist", - /* 176 */ "tablelist ::= ids cpxName", - /* 177 */ "tablelist ::= ids cpxName ids", - /* 178 */ "tablelist ::= tablelist COMMA ids cpxName", - /* 179 */ "tablelist ::= tablelist COMMA ids cpxName ids", - /* 180 */ "tmvar ::= VARIABLE", - /* 181 */ "interval_opt ::= INTERVAL LP tmvar RP", - /* 182 */ "interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP", - /* 183 */ "interval_opt ::=", - /* 184 */ "session_option ::=", - /* 185 */ "session_option ::= SESSION LP ids cpxName COMMA tmvar RP", - /* 186 */ "fill_opt ::=", - /* 187 */ "fill_opt ::= FILL LP ID COMMA tagitemlist RP", - /* 188 */ "fill_opt ::= FILL LP ID RP", - /* 189 */ "sliding_opt ::= SLIDING LP tmvar RP", - /* 190 */ "sliding_opt ::=", - /* 191 */ "orderby_opt ::=", - /* 192 */ "orderby_opt ::= ORDER BY sortlist", - /* 193 */ "sortlist ::= sortlist COMMA item sortorder", - /* 194 */ "sortlist ::= item sortorder", - /* 195 */ "item ::= ids cpxName", - /* 196 */ "sortorder ::= ASC", - /* 197 */ "sortorder ::= DESC", - /* 198 */ "sortorder ::=", - /* 199 */ "groupby_opt ::=", - /* 200 */ "groupby_opt ::= GROUP BY grouplist", - /* 201 */ "grouplist ::= grouplist COMMA item", - /* 202 */ "grouplist ::= item", - /* 203 */ "having_opt ::=", - /* 204 */ "having_opt ::= HAVING expr", - /* 205 */ "limit_opt ::=", - /* 206 */ "limit_opt ::= LIMIT signed", - /* 207 */ "limit_opt ::= LIMIT signed OFFSET signed", - /* 208 */ "limit_opt ::= LIMIT signed COMMA signed", - /* 209 */ "slimit_opt ::=", - /* 210 */ "slimit_opt ::= SLIMIT signed", - /* 211 */ "slimit_opt ::= SLIMIT signed SOFFSET signed", - /* 212 */ "slimit_opt ::= SLIMIT signed COMMA signed", - /* 213 */ "where_opt ::=", - /* 214 */ "where_opt ::= WHERE expr", - /* 215 */ "expr ::= LP expr RP", - /* 216 */ "expr ::= ID", - /* 217 */ "expr ::= ID DOT ID", - /* 218 */ "expr ::= ID DOT STAR", - /* 219 */ "expr ::= INTEGER", - /* 220 */ "expr ::= MINUS INTEGER", - /* 221 */ "expr ::= PLUS INTEGER", - /* 222 */ "expr ::= FLOAT", - /* 223 */ "expr ::= MINUS FLOAT", - /* 224 */ "expr ::= PLUS FLOAT", - /* 225 */ "expr ::= STRING", - /* 226 */ "expr ::= NOW", - /* 227 */ "expr ::= VARIABLE", - /* 228 */ "expr ::= BOOL", - /* 229 */ "expr ::= ID LP exprlist RP", - /* 230 */ "expr ::= ID LP STAR RP", - /* 231 */ "expr ::= expr IS NULL", - /* 232 */ "expr ::= expr IS NOT NULL", - /* 233 */ "expr ::= expr LT expr", - /* 234 */ "expr ::= expr GT expr", - /* 235 */ "expr ::= expr LE expr", - /* 236 */ "expr ::= expr GE expr", - /* 237 */ "expr ::= expr NE expr", - /* 238 */ "expr ::= expr EQ expr", - /* 239 */ "expr ::= expr BETWEEN expr AND expr", - /* 240 */ "expr ::= expr AND expr", - /* 241 */ "expr ::= expr OR expr", - /* 242 */ "expr ::= expr PLUS expr", - /* 243 */ "expr ::= expr MINUS expr", - /* 244 */ "expr ::= expr STAR expr", - /* 245 */ "expr ::= expr SLASH expr", - /* 246 */ "expr ::= expr REM expr", - /* 247 */ "expr ::= expr LIKE expr", - /* 248 */ "expr ::= expr IN LP exprlist RP", - /* 249 */ "exprlist ::= exprlist COMMA expritem", - /* 250 */ "exprlist ::= expritem", - /* 251 */ "expritem ::= expr", - /* 252 */ "expritem ::=", - /* 253 */ "cmd ::= RESET QUERY CACHE", - /* 254 */ "cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist", - /* 255 */ "cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids", - /* 256 */ "cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist", - /* 257 */ "cmd ::= ALTER TABLE ids cpxName DROP TAG ids", - /* 258 */ "cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids", - /* 259 */ "cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem", - /* 260 */ "cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist", - /* 261 */ "cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids", - /* 262 */ "cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist", - /* 263 */ "cmd ::= ALTER STABLE ids cpxName DROP TAG ids", - /* 264 */ "cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids", - /* 265 */ "cmd ::= KILL CONNECTION INTEGER", - /* 266 */ "cmd ::= KILL STREAM INTEGER COLON INTEGER", - /* 267 */ "cmd ::= KILL QUERY INTEGER COLON INTEGER", + /* 176 */ "from ::= FROM LP union RP", + /* 177 */ "tablelist ::= ids cpxName", + /* 178 */ "tablelist ::= ids cpxName ids", + /* 179 */ "tablelist ::= tablelist COMMA ids cpxName", + /* 180 */ "tablelist ::= tablelist COMMA ids cpxName ids", + /* 181 */ "tmvar ::= VARIABLE", + /* 182 */ "interval_opt ::= INTERVAL LP tmvar RP", + /* 183 */ "interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP", + /* 184 */ "interval_opt ::=", + /* 185 */ "session_option ::=", + /* 186 */ "session_option ::= SESSION LP ids cpxName COMMA tmvar RP", + /* 187 */ "fill_opt ::=", + /* 188 */ "fill_opt ::= FILL LP ID COMMA tagitemlist RP", + /* 189 */ "fill_opt ::= FILL LP ID RP", + /* 190 */ "sliding_opt ::= SLIDING LP tmvar RP", + /* 191 */ "sliding_opt ::=", + /* 192 */ "orderby_opt ::=", + /* 193 */ "orderby_opt ::= ORDER BY sortlist", + /* 194 */ "sortlist ::= sortlist COMMA item sortorder", + /* 195 */ "sortlist ::= item sortorder", + /* 196 */ "item ::= ids cpxName", + /* 197 */ "sortorder ::= ASC", + /* 198 */ "sortorder ::= DESC", + /* 199 */ "sortorder ::=", + /* 200 */ "groupby_opt ::=", + /* 201 */ "groupby_opt ::= GROUP BY grouplist", + /* 202 */ "grouplist ::= grouplist COMMA item", + /* 203 */ "grouplist ::= item", + /* 204 */ "having_opt ::=", + /* 205 */ "having_opt ::= HAVING expr", + /* 206 */ "limit_opt ::=", + /* 207 */ "limit_opt ::= LIMIT signed", + /* 208 */ "limit_opt ::= LIMIT signed OFFSET signed", + /* 209 */ "limit_opt ::= LIMIT signed COMMA signed", + /* 210 */ "slimit_opt ::=", + /* 211 */ "slimit_opt ::= SLIMIT signed", + /* 212 */ "slimit_opt ::= SLIMIT signed SOFFSET signed", + /* 213 */ "slimit_opt ::= SLIMIT signed COMMA signed", + /* 214 */ "where_opt ::=", + /* 215 */ "where_opt ::= WHERE expr", + /* 216 */ "expr ::= LP expr RP", + /* 217 */ "expr ::= ID", + /* 218 */ "expr ::= ID DOT ID", + /* 219 */ "expr ::= ID DOT STAR", + /* 220 */ "expr ::= INTEGER", + /* 221 */ "expr ::= MINUS INTEGER", + /* 222 */ "expr ::= PLUS INTEGER", + /* 223 */ "expr ::= FLOAT", + /* 224 */ "expr ::= MINUS FLOAT", + /* 225 */ "expr ::= PLUS FLOAT", + /* 226 */ "expr ::= STRING", + /* 227 */ "expr ::= NOW", + /* 228 */ "expr ::= VARIABLE", + /* 229 */ "expr ::= BOOL", + /* 230 */ "expr ::= ID LP exprlist RP", + /* 231 */ "expr ::= ID LP STAR RP", + /* 232 */ "expr ::= expr IS NULL", + /* 233 */ "expr ::= expr IS NOT NULL", + /* 234 */ "expr ::= expr LT expr", + /* 235 */ "expr ::= expr GT expr", + /* 236 */ "expr ::= expr LE expr", + /* 237 */ "expr ::= expr GE expr", + /* 238 */ "expr ::= expr NE expr", + /* 239 */ "expr ::= expr EQ expr", + /* 240 */ "expr ::= expr BETWEEN expr AND expr", + /* 241 */ "expr ::= expr AND expr", + /* 242 */ "expr ::= expr OR expr", + /* 243 */ "expr ::= expr PLUS expr", + /* 244 */ "expr ::= expr MINUS expr", + /* 245 */ "expr ::= expr STAR expr", + /* 246 */ "expr ::= expr SLASH expr", + /* 247 */ "expr ::= expr REM expr", + /* 248 */ "expr ::= expr LIKE expr", + /* 249 */ "expr ::= expr IN LP exprlist RP", + /* 250 */ "exprlist ::= exprlist COMMA expritem", + /* 251 */ "exprlist ::= expritem", + /* 252 */ "expritem ::= expr", + /* 253 */ "expritem ::=", + /* 254 */ "cmd ::= RESET QUERY CACHE", + /* 255 */ "cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist", + /* 256 */ "cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids", + /* 257 */ "cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist", + /* 258 */ "cmd ::= ALTER TABLE ids cpxName DROP TAG ids", + /* 259 */ "cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids", + /* 260 */ "cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem", + /* 261 */ "cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist", + /* 262 */ "cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids", + /* 263 */ "cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist", + /* 264 */ "cmd ::= ALTER STABLE ids cpxName DROP TAG ids", + /* 265 */ "cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids", + /* 266 */ "cmd ::= KILL CONNECTION INTEGER", + /* 267 */ "cmd ::= KILL STREAM INTEGER COLON INTEGER", + /* 268 */ "cmd ::= KILL QUERY INTEGER COLON INTEGER", }; #endif /* NDEBUG */ @@ -1432,52 +1437,52 @@ static void yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 213: /* keep */ - case 214: /* tagitemlist */ - case 235: /* columnlist */ - case 236: /* tagNamelist */ - case 245: /* fill_opt */ - case 247: /* groupby_opt */ - case 248: /* orderby_opt */ - case 259: /* sortlist */ - case 263: /* grouplist */ + case 212: /* keep */ + case 213: /* tagitemlist */ + case 234: /* columnlist */ + case 235: /* tagNamelist */ + case 244: /* fill_opt */ + case 246: /* groupby_opt */ + case 247: /* orderby_opt */ + case 258: /* sortlist */ + case 262: /* grouplist */ { -taosArrayDestroy((yypminor->yy193)); +taosArrayDestroy((yypminor->yy291)); } break; - case 233: /* create_table_list */ + case 232: /* create_table_list */ { -destroyCreateTableSql((yypminor->yy190)); +destroyCreateTableSql((yypminor->yy412)); } break; - case 237: /* select */ + case 236: /* select */ { -doDestroyQuerySql((yypminor->yy288)); +destroyQuerySqlNode((yypminor->yy110)); } break; - case 240: /* selcollist */ - case 253: /* sclp */ - case 264: /* exprlist */ + case 239: /* selcollist */ + case 252: /* sclp */ + case 263: /* exprlist */ { -tSqlExprListDestroy((yypminor->yy178)); +tSqlExprListDestroy((yypminor->yy291)); } break; - case 242: /* where_opt */ - case 249: /* having_opt */ - case 255: /* expr */ - case 265: /* expritem */ + case 241: /* where_opt */ + case 248: /* having_opt */ + case 254: /* expr */ + case 264: /* expritem */ { -tSqlExprDestroy((yypminor->yy134)); +tSqlExprDestroy((yypminor->yy436)); } break; - case 252: /* union */ + case 251: /* union */ { -destroyAllSelectClause((yypminor->yy21)); +destroyAllSelectClause((yypminor->yy154)); } break; - case 260: /* sortitem */ + case 259: /* sortitem */ { -tVariantDestroy(&(yypminor->yy442)); +tVariantDestroy(&(yypminor->yy216)); } break; /********* End destructor definitions *****************************************/ @@ -1766,274 +1771,275 @@ static void yy_shift( /* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side ** of that rule */ static const YYCODETYPE yyRuleInfoLhs[] = { - 191, /* (0) program ::= cmd */ - 192, /* (1) cmd ::= SHOW DATABASES */ - 192, /* (2) cmd ::= SHOW TOPICS */ - 192, /* (3) cmd ::= SHOW FUNCTIONS */ - 192, /* (4) cmd ::= SHOW MNODES */ - 192, /* (5) cmd ::= SHOW DNODES */ - 192, /* (6) cmd ::= SHOW ACCOUNTS */ - 192, /* (7) cmd ::= SHOW USERS */ - 192, /* (8) cmd ::= SHOW MODULES */ - 192, /* (9) cmd ::= SHOW QUERIES */ - 192, /* (10) cmd ::= SHOW CONNECTIONS */ - 192, /* (11) cmd ::= SHOW STREAMS */ - 192, /* (12) cmd ::= SHOW VARIABLES */ - 192, /* (13) cmd ::= SHOW SCORES */ - 192, /* (14) cmd ::= SHOW GRANTS */ - 192, /* (15) cmd ::= SHOW VNODES */ - 192, /* (16) cmd ::= SHOW VNODES IPTOKEN */ - 193, /* (17) dbPrefix ::= */ - 193, /* (18) dbPrefix ::= ids DOT */ - 195, /* (19) cpxName ::= */ - 195, /* (20) cpxName ::= DOT ids */ - 192, /* (21) cmd ::= SHOW CREATE TABLE ids cpxName */ - 192, /* (22) cmd ::= SHOW CREATE DATABASE ids */ - 192, /* (23) cmd ::= SHOW dbPrefix TABLES */ - 192, /* (24) cmd ::= SHOW dbPrefix TABLES LIKE ids */ - 192, /* (25) cmd ::= SHOW dbPrefix STABLES */ - 192, /* (26) cmd ::= SHOW dbPrefix STABLES LIKE ids */ - 192, /* (27) cmd ::= SHOW dbPrefix VGROUPS */ - 192, /* (28) cmd ::= SHOW dbPrefix VGROUPS ids */ - 192, /* (29) cmd ::= DROP TABLE ifexists ids cpxName */ - 192, /* (30) cmd ::= DROP STABLE ifexists ids cpxName */ - 192, /* (31) cmd ::= DROP DATABASE ifexists ids */ - 192, /* (32) cmd ::= DROP TOPIC ifexists ids */ - 192, /* (33) cmd ::= DROP FUNCTION ids */ - 192, /* (34) cmd ::= DROP DNODE ids */ - 192, /* (35) cmd ::= DROP USER ids */ - 192, /* (36) cmd ::= DROP ACCOUNT ids */ - 192, /* (37) cmd ::= USE ids */ - 192, /* (38) cmd ::= DESCRIBE ids cpxName */ - 192, /* (39) cmd ::= ALTER USER ids PASS ids */ - 192, /* (40) cmd ::= ALTER USER ids PRIVILEGE ids */ - 192, /* (41) cmd ::= ALTER DNODE ids ids */ - 192, /* (42) cmd ::= ALTER DNODE ids ids ids */ - 192, /* (43) cmd ::= ALTER LOCAL ids */ - 192, /* (44) cmd ::= ALTER LOCAL ids ids */ - 192, /* (45) cmd ::= ALTER DATABASE ids alter_db_optr */ - 192, /* (46) cmd ::= ALTER TOPIC ids alter_topic_optr */ - 192, /* (47) cmd ::= ALTER ACCOUNT ids acct_optr */ - 192, /* (48) cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ - 194, /* (49) ids ::= ID */ - 194, /* (50) ids ::= STRING */ - 196, /* (51) ifexists ::= IF EXISTS */ - 196, /* (52) ifexists ::= */ - 200, /* (53) ifnotexists ::= IF NOT EXISTS */ - 200, /* (54) ifnotexists ::= */ - 192, /* (55) cmd ::= CREATE DNODE ids */ - 192, /* (56) cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ - 192, /* (57) cmd ::= CREATE DATABASE ifnotexists ids db_optr */ - 192, /* (58) cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ - 192, /* (59) cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename */ - 192, /* (60) cmd ::= CREATE USER ids PASS ids */ - 204, /* (61) pps ::= */ - 204, /* (62) pps ::= PPS INTEGER */ - 205, /* (63) tseries ::= */ - 205, /* (64) tseries ::= TSERIES INTEGER */ - 206, /* (65) dbs ::= */ - 206, /* (66) dbs ::= DBS INTEGER */ - 207, /* (67) streams ::= */ - 207, /* (68) streams ::= STREAMS INTEGER */ - 208, /* (69) storage ::= */ - 208, /* (70) storage ::= STORAGE INTEGER */ - 209, /* (71) qtime ::= */ - 209, /* (72) qtime ::= QTIME INTEGER */ - 210, /* (73) users ::= */ - 210, /* (74) users ::= USERS INTEGER */ - 211, /* (75) conns ::= */ - 211, /* (76) conns ::= CONNS INTEGER */ - 212, /* (77) state ::= */ - 212, /* (78) state ::= STATE ids */ - 199, /* (79) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ - 213, /* (80) keep ::= KEEP tagitemlist */ - 215, /* (81) cache ::= CACHE INTEGER */ - 216, /* (82) replica ::= REPLICA INTEGER */ - 217, /* (83) quorum ::= QUORUM INTEGER */ - 218, /* (84) days ::= DAYS INTEGER */ - 219, /* (85) minrows ::= MINROWS INTEGER */ - 220, /* (86) maxrows ::= MAXROWS INTEGER */ - 221, /* (87) blocks ::= BLOCKS INTEGER */ - 222, /* (88) ctime ::= CTIME INTEGER */ - 223, /* (89) wal ::= WAL INTEGER */ - 224, /* (90) fsync ::= FSYNC INTEGER */ - 225, /* (91) comp ::= COMP INTEGER */ - 226, /* (92) prec ::= PRECISION STRING */ - 227, /* (93) update ::= UPDATE INTEGER */ - 228, /* (94) cachelast ::= CACHELAST INTEGER */ - 229, /* (95) partitions ::= PARTITIONS INTEGER */ - 201, /* (96) db_optr ::= */ - 201, /* (97) db_optr ::= db_optr cache */ - 201, /* (98) db_optr ::= db_optr replica */ - 201, /* (99) db_optr ::= db_optr quorum */ - 201, /* (100) db_optr ::= db_optr days */ - 201, /* (101) db_optr ::= db_optr minrows */ - 201, /* (102) db_optr ::= db_optr maxrows */ - 201, /* (103) db_optr ::= db_optr blocks */ - 201, /* (104) db_optr ::= db_optr ctime */ - 201, /* (105) db_optr ::= db_optr wal */ - 201, /* (106) db_optr ::= db_optr fsync */ - 201, /* (107) db_optr ::= db_optr comp */ - 201, /* (108) db_optr ::= db_optr prec */ - 201, /* (109) db_optr ::= db_optr keep */ - 201, /* (110) db_optr ::= db_optr update */ - 201, /* (111) db_optr ::= db_optr cachelast */ - 202, /* (112) topic_optr ::= db_optr */ - 202, /* (113) topic_optr ::= topic_optr partitions */ - 197, /* (114) alter_db_optr ::= */ - 197, /* (115) alter_db_optr ::= alter_db_optr replica */ - 197, /* (116) alter_db_optr ::= alter_db_optr quorum */ - 197, /* (117) alter_db_optr ::= alter_db_optr keep */ - 197, /* (118) alter_db_optr ::= alter_db_optr blocks */ - 197, /* (119) alter_db_optr ::= alter_db_optr comp */ - 197, /* (120) alter_db_optr ::= alter_db_optr wal */ - 197, /* (121) alter_db_optr ::= alter_db_optr fsync */ - 197, /* (122) alter_db_optr ::= alter_db_optr update */ - 197, /* (123) alter_db_optr ::= alter_db_optr cachelast */ - 198, /* (124) alter_topic_optr ::= alter_db_optr */ - 198, /* (125) alter_topic_optr ::= alter_topic_optr partitions */ - 203, /* (126) typename ::= ids */ - 203, /* (127) typename ::= ids LP signed RP */ - 203, /* (128) typename ::= ids UNSIGNED */ - 230, /* (129) signed ::= INTEGER */ - 230, /* (130) signed ::= PLUS INTEGER */ - 230, /* (131) signed ::= MINUS INTEGER */ - 192, /* (132) cmd ::= CREATE TABLE create_table_args */ - 192, /* (133) cmd ::= CREATE TABLE create_stable_args */ - 192, /* (134) cmd ::= CREATE STABLE create_stable_args */ - 192, /* (135) cmd ::= CREATE TABLE create_table_list */ - 233, /* (136) create_table_list ::= create_from_stable */ - 233, /* (137) create_table_list ::= create_table_list create_from_stable */ - 231, /* (138) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ - 232, /* (139) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ - 234, /* (140) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ - 234, /* (141) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ - 236, /* (142) tagNamelist ::= tagNamelist COMMA ids */ - 236, /* (143) tagNamelist ::= ids */ - 231, /* (144) create_table_args ::= ifnotexists ids cpxName AS select */ - 235, /* (145) columnlist ::= columnlist COMMA column */ - 235, /* (146) columnlist ::= column */ - 238, /* (147) column ::= ids typename */ - 214, /* (148) tagitemlist ::= tagitemlist COMMA tagitem */ - 214, /* (149) tagitemlist ::= tagitem */ - 239, /* (150) tagitem ::= INTEGER */ - 239, /* (151) tagitem ::= FLOAT */ - 239, /* (152) tagitem ::= STRING */ - 239, /* (153) tagitem ::= BOOL */ - 239, /* (154) tagitem ::= NULL */ - 239, /* (155) tagitem ::= MINUS INTEGER */ - 239, /* (156) tagitem ::= MINUS FLOAT */ - 239, /* (157) tagitem ::= PLUS INTEGER */ - 239, /* (158) tagitem ::= PLUS FLOAT */ - 237, /* (159) select ::= SELECT selcollist from where_opt interval_opt session_option fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */ - 252, /* (160) union ::= select */ - 252, /* (161) union ::= LP union RP */ - 252, /* (162) union ::= union UNION ALL select */ - 252, /* (163) union ::= union UNION ALL LP select RP */ - 192, /* (164) cmd ::= union */ - 237, /* (165) select ::= SELECT selcollist */ - 253, /* (166) sclp ::= selcollist COMMA */ - 253, /* (167) sclp ::= */ - 240, /* (168) selcollist ::= sclp distinct expr as */ - 240, /* (169) selcollist ::= sclp STAR */ - 256, /* (170) as ::= AS ids */ - 256, /* (171) as ::= ids */ - 256, /* (172) as ::= */ - 254, /* (173) distinct ::= DISTINCT */ - 254, /* (174) distinct ::= */ - 241, /* (175) from ::= FROM tablelist */ - 257, /* (176) tablelist ::= ids cpxName */ - 257, /* (177) tablelist ::= ids cpxName ids */ - 257, /* (178) tablelist ::= tablelist COMMA ids cpxName */ - 257, /* (179) tablelist ::= tablelist COMMA ids cpxName ids */ - 258, /* (180) tmvar ::= VARIABLE */ - 243, /* (181) interval_opt ::= INTERVAL LP tmvar RP */ - 243, /* (182) interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ - 243, /* (183) interval_opt ::= */ - 244, /* (184) session_option ::= */ - 244, /* (185) session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ - 245, /* (186) fill_opt ::= */ - 245, /* (187) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ - 245, /* (188) fill_opt ::= FILL LP ID RP */ - 246, /* (189) sliding_opt ::= SLIDING LP tmvar RP */ - 246, /* (190) sliding_opt ::= */ - 248, /* (191) orderby_opt ::= */ - 248, /* (192) orderby_opt ::= ORDER BY sortlist */ - 259, /* (193) sortlist ::= sortlist COMMA item sortorder */ - 259, /* (194) sortlist ::= item sortorder */ - 261, /* (195) item ::= ids cpxName */ - 262, /* (196) sortorder ::= ASC */ - 262, /* (197) sortorder ::= DESC */ - 262, /* (198) sortorder ::= */ - 247, /* (199) groupby_opt ::= */ - 247, /* (200) groupby_opt ::= GROUP BY grouplist */ - 263, /* (201) grouplist ::= grouplist COMMA item */ - 263, /* (202) grouplist ::= item */ - 249, /* (203) having_opt ::= */ - 249, /* (204) having_opt ::= HAVING expr */ - 251, /* (205) limit_opt ::= */ - 251, /* (206) limit_opt ::= LIMIT signed */ - 251, /* (207) limit_opt ::= LIMIT signed OFFSET signed */ - 251, /* (208) limit_opt ::= LIMIT signed COMMA signed */ - 250, /* (209) slimit_opt ::= */ - 250, /* (210) slimit_opt ::= SLIMIT signed */ - 250, /* (211) slimit_opt ::= SLIMIT signed SOFFSET signed */ - 250, /* (212) slimit_opt ::= SLIMIT signed COMMA signed */ - 242, /* (213) where_opt ::= */ - 242, /* (214) where_opt ::= WHERE expr */ - 255, /* (215) expr ::= LP expr RP */ - 255, /* (216) expr ::= ID */ - 255, /* (217) expr ::= ID DOT ID */ - 255, /* (218) expr ::= ID DOT STAR */ - 255, /* (219) expr ::= INTEGER */ - 255, /* (220) expr ::= MINUS INTEGER */ - 255, /* (221) expr ::= PLUS INTEGER */ - 255, /* (222) expr ::= FLOAT */ - 255, /* (223) expr ::= MINUS FLOAT */ - 255, /* (224) expr ::= PLUS FLOAT */ - 255, /* (225) expr ::= STRING */ - 255, /* (226) expr ::= NOW */ - 255, /* (227) expr ::= VARIABLE */ - 255, /* (228) expr ::= BOOL */ - 255, /* (229) expr ::= ID LP exprlist RP */ - 255, /* (230) expr ::= ID LP STAR RP */ - 255, /* (231) expr ::= expr IS NULL */ - 255, /* (232) expr ::= expr IS NOT NULL */ - 255, /* (233) expr ::= expr LT expr */ - 255, /* (234) expr ::= expr GT expr */ - 255, /* (235) expr ::= expr LE expr */ - 255, /* (236) expr ::= expr GE expr */ - 255, /* (237) expr ::= expr NE expr */ - 255, /* (238) expr ::= expr EQ expr */ - 255, /* (239) expr ::= expr BETWEEN expr AND expr */ - 255, /* (240) expr ::= expr AND expr */ - 255, /* (241) expr ::= expr OR expr */ - 255, /* (242) expr ::= expr PLUS expr */ - 255, /* (243) expr ::= expr MINUS expr */ - 255, /* (244) expr ::= expr STAR expr */ - 255, /* (245) expr ::= expr SLASH expr */ - 255, /* (246) expr ::= expr REM expr */ - 255, /* (247) expr ::= expr LIKE expr */ - 255, /* (248) expr ::= expr IN LP exprlist RP */ - 264, /* (249) exprlist ::= exprlist COMMA expritem */ - 264, /* (250) exprlist ::= expritem */ - 265, /* (251) expritem ::= expr */ - 265, /* (252) expritem ::= */ - 192, /* (253) cmd ::= RESET QUERY CACHE */ - 192, /* (254) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ - 192, /* (255) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ - 192, /* (256) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ - 192, /* (257) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ - 192, /* (258) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ - 192, /* (259) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ - 192, /* (260) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ - 192, /* (261) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ - 192, /* (262) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ - 192, /* (263) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ - 192, /* (264) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ - 192, /* (265) cmd ::= KILL CONNECTION INTEGER */ - 192, /* (266) cmd ::= KILL STREAM INTEGER COLON INTEGER */ - 192, /* (267) cmd ::= KILL QUERY INTEGER COLON INTEGER */ + 190, /* (0) program ::= cmd */ + 191, /* (1) cmd ::= SHOW DATABASES */ + 191, /* (2) cmd ::= SHOW TOPICS */ + 191, /* (3) cmd ::= SHOW FUNCTIONS */ + 191, /* (4) cmd ::= SHOW MNODES */ + 191, /* (5) cmd ::= SHOW DNODES */ + 191, /* (6) cmd ::= SHOW ACCOUNTS */ + 191, /* (7) cmd ::= SHOW USERS */ + 191, /* (8) cmd ::= SHOW MODULES */ + 191, /* (9) cmd ::= SHOW QUERIES */ + 191, /* (10) cmd ::= SHOW CONNECTIONS */ + 191, /* (11) cmd ::= SHOW STREAMS */ + 191, /* (12) cmd ::= SHOW VARIABLES */ + 191, /* (13) cmd ::= SHOW SCORES */ + 191, /* (14) cmd ::= SHOW GRANTS */ + 191, /* (15) cmd ::= SHOW VNODES */ + 191, /* (16) cmd ::= SHOW VNODES IPTOKEN */ + 192, /* (17) dbPrefix ::= */ + 192, /* (18) dbPrefix ::= ids DOT */ + 194, /* (19) cpxName ::= */ + 194, /* (20) cpxName ::= DOT ids */ + 191, /* (21) cmd ::= SHOW CREATE TABLE ids cpxName */ + 191, /* (22) cmd ::= SHOW CREATE DATABASE ids */ + 191, /* (23) cmd ::= SHOW dbPrefix TABLES */ + 191, /* (24) cmd ::= SHOW dbPrefix TABLES LIKE ids */ + 191, /* (25) cmd ::= SHOW dbPrefix STABLES */ + 191, /* (26) cmd ::= SHOW dbPrefix STABLES LIKE ids */ + 191, /* (27) cmd ::= SHOW dbPrefix VGROUPS */ + 191, /* (28) cmd ::= SHOW dbPrefix VGROUPS ids */ + 191, /* (29) cmd ::= DROP TABLE ifexists ids cpxName */ + 191, /* (30) cmd ::= DROP STABLE ifexists ids cpxName */ + 191, /* (31) cmd ::= DROP DATABASE ifexists ids */ + 191, /* (32) cmd ::= DROP TOPIC ifexists ids */ + 191, /* (33) cmd ::= DROP FUNCTION ids */ + 191, /* (34) cmd ::= DROP DNODE ids */ + 191, /* (35) cmd ::= DROP USER ids */ + 191, /* (36) cmd ::= DROP ACCOUNT ids */ + 191, /* (37) cmd ::= USE ids */ + 191, /* (38) cmd ::= DESCRIBE ids cpxName */ + 191, /* (39) cmd ::= ALTER USER ids PASS ids */ + 191, /* (40) cmd ::= ALTER USER ids PRIVILEGE ids */ + 191, /* (41) cmd ::= ALTER DNODE ids ids */ + 191, /* (42) cmd ::= ALTER DNODE ids ids ids */ + 191, /* (43) cmd ::= ALTER LOCAL ids */ + 191, /* (44) cmd ::= ALTER LOCAL ids ids */ + 191, /* (45) cmd ::= ALTER DATABASE ids alter_db_optr */ + 191, /* (46) cmd ::= ALTER TOPIC ids alter_topic_optr */ + 191, /* (47) cmd ::= ALTER ACCOUNT ids acct_optr */ + 191, /* (48) cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ + 193, /* (49) ids ::= ID */ + 193, /* (50) ids ::= STRING */ + 195, /* (51) ifexists ::= IF EXISTS */ + 195, /* (52) ifexists ::= */ + 199, /* (53) ifnotexists ::= IF NOT EXISTS */ + 199, /* (54) ifnotexists ::= */ + 191, /* (55) cmd ::= CREATE DNODE ids */ + 191, /* (56) cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ + 191, /* (57) cmd ::= CREATE DATABASE ifnotexists ids db_optr */ + 191, /* (58) cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ + 191, /* (59) cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename */ + 191, /* (60) cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename */ + 191, /* (61) cmd ::= CREATE USER ids PASS ids */ + 203, /* (62) pps ::= */ + 203, /* (63) pps ::= PPS INTEGER */ + 204, /* (64) tseries ::= */ + 204, /* (65) tseries ::= TSERIES INTEGER */ + 205, /* (66) dbs ::= */ + 205, /* (67) dbs ::= DBS INTEGER */ + 206, /* (68) streams ::= */ + 206, /* (69) streams ::= STREAMS INTEGER */ + 207, /* (70) storage ::= */ + 207, /* (71) storage ::= STORAGE INTEGER */ + 208, /* (72) qtime ::= */ + 208, /* (73) qtime ::= QTIME INTEGER */ + 209, /* (74) users ::= */ + 209, /* (75) users ::= USERS INTEGER */ + 210, /* (76) conns ::= */ + 210, /* (77) conns ::= CONNS INTEGER */ + 211, /* (78) state ::= */ + 211, /* (79) state ::= STATE ids */ + 198, /* (80) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ + 212, /* (81) keep ::= KEEP tagitemlist */ + 214, /* (82) cache ::= CACHE INTEGER */ + 215, /* (83) replica ::= REPLICA INTEGER */ + 216, /* (84) quorum ::= QUORUM INTEGER */ + 217, /* (85) days ::= DAYS INTEGER */ + 218, /* (86) minrows ::= MINROWS INTEGER */ + 219, /* (87) maxrows ::= MAXROWS INTEGER */ + 220, /* (88) blocks ::= BLOCKS INTEGER */ + 221, /* (89) ctime ::= CTIME INTEGER */ + 222, /* (90) wal ::= WAL INTEGER */ + 223, /* (91) fsync ::= FSYNC INTEGER */ + 224, /* (92) comp ::= COMP INTEGER */ + 225, /* (93) prec ::= PRECISION STRING */ + 226, /* (94) update ::= UPDATE INTEGER */ + 227, /* (95) cachelast ::= CACHELAST INTEGER */ + 228, /* (96) partitions ::= PARTITIONS INTEGER */ + 200, /* (97) db_optr ::= */ + 200, /* (98) db_optr ::= db_optr cache */ + 200, /* (99) db_optr ::= db_optr replica */ + 200, /* (100) db_optr ::= db_optr quorum */ + 200, /* (101) db_optr ::= db_optr days */ + 200, /* (102) db_optr ::= db_optr minrows */ + 200, /* (103) db_optr ::= db_optr maxrows */ + 200, /* (104) db_optr ::= db_optr blocks */ + 200, /* (105) db_optr ::= db_optr ctime */ + 200, /* (106) db_optr ::= db_optr wal */ + 200, /* (107) db_optr ::= db_optr fsync */ + 200, /* (108) db_optr ::= db_optr comp */ + 200, /* (109) db_optr ::= db_optr prec */ + 200, /* (110) db_optr ::= db_optr keep */ + 200, /* (111) db_optr ::= db_optr update */ + 200, /* (112) db_optr ::= db_optr cachelast */ + 201, /* (113) topic_optr ::= db_optr */ + 201, /* (114) topic_optr ::= topic_optr partitions */ + 196, /* (115) alter_db_optr ::= */ + 196, /* (116) alter_db_optr ::= alter_db_optr replica */ + 196, /* (117) alter_db_optr ::= alter_db_optr quorum */ + 196, /* (118) alter_db_optr ::= alter_db_optr keep */ + 196, /* (119) alter_db_optr ::= alter_db_optr blocks */ + 196, /* (120) alter_db_optr ::= alter_db_optr comp */ + 196, /* (121) alter_db_optr ::= alter_db_optr wal */ + 196, /* (122) alter_db_optr ::= alter_db_optr fsync */ + 196, /* (123) alter_db_optr ::= alter_db_optr update */ + 196, /* (124) alter_db_optr ::= alter_db_optr cachelast */ + 197, /* (125) alter_topic_optr ::= alter_db_optr */ + 197, /* (126) alter_topic_optr ::= alter_topic_optr partitions */ + 202, /* (127) typename ::= ids */ + 202, /* (128) typename ::= ids LP signed RP */ + 202, /* (129) typename ::= ids UNSIGNED */ + 229, /* (130) signed ::= INTEGER */ + 229, /* (131) signed ::= PLUS INTEGER */ + 229, /* (132) signed ::= MINUS INTEGER */ + 191, /* (133) cmd ::= CREATE TABLE create_table_args */ + 191, /* (134) cmd ::= CREATE TABLE create_stable_args */ + 191, /* (135) cmd ::= CREATE STABLE create_stable_args */ + 191, /* (136) cmd ::= CREATE TABLE create_table_list */ + 232, /* (137) create_table_list ::= create_from_stable */ + 232, /* (138) create_table_list ::= create_table_list create_from_stable */ + 230, /* (139) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ + 231, /* (140) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ + 233, /* (141) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ + 233, /* (142) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ + 235, /* (143) tagNamelist ::= tagNamelist COMMA ids */ + 235, /* (144) tagNamelist ::= ids */ + 230, /* (145) create_table_args ::= ifnotexists ids cpxName AS select */ + 234, /* (146) columnlist ::= columnlist COMMA column */ + 234, /* (147) columnlist ::= column */ + 237, /* (148) column ::= ids typename */ + 213, /* (149) tagitemlist ::= tagitemlist COMMA tagitem */ + 213, /* (150) tagitemlist ::= tagitem */ + 238, /* (151) tagitem ::= INTEGER */ + 238, /* (152) tagitem ::= FLOAT */ + 238, /* (153) tagitem ::= STRING */ + 238, /* (154) tagitem ::= BOOL */ + 238, /* (155) tagitem ::= NULL */ + 238, /* (156) tagitem ::= MINUS INTEGER */ + 238, /* (157) tagitem ::= MINUS FLOAT */ + 238, /* (158) tagitem ::= PLUS INTEGER */ + 238, /* (159) tagitem ::= PLUS FLOAT */ + 236, /* (160) select ::= SELECT selcollist from where_opt interval_opt session_option fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */ + 236, /* (161) select ::= LP select RP */ + 251, /* (162) union ::= select */ + 251, /* (163) union ::= union UNION ALL select */ + 191, /* (164) cmd ::= union */ + 236, /* (165) select ::= SELECT selcollist */ + 252, /* (166) sclp ::= selcollist COMMA */ + 252, /* (167) sclp ::= */ + 239, /* (168) selcollist ::= sclp distinct expr as */ + 239, /* (169) selcollist ::= sclp STAR */ + 255, /* (170) as ::= AS ids */ + 255, /* (171) as ::= ids */ + 255, /* (172) as ::= */ + 253, /* (173) distinct ::= DISTINCT */ + 253, /* (174) distinct ::= */ + 240, /* (175) from ::= FROM tablelist */ + 240, /* (176) from ::= FROM LP union RP */ + 256, /* (177) tablelist ::= ids cpxName */ + 256, /* (178) tablelist ::= ids cpxName ids */ + 256, /* (179) tablelist ::= tablelist COMMA ids cpxName */ + 256, /* (180) tablelist ::= tablelist COMMA ids cpxName ids */ + 257, /* (181) tmvar ::= VARIABLE */ + 242, /* (182) interval_opt ::= INTERVAL LP tmvar RP */ + 242, /* (183) interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ + 242, /* (184) interval_opt ::= */ + 243, /* (185) session_option ::= */ + 243, /* (186) session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ + 244, /* (187) fill_opt ::= */ + 244, /* (188) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ + 244, /* (189) fill_opt ::= FILL LP ID RP */ + 245, /* (190) sliding_opt ::= SLIDING LP tmvar RP */ + 245, /* (191) sliding_opt ::= */ + 247, /* (192) orderby_opt ::= */ + 247, /* (193) orderby_opt ::= ORDER BY sortlist */ + 258, /* (194) sortlist ::= sortlist COMMA item sortorder */ + 258, /* (195) sortlist ::= item sortorder */ + 260, /* (196) item ::= ids cpxName */ + 261, /* (197) sortorder ::= ASC */ + 261, /* (198) sortorder ::= DESC */ + 261, /* (199) sortorder ::= */ + 246, /* (200) groupby_opt ::= */ + 246, /* (201) groupby_opt ::= GROUP BY grouplist */ + 262, /* (202) grouplist ::= grouplist COMMA item */ + 262, /* (203) grouplist ::= item */ + 248, /* (204) having_opt ::= */ + 248, /* (205) having_opt ::= HAVING expr */ + 250, /* (206) limit_opt ::= */ + 250, /* (207) limit_opt ::= LIMIT signed */ + 250, /* (208) limit_opt ::= LIMIT signed OFFSET signed */ + 250, /* (209) limit_opt ::= LIMIT signed COMMA signed */ + 249, /* (210) slimit_opt ::= */ + 249, /* (211) slimit_opt ::= SLIMIT signed */ + 249, /* (212) slimit_opt ::= SLIMIT signed SOFFSET signed */ + 249, /* (213) slimit_opt ::= SLIMIT signed COMMA signed */ + 241, /* (214) where_opt ::= */ + 241, /* (215) where_opt ::= WHERE expr */ + 254, /* (216) expr ::= LP expr RP */ + 254, /* (217) expr ::= ID */ + 254, /* (218) expr ::= ID DOT ID */ + 254, /* (219) expr ::= ID DOT STAR */ + 254, /* (220) expr ::= INTEGER */ + 254, /* (221) expr ::= MINUS INTEGER */ + 254, /* (222) expr ::= PLUS INTEGER */ + 254, /* (223) expr ::= FLOAT */ + 254, /* (224) expr ::= MINUS FLOAT */ + 254, /* (225) expr ::= PLUS FLOAT */ + 254, /* (226) expr ::= STRING */ + 254, /* (227) expr ::= NOW */ + 254, /* (228) expr ::= VARIABLE */ + 254, /* (229) expr ::= BOOL */ + 254, /* (230) expr ::= ID LP exprlist RP */ + 254, /* (231) expr ::= ID LP STAR RP */ + 254, /* (232) expr ::= expr IS NULL */ + 254, /* (233) expr ::= expr IS NOT NULL */ + 254, /* (234) expr ::= expr LT expr */ + 254, /* (235) expr ::= expr GT expr */ + 254, /* (236) expr ::= expr LE expr */ + 254, /* (237) expr ::= expr GE expr */ + 254, /* (238) expr ::= expr NE expr */ + 254, /* (239) expr ::= expr EQ expr */ + 254, /* (240) expr ::= expr BETWEEN expr AND expr */ + 254, /* (241) expr ::= expr AND expr */ + 254, /* (242) expr ::= expr OR expr */ + 254, /* (243) expr ::= expr PLUS expr */ + 254, /* (244) expr ::= expr MINUS expr */ + 254, /* (245) expr ::= expr STAR expr */ + 254, /* (246) expr ::= expr SLASH expr */ + 254, /* (247) expr ::= expr REM expr */ + 254, /* (248) expr ::= expr LIKE expr */ + 254, /* (249) expr ::= expr IN LP exprlist RP */ + 263, /* (250) exprlist ::= exprlist COMMA expritem */ + 263, /* (251) exprlist ::= expritem */ + 264, /* (252) expritem ::= expr */ + 264, /* (253) expritem ::= */ + 191, /* (254) cmd ::= RESET QUERY CACHE */ + 191, /* (255) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ + 191, /* (256) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ + 191, /* (257) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ + 191, /* (258) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ + 191, /* (259) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ + 191, /* (260) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ + 191, /* (261) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ + 191, /* (262) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ + 191, /* (263) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ + 191, /* (264) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ + 191, /* (265) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ + 191, /* (266) cmd ::= KILL CONNECTION INTEGER */ + 191, /* (267) cmd ::= KILL STREAM INTEGER COLON INTEGER */ + 191, /* (268) cmd ::= KILL QUERY INTEGER COLON INTEGER */ }; /* For rule J, yyRuleInfoNRhs[J] contains the negative of the number @@ -2099,110 +2105,110 @@ static const signed char yyRuleInfoNRhs[] = { -5, /* (57) cmd ::= CREATE DATABASE ifnotexists ids db_optr */ -5, /* (58) cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ -7, /* (59) cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename */ - -5, /* (60) cmd ::= CREATE USER ids PASS ids */ - 0, /* (61) pps ::= */ - -2, /* (62) pps ::= PPS INTEGER */ - 0, /* (63) tseries ::= */ - -2, /* (64) tseries ::= TSERIES INTEGER */ - 0, /* (65) dbs ::= */ - -2, /* (66) dbs ::= DBS INTEGER */ - 0, /* (67) streams ::= */ - -2, /* (68) streams ::= STREAMS INTEGER */ - 0, /* (69) storage ::= */ - -2, /* (70) storage ::= STORAGE INTEGER */ - 0, /* (71) qtime ::= */ - -2, /* (72) qtime ::= QTIME INTEGER */ - 0, /* (73) users ::= */ - -2, /* (74) users ::= USERS INTEGER */ - 0, /* (75) conns ::= */ - -2, /* (76) conns ::= CONNS INTEGER */ - 0, /* (77) state ::= */ - -2, /* (78) state ::= STATE ids */ - -9, /* (79) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ - -2, /* (80) keep ::= KEEP tagitemlist */ - -2, /* (81) cache ::= CACHE INTEGER */ - -2, /* (82) replica ::= REPLICA INTEGER */ - -2, /* (83) quorum ::= QUORUM INTEGER */ - -2, /* (84) days ::= DAYS INTEGER */ - -2, /* (85) minrows ::= MINROWS INTEGER */ - -2, /* (86) maxrows ::= MAXROWS INTEGER */ - -2, /* (87) blocks ::= BLOCKS INTEGER */ - -2, /* (88) ctime ::= CTIME INTEGER */ - -2, /* (89) wal ::= WAL INTEGER */ - -2, /* (90) fsync ::= FSYNC INTEGER */ - -2, /* (91) comp ::= COMP INTEGER */ - -2, /* (92) prec ::= PRECISION STRING */ - -2, /* (93) update ::= UPDATE INTEGER */ - -2, /* (94) cachelast ::= CACHELAST INTEGER */ - -2, /* (95) partitions ::= PARTITIONS INTEGER */ - 0, /* (96) db_optr ::= */ - -2, /* (97) db_optr ::= db_optr cache */ - -2, /* (98) db_optr ::= db_optr replica */ - -2, /* (99) db_optr ::= db_optr quorum */ - -2, /* (100) db_optr ::= db_optr days */ - -2, /* (101) db_optr ::= db_optr minrows */ - -2, /* (102) db_optr ::= db_optr maxrows */ - -2, /* (103) db_optr ::= db_optr blocks */ - -2, /* (104) db_optr ::= db_optr ctime */ - -2, /* (105) db_optr ::= db_optr wal */ - -2, /* (106) db_optr ::= db_optr fsync */ - -2, /* (107) db_optr ::= db_optr comp */ - -2, /* (108) db_optr ::= db_optr prec */ - -2, /* (109) db_optr ::= db_optr keep */ - -2, /* (110) db_optr ::= db_optr update */ - -2, /* (111) db_optr ::= db_optr cachelast */ - -1, /* (112) topic_optr ::= db_optr */ - -2, /* (113) topic_optr ::= topic_optr partitions */ - 0, /* (114) alter_db_optr ::= */ - -2, /* (115) alter_db_optr ::= alter_db_optr replica */ - -2, /* (116) alter_db_optr ::= alter_db_optr quorum */ - -2, /* (117) alter_db_optr ::= alter_db_optr keep */ - -2, /* (118) alter_db_optr ::= alter_db_optr blocks */ - -2, /* (119) alter_db_optr ::= alter_db_optr comp */ - -2, /* (120) alter_db_optr ::= alter_db_optr wal */ - -2, /* (121) alter_db_optr ::= alter_db_optr fsync */ - -2, /* (122) alter_db_optr ::= alter_db_optr update */ - -2, /* (123) alter_db_optr ::= alter_db_optr cachelast */ - -1, /* (124) alter_topic_optr ::= alter_db_optr */ - -2, /* (125) alter_topic_optr ::= alter_topic_optr partitions */ - -1, /* (126) typename ::= ids */ - -4, /* (127) typename ::= ids LP signed RP */ - -2, /* (128) typename ::= ids UNSIGNED */ - -1, /* (129) signed ::= INTEGER */ - -2, /* (130) signed ::= PLUS INTEGER */ - -2, /* (131) signed ::= MINUS INTEGER */ - -3, /* (132) cmd ::= CREATE TABLE create_table_args */ - -3, /* (133) cmd ::= CREATE TABLE create_stable_args */ - -3, /* (134) cmd ::= CREATE STABLE create_stable_args */ - -3, /* (135) cmd ::= CREATE TABLE create_table_list */ - -1, /* (136) create_table_list ::= create_from_stable */ - -2, /* (137) create_table_list ::= create_table_list create_from_stable */ - -6, /* (138) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ - -10, /* (139) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ - -10, /* (140) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ - -13, /* (141) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ - -3, /* (142) tagNamelist ::= tagNamelist COMMA ids */ - -1, /* (143) tagNamelist ::= ids */ - -5, /* (144) create_table_args ::= ifnotexists ids cpxName AS select */ - -3, /* (145) columnlist ::= columnlist COMMA column */ - -1, /* (146) columnlist ::= column */ - -2, /* (147) column ::= ids typename */ - -3, /* (148) tagitemlist ::= tagitemlist COMMA tagitem */ - -1, /* (149) tagitemlist ::= tagitem */ - -1, /* (150) tagitem ::= INTEGER */ - -1, /* (151) tagitem ::= FLOAT */ - -1, /* (152) tagitem ::= STRING */ - -1, /* (153) tagitem ::= BOOL */ - -1, /* (154) tagitem ::= NULL */ - -2, /* (155) tagitem ::= MINUS INTEGER */ - -2, /* (156) tagitem ::= MINUS FLOAT */ - -2, /* (157) tagitem ::= PLUS INTEGER */ - -2, /* (158) tagitem ::= PLUS FLOAT */ - -13, /* (159) select ::= SELECT selcollist from where_opt interval_opt session_option fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */ - -1, /* (160) union ::= select */ - -3, /* (161) union ::= LP union RP */ - -4, /* (162) union ::= union UNION ALL select */ - -6, /* (163) union ::= union UNION ALL LP select RP */ + -8, /* (60) cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename */ + -5, /* (61) cmd ::= CREATE USER ids PASS ids */ + 0, /* (62) pps ::= */ + -2, /* (63) pps ::= PPS INTEGER */ + 0, /* (64) tseries ::= */ + -2, /* (65) tseries ::= TSERIES INTEGER */ + 0, /* (66) dbs ::= */ + -2, /* (67) dbs ::= DBS INTEGER */ + 0, /* (68) streams ::= */ + -2, /* (69) streams ::= STREAMS INTEGER */ + 0, /* (70) storage ::= */ + -2, /* (71) storage ::= STORAGE INTEGER */ + 0, /* (72) qtime ::= */ + -2, /* (73) qtime ::= QTIME INTEGER */ + 0, /* (74) users ::= */ + -2, /* (75) users ::= USERS INTEGER */ + 0, /* (76) conns ::= */ + -2, /* (77) conns ::= CONNS INTEGER */ + 0, /* (78) state ::= */ + -2, /* (79) state ::= STATE ids */ + -9, /* (80) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ + -2, /* (81) keep ::= KEEP tagitemlist */ + -2, /* (82) cache ::= CACHE INTEGER */ + -2, /* (83) replica ::= REPLICA INTEGER */ + -2, /* (84) quorum ::= QUORUM INTEGER */ + -2, /* (85) days ::= DAYS INTEGER */ + -2, /* (86) minrows ::= MINROWS INTEGER */ + -2, /* (87) maxrows ::= MAXROWS INTEGER */ + -2, /* (88) blocks ::= BLOCKS INTEGER */ + -2, /* (89) ctime ::= CTIME INTEGER */ + -2, /* (90) wal ::= WAL INTEGER */ + -2, /* (91) fsync ::= FSYNC INTEGER */ + -2, /* (92) comp ::= COMP INTEGER */ + -2, /* (93) prec ::= PRECISION STRING */ + -2, /* (94) update ::= UPDATE INTEGER */ + -2, /* (95) cachelast ::= CACHELAST INTEGER */ + -2, /* (96) partitions ::= PARTITIONS INTEGER */ + 0, /* (97) db_optr ::= */ + -2, /* (98) db_optr ::= db_optr cache */ + -2, /* (99) db_optr ::= db_optr replica */ + -2, /* (100) db_optr ::= db_optr quorum */ + -2, /* (101) db_optr ::= db_optr days */ + -2, /* (102) db_optr ::= db_optr minrows */ + -2, /* (103) db_optr ::= db_optr maxrows */ + -2, /* (104) db_optr ::= db_optr blocks */ + -2, /* (105) db_optr ::= db_optr ctime */ + -2, /* (106) db_optr ::= db_optr wal */ + -2, /* (107) db_optr ::= db_optr fsync */ + -2, /* (108) db_optr ::= db_optr comp */ + -2, /* (109) db_optr ::= db_optr prec */ + -2, /* (110) db_optr ::= db_optr keep */ + -2, /* (111) db_optr ::= db_optr update */ + -2, /* (112) db_optr ::= db_optr cachelast */ + -1, /* (113) topic_optr ::= db_optr */ + -2, /* (114) topic_optr ::= topic_optr partitions */ + 0, /* (115) alter_db_optr ::= */ + -2, /* (116) alter_db_optr ::= alter_db_optr replica */ + -2, /* (117) alter_db_optr ::= alter_db_optr quorum */ + -2, /* (118) alter_db_optr ::= alter_db_optr keep */ + -2, /* (119) alter_db_optr ::= alter_db_optr blocks */ + -2, /* (120) alter_db_optr ::= alter_db_optr comp */ + -2, /* (121) alter_db_optr ::= alter_db_optr wal */ + -2, /* (122) alter_db_optr ::= alter_db_optr fsync */ + -2, /* (123) alter_db_optr ::= alter_db_optr update */ + -2, /* (124) alter_db_optr ::= alter_db_optr cachelast */ + -1, /* (125) alter_topic_optr ::= alter_db_optr */ + -2, /* (126) alter_topic_optr ::= alter_topic_optr partitions */ + -1, /* (127) typename ::= ids */ + -4, /* (128) typename ::= ids LP signed RP */ + -2, /* (129) typename ::= ids UNSIGNED */ + -1, /* (130) signed ::= INTEGER */ + -2, /* (131) signed ::= PLUS INTEGER */ + -2, /* (132) signed ::= MINUS INTEGER */ + -3, /* (133) cmd ::= CREATE TABLE create_table_args */ + -3, /* (134) cmd ::= CREATE TABLE create_stable_args */ + -3, /* (135) cmd ::= CREATE STABLE create_stable_args */ + -3, /* (136) cmd ::= CREATE TABLE create_table_list */ + -1, /* (137) create_table_list ::= create_from_stable */ + -2, /* (138) create_table_list ::= create_table_list create_from_stable */ + -6, /* (139) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ + -10, /* (140) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ + -10, /* (141) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ + -13, /* (142) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ + -3, /* (143) tagNamelist ::= tagNamelist COMMA ids */ + -1, /* (144) tagNamelist ::= ids */ + -5, /* (145) create_table_args ::= ifnotexists ids cpxName AS select */ + -3, /* (146) columnlist ::= columnlist COMMA column */ + -1, /* (147) columnlist ::= column */ + -2, /* (148) column ::= ids typename */ + -3, /* (149) tagitemlist ::= tagitemlist COMMA tagitem */ + -1, /* (150) tagitemlist ::= tagitem */ + -1, /* (151) tagitem ::= INTEGER */ + -1, /* (152) tagitem ::= FLOAT */ + -1, /* (153) tagitem ::= STRING */ + -1, /* (154) tagitem ::= BOOL */ + -1, /* (155) tagitem ::= NULL */ + -2, /* (156) tagitem ::= MINUS INTEGER */ + -2, /* (157) tagitem ::= MINUS FLOAT */ + -2, /* (158) tagitem ::= PLUS INTEGER */ + -2, /* (159) tagitem ::= PLUS FLOAT */ + -13, /* (160) select ::= SELECT selcollist from where_opt interval_opt session_option fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */ + -3, /* (161) select ::= LP select RP */ + -1, /* (162) union ::= select */ + -4, /* (163) union ::= union UNION ALL select */ -1, /* (164) cmd ::= union */ -2, /* (165) select ::= SELECT selcollist */ -2, /* (166) sclp ::= selcollist COMMA */ @@ -2215,98 +2221,99 @@ static const signed char yyRuleInfoNRhs[] = { -1, /* (173) distinct ::= DISTINCT */ 0, /* (174) distinct ::= */ -2, /* (175) from ::= FROM tablelist */ - -2, /* (176) tablelist ::= ids cpxName */ - -3, /* (177) tablelist ::= ids cpxName ids */ - -4, /* (178) tablelist ::= tablelist COMMA ids cpxName */ - -5, /* (179) tablelist ::= tablelist COMMA ids cpxName ids */ - -1, /* (180) tmvar ::= VARIABLE */ - -4, /* (181) interval_opt ::= INTERVAL LP tmvar RP */ - -6, /* (182) interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ - 0, /* (183) interval_opt ::= */ - 0, /* (184) session_option ::= */ - -7, /* (185) session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ - 0, /* (186) fill_opt ::= */ - -6, /* (187) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ - -4, /* (188) fill_opt ::= FILL LP ID RP */ - -4, /* (189) sliding_opt ::= SLIDING LP tmvar RP */ - 0, /* (190) sliding_opt ::= */ - 0, /* (191) orderby_opt ::= */ - -3, /* (192) orderby_opt ::= ORDER BY sortlist */ - -4, /* (193) sortlist ::= sortlist COMMA item sortorder */ - -2, /* (194) sortlist ::= item sortorder */ - -2, /* (195) item ::= ids cpxName */ - -1, /* (196) sortorder ::= ASC */ - -1, /* (197) sortorder ::= DESC */ - 0, /* (198) sortorder ::= */ - 0, /* (199) groupby_opt ::= */ - -3, /* (200) groupby_opt ::= GROUP BY grouplist */ - -3, /* (201) grouplist ::= grouplist COMMA item */ - -1, /* (202) grouplist ::= item */ - 0, /* (203) having_opt ::= */ - -2, /* (204) having_opt ::= HAVING expr */ - 0, /* (205) limit_opt ::= */ - -2, /* (206) limit_opt ::= LIMIT signed */ - -4, /* (207) limit_opt ::= LIMIT signed OFFSET signed */ - -4, /* (208) limit_opt ::= LIMIT signed COMMA signed */ - 0, /* (209) slimit_opt ::= */ - -2, /* (210) slimit_opt ::= SLIMIT signed */ - -4, /* (211) slimit_opt ::= SLIMIT signed SOFFSET signed */ - -4, /* (212) slimit_opt ::= SLIMIT signed COMMA signed */ - 0, /* (213) where_opt ::= */ - -2, /* (214) where_opt ::= WHERE expr */ - -3, /* (215) expr ::= LP expr RP */ - -1, /* (216) expr ::= ID */ - -3, /* (217) expr ::= ID DOT ID */ - -3, /* (218) expr ::= ID DOT STAR */ - -1, /* (219) expr ::= INTEGER */ - -2, /* (220) expr ::= MINUS INTEGER */ - -2, /* (221) expr ::= PLUS INTEGER */ - -1, /* (222) expr ::= FLOAT */ - -2, /* (223) expr ::= MINUS FLOAT */ - -2, /* (224) expr ::= PLUS FLOAT */ - -1, /* (225) expr ::= STRING */ - -1, /* (226) expr ::= NOW */ - -1, /* (227) expr ::= VARIABLE */ - -1, /* (228) expr ::= BOOL */ - -4, /* (229) expr ::= ID LP exprlist RP */ - -4, /* (230) expr ::= ID LP STAR RP */ - -3, /* (231) expr ::= expr IS NULL */ - -4, /* (232) expr ::= expr IS NOT NULL */ - -3, /* (233) expr ::= expr LT expr */ - -3, /* (234) expr ::= expr GT expr */ - -3, /* (235) expr ::= expr LE expr */ - -3, /* (236) expr ::= expr GE expr */ - -3, /* (237) expr ::= expr NE expr */ - -3, /* (238) expr ::= expr EQ expr */ - -5, /* (239) expr ::= expr BETWEEN expr AND expr */ - -3, /* (240) expr ::= expr AND expr */ - -3, /* (241) expr ::= expr OR expr */ - -3, /* (242) expr ::= expr PLUS expr */ - -3, /* (243) expr ::= expr MINUS expr */ - -3, /* (244) expr ::= expr STAR expr */ - -3, /* (245) expr ::= expr SLASH expr */ - -3, /* (246) expr ::= expr REM expr */ - -3, /* (247) expr ::= expr LIKE expr */ - -5, /* (248) expr ::= expr IN LP exprlist RP */ - -3, /* (249) exprlist ::= exprlist COMMA expritem */ - -1, /* (250) exprlist ::= expritem */ - -1, /* (251) expritem ::= expr */ - 0, /* (252) expritem ::= */ - -3, /* (253) cmd ::= RESET QUERY CACHE */ - -7, /* (254) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ - -7, /* (255) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ - -7, /* (256) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ - -7, /* (257) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ - -8, /* (258) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ - -9, /* (259) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ - -7, /* (260) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ - -7, /* (261) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ - -7, /* (262) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ - -7, /* (263) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ - -8, /* (264) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ - -3, /* (265) cmd ::= KILL CONNECTION INTEGER */ - -5, /* (266) cmd ::= KILL STREAM INTEGER COLON INTEGER */ - -5, /* (267) cmd ::= KILL QUERY INTEGER COLON INTEGER */ + -4, /* (176) from ::= FROM LP union RP */ + -2, /* (177) tablelist ::= ids cpxName */ + -3, /* (178) tablelist ::= ids cpxName ids */ + -4, /* (179) tablelist ::= tablelist COMMA ids cpxName */ + -5, /* (180) tablelist ::= tablelist COMMA ids cpxName ids */ + -1, /* (181) tmvar ::= VARIABLE */ + -4, /* (182) interval_opt ::= INTERVAL LP tmvar RP */ + -6, /* (183) interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ + 0, /* (184) interval_opt ::= */ + 0, /* (185) session_option ::= */ + -7, /* (186) session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ + 0, /* (187) fill_opt ::= */ + -6, /* (188) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ + -4, /* (189) fill_opt ::= FILL LP ID RP */ + -4, /* (190) sliding_opt ::= SLIDING LP tmvar RP */ + 0, /* (191) sliding_opt ::= */ + 0, /* (192) orderby_opt ::= */ + -3, /* (193) orderby_opt ::= ORDER BY sortlist */ + -4, /* (194) sortlist ::= sortlist COMMA item sortorder */ + -2, /* (195) sortlist ::= item sortorder */ + -2, /* (196) item ::= ids cpxName */ + -1, /* (197) sortorder ::= ASC */ + -1, /* (198) sortorder ::= DESC */ + 0, /* (199) sortorder ::= */ + 0, /* (200) groupby_opt ::= */ + -3, /* (201) groupby_opt ::= GROUP BY grouplist */ + -3, /* (202) grouplist ::= grouplist COMMA item */ + -1, /* (203) grouplist ::= item */ + 0, /* (204) having_opt ::= */ + -2, /* (205) having_opt ::= HAVING expr */ + 0, /* (206) limit_opt ::= */ + -2, /* (207) limit_opt ::= LIMIT signed */ + -4, /* (208) limit_opt ::= LIMIT signed OFFSET signed */ + -4, /* (209) limit_opt ::= LIMIT signed COMMA signed */ + 0, /* (210) slimit_opt ::= */ + -2, /* (211) slimit_opt ::= SLIMIT signed */ + -4, /* (212) slimit_opt ::= SLIMIT signed SOFFSET signed */ + -4, /* (213) slimit_opt ::= SLIMIT signed COMMA signed */ + 0, /* (214) where_opt ::= */ + -2, /* (215) where_opt ::= WHERE expr */ + -3, /* (216) expr ::= LP expr RP */ + -1, /* (217) expr ::= ID */ + -3, /* (218) expr ::= ID DOT ID */ + -3, /* (219) expr ::= ID DOT STAR */ + -1, /* (220) expr ::= INTEGER */ + -2, /* (221) expr ::= MINUS INTEGER */ + -2, /* (222) expr ::= PLUS INTEGER */ + -1, /* (223) expr ::= FLOAT */ + -2, /* (224) expr ::= MINUS FLOAT */ + -2, /* (225) expr ::= PLUS FLOAT */ + -1, /* (226) expr ::= STRING */ + -1, /* (227) expr ::= NOW */ + -1, /* (228) expr ::= VARIABLE */ + -1, /* (229) expr ::= BOOL */ + -4, /* (230) expr ::= ID LP exprlist RP */ + -4, /* (231) expr ::= ID LP STAR RP */ + -3, /* (232) expr ::= expr IS NULL */ + -4, /* (233) expr ::= expr IS NOT NULL */ + -3, /* (234) expr ::= expr LT expr */ + -3, /* (235) expr ::= expr GT expr */ + -3, /* (236) expr ::= expr LE expr */ + -3, /* (237) expr ::= expr GE expr */ + -3, /* (238) expr ::= expr NE expr */ + -3, /* (239) expr ::= expr EQ expr */ + -5, /* (240) expr ::= expr BETWEEN expr AND expr */ + -3, /* (241) expr ::= expr AND expr */ + -3, /* (242) expr ::= expr OR expr */ + -3, /* (243) expr ::= expr PLUS expr */ + -3, /* (244) expr ::= expr MINUS expr */ + -3, /* (245) expr ::= expr STAR expr */ + -3, /* (246) expr ::= expr SLASH expr */ + -3, /* (247) expr ::= expr REM expr */ + -3, /* (248) expr ::= expr LIKE expr */ + -5, /* (249) expr ::= expr IN LP exprlist RP */ + -3, /* (250) exprlist ::= exprlist COMMA expritem */ + -1, /* (251) exprlist ::= expritem */ + -1, /* (252) expritem ::= expr */ + 0, /* (253) expritem ::= */ + -3, /* (254) cmd ::= RESET QUERY CACHE */ + -7, /* (255) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ + -7, /* (256) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ + -7, /* (257) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ + -7, /* (258) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ + -8, /* (259) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ + -9, /* (260) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ + -7, /* (261) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ + -7, /* (262) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ + -7, /* (263) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ + -7, /* (264) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ + -8, /* (265) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ + -3, /* (266) cmd ::= KILL CONNECTION INTEGER */ + -5, /* (267) cmd ::= KILL STREAM INTEGER COLON INTEGER */ + -5, /* (268) cmd ::= KILL QUERY INTEGER COLON INTEGER */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -2397,9 +2404,9 @@ static YYACTIONTYPE yy_reduce( /********** Begin reduce actions **********************************************/ YYMINORTYPE yylhsminor; case 0: /* program ::= cmd */ - case 132: /* cmd ::= CREATE TABLE create_table_args */ yytestcase(yyruleno==132); - case 133: /* cmd ::= CREATE TABLE create_stable_args */ yytestcase(yyruleno==133); - case 134: /* cmd ::= CREATE STABLE create_stable_args */ yytestcase(yyruleno==134); + case 133: /* cmd ::= CREATE TABLE create_table_args */ yytestcase(yyruleno==133); + case 134: /* cmd ::= CREATE TABLE create_stable_args */ yytestcase(yyruleno==134); + case 135: /* cmd ::= CREATE STABLE create_stable_args */ yytestcase(yyruleno==135); {} break; case 1: /* cmd ::= SHOW DATABASES */ @@ -2466,12 +2473,12 @@ static YYACTIONTYPE yy_reduce( case 21: /* cmd ::= SHOW CREATE TABLE ids cpxName */ { yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - setDCLSQLElems(pInfo, TSDB_SQL_SHOW_CREATE_TABLE, 1, &yymsp[-1].minor.yy0); + setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_TABLE, 1, &yymsp[-1].minor.yy0); } break; case 22: /* cmd ::= SHOW CREATE DATABASE ids */ { - setDCLSQLElems(pInfo, TSDB_SQL_SHOW_CREATE_DATABASE, 1, &yymsp[0].minor.yy0); + setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_DATABASE, 1, &yymsp[0].minor.yy0); } break; case 23: /* cmd ::= SHOW dbPrefix TABLES */ @@ -2492,21 +2499,21 @@ static YYACTIONTYPE yy_reduce( case 26: /* cmd ::= SHOW dbPrefix STABLES LIKE ids */ { SStrToken token; - setDbName(&token, &yymsp[-3].minor.yy0); + tSetDbName(&token, &yymsp[-3].minor.yy0); setShowOptions(pInfo, TSDB_MGMT_TABLE_METRIC, &token, &yymsp[0].minor.yy0); } break; case 27: /* cmd ::= SHOW dbPrefix VGROUPS */ { SStrToken token; - setDbName(&token, &yymsp[-1].minor.yy0); + tSetDbName(&token, &yymsp[-1].minor.yy0); setShowOptions(pInfo, TSDB_MGMT_TABLE_VGROUP, &token, 0); } break; case 28: /* cmd ::= SHOW dbPrefix VGROUPS ids */ { SStrToken token; - setDbName(&token, &yymsp[-2].minor.yy0); + tSetDbName(&token, &yymsp[-2].minor.yy0); setShowOptions(pInfo, TSDB_MGMT_TABLE_VGROUP, &token, &yymsp[0].minor.yy0); } break; @@ -2532,21 +2539,21 @@ static YYACTIONTYPE yy_reduce( { setDropFuncInfo(pInfo, TSDB_SQL_DROP_FUNCTION, &yymsp[0].minor.yy0); } break; case 34: /* cmd ::= DROP DNODE ids */ -{ setDCLSQLElems(pInfo, TSDB_SQL_DROP_DNODE, 1, &yymsp[0].minor.yy0); } +{ setDCLSqlElems(pInfo, TSDB_SQL_DROP_DNODE, 1, &yymsp[0].minor.yy0); } break; case 35: /* cmd ::= DROP USER ids */ -{ setDCLSQLElems(pInfo, TSDB_SQL_DROP_USER, 1, &yymsp[0].minor.yy0); } +{ setDCLSqlElems(pInfo, TSDB_SQL_DROP_USER, 1, &yymsp[0].minor.yy0); } break; case 36: /* cmd ::= DROP ACCOUNT ids */ -{ setDCLSQLElems(pInfo, TSDB_SQL_DROP_ACCT, 1, &yymsp[0].minor.yy0); } +{ setDCLSqlElems(pInfo, TSDB_SQL_DROP_ACCT, 1, &yymsp[0].minor.yy0); } break; case 37: /* cmd ::= USE ids */ -{ setDCLSQLElems(pInfo, TSDB_SQL_USE_DB, 1, &yymsp[0].minor.yy0);} +{ setDCLSqlElems(pInfo, TSDB_SQL_USE_DB, 1, &yymsp[0].minor.yy0);} break; case 38: /* cmd ::= DESCRIBE ids cpxName */ { yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - setDCLSQLElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &yymsp[-1].minor.yy0); + setDCLSqlElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &yymsp[-1].minor.yy0); } break; case 39: /* cmd ::= ALTER USER ids PASS ids */ @@ -2556,26 +2563,26 @@ static YYACTIONTYPE yy_reduce( { setAlterUserSql(pInfo, TSDB_ALTER_USER_PRIVILEGES, &yymsp[-2].minor.yy0, NULL, &yymsp[0].minor.yy0);} break; case 41: /* cmd ::= ALTER DNODE ids ids */ -{ setDCLSQLElems(pInfo, TSDB_SQL_CFG_DNODE, 2, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } +{ setDCLSqlElems(pInfo, TSDB_SQL_CFG_DNODE, 2, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } break; case 42: /* cmd ::= ALTER DNODE ids ids ids */ -{ setDCLSQLElems(pInfo, TSDB_SQL_CFG_DNODE, 3, &yymsp[-2].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } +{ setDCLSqlElems(pInfo, TSDB_SQL_CFG_DNODE, 3, &yymsp[-2].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } break; case 43: /* cmd ::= ALTER LOCAL ids */ -{ setDCLSQLElems(pInfo, TSDB_SQL_CFG_LOCAL, 1, &yymsp[0].minor.yy0); } +{ setDCLSqlElems(pInfo, TSDB_SQL_CFG_LOCAL, 1, &yymsp[0].minor.yy0); } break; case 44: /* cmd ::= ALTER LOCAL ids ids */ -{ setDCLSQLElems(pInfo, TSDB_SQL_CFG_LOCAL, 2, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } +{ setDCLSqlElems(pInfo, TSDB_SQL_CFG_LOCAL, 2, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } break; case 45: /* cmd ::= ALTER DATABASE ids alter_db_optr */ case 46: /* cmd ::= ALTER TOPIC ids alter_topic_optr */ yytestcase(yyruleno==46); -{ SStrToken t = {0}; setCreateDbInfo(pInfo, TSDB_SQL_ALTER_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy114, &t);} +{ SStrToken t = {0}; setCreateDbInfo(pInfo, TSDB_SQL_ALTER_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy122, &t);} break; case 47: /* cmd ::= ALTER ACCOUNT ids acct_optr */ -{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-1].minor.yy0, NULL, &yymsp[0].minor.yy183);} +{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-1].minor.yy0, NULL, &yymsp[0].minor.yy211);} break; case 48: /* cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ -{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy183);} +{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy211);} break; case 49: /* ids ::= ID */ case 50: /* ids ::= STRING */ yytestcase(yyruleno==50); @@ -2594,368 +2601,368 @@ static YYACTIONTYPE yy_reduce( { yymsp[-2].minor.yy0.n = 1;} break; case 55: /* cmd ::= CREATE DNODE ids */ -{ setDCLSQLElems(pInfo, TSDB_SQL_CREATE_DNODE, 1, &yymsp[0].minor.yy0);} +{ setDCLSqlElems(pInfo, TSDB_SQL_CREATE_DNODE, 1, &yymsp[0].minor.yy0);} break; case 56: /* cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ -{ setCreateAcctSql(pInfo, TSDB_SQL_CREATE_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy183);} +{ setCreateAcctSql(pInfo, TSDB_SQL_CREATE_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy211);} break; case 57: /* cmd ::= CREATE DATABASE ifnotexists ids db_optr */ case 58: /* cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ yytestcase(yyruleno==58); -{ setCreateDbInfo(pInfo, TSDB_SQL_CREATE_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy114, &yymsp[-2].minor.yy0);} +{ setCreateDbInfo(pInfo, TSDB_SQL_CREATE_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy122, &yymsp[-2].minor.yy0);} break; case 59: /* cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename */ -{ setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &yymsp[-4].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy27);} +{ setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &yymsp[-4].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy153, 1);} break; - case 60: /* cmd ::= CREATE USER ids PASS ids */ + case 60: /* cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename */ +{ setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &yymsp[-4].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy153, 2);} + break; + case 61: /* cmd ::= CREATE USER ids PASS ids */ { setCreateUserSql(pInfo, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);} break; - case 61: /* pps ::= */ - case 63: /* tseries ::= */ yytestcase(yyruleno==63); - case 65: /* dbs ::= */ yytestcase(yyruleno==65); - case 67: /* streams ::= */ yytestcase(yyruleno==67); - case 69: /* storage ::= */ yytestcase(yyruleno==69); - case 71: /* qtime ::= */ yytestcase(yyruleno==71); - case 73: /* users ::= */ yytestcase(yyruleno==73); - case 75: /* conns ::= */ yytestcase(yyruleno==75); - case 77: /* state ::= */ yytestcase(yyruleno==77); + case 62: /* pps ::= */ + case 64: /* tseries ::= */ yytestcase(yyruleno==64); + case 66: /* dbs ::= */ yytestcase(yyruleno==66); + case 68: /* streams ::= */ yytestcase(yyruleno==68); + case 70: /* storage ::= */ yytestcase(yyruleno==70); + case 72: /* qtime ::= */ yytestcase(yyruleno==72); + case 74: /* users ::= */ yytestcase(yyruleno==74); + case 76: /* conns ::= */ yytestcase(yyruleno==76); + case 78: /* state ::= */ yytestcase(yyruleno==78); { yymsp[1].minor.yy0.n = 0; } break; - case 62: /* pps ::= PPS INTEGER */ - case 64: /* tseries ::= TSERIES INTEGER */ yytestcase(yyruleno==64); - case 66: /* dbs ::= DBS INTEGER */ yytestcase(yyruleno==66); - case 68: /* streams ::= STREAMS INTEGER */ yytestcase(yyruleno==68); - case 70: /* storage ::= STORAGE INTEGER */ yytestcase(yyruleno==70); - case 72: /* qtime ::= QTIME INTEGER */ yytestcase(yyruleno==72); - case 74: /* users ::= USERS INTEGER */ yytestcase(yyruleno==74); - case 76: /* conns ::= CONNS INTEGER */ yytestcase(yyruleno==76); - case 78: /* state ::= STATE ids */ yytestcase(yyruleno==78); + case 63: /* pps ::= PPS INTEGER */ + case 65: /* tseries ::= TSERIES INTEGER */ yytestcase(yyruleno==65); + case 67: /* dbs ::= DBS INTEGER */ yytestcase(yyruleno==67); + case 69: /* streams ::= STREAMS INTEGER */ yytestcase(yyruleno==69); + case 71: /* storage ::= STORAGE INTEGER */ yytestcase(yyruleno==71); + case 73: /* qtime ::= QTIME INTEGER */ yytestcase(yyruleno==73); + case 75: /* users ::= USERS INTEGER */ yytestcase(yyruleno==75); + case 77: /* conns ::= CONNS INTEGER */ yytestcase(yyruleno==77); + case 79: /* state ::= STATE ids */ yytestcase(yyruleno==79); { yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } break; - case 79: /* acct_optr ::= pps tseries storage streams qtime dbs users conns state */ + case 80: /* acct_optr ::= pps tseries storage streams qtime dbs users conns state */ { - yylhsminor.yy183.maxUsers = (yymsp[-2].minor.yy0.n>0)?atoi(yymsp[-2].minor.yy0.z):-1; - yylhsminor.yy183.maxDbs = (yymsp[-3].minor.yy0.n>0)?atoi(yymsp[-3].minor.yy0.z):-1; - yylhsminor.yy183.maxTimeSeries = (yymsp[-7].minor.yy0.n>0)?atoi(yymsp[-7].minor.yy0.z):-1; - yylhsminor.yy183.maxStreams = (yymsp[-5].minor.yy0.n>0)?atoi(yymsp[-5].minor.yy0.z):-1; - yylhsminor.yy183.maxPointsPerSecond = (yymsp[-8].minor.yy0.n>0)?atoi(yymsp[-8].minor.yy0.z):-1; - yylhsminor.yy183.maxStorage = (yymsp[-6].minor.yy0.n>0)?strtoll(yymsp[-6].minor.yy0.z, NULL, 10):-1; - yylhsminor.yy183.maxQueryTime = (yymsp[-4].minor.yy0.n>0)?strtoll(yymsp[-4].minor.yy0.z, NULL, 10):-1; - yylhsminor.yy183.maxConnections = (yymsp[-1].minor.yy0.n>0)?atoi(yymsp[-1].minor.yy0.z):-1; - yylhsminor.yy183.stat = yymsp[0].minor.yy0; -} - yymsp[-8].minor.yy183 = yylhsminor.yy183; - break; - case 80: /* keep ::= KEEP tagitemlist */ -{ yymsp[-1].minor.yy193 = yymsp[0].minor.yy193; } - break; - case 81: /* cache ::= CACHE INTEGER */ - case 82: /* replica ::= REPLICA INTEGER */ yytestcase(yyruleno==82); - case 83: /* quorum ::= QUORUM INTEGER */ yytestcase(yyruleno==83); - case 84: /* days ::= DAYS INTEGER */ yytestcase(yyruleno==84); - case 85: /* minrows ::= MINROWS INTEGER */ yytestcase(yyruleno==85); - case 86: /* maxrows ::= MAXROWS INTEGER */ yytestcase(yyruleno==86); - case 87: /* blocks ::= BLOCKS INTEGER */ yytestcase(yyruleno==87); - case 88: /* ctime ::= CTIME INTEGER */ yytestcase(yyruleno==88); - case 89: /* wal ::= WAL INTEGER */ yytestcase(yyruleno==89); - case 90: /* fsync ::= FSYNC INTEGER */ yytestcase(yyruleno==90); - case 91: /* comp ::= COMP INTEGER */ yytestcase(yyruleno==91); - case 92: /* prec ::= PRECISION STRING */ yytestcase(yyruleno==92); - case 93: /* update ::= UPDATE INTEGER */ yytestcase(yyruleno==93); - case 94: /* cachelast ::= CACHELAST INTEGER */ yytestcase(yyruleno==94); - case 95: /* partitions ::= PARTITIONS INTEGER */ yytestcase(yyruleno==95); + yylhsminor.yy211.maxUsers = (yymsp[-2].minor.yy0.n>0)?atoi(yymsp[-2].minor.yy0.z):-1; + yylhsminor.yy211.maxDbs = (yymsp[-3].minor.yy0.n>0)?atoi(yymsp[-3].minor.yy0.z):-1; + yylhsminor.yy211.maxTimeSeries = (yymsp[-7].minor.yy0.n>0)?atoi(yymsp[-7].minor.yy0.z):-1; + yylhsminor.yy211.maxStreams = (yymsp[-5].minor.yy0.n>0)?atoi(yymsp[-5].minor.yy0.z):-1; + yylhsminor.yy211.maxPointsPerSecond = (yymsp[-8].minor.yy0.n>0)?atoi(yymsp[-8].minor.yy0.z):-1; + yylhsminor.yy211.maxStorage = (yymsp[-6].minor.yy0.n>0)?strtoll(yymsp[-6].minor.yy0.z, NULL, 10):-1; + yylhsminor.yy211.maxQueryTime = (yymsp[-4].minor.yy0.n>0)?strtoll(yymsp[-4].minor.yy0.z, NULL, 10):-1; + yylhsminor.yy211.maxConnections = (yymsp[-1].minor.yy0.n>0)?atoi(yymsp[-1].minor.yy0.z):-1; + yylhsminor.yy211.stat = yymsp[0].minor.yy0; +} + yymsp[-8].minor.yy211 = yylhsminor.yy211; + break; + case 81: /* keep ::= KEEP tagitemlist */ +{ yymsp[-1].minor.yy291 = yymsp[0].minor.yy291; } + break; + case 82: /* cache ::= CACHE INTEGER */ + case 83: /* replica ::= REPLICA INTEGER */ yytestcase(yyruleno==83); + case 84: /* quorum ::= QUORUM INTEGER */ yytestcase(yyruleno==84); + case 85: /* days ::= DAYS INTEGER */ yytestcase(yyruleno==85); + case 86: /* minrows ::= MINROWS INTEGER */ yytestcase(yyruleno==86); + case 87: /* maxrows ::= MAXROWS INTEGER */ yytestcase(yyruleno==87); + case 88: /* blocks ::= BLOCKS INTEGER */ yytestcase(yyruleno==88); + case 89: /* ctime ::= CTIME INTEGER */ yytestcase(yyruleno==89); + case 90: /* wal ::= WAL INTEGER */ yytestcase(yyruleno==90); + case 91: /* fsync ::= FSYNC INTEGER */ yytestcase(yyruleno==91); + case 92: /* comp ::= COMP INTEGER */ yytestcase(yyruleno==92); + case 93: /* prec ::= PRECISION STRING */ yytestcase(yyruleno==93); + case 94: /* update ::= UPDATE INTEGER */ yytestcase(yyruleno==94); + case 95: /* cachelast ::= CACHELAST INTEGER */ yytestcase(yyruleno==95); + case 96: /* partitions ::= PARTITIONS INTEGER */ yytestcase(yyruleno==96); { yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } break; - case 96: /* db_optr ::= */ -{setDefaultCreateDbOption(&yymsp[1].minor.yy114); yymsp[1].minor.yy114.dbType = TSDB_DB_TYPE_DEFAULT;} - break; - case 97: /* db_optr ::= db_optr cache */ -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.cacheBlockSize = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 98: /* db_optr ::= db_optr replica */ - case 115: /* alter_db_optr ::= alter_db_optr replica */ yytestcase(yyruleno==115); -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.replica = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 99: /* db_optr ::= db_optr quorum */ - case 116: /* alter_db_optr ::= alter_db_optr quorum */ yytestcase(yyruleno==116); -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.quorum = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 100: /* db_optr ::= db_optr days */ -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.daysPerFile = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 101: /* db_optr ::= db_optr minrows */ -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.minRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 102: /* db_optr ::= db_optr maxrows */ -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.maxRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 103: /* db_optr ::= db_optr blocks */ - case 118: /* alter_db_optr ::= alter_db_optr blocks */ yytestcase(yyruleno==118); -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.numOfBlocks = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 104: /* db_optr ::= db_optr ctime */ -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.commitTime = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 105: /* db_optr ::= db_optr wal */ - case 120: /* alter_db_optr ::= alter_db_optr wal */ yytestcase(yyruleno==120); -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.walLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 106: /* db_optr ::= db_optr fsync */ - case 121: /* alter_db_optr ::= alter_db_optr fsync */ yytestcase(yyruleno==121); -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.fsyncPeriod = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 107: /* db_optr ::= db_optr comp */ - case 119: /* alter_db_optr ::= alter_db_optr comp */ yytestcase(yyruleno==119); -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.compressionLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 108: /* db_optr ::= db_optr prec */ -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.precision = yymsp[0].minor.yy0; } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 109: /* db_optr ::= db_optr keep */ - case 117: /* alter_db_optr ::= alter_db_optr keep */ yytestcase(yyruleno==117); -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.keep = yymsp[0].minor.yy193; } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 110: /* db_optr ::= db_optr update */ - case 122: /* alter_db_optr ::= alter_db_optr update */ yytestcase(yyruleno==122); -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.update = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 111: /* db_optr ::= db_optr cachelast */ - case 123: /* alter_db_optr ::= alter_db_optr cachelast */ yytestcase(yyruleno==123); -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.cachelast = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 112: /* topic_optr ::= db_optr */ - case 124: /* alter_topic_optr ::= alter_db_optr */ yytestcase(yyruleno==124); -{ yylhsminor.yy114 = yymsp[0].minor.yy114; yylhsminor.yy114.dbType = TSDB_DB_TYPE_TOPIC; } - yymsp[0].minor.yy114 = yylhsminor.yy114; - break; - case 113: /* topic_optr ::= topic_optr partitions */ - case 125: /* alter_topic_optr ::= alter_topic_optr partitions */ yytestcase(yyruleno==125); -{ yylhsminor.yy114 = yymsp[-1].minor.yy114; yylhsminor.yy114.partitions = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy114 = yylhsminor.yy114; - break; - case 114: /* alter_db_optr ::= */ -{ setDefaultCreateDbOption(&yymsp[1].minor.yy114); yymsp[1].minor.yy114.dbType = TSDB_DB_TYPE_DEFAULT;} - break; - case 126: /* typename ::= ids */ + case 97: /* db_optr ::= */ +{setDefaultCreateDbOption(&yymsp[1].minor.yy122); yymsp[1].minor.yy122.dbType = TSDB_DB_TYPE_DEFAULT;} + break; + case 98: /* db_optr ::= db_optr cache */ +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.cacheBlockSize = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 99: /* db_optr ::= db_optr replica */ + case 116: /* alter_db_optr ::= alter_db_optr replica */ yytestcase(yyruleno==116); +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.replica = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 100: /* db_optr ::= db_optr quorum */ + case 117: /* alter_db_optr ::= alter_db_optr quorum */ yytestcase(yyruleno==117); +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.quorum = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 101: /* db_optr ::= db_optr days */ +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.daysPerFile = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 102: /* db_optr ::= db_optr minrows */ +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.minRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 103: /* db_optr ::= db_optr maxrows */ +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.maxRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 104: /* db_optr ::= db_optr blocks */ + case 119: /* alter_db_optr ::= alter_db_optr blocks */ yytestcase(yyruleno==119); +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.numOfBlocks = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 105: /* db_optr ::= db_optr ctime */ +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.commitTime = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 106: /* db_optr ::= db_optr wal */ + case 121: /* alter_db_optr ::= alter_db_optr wal */ yytestcase(yyruleno==121); +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.walLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 107: /* db_optr ::= db_optr fsync */ + case 122: /* alter_db_optr ::= alter_db_optr fsync */ yytestcase(yyruleno==122); +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.fsyncPeriod = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 108: /* db_optr ::= db_optr comp */ + case 120: /* alter_db_optr ::= alter_db_optr comp */ yytestcase(yyruleno==120); +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.compressionLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 109: /* db_optr ::= db_optr prec */ +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.precision = yymsp[0].minor.yy0; } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 110: /* db_optr ::= db_optr keep */ + case 118: /* alter_db_optr ::= alter_db_optr keep */ yytestcase(yyruleno==118); +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.keep = yymsp[0].minor.yy291; } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 111: /* db_optr ::= db_optr update */ + case 123: /* alter_db_optr ::= alter_db_optr update */ yytestcase(yyruleno==123); +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.update = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 112: /* db_optr ::= db_optr cachelast */ + case 124: /* alter_db_optr ::= alter_db_optr cachelast */ yytestcase(yyruleno==124); +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.cachelast = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 113: /* topic_optr ::= db_optr */ + case 125: /* alter_topic_optr ::= alter_db_optr */ yytestcase(yyruleno==125); +{ yylhsminor.yy122 = yymsp[0].minor.yy122; yylhsminor.yy122.dbType = TSDB_DB_TYPE_TOPIC; } + yymsp[0].minor.yy122 = yylhsminor.yy122; + break; + case 114: /* topic_optr ::= topic_optr partitions */ + case 126: /* alter_topic_optr ::= alter_topic_optr partitions */ yytestcase(yyruleno==126); +{ yylhsminor.yy122 = yymsp[-1].minor.yy122; yylhsminor.yy122.partitions = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[-1].minor.yy122 = yylhsminor.yy122; + break; + case 115: /* alter_db_optr ::= */ +{ setDefaultCreateDbOption(&yymsp[1].minor.yy122); yymsp[1].minor.yy122.dbType = TSDB_DB_TYPE_DEFAULT;} + break; + case 127: /* typename ::= ids */ { yymsp[0].minor.yy0.type = 0; - tSqlSetColumnType (&yylhsminor.yy27, &yymsp[0].minor.yy0); + tSetColumnType (&yylhsminor.yy153, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy27 = yylhsminor.yy27; + yymsp[0].minor.yy153 = yylhsminor.yy153; break; - case 127: /* typename ::= ids LP signed RP */ + case 128: /* typename ::= ids LP signed RP */ { - if (yymsp[-1].minor.yy473 <= 0) { + if (yymsp[-1].minor.yy179 <= 0) { yymsp[-3].minor.yy0.type = 0; - tSqlSetColumnType(&yylhsminor.yy27, &yymsp[-3].minor.yy0); + tSetColumnType(&yylhsminor.yy153, &yymsp[-3].minor.yy0); } else { - yymsp[-3].minor.yy0.type = -yymsp[-1].minor.yy473; // negative value of name length - tSqlSetColumnType(&yylhsminor.yy27, &yymsp[-3].minor.yy0); + yymsp[-3].minor.yy0.type = -yymsp[-1].minor.yy179; // negative value of name length + tSetColumnType(&yylhsminor.yy153, &yymsp[-3].minor.yy0); } } - yymsp[-3].minor.yy27 = yylhsminor.yy27; + yymsp[-3].minor.yy153 = yylhsminor.yy153; break; - case 128: /* typename ::= ids UNSIGNED */ + case 129: /* typename ::= ids UNSIGNED */ { yymsp[-1].minor.yy0.type = 0; yymsp[-1].minor.yy0.n = ((yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n) - yymsp[-1].minor.yy0.z); - tSqlSetColumnType (&yylhsminor.yy27, &yymsp[-1].minor.yy0); + tSetColumnType (&yylhsminor.yy153, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy27 = yylhsminor.yy27; + yymsp[-1].minor.yy153 = yylhsminor.yy153; break; - case 129: /* signed ::= INTEGER */ -{ yylhsminor.yy473 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[0].minor.yy473 = yylhsminor.yy473; + case 130: /* signed ::= INTEGER */ +{ yylhsminor.yy179 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + yymsp[0].minor.yy179 = yylhsminor.yy179; break; - case 130: /* signed ::= PLUS INTEGER */ -{ yymsp[-1].minor.yy473 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + case 131: /* signed ::= PLUS INTEGER */ +{ yymsp[-1].minor.yy179 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } break; - case 131: /* signed ::= MINUS INTEGER */ -{ yymsp[-1].minor.yy473 = -strtol(yymsp[0].minor.yy0.z, NULL, 10);} + case 132: /* signed ::= MINUS INTEGER */ +{ yymsp[-1].minor.yy179 = -strtol(yymsp[0].minor.yy0.z, NULL, 10);} break; - case 135: /* cmd ::= CREATE TABLE create_table_list */ -{ pInfo->type = TSDB_SQL_CREATE_TABLE; pInfo->pCreateTableInfo = yymsp[0].minor.yy190;} + case 136: /* cmd ::= CREATE TABLE create_table_list */ +{ pInfo->type = TSDB_SQL_CREATE_TABLE; pInfo->pCreateTableInfo = yymsp[0].minor.yy412;} break; - case 136: /* create_table_list ::= create_from_stable */ + case 137: /* create_table_list ::= create_from_stable */ { - SCreateTableSQL* pCreateTable = calloc(1, sizeof(SCreateTableSQL)); + SCreateTableSql* pCreateTable = calloc(1, sizeof(SCreateTableSql)); pCreateTable->childTableInfo = taosArrayInit(4, sizeof(SCreatedTableInfo)); - taosArrayPush(pCreateTable->childTableInfo, &yymsp[0].minor.yy192); + taosArrayPush(pCreateTable->childTableInfo, &yymsp[0].minor.yy446); pCreateTable->type = TSQL_CREATE_TABLE_FROM_STABLE; - yylhsminor.yy190 = pCreateTable; + yylhsminor.yy412 = pCreateTable; } - yymsp[0].minor.yy190 = yylhsminor.yy190; + yymsp[0].minor.yy412 = yylhsminor.yy412; break; - case 137: /* create_table_list ::= create_table_list create_from_stable */ + case 138: /* create_table_list ::= create_table_list create_from_stable */ { - taosArrayPush(yymsp[-1].minor.yy190->childTableInfo, &yymsp[0].minor.yy192); - yylhsminor.yy190 = yymsp[-1].minor.yy190; + taosArrayPush(yymsp[-1].minor.yy412->childTableInfo, &yymsp[0].minor.yy446); + yylhsminor.yy412 = yymsp[-1].minor.yy412; } - yymsp[-1].minor.yy190 = yylhsminor.yy190; + yymsp[-1].minor.yy412 = yylhsminor.yy412; break; - case 138: /* create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ + case 139: /* create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ { - yylhsminor.yy190 = tSetCreateSqlElems(yymsp[-1].minor.yy193, NULL, NULL, TSQL_CREATE_TABLE); - setSqlInfo(pInfo, yylhsminor.yy190, NULL, TSDB_SQL_CREATE_TABLE); + yylhsminor.yy412 = tSetCreateTableInfo(yymsp[-1].minor.yy291, NULL, NULL, TSQL_CREATE_TABLE); + setSqlInfo(pInfo, yylhsminor.yy412, NULL, TSDB_SQL_CREATE_TABLE); yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; setCreatedTableName(pInfo, &yymsp[-4].minor.yy0, &yymsp[-5].minor.yy0); } - yymsp[-5].minor.yy190 = yylhsminor.yy190; + yymsp[-5].minor.yy412 = yylhsminor.yy412; break; - case 139: /* create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ + case 140: /* create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ { - yylhsminor.yy190 = tSetCreateSqlElems(yymsp[-5].minor.yy193, yymsp[-1].minor.yy193, NULL, TSQL_CREATE_STABLE); - setSqlInfo(pInfo, yylhsminor.yy190, NULL, TSDB_SQL_CREATE_TABLE); + yylhsminor.yy412 = tSetCreateTableInfo(yymsp[-5].minor.yy291, yymsp[-1].minor.yy291, NULL, TSQL_CREATE_STABLE); + setSqlInfo(pInfo, yylhsminor.yy412, NULL, TSDB_SQL_CREATE_TABLE); yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; setCreatedTableName(pInfo, &yymsp[-8].minor.yy0, &yymsp[-9].minor.yy0); } - yymsp[-9].minor.yy190 = yylhsminor.yy190; + yymsp[-9].minor.yy412 = yylhsminor.yy412; break; - case 140: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ + case 141: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ { yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; - yylhsminor.yy192 = createNewChildTableInfo(&yymsp[-5].minor.yy0, NULL, yymsp[-1].minor.yy193, &yymsp[-8].minor.yy0, &yymsp[-9].minor.yy0); + yylhsminor.yy446 = createNewChildTableInfo(&yymsp[-5].minor.yy0, NULL, yymsp[-1].minor.yy291, &yymsp[-8].minor.yy0, &yymsp[-9].minor.yy0); } - yymsp[-9].minor.yy192 = yylhsminor.yy192; + yymsp[-9].minor.yy446 = yylhsminor.yy446; break; - case 141: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ + case 142: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ { yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; yymsp[-11].minor.yy0.n += yymsp[-10].minor.yy0.n; - yylhsminor.yy192 = createNewChildTableInfo(&yymsp[-8].minor.yy0, yymsp[-5].minor.yy193, yymsp[-1].minor.yy193, &yymsp[-11].minor.yy0, &yymsp[-12].minor.yy0); + yylhsminor.yy446 = createNewChildTableInfo(&yymsp[-8].minor.yy0, yymsp[-5].minor.yy291, yymsp[-1].minor.yy291, &yymsp[-11].minor.yy0, &yymsp[-12].minor.yy0); } - yymsp[-12].minor.yy192 = yylhsminor.yy192; + yymsp[-12].minor.yy446 = yylhsminor.yy446; break; - case 142: /* tagNamelist ::= tagNamelist COMMA ids */ -{taosArrayPush(yymsp[-2].minor.yy193, &yymsp[0].minor.yy0); yylhsminor.yy193 = yymsp[-2].minor.yy193; } - yymsp[-2].minor.yy193 = yylhsminor.yy193; + case 143: /* tagNamelist ::= tagNamelist COMMA ids */ +{taosArrayPush(yymsp[-2].minor.yy291, &yymsp[0].minor.yy0); yylhsminor.yy291 = yymsp[-2].minor.yy291; } + yymsp[-2].minor.yy291 = yylhsminor.yy291; break; - case 143: /* tagNamelist ::= ids */ -{yylhsminor.yy193 = taosArrayInit(4, sizeof(SStrToken)); taosArrayPush(yylhsminor.yy193, &yymsp[0].minor.yy0);} - yymsp[0].minor.yy193 = yylhsminor.yy193; + case 144: /* tagNamelist ::= ids */ +{yylhsminor.yy291 = taosArrayInit(4, sizeof(SStrToken)); taosArrayPush(yylhsminor.yy291, &yymsp[0].minor.yy0);} + yymsp[0].minor.yy291 = yylhsminor.yy291; break; - case 144: /* create_table_args ::= ifnotexists ids cpxName AS select */ + case 145: /* create_table_args ::= ifnotexists ids cpxName AS select */ { - yylhsminor.yy190 = tSetCreateSqlElems(NULL, NULL, yymsp[0].minor.yy288, TSQL_CREATE_STREAM); - setSqlInfo(pInfo, yylhsminor.yy190, NULL, TSDB_SQL_CREATE_TABLE); + yylhsminor.yy412 = tSetCreateTableInfo(NULL, NULL, yymsp[0].minor.yy110, TSQL_CREATE_STREAM); + setSqlInfo(pInfo, yylhsminor.yy412, NULL, TSDB_SQL_CREATE_TABLE); yymsp[-3].minor.yy0.n += yymsp[-2].minor.yy0.n; setCreatedTableName(pInfo, &yymsp[-3].minor.yy0, &yymsp[-4].minor.yy0); } - yymsp[-4].minor.yy190 = yylhsminor.yy190; + yymsp[-4].minor.yy412 = yylhsminor.yy412; break; - case 145: /* columnlist ::= columnlist COMMA column */ -{taosArrayPush(yymsp[-2].minor.yy193, &yymsp[0].minor.yy27); yylhsminor.yy193 = yymsp[-2].minor.yy193; } - yymsp[-2].minor.yy193 = yylhsminor.yy193; + case 146: /* columnlist ::= columnlist COMMA column */ +{taosArrayPush(yymsp[-2].minor.yy291, &yymsp[0].minor.yy153); yylhsminor.yy291 = yymsp[-2].minor.yy291; } + yymsp[-2].minor.yy291 = yylhsminor.yy291; break; - case 146: /* columnlist ::= column */ -{yylhsminor.yy193 = taosArrayInit(4, sizeof(TAOS_FIELD)); taosArrayPush(yylhsminor.yy193, &yymsp[0].minor.yy27);} - yymsp[0].minor.yy193 = yylhsminor.yy193; + case 147: /* columnlist ::= column */ +{yylhsminor.yy291 = taosArrayInit(4, sizeof(TAOS_FIELD)); taosArrayPush(yylhsminor.yy291, &yymsp[0].minor.yy153);} + yymsp[0].minor.yy291 = yylhsminor.yy291; break; - case 147: /* column ::= ids typename */ + case 148: /* column ::= ids typename */ { - tSqlSetColumnInfo(&yylhsminor.yy27, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy27); + tSetColumnInfo(&yylhsminor.yy153, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy153); } - yymsp[-1].minor.yy27 = yylhsminor.yy27; + yymsp[-1].minor.yy153 = yylhsminor.yy153; break; - case 148: /* tagitemlist ::= tagitemlist COMMA tagitem */ -{ yylhsminor.yy193 = tVariantListAppend(yymsp[-2].minor.yy193, &yymsp[0].minor.yy442, -1); } - yymsp[-2].minor.yy193 = yylhsminor.yy193; + case 149: /* tagitemlist ::= tagitemlist COMMA tagitem */ +{ yylhsminor.yy291 = tVariantListAppend(yymsp[-2].minor.yy291, &yymsp[0].minor.yy216, -1); } + yymsp[-2].minor.yy291 = yylhsminor.yy291; break; - case 149: /* tagitemlist ::= tagitem */ -{ yylhsminor.yy193 = tVariantListAppend(NULL, &yymsp[0].minor.yy442, -1); } - yymsp[0].minor.yy193 = yylhsminor.yy193; + case 150: /* tagitemlist ::= tagitem */ +{ yylhsminor.yy291 = tVariantListAppend(NULL, &yymsp[0].minor.yy216, -1); } + yymsp[0].minor.yy291 = yylhsminor.yy291; break; - case 150: /* tagitem ::= INTEGER */ - case 151: /* tagitem ::= FLOAT */ yytestcase(yyruleno==151); - case 152: /* tagitem ::= STRING */ yytestcase(yyruleno==152); - case 153: /* tagitem ::= BOOL */ yytestcase(yyruleno==153); -{ toTSDBType(yymsp[0].minor.yy0.type); tVariantCreate(&yylhsminor.yy442, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy442 = yylhsminor.yy442; + case 151: /* tagitem ::= INTEGER */ + case 152: /* tagitem ::= FLOAT */ yytestcase(yyruleno==152); + case 153: /* tagitem ::= STRING */ yytestcase(yyruleno==153); + case 154: /* tagitem ::= BOOL */ yytestcase(yyruleno==154); +{ toTSDBType(yymsp[0].minor.yy0.type); tVariantCreate(&yylhsminor.yy216, &yymsp[0].minor.yy0); } + yymsp[0].minor.yy216 = yylhsminor.yy216; break; - case 154: /* tagitem ::= NULL */ -{ yymsp[0].minor.yy0.type = 0; tVariantCreate(&yylhsminor.yy442, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy442 = yylhsminor.yy442; + case 155: /* tagitem ::= NULL */ +{ yymsp[0].minor.yy0.type = 0; tVariantCreate(&yylhsminor.yy216, &yymsp[0].minor.yy0); } + yymsp[0].minor.yy216 = yylhsminor.yy216; break; - case 155: /* tagitem ::= MINUS INTEGER */ - case 156: /* tagitem ::= MINUS FLOAT */ yytestcase(yyruleno==156); - case 157: /* tagitem ::= PLUS INTEGER */ yytestcase(yyruleno==157); - case 158: /* tagitem ::= PLUS FLOAT */ yytestcase(yyruleno==158); + case 156: /* tagitem ::= MINUS INTEGER */ + case 157: /* tagitem ::= MINUS FLOAT */ yytestcase(yyruleno==157); + case 158: /* tagitem ::= PLUS INTEGER */ yytestcase(yyruleno==158); + case 159: /* tagitem ::= PLUS FLOAT */ yytestcase(yyruleno==159); { yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = yymsp[0].minor.yy0.type; toTSDBType(yymsp[-1].minor.yy0.type); - tVariantCreate(&yylhsminor.yy442, &yymsp[-1].minor.yy0); + tVariantCreate(&yylhsminor.yy216, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy442 = yylhsminor.yy442; + yymsp[-1].minor.yy216 = yylhsminor.yy216; break; - case 159: /* select ::= SELECT selcollist from where_opt interval_opt session_option fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */ + case 160: /* select ::= SELECT selcollist from where_opt interval_opt session_option fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */ { - yylhsminor.yy288 = tSetQuerySqlNode(&yymsp[-12].minor.yy0, yymsp[-11].minor.yy178, yymsp[-10].minor.yy193, yymsp[-9].minor.yy134, yymsp[-4].minor.yy193, yymsp[-3].minor.yy193, &yymsp[-8].minor.yy392, &yymsp[-7].minor.yy447, &yymsp[-5].minor.yy0, yymsp[-6].minor.yy193, &yymsp[0].minor.yy482, &yymsp[-1].minor.yy482); + yylhsminor.yy110 = tSetQuerySqlNode(&yymsp[-12].minor.yy0, yymsp[-11].minor.yy291, yymsp[-10].minor.yy232, yymsp[-9].minor.yy436, yymsp[-4].minor.yy291, yymsp[-3].minor.yy291, &yymsp[-8].minor.yy400, &yymsp[-7].minor.yy139, &yymsp[-5].minor.yy0, yymsp[-6].minor.yy291, &yymsp[0].minor.yy74, &yymsp[-1].minor.yy74); } - yymsp[-12].minor.yy288 = yylhsminor.yy288; - break; - case 160: /* union ::= select */ -{ yylhsminor.yy21 = setSubclause(NULL, yymsp[0].minor.yy288); } - yymsp[0].minor.yy21 = yylhsminor.yy21; + yymsp[-12].minor.yy110 = yylhsminor.yy110; break; - case 161: /* union ::= LP union RP */ -{ yymsp[-2].minor.yy21 = yymsp[-1].minor.yy21; } + case 161: /* select ::= LP select RP */ +{yymsp[-2].minor.yy110 = yymsp[-1].minor.yy110;} break; - case 162: /* union ::= union UNION ALL select */ -{ yylhsminor.yy21 = appendSelectClause(yymsp[-3].minor.yy21, yymsp[0].minor.yy288); } - yymsp[-3].minor.yy21 = yylhsminor.yy21; + case 162: /* union ::= select */ +{ yylhsminor.yy154 = setSubclause(NULL, yymsp[0].minor.yy110); } + yymsp[0].minor.yy154 = yylhsminor.yy154; break; - case 163: /* union ::= union UNION ALL LP select RP */ -{ yylhsminor.yy21 = appendSelectClause(yymsp[-5].minor.yy21, yymsp[-1].minor.yy288); } - yymsp[-5].minor.yy21 = yylhsminor.yy21; + case 163: /* union ::= union UNION ALL select */ +{ yylhsminor.yy154 = appendSelectClause(yymsp[-3].minor.yy154, yymsp[0].minor.yy110); } + yymsp[-3].minor.yy154 = yylhsminor.yy154; break; case 164: /* cmd ::= union */ -{ setSqlInfo(pInfo, yymsp[0].minor.yy21, NULL, TSDB_SQL_SELECT); } +{ setSqlInfo(pInfo, yymsp[0].minor.yy154, NULL, TSDB_SQL_SELECT); } break; case 165: /* select ::= SELECT selcollist */ { - yylhsminor.yy288 = tSetQuerySqlNode(&yymsp[-1].minor.yy0, yymsp[0].minor.yy178, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + yylhsminor.yy110 = tSetQuerySqlNode(&yymsp[-1].minor.yy0, yymsp[0].minor.yy291, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } - yymsp[-1].minor.yy288 = yylhsminor.yy288; + yymsp[-1].minor.yy110 = yylhsminor.yy110; break; case 166: /* sclp ::= selcollist COMMA */ -{yylhsminor.yy178 = yymsp[-1].minor.yy178;} - yymsp[-1].minor.yy178 = yylhsminor.yy178; +{yylhsminor.yy291 = yymsp[-1].minor.yy291;} + yymsp[-1].minor.yy291 = yylhsminor.yy291; break; case 167: /* sclp ::= */ -{yymsp[1].minor.yy178 = 0;} + case 192: /* orderby_opt ::= */ yytestcase(yyruleno==192); +{yymsp[1].minor.yy291 = 0;} break; case 168: /* selcollist ::= sclp distinct expr as */ { - yylhsminor.yy178 = tSqlExprListAppend(yymsp[-3].minor.yy178, yymsp[-1].minor.yy134, yymsp[-2].minor.yy0.n? &yymsp[-2].minor.yy0:0, yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0); + yylhsminor.yy291 = tSqlExprListAppend(yymsp[-3].minor.yy291, yymsp[-1].minor.yy436, yymsp[-2].minor.yy0.n? &yymsp[-2].minor.yy0:0, yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0); } - yymsp[-3].minor.yy178 = yylhsminor.yy178; + yymsp[-3].minor.yy291 = yylhsminor.yy291; break; case 169: /* selcollist ::= sclp STAR */ { - tSQLExpr *pNode = tSqlExprIdValueCreate(NULL, TK_ALL); - yylhsminor.yy178 = tSqlExprListAppend(yymsp[-1].minor.yy178, pNode, 0, 0); + tSqlExpr *pNode = tSqlExprCreateIdValue(NULL, TK_ALL); + yylhsminor.yy291 = tSqlExprListAppend(yymsp[-1].minor.yy291, pNode, 0, 0); } - yymsp[-1].minor.yy178 = yylhsminor.yy178; + yymsp[-1].minor.yy291 = yylhsminor.yy291; break; case 170: /* as ::= AS ids */ { yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } @@ -2972,359 +2979,356 @@ static YYACTIONTYPE yy_reduce( yymsp[0].minor.yy0 = yylhsminor.yy0; break; case 175: /* from ::= FROM tablelist */ -{yymsp[-1].minor.yy193 = yymsp[0].minor.yy193;} +{yymsp[-1].minor.yy232 = yymsp[0].minor.yy291;} + break; + case 176: /* from ::= FROM LP union RP */ +{yymsp[-3].minor.yy232 = yymsp[-1].minor.yy154;} break; - case 176: /* tablelist ::= ids cpxName */ + case 177: /* tablelist ::= ids cpxName */ { toTSDBType(yymsp[-1].minor.yy0.type); yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - yylhsminor.yy193 = tVariantListAppendToken(NULL, &yymsp[-1].minor.yy0, -1); - yylhsminor.yy193 = tVariantListAppendToken(yylhsminor.yy193, &yymsp[-1].minor.yy0, -1); // table alias name + yylhsminor.yy291 = setTableNameList(NULL, &yymsp[-1].minor.yy0, NULL); } - yymsp[-1].minor.yy193 = yylhsminor.yy193; + yymsp[-1].minor.yy291 = yylhsminor.yy291; break; - case 177: /* tablelist ::= ids cpxName ids */ + case 178: /* tablelist ::= ids cpxName ids */ { toTSDBType(yymsp[-2].minor.yy0.type); toTSDBType(yymsp[0].minor.yy0.type); yymsp[-2].minor.yy0.n += yymsp[-1].minor.yy0.n; - yylhsminor.yy193 = tVariantListAppendToken(NULL, &yymsp[-2].minor.yy0, -1); - yylhsminor.yy193 = tVariantListAppendToken(yylhsminor.yy193, &yymsp[0].minor.yy0, -1); + yylhsminor.yy291 = setTableNameList(NULL, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy193 = yylhsminor.yy193; + yymsp[-2].minor.yy291 = yylhsminor.yy291; break; - case 178: /* tablelist ::= tablelist COMMA ids cpxName */ + case 179: /* tablelist ::= tablelist COMMA ids cpxName */ { toTSDBType(yymsp[-1].minor.yy0.type); yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - yylhsminor.yy193 = tVariantListAppendToken(yymsp[-3].minor.yy193, &yymsp[-1].minor.yy0, -1); - yylhsminor.yy193 = tVariantListAppendToken(yylhsminor.yy193, &yymsp[-1].minor.yy0, -1); + yylhsminor.yy291 = setTableNameList(yymsp[-3].minor.yy291, &yymsp[-1].minor.yy0, NULL); } - yymsp[-3].minor.yy193 = yylhsminor.yy193; + yymsp[-3].minor.yy291 = yylhsminor.yy291; break; - case 179: /* tablelist ::= tablelist COMMA ids cpxName ids */ + case 180: /* tablelist ::= tablelist COMMA ids cpxName ids */ { toTSDBType(yymsp[-2].minor.yy0.type); toTSDBType(yymsp[0].minor.yy0.type); yymsp[-2].minor.yy0.n += yymsp[-1].minor.yy0.n; - yylhsminor.yy193 = tVariantListAppendToken(yymsp[-4].minor.yy193, &yymsp[-2].minor.yy0, -1); - yylhsminor.yy193 = tVariantListAppendToken(yylhsminor.yy193, &yymsp[0].minor.yy0, -1); + + yylhsminor.yy291 = setTableNameList(yymsp[-4].minor.yy291, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } - yymsp[-4].minor.yy193 = yylhsminor.yy193; + yymsp[-4].minor.yy291 = yylhsminor.yy291; break; - case 180: /* tmvar ::= VARIABLE */ + case 181: /* tmvar ::= VARIABLE */ {yylhsminor.yy0 = yymsp[0].minor.yy0;} yymsp[0].minor.yy0 = yylhsminor.yy0; break; - case 181: /* interval_opt ::= INTERVAL LP tmvar RP */ -{yymsp[-3].minor.yy392.interval = yymsp[-1].minor.yy0; yymsp[-3].minor.yy392.offset.n = 0;} + case 182: /* interval_opt ::= INTERVAL LP tmvar RP */ +{yymsp[-3].minor.yy400.interval = yymsp[-1].minor.yy0; yymsp[-3].minor.yy400.offset.n = 0;} break; - case 182: /* interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ -{yymsp[-5].minor.yy392.interval = yymsp[-3].minor.yy0; yymsp[-5].minor.yy392.offset = yymsp[-1].minor.yy0;} + case 183: /* interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ +{yymsp[-5].minor.yy400.interval = yymsp[-3].minor.yy0; yymsp[-5].minor.yy400.offset = yymsp[-1].minor.yy0;} break; - case 183: /* interval_opt ::= */ -{memset(&yymsp[1].minor.yy392, 0, sizeof(yymsp[1].minor.yy392));} + case 184: /* interval_opt ::= */ +{memset(&yymsp[1].minor.yy400, 0, sizeof(yymsp[1].minor.yy400));} break; - case 184: /* session_option ::= */ -{yymsp[1].minor.yy447.col.n = 0; yymsp[1].minor.yy447.gap.n = 0;} + case 185: /* session_option ::= */ +{yymsp[1].minor.yy139.col.n = 0; yymsp[1].minor.yy139.gap.n = 0;} break; - case 185: /* session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ + case 186: /* session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - yymsp[-6].minor.yy447.col = yymsp[-4].minor.yy0; - yymsp[-6].minor.yy447.gap = yymsp[-1].minor.yy0; + yymsp[-6].minor.yy139.col = yymsp[-4].minor.yy0; + yymsp[-6].minor.yy139.gap = yymsp[-1].minor.yy0; } break; - case 186: /* fill_opt ::= */ -{ yymsp[1].minor.yy193 = 0; } + case 187: /* fill_opt ::= */ +{ yymsp[1].minor.yy291 = 0; } break; - case 187: /* fill_opt ::= FILL LP ID COMMA tagitemlist RP */ + case 188: /* fill_opt ::= FILL LP ID COMMA tagitemlist RP */ { tVariant A = {0}; toTSDBType(yymsp[-3].minor.yy0.type); tVariantCreate(&A, &yymsp[-3].minor.yy0); - tVariantListInsert(yymsp[-1].minor.yy193, &A, -1, 0); - yymsp[-5].minor.yy193 = yymsp[-1].minor.yy193; + tVariantListInsert(yymsp[-1].minor.yy291, &A, -1, 0); + yymsp[-5].minor.yy291 = yymsp[-1].minor.yy291; } break; - case 188: /* fill_opt ::= FILL LP ID RP */ + case 189: /* fill_opt ::= FILL LP ID RP */ { toTSDBType(yymsp[-1].minor.yy0.type); - yymsp[-3].minor.yy193 = tVariantListAppendToken(NULL, &yymsp[-1].minor.yy0, -1); + yymsp[-3].minor.yy291 = tVariantListAppendToken(NULL, &yymsp[-1].minor.yy0, -1); } break; - case 189: /* sliding_opt ::= SLIDING LP tmvar RP */ + case 190: /* sliding_opt ::= SLIDING LP tmvar RP */ {yymsp[-3].minor.yy0 = yymsp[-1].minor.yy0; } break; - case 190: /* sliding_opt ::= */ + case 191: /* sliding_opt ::= */ {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = NULL; yymsp[1].minor.yy0.type = 0; } break; - case 191: /* orderby_opt ::= */ -{yymsp[1].minor.yy193 = 0;} - break; - case 192: /* orderby_opt ::= ORDER BY sortlist */ -{yymsp[-2].minor.yy193 = yymsp[0].minor.yy193;} + case 193: /* orderby_opt ::= ORDER BY sortlist */ +{yymsp[-2].minor.yy291 = yymsp[0].minor.yy291;} break; - case 193: /* sortlist ::= sortlist COMMA item sortorder */ + case 194: /* sortlist ::= sortlist COMMA item sortorder */ { - yylhsminor.yy193 = tVariantListAppend(yymsp[-3].minor.yy193, &yymsp[-1].minor.yy442, yymsp[0].minor.yy312); + yylhsminor.yy291 = tVariantListAppend(yymsp[-3].minor.yy291, &yymsp[-1].minor.yy216, yymsp[0].minor.yy382); } - yymsp[-3].minor.yy193 = yylhsminor.yy193; + yymsp[-3].minor.yy291 = yylhsminor.yy291; break; - case 194: /* sortlist ::= item sortorder */ + case 195: /* sortlist ::= item sortorder */ { - yylhsminor.yy193 = tVariantListAppend(NULL, &yymsp[-1].minor.yy442, yymsp[0].minor.yy312); + yylhsminor.yy291 = tVariantListAppend(NULL, &yymsp[-1].minor.yy216, yymsp[0].minor.yy382); } - yymsp[-1].minor.yy193 = yylhsminor.yy193; + yymsp[-1].minor.yy291 = yylhsminor.yy291; break; - case 195: /* item ::= ids cpxName */ + case 196: /* item ::= ids cpxName */ { toTSDBType(yymsp[-1].minor.yy0.type); yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - tVariantCreate(&yylhsminor.yy442, &yymsp[-1].minor.yy0); + tVariantCreate(&yylhsminor.yy216, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy442 = yylhsminor.yy442; + yymsp[-1].minor.yy216 = yylhsminor.yy216; break; - case 196: /* sortorder ::= ASC */ -{ yymsp[0].minor.yy312 = TSDB_ORDER_ASC; } + case 197: /* sortorder ::= ASC */ +{ yymsp[0].minor.yy382 = TSDB_ORDER_ASC; } break; - case 197: /* sortorder ::= DESC */ -{ yymsp[0].minor.yy312 = TSDB_ORDER_DESC;} + case 198: /* sortorder ::= DESC */ +{ yymsp[0].minor.yy382 = TSDB_ORDER_DESC;} break; - case 198: /* sortorder ::= */ -{ yymsp[1].minor.yy312 = TSDB_ORDER_ASC; } + case 199: /* sortorder ::= */ +{ yymsp[1].minor.yy382 = TSDB_ORDER_ASC; } break; - case 199: /* groupby_opt ::= */ -{ yymsp[1].minor.yy193 = 0;} + case 200: /* groupby_opt ::= */ +{ yymsp[1].minor.yy291 = 0;} break; - case 200: /* groupby_opt ::= GROUP BY grouplist */ -{ yymsp[-2].minor.yy193 = yymsp[0].minor.yy193;} + case 201: /* groupby_opt ::= GROUP BY grouplist */ +{ yymsp[-2].minor.yy291 = yymsp[0].minor.yy291;} break; - case 201: /* grouplist ::= grouplist COMMA item */ + case 202: /* grouplist ::= grouplist COMMA item */ { - yylhsminor.yy193 = tVariantListAppend(yymsp[-2].minor.yy193, &yymsp[0].minor.yy442, -1); + yylhsminor.yy291 = tVariantListAppend(yymsp[-2].minor.yy291, &yymsp[0].minor.yy216, -1); } - yymsp[-2].minor.yy193 = yylhsminor.yy193; + yymsp[-2].minor.yy291 = yylhsminor.yy291; break; - case 202: /* grouplist ::= item */ + case 203: /* grouplist ::= item */ { - yylhsminor.yy193 = tVariantListAppend(NULL, &yymsp[0].minor.yy442, -1); + yylhsminor.yy291 = tVariantListAppend(NULL, &yymsp[0].minor.yy216, -1); } - yymsp[0].minor.yy193 = yylhsminor.yy193; + yymsp[0].minor.yy291 = yylhsminor.yy291; break; - case 203: /* having_opt ::= */ - case 213: /* where_opt ::= */ yytestcase(yyruleno==213); - case 252: /* expritem ::= */ yytestcase(yyruleno==252); -{yymsp[1].minor.yy134 = 0;} + case 204: /* having_opt ::= */ + case 214: /* where_opt ::= */ yytestcase(yyruleno==214); + case 253: /* expritem ::= */ yytestcase(yyruleno==253); +{yymsp[1].minor.yy436 = 0;} break; - case 204: /* having_opt ::= HAVING expr */ - case 214: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==214); -{yymsp[-1].minor.yy134 = yymsp[0].minor.yy134;} + case 205: /* having_opt ::= HAVING expr */ + case 215: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==215); +{yymsp[-1].minor.yy436 = yymsp[0].minor.yy436;} break; - case 205: /* limit_opt ::= */ - case 209: /* slimit_opt ::= */ yytestcase(yyruleno==209); -{yymsp[1].minor.yy482.limit = -1; yymsp[1].minor.yy482.offset = 0;} + case 206: /* limit_opt ::= */ + case 210: /* slimit_opt ::= */ yytestcase(yyruleno==210); +{yymsp[1].minor.yy74.limit = -1; yymsp[1].minor.yy74.offset = 0;} break; - case 206: /* limit_opt ::= LIMIT signed */ - case 210: /* slimit_opt ::= SLIMIT signed */ yytestcase(yyruleno==210); -{yymsp[-1].minor.yy482.limit = yymsp[0].minor.yy473; yymsp[-1].minor.yy482.offset = 0;} + case 207: /* limit_opt ::= LIMIT signed */ + case 211: /* slimit_opt ::= SLIMIT signed */ yytestcase(yyruleno==211); +{yymsp[-1].minor.yy74.limit = yymsp[0].minor.yy179; yymsp[-1].minor.yy74.offset = 0;} break; - case 207: /* limit_opt ::= LIMIT signed OFFSET signed */ -{ yymsp[-3].minor.yy482.limit = yymsp[-2].minor.yy473; yymsp[-3].minor.yy482.offset = yymsp[0].minor.yy473;} + case 208: /* limit_opt ::= LIMIT signed OFFSET signed */ +{ yymsp[-3].minor.yy74.limit = yymsp[-2].minor.yy179; yymsp[-3].minor.yy74.offset = yymsp[0].minor.yy179;} break; - case 208: /* limit_opt ::= LIMIT signed COMMA signed */ -{ yymsp[-3].minor.yy482.limit = yymsp[0].minor.yy473; yymsp[-3].minor.yy482.offset = yymsp[-2].minor.yy473;} + case 209: /* limit_opt ::= LIMIT signed COMMA signed */ +{ yymsp[-3].minor.yy74.limit = yymsp[0].minor.yy179; yymsp[-3].minor.yy74.offset = yymsp[-2].minor.yy179;} break; - case 211: /* slimit_opt ::= SLIMIT signed SOFFSET signed */ -{yymsp[-3].minor.yy482.limit = yymsp[-2].minor.yy473; yymsp[-3].minor.yy482.offset = yymsp[0].minor.yy473;} + case 212: /* slimit_opt ::= SLIMIT signed SOFFSET signed */ +{yymsp[-3].minor.yy74.limit = yymsp[-2].minor.yy179; yymsp[-3].minor.yy74.offset = yymsp[0].minor.yy179;} break; - case 212: /* slimit_opt ::= SLIMIT signed COMMA signed */ -{yymsp[-3].minor.yy482.limit = yymsp[0].minor.yy473; yymsp[-3].minor.yy482.offset = yymsp[-2].minor.yy473;} + case 213: /* slimit_opt ::= SLIMIT signed COMMA signed */ +{yymsp[-3].minor.yy74.limit = yymsp[0].minor.yy179; yymsp[-3].minor.yy74.offset = yymsp[-2].minor.yy179;} break; - case 215: /* expr ::= LP expr RP */ -{yylhsminor.yy134 = yymsp[-1].minor.yy134; yylhsminor.yy134->token.z = yymsp[-2].minor.yy0.z; yylhsminor.yy134->token.n = (yymsp[0].minor.yy0.z - yymsp[-2].minor.yy0.z + 1);} - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 216: /* expr ::= LP expr RP */ +{yylhsminor.yy436 = yymsp[-1].minor.yy436; yylhsminor.yy436->token.z = yymsp[-2].minor.yy0.z; yylhsminor.yy436->token.n = (yymsp[0].minor.yy0.z - yymsp[-2].minor.yy0.z + 1);} + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 216: /* expr ::= ID */ -{ yylhsminor.yy134 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_ID);} - yymsp[0].minor.yy134 = yylhsminor.yy134; + case 217: /* expr ::= ID */ +{ yylhsminor.yy436 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_ID);} + yymsp[0].minor.yy436 = yylhsminor.yy436; break; - case 217: /* expr ::= ID DOT ID */ -{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy134 = tSqlExprIdValueCreate(&yymsp[-2].minor.yy0, TK_ID);} - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 218: /* expr ::= ID DOT ID */ +{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy436 = tSqlExprCreateIdValue(&yymsp[-2].minor.yy0, TK_ID);} + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 218: /* expr ::= ID DOT STAR */ -{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy134 = tSqlExprIdValueCreate(&yymsp[-2].minor.yy0, TK_ALL);} - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 219: /* expr ::= ID DOT STAR */ +{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy436 = tSqlExprCreateIdValue(&yymsp[-2].minor.yy0, TK_ALL);} + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 219: /* expr ::= INTEGER */ -{ yylhsminor.yy134 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_INTEGER);} - yymsp[0].minor.yy134 = yylhsminor.yy134; + case 220: /* expr ::= INTEGER */ +{ yylhsminor.yy436 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_INTEGER);} + yymsp[0].minor.yy436 = yylhsminor.yy436; break; - case 220: /* expr ::= MINUS INTEGER */ - case 221: /* expr ::= PLUS INTEGER */ yytestcase(yyruleno==221); -{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_INTEGER; yylhsminor.yy134 = tSqlExprIdValueCreate(&yymsp[-1].minor.yy0, TK_INTEGER);} - yymsp[-1].minor.yy134 = yylhsminor.yy134; + case 221: /* expr ::= MINUS INTEGER */ + case 222: /* expr ::= PLUS INTEGER */ yytestcase(yyruleno==222); +{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_INTEGER; yylhsminor.yy436 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_INTEGER);} + yymsp[-1].minor.yy436 = yylhsminor.yy436; break; - case 222: /* expr ::= FLOAT */ -{ yylhsminor.yy134 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_FLOAT);} - yymsp[0].minor.yy134 = yylhsminor.yy134; + case 223: /* expr ::= FLOAT */ +{ yylhsminor.yy436 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_FLOAT);} + yymsp[0].minor.yy436 = yylhsminor.yy436; break; - case 223: /* expr ::= MINUS FLOAT */ - case 224: /* expr ::= PLUS FLOAT */ yytestcase(yyruleno==224); -{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_FLOAT; yylhsminor.yy134 = tSqlExprIdValueCreate(&yymsp[-1].minor.yy0, TK_FLOAT);} - yymsp[-1].minor.yy134 = yylhsminor.yy134; + case 224: /* expr ::= MINUS FLOAT */ + case 225: /* expr ::= PLUS FLOAT */ yytestcase(yyruleno==225); +{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_FLOAT; yylhsminor.yy436 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_FLOAT);} + yymsp[-1].minor.yy436 = yylhsminor.yy436; break; - case 225: /* expr ::= STRING */ -{ yylhsminor.yy134 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_STRING);} - yymsp[0].minor.yy134 = yylhsminor.yy134; + case 226: /* expr ::= STRING */ +{ yylhsminor.yy436 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_STRING);} + yymsp[0].minor.yy436 = yylhsminor.yy436; break; - case 226: /* expr ::= NOW */ -{ yylhsminor.yy134 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_NOW); } - yymsp[0].minor.yy134 = yylhsminor.yy134; + case 227: /* expr ::= NOW */ +{ yylhsminor.yy436 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_NOW); } + yymsp[0].minor.yy436 = yylhsminor.yy436; break; - case 227: /* expr ::= VARIABLE */ -{ yylhsminor.yy134 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_VARIABLE);} - yymsp[0].minor.yy134 = yylhsminor.yy134; + case 228: /* expr ::= VARIABLE */ +{ yylhsminor.yy436 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_VARIABLE);} + yymsp[0].minor.yy436 = yylhsminor.yy436; break; - case 228: /* expr ::= BOOL */ -{ yylhsminor.yy134 = tSqlExprIdValueCreate(&yymsp[0].minor.yy0, TK_BOOL);} - yymsp[0].minor.yy134 = yylhsminor.yy134; + case 229: /* expr ::= BOOL */ +{ yylhsminor.yy436 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_BOOL);} + yymsp[0].minor.yy436 = yylhsminor.yy436; break; - case 229: /* expr ::= ID LP exprlist RP */ -{ yylhsminor.yy134 = tSqlExprCreateFunction(yymsp[-1].minor.yy178, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } - yymsp[-3].minor.yy134 = yylhsminor.yy134; + case 230: /* expr ::= ID LP exprlist RP */ +{ yylhsminor.yy436 = tSqlExprCreateFunction(yymsp[-1].minor.yy291, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } + yymsp[-3].minor.yy436 = yylhsminor.yy436; break; - case 230: /* expr ::= ID LP STAR RP */ -{ yylhsminor.yy134 = tSqlExprCreateFunction(NULL, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } - yymsp[-3].minor.yy134 = yylhsminor.yy134; + case 231: /* expr ::= ID LP STAR RP */ +{ yylhsminor.yy436 = tSqlExprCreateFunction(NULL, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } + yymsp[-3].minor.yy436 = yylhsminor.yy436; break; - case 231: /* expr ::= expr IS NULL */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, NULL, TK_ISNULL);} - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 232: /* expr ::= expr IS NULL */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, NULL, TK_ISNULL);} + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 232: /* expr ::= expr IS NOT NULL */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-3].minor.yy134, NULL, TK_NOTNULL);} - yymsp[-3].minor.yy134 = yylhsminor.yy134; + case 233: /* expr ::= expr IS NOT NULL */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-3].minor.yy436, NULL, TK_NOTNULL);} + yymsp[-3].minor.yy436 = yylhsminor.yy436; break; - case 233: /* expr ::= expr LT expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_LT);} - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 234: /* expr ::= expr LT expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_LT);} + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 234: /* expr ::= expr GT expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_GT);} - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 235: /* expr ::= expr GT expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_GT);} + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 235: /* expr ::= expr LE expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_LE);} - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 236: /* expr ::= expr LE expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_LE);} + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 236: /* expr ::= expr GE expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_GE);} - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 237: /* expr ::= expr GE expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_GE);} + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 237: /* expr ::= expr NE expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_NE);} - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 238: /* expr ::= expr NE expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_NE);} + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 238: /* expr ::= expr EQ expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_EQ);} - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 239: /* expr ::= expr EQ expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_EQ);} + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 239: /* expr ::= expr BETWEEN expr AND expr */ -{ tSQLExpr* X2 = tSqlExprClone(yymsp[-4].minor.yy134); yylhsminor.yy134 = tSqlExprCreate(tSqlExprCreate(yymsp[-4].minor.yy134, yymsp[-2].minor.yy134, TK_GE), tSqlExprCreate(X2, yymsp[0].minor.yy134, TK_LE), TK_AND);} - yymsp[-4].minor.yy134 = yylhsminor.yy134; + case 240: /* expr ::= expr BETWEEN expr AND expr */ +{ tSqlExpr* X2 = tSqlExprClone(yymsp[-4].minor.yy436); yylhsminor.yy436 = tSqlExprCreate(tSqlExprCreate(yymsp[-4].minor.yy436, yymsp[-2].minor.yy436, TK_GE), tSqlExprCreate(X2, yymsp[0].minor.yy436, TK_LE), TK_AND);} + yymsp[-4].minor.yy436 = yylhsminor.yy436; break; - case 240: /* expr ::= expr AND expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_AND);} - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 241: /* expr ::= expr AND expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_AND);} + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 241: /* expr ::= expr OR expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_OR); } - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 242: /* expr ::= expr OR expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_OR); } + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 242: /* expr ::= expr PLUS expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_PLUS); } - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 243: /* expr ::= expr PLUS expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_PLUS); } + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 243: /* expr ::= expr MINUS expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_MINUS); } - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 244: /* expr ::= expr MINUS expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_MINUS); } + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 244: /* expr ::= expr STAR expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_STAR); } - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 245: /* expr ::= expr STAR expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_STAR); } + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 245: /* expr ::= expr SLASH expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_DIVIDE);} - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 246: /* expr ::= expr SLASH expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_DIVIDE);} + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 246: /* expr ::= expr REM expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_REM); } - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 247: /* expr ::= expr REM expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_REM); } + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 247: /* expr ::= expr LIKE expr */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-2].minor.yy134, yymsp[0].minor.yy134, TK_LIKE); } - yymsp[-2].minor.yy134 = yylhsminor.yy134; + case 248: /* expr ::= expr LIKE expr */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-2].minor.yy436, yymsp[0].minor.yy436, TK_LIKE); } + yymsp[-2].minor.yy436 = yylhsminor.yy436; break; - case 248: /* expr ::= expr IN LP exprlist RP */ -{yylhsminor.yy134 = tSqlExprCreate(yymsp[-4].minor.yy134, (tSQLExpr*)yymsp[-1].minor.yy178, TK_IN); } - yymsp[-4].minor.yy134 = yylhsminor.yy134; + case 249: /* expr ::= expr IN LP exprlist RP */ +{yylhsminor.yy436 = tSqlExprCreate(yymsp[-4].minor.yy436, (tSqlExpr*)yymsp[-1].minor.yy291, TK_IN); } + yymsp[-4].minor.yy436 = yylhsminor.yy436; break; - case 249: /* exprlist ::= exprlist COMMA expritem */ -{yylhsminor.yy178 = tSqlExprListAppend(yymsp[-2].minor.yy178,yymsp[0].minor.yy134,0, 0);} - yymsp[-2].minor.yy178 = yylhsminor.yy178; + case 250: /* exprlist ::= exprlist COMMA expritem */ +{yylhsminor.yy291 = tSqlExprListAppend(yymsp[-2].minor.yy291,yymsp[0].minor.yy436,0, 0);} + yymsp[-2].minor.yy291 = yylhsminor.yy291; break; - case 250: /* exprlist ::= expritem */ -{yylhsminor.yy178 = tSqlExprListAppend(0,yymsp[0].minor.yy134,0, 0);} - yymsp[0].minor.yy178 = yylhsminor.yy178; + case 251: /* exprlist ::= expritem */ +{yylhsminor.yy291 = tSqlExprListAppend(0,yymsp[0].minor.yy436,0, 0);} + yymsp[0].minor.yy291 = yylhsminor.yy291; break; - case 251: /* expritem ::= expr */ -{yylhsminor.yy134 = yymsp[0].minor.yy134;} - yymsp[0].minor.yy134 = yylhsminor.yy134; + case 252: /* expritem ::= expr */ +{yylhsminor.yy436 = yymsp[0].minor.yy436;} + yymsp[0].minor.yy436 = yylhsminor.yy436; break; - case 253: /* cmd ::= RESET QUERY CACHE */ -{ setDCLSQLElems(pInfo, TSDB_SQL_RESET_CACHE, 0);} + case 254: /* cmd ::= RESET QUERY CACHE */ +{ setDCLSqlElems(pInfo, TSDB_SQL_RESET_CACHE, 0);} break; - case 254: /* cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ + case 255: /* cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, yymsp[0].minor.yy193, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy291, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; - case 255: /* cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ + case 256: /* cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; toTSDBType(yymsp[0].minor.yy0.type); SArray* K = tVariantListAppendToken(NULL, &yymsp[0].minor.yy0, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; - case 256: /* cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ + case 257: /* cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, yymsp[0].minor.yy193, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy291, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; - case 257: /* cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ + case 258: /* cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; toTSDBType(yymsp[0].minor.yy0.type); SArray* A = tVariantListAppendToken(NULL, &yymsp[0].minor.yy0, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, NULL, A, TSDB_ALTER_TABLE_DROP_TAG_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, NULL, A, TSDB_ALTER_TABLE_DROP_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; - case 258: /* cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ + case 259: /* cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ { yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; @@ -3334,59 +3338,59 @@ static YYACTIONTYPE yy_reduce( toTSDBType(yymsp[0].minor.yy0.type); A = tVariantListAppendToken(A, &yymsp[0].minor.yy0, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-5].minor.yy0, NULL, A, TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-5].minor.yy0, NULL, A, TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; - case 259: /* cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ + case 260: /* cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ { yymsp[-6].minor.yy0.n += yymsp[-5].minor.yy0.n; toTSDBType(yymsp[-2].minor.yy0.type); SArray* A = tVariantListAppendToken(NULL, &yymsp[-2].minor.yy0, -1); - A = tVariantListAppend(A, &yymsp[0].minor.yy442, -1); + A = tVariantListAppend(A, &yymsp[0].minor.yy216, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-6].minor.yy0, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_VAL, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-6].minor.yy0, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_VAL, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; - case 260: /* cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ + case 261: /* cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, yymsp[0].minor.yy193, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy291, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; - case 261: /* cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ + case 262: /* cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; toTSDBType(yymsp[0].minor.yy0.type); SArray* K = tVariantListAppendToken(NULL, &yymsp[0].minor.yy0, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; - case 262: /* cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ + case 263: /* cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, yymsp[0].minor.yy193, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy291, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; - case 263: /* cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ + case 264: /* cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; toTSDBType(yymsp[0].minor.yy0.type); SArray* A = tVariantListAppendToken(NULL, &yymsp[0].minor.yy0, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-4].minor.yy0, NULL, A, TSDB_ALTER_TABLE_DROP_TAG_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, NULL, A, TSDB_ALTER_TABLE_DROP_TAG_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; - case 264: /* cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ + case 265: /* cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ { yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; @@ -3396,17 +3400,17 @@ static YYACTIONTYPE yy_reduce( toTSDBType(yymsp[0].minor.yy0.type); A = tVariantListAppendToken(A, &yymsp[0].minor.yy0, -1); - SAlterTableInfo* pAlterTable = tAlterTableSqlElems(&yymsp[-5].minor.yy0, NULL, A, TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-5].minor.yy0, NULL, A, TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } break; - case 265: /* cmd ::= KILL CONNECTION INTEGER */ + case 266: /* cmd ::= KILL CONNECTION INTEGER */ {setKillSql(pInfo, TSDB_SQL_KILL_CONNECTION, &yymsp[0].minor.yy0);} break; - case 266: /* cmd ::= KILL STREAM INTEGER COLON INTEGER */ + case 267: /* cmd ::= KILL STREAM INTEGER COLON INTEGER */ {yymsp[-2].minor.yy0.n += (yymsp[-1].minor.yy0.n + yymsp[0].minor.yy0.n); setKillSql(pInfo, TSDB_SQL_KILL_STREAM, &yymsp[-2].minor.yy0);} break; - case 267: /* cmd ::= KILL QUERY INTEGER COLON INTEGER */ + case 268: /* cmd ::= KILL QUERY INTEGER COLON INTEGER */ {yymsp[-2].minor.yy0.n += (yymsp[-1].minor.yy0.n + yymsp[0].minor.yy0.n); setKillSql(pInfo, TSDB_SQL_KILL_QUERY, &yymsp[-2].minor.yy0);} break; default: diff --git a/src/sync/inc/syncInt.h b/src/sync/inc/syncInt.h index 91613ae35107f0a667798e730f6021687e3ced5e..2b87938474d9385e5d093dcf524be777eb22db27 100644 --- a/src/sync/inc/syncInt.h +++ b/src/sync/inc/syncInt.h @@ -117,6 +117,7 @@ typedef struct SSyncNode { FStartSyncFile startSyncFileFp; FStopSyncFile stopSyncFileFp; FGetVersion getVersionFp; + FResetVersion resetVersionFp; FSendFile sendFileFp; FRecvFile recvFileFp; pthread_mutex_t mutex; diff --git a/src/sync/src/syncMain.c b/src/sync/src/syncMain.c index 956ccdc0730e345d2e0ece3bcf45e4d0e9b3c14d..264bbf6b925b2244e38915326f7b9eaf9e8831ad 100644 --- a/src/sync/src/syncMain.c +++ b/src/sync/src/syncMain.c @@ -56,7 +56,7 @@ static void syncMonitorNodeRole(void *param, void *tmrId); static void syncProcessFwdAck(SSyncNode *pNode, SFwdInfo *pFwdInfo, int32_t code); static int32_t syncSaveFwdInfo(SSyncNode *pNode, uint64_t version, void *mhandle); static void syncRestartPeer(SSyncPeer *pPeer); -static int32_t syncForwardToPeerImpl(SSyncNode *pNode, void *data, void *mhandle, int32_t qtyp); +static int32_t syncForwardToPeerImpl(SSyncNode *pNode, void *data, void *mhandle, int32_t qtype, bool force); static SSyncPeer *syncAddPeer(SSyncNode *pNode, const SNodeInfo *pInfo); static void syncStartCheckPeerConn(SSyncPeer *pPeer); @@ -182,6 +182,7 @@ int64_t syncStart(const SSyncInfo *pInfo) { pNode->startSyncFileFp = pInfo->startSyncFileFp; pNode->stopSyncFileFp = pInfo->stopSyncFileFp; pNode->getVersionFp = pInfo->getVersionFp; + pNode->resetVersionFp = pInfo->resetVersionFp; pNode->sendFileFp = pInfo->sendFileFp; pNode->recvFileFp = pInfo->recvFileFp; @@ -377,24 +378,24 @@ int32_t syncReconfig(int64_t rid, const SSyncCfg *pNewCfg) { return 0; } -int32_t syncForwardToPeer(int64_t rid, void *data, void *mhandle, int32_t qtype) { +int32_t syncForwardToPeer(int64_t rid, void *data, void *mhandle, int32_t qtype, bool force) { if (rid <= 0) return 0; SSyncNode *pNode = syncAcquireNode(rid); if (pNode == NULL) return 0; - int32_t code = syncForwardToPeerImpl(pNode, data, mhandle, qtype); + int32_t code = syncForwardToPeerImpl(pNode, data, mhandle, qtype, force); syncReleaseNode(pNode); return code; } -void syncConfirmForward(int64_t rid, uint64_t version, int32_t code) { +void syncConfirmForward(int64_t rid, uint64_t version, int32_t code, bool force) { SSyncNode *pNode = syncAcquireNode(rid); if (pNode == NULL) return; SSyncPeer *pPeer = pNode->pMaster; - if (pPeer && pNode->quorum > 1) { + if (pPeer && (pNode->quorum > 1 || force)) { SFwdRsp rsp; syncBuildSyncFwdRsp(&rsp, pNode->vgId, version, code); @@ -1413,7 +1414,7 @@ static void syncMonitorFwdInfos(void *param, void *tmrId) { syncReleaseNode(pNode); } -static int32_t syncForwardToPeerImpl(SSyncNode *pNode, void *data, void *mhandle, int32_t qtype) { +static int32_t syncForwardToPeerImpl(SSyncNode *pNode, void *data, void *mhandle, int32_t qtype, bool force) { SSyncPeer *pPeer; SSyncHead *pSyncHead; SWalHead * pWalHead = data; @@ -1457,7 +1458,7 @@ static int32_t syncForwardToPeerImpl(SSyncNode *pNode, void *data, void *mhandle if (pPeer == NULL || pPeer->peerFd < 0) continue; if (pPeer->role != TAOS_SYNC_ROLE_SLAVE && pPeer->sstatus != TAOS_SYNC_STATUS_CACHE) continue; - if (pNode->quorum > 1 && code == 0) { + if ((pNode->quorum > 1 || force) && code == 0) { code = syncSaveFwdInfo(pNode, pWalHead->version, mhandle); if (code >= 0) code = 1; } diff --git a/src/sync/src/syncRestore.c b/src/sync/src/syncRestore.c index c0d66316cd5b802ddcaddf1015d4ceca1aa3b2c5..22d0a2758131f3880adc63f3777528c8e3d06ff9 100644 --- a/src/sync/src/syncRestore.c +++ b/src/sync/src/syncRestore.c @@ -238,6 +238,7 @@ static int32_t syncRestoreDataStepByStep(SSyncPeer *pPeer) { (*pNode->stopSyncFileFp)(pNode->vgId, fversion); nodeVersion = fversion; + if (pNode->resetVersionFp) (*pNode->resetVersionFp)(pNode->vgId, fversion); sInfo("%s, start to restore wal, fver:%" PRIu64, pPeer->id, nodeVersion); uint64_t wver = 0; diff --git a/src/sync/src/syncRetrieve.c b/src/sync/src/syncRetrieve.c index be4073760dfa551878301bc3bd4f2405b12b77cf..505ba68c41f2c2373dba3322b6ed31ba0ac853f1 100644 --- a/src/sync/src/syncRetrieve.c +++ b/src/sync/src/syncRetrieve.c @@ -29,7 +29,7 @@ static int32_t syncGetWalVersion(SSyncNode *pNode, SSyncPeer *pPeer) { uint64_t fver, wver; int32_t code = (*pNode->getVersionFp)(pNode->vgId, &fver, &wver); if (code != 0) { - sDebug("%s, vnode is commiting while retrieve, last wver:%" PRIu64, pPeer->id, pPeer->lastWalVer); + sInfo("%s, vnode is commiting while retrieve, last wver:%" PRIu64, pPeer->id, pPeer->lastWalVer); return -1; } @@ -41,12 +41,12 @@ static bool syncIsWalModified(SSyncNode *pNode, SSyncPeer *pPeer) { uint64_t fver, wver; int32_t code = (*pNode->getVersionFp)(pNode->vgId, &fver, &wver); if (code != 0) { - sDebug("%s, vnode is commiting while retrieve, last wver:%" PRIu64, pPeer->id, pPeer->lastWalVer); + sInfo("%s, vnode is commiting while retrieve, last wver:%" PRIu64, pPeer->id, pPeer->lastWalVer); return true; } if (wver != pPeer->lastWalVer) { - sDebug("%s, wal is modified while retrieve, wver:%" PRIu64 ", last:%" PRIu64, pPeer->id, wver, pPeer->lastWalVer); + sInfo("%s, wal is modified while retrieve, wver:%" PRIu64 ", last:%" PRIu64, pPeer->id, wver, pPeer->lastWalVer); return true; } @@ -57,7 +57,7 @@ static int32_t syncGetFileVersion(SSyncNode *pNode, SSyncPeer *pPeer) { uint64_t fver, wver; int32_t code = (*pNode->getVersionFp)(pNode->vgId, &fver, &wver); if (code != 0) { - sDebug("%s, vnode is commiting while get fver for retrieve, last fver:%" PRIu64, pPeer->id, pPeer->lastFileVer); + sInfo("%s, vnode is commiting while get fver for retrieve, last fver:%" PRIu64, pPeer->id, pPeer->lastFileVer); return -1; } @@ -69,13 +69,13 @@ static bool syncAreFilesModified(SSyncNode *pNode, SSyncPeer *pPeer) { uint64_t fver, wver; int32_t code = (*pNode->getVersionFp)(pNode->vgId, &fver, &wver); if (code != 0) { - sDebug("%s, vnode is commiting while retrieve, last fver:%" PRIu64, pPeer->id, pPeer->lastFileVer); + sInfo("%s, vnode is commiting while retrieve, last fver:%" PRIu64, pPeer->id, pPeer->lastFileVer); pPeer->fileChanged = 1; return true; } if (fver != pPeer->lastFileVer) { - sDebug("%s, files are modified while retrieve, fver:%" PRIu64 ", last:%" PRIu64, pPeer->id, fver, pPeer->lastFileVer); + sInfo("%s, files are modified while retrieve, fver:%" PRIu64 ", last:%" PRIu64, pPeer->id, fver, pPeer->lastFileVer); pPeer->fileChanged = 1; return true; } @@ -143,13 +143,13 @@ static int32_t syncReadOneWalRecord(int32_t sfd, SWalHead *pHead) { } if (ret == 0) { - sDebug("sfd:%d, read to the end of file, ret:%d", sfd, ret); + sInfo("sfd:%d, read to the end of file, ret:%d", sfd, ret); return 0; } if (ret != sizeof(SWalHead)) { // file is not at end yet, it shall be reloaded - sDebug("sfd:%d, a partial wal head is read out, ret:%d", sfd, ret); + sInfo("sfd:%d, a partial wal head is read out, ret:%d", sfd, ret); return 0; } @@ -163,7 +163,7 @@ static int32_t syncReadOneWalRecord(int32_t sfd, SWalHead *pHead) { if (ret != pHead->len) { // file is not at end yet, it shall be reloaded - sDebug("sfd:%d, a partial wal conetnt is read out, ret:%d", sfd, ret); + sInfo("sfd:%d, a partial wal conetnt is read out, ret:%d", sfd, ret); return 0; } @@ -184,7 +184,7 @@ static int64_t syncRetrieveLastWal(SSyncPeer *pPeer, char *name, uint64_t fversi return -1; } - sDebug("%s, retrieve last wal:%s, offset:%" PRId64 " fver:%" PRIu64, pPeer->id, name, offset, fversion); + sInfo("%s, retrieve last wal:%s, offset:%" PRId64 " fver:%" PRIu64, pPeer->id, name, offset, fversion); SWalHead *pHead = malloc(SYNC_MAX_SIZE); int64_t bytes = 0; @@ -198,7 +198,7 @@ static int64_t syncRetrieveLastWal(SSyncPeer *pPeer, char *name, uint64_t fversi if (code == 0) { code = bytes; - sDebug("%s, read to the end of wal, bytes:%" PRId64, pPeer->id, bytes); + sInfo("%s, read to the end of wal, bytes:%" PRId64, pPeer->id, bytes); break; } @@ -217,7 +217,7 @@ static int64_t syncRetrieveLastWal(SSyncPeer *pPeer, char *name, uint64_t fversi if (pHead->version >= fversion && fversion > 0) { code = 0; - sDebug("%s, retrieve wal finished, hver:%" PRIu64 " fver:%" PRIu64, pPeer->id, pHead->version, fversion); + sInfo("%s, retrieve wal finished, hver:%" PRIu64 " fver:%" PRIu64, pPeer->id, pHead->version, fversion); break; } } @@ -237,7 +237,7 @@ static int64_t syncProcessLastWal(SSyncPeer *pPeer, char *wname, int64_t index) // get full path to wal file snprintf(fname, sizeof(fname), "%s/%s", pNode->path, wname); - sDebug("%s, start to retrieve last wal:%s", pPeer->id, fname); + sInfo("%s, start to retrieve last wal:%s", pPeer->id, fname); while (1) { if (syncAreFilesModified(pNode, pPeer)) return -1; @@ -245,7 +245,7 @@ static int64_t syncProcessLastWal(SSyncPeer *pPeer, char *wname, int64_t index) int64_t bytes = syncRetrieveLastWal(pPeer, fname, fversion, offset); if (bytes < 0) { - sDebug("%s, failed to retrieve last wal, bytes:%" PRId64, pPeer->id, bytes); + sInfo("%s, failed to retrieve last wal, bytes:%" PRId64, pPeer->id, bytes); return bytes; } @@ -257,13 +257,13 @@ static int64_t syncProcessLastWal(SSyncPeer *pPeer, char *wname, int64_t index) if (fversion == 0) { pPeer->sstatus = TAOS_SYNC_STATUS_CACHE; // start to forward pkt fversion = nodeVersion; // must read data to fversion - sDebug("%s, set sstatus:%s and fver:%" PRIu64, pPeer->id, syncStatus[pPeer->sstatus], fversion); + sInfo("%s, set sstatus:%s and fver:%" PRIu64, pPeer->id, syncStatus[pPeer->sstatus], fversion); } } // if all data up to fversion is read out, it is over if (pPeer->sversion >= fversion && fversion > 0) { - sDebug("%s, data up to fver:%" PRIu64 " has been read out, bytes:%" PRId64 " sver:%" PRIu64, pPeer->id, fversion, bytes, + sInfo("%s, data up to fver:%" PRIu64 " has been read out, bytes:%" PRId64 " sver:%" PRIu64, pPeer->id, fversion, bytes, pPeer->sversion); return 0; } @@ -277,7 +277,7 @@ static int64_t syncProcessLastWal(SSyncPeer *pPeer, char *wname, int64_t index) // if bytes > 0, file is updated, or fversion is not reached but file still open, read again once = 1; offset += bytes; - sDebug("%s, continue retrieve last wal, bytes:%" PRId64 " offset:%" PRId64 " sver:%" PRIu64 " fver:%" PRIu64, pPeer->id, + sInfo("%s, continue retrieve last wal, bytes:%" PRId64 " offset:%" PRId64 " sver:%" PRIu64 " fver:%" PRIu64, pPeer->id, bytes, offset, pPeer->sversion, fversion); } @@ -303,7 +303,7 @@ static int64_t syncRetrieveWal(SSyncPeer *pPeer) { if (wname[0] == 0) { // no wal file code = 0; - sDebug("%s, no wal file anymore", pPeer->id); + sInfo("%s, no wal file anymore", pPeer->id); break; } @@ -320,12 +320,12 @@ static int64_t syncRetrieveWal(SSyncPeer *pPeer) { struct stat fstat; if (stat(fname, &fstat) < 0) { code = -1; - sDebug("%s, failed to stat wal:%s for retrieve since %s, code:0x%" PRIx64, pPeer->id, fname, strerror(errno), code); + sInfo("%s, failed to stat wal:%s for retrieve since %s, code:0x%" PRIx64, pPeer->id, fname, strerror(errno), code); break; } size = fstat.st_size; - sDebug("%s, retrieve wal:%s size:%d", pPeer->id, fname, size); + sInfo("%s, retrieve wal:%s size:%d", pPeer->id, fname, size); int32_t sfd = open(fname, O_RDONLY | O_BINARY); if (sfd < 0) { @@ -334,7 +334,7 @@ static int64_t syncRetrieveWal(SSyncPeer *pPeer) { break; } - code = (int32_t)taosSendFile(pPeer->syncFd, sfd, NULL, size); + code = taosSendFile(pPeer->syncFd, sfd, NULL, size); close(sfd); if (code < 0) { sError("%s, failed to send wal:%s for retrieve since %s, code:0x%" PRIx64, pPeer->id, fname, strerror(errno), code); @@ -374,7 +374,7 @@ static int32_t syncRetrieveFirstPkt(SSyncPeer *pPeer) { sError("%s, failed to send sync-data msg since %s, tranId:%u", pPeer->id, strerror(errno), msg.tranId); return -1; } - sDebug("%s, send sync-data msg to peer, tranId:%u", pPeer->id, msg.tranId); + sInfo("%s, send sync-data msg to peer, tranId:%u", pPeer->id, msg.tranId); SSyncRsp rsp; if (taosReadMsg(pPeer->syncFd, &rsp, sizeof(SSyncRsp)) != sizeof(SSyncRsp)) { @@ -382,7 +382,7 @@ static int32_t syncRetrieveFirstPkt(SSyncPeer *pPeer) { return -1; } - sDebug("%s, recv sync-data rsp from peer, tranId:%u rsp-tranId:%u", pPeer->id, msg.tranId, rsp.tranId); + sInfo("%s, recv sync-data rsp from peer, tranId:%u rsp-tranId:%u", pPeer->id, msg.tranId, rsp.tranId); return 0; } diff --git a/src/tfs/inc/tfsint.h b/src/tfs/inc/tfsint.h index fa4cd597237a957064e1cca74fe089051db450c6..619ef6df73444934a949955af41c85f359660116 100644 --- a/src/tfs/inc/tfsint.h +++ b/src/tfs/inc/tfsint.h @@ -41,6 +41,7 @@ extern int fsDebugFlag; // tdisk.c ====================================================== typedef struct { int64_t size; + int64_t used; int64_t free; } SDiskMeta; @@ -56,6 +57,7 @@ typedef struct SDisk { #define DISK_DIR(pd) ((pd)->dir) #define DISK_META(pd) ((pd)->dmeta) #define DISK_SIZE(pd) ((pd)->dmeta.size) +#define DISK_USED_SIZE(pd) ((pd)->dmeta.used) #define DISK_FREE_SIZE(pd) ((pd)->dmeta.free) SDisk *tfsNewDisk(int level, int id, const char *dir); @@ -65,6 +67,7 @@ int tfsUpdateDiskInfo(SDisk *pDisk); // ttier.c ====================================================== typedef struct { int64_t size; + int64_t used; int64_t free; int16_t nAvailDisks; // # of Available disks } STierMeta; @@ -96,4 +99,4 @@ void tfsPosNextId(STier *pTier); } #endif -#endif \ No newline at end of file +#endif diff --git a/src/tfs/src/tdisk.c b/src/tfs/src/tdisk.c index 37798d3a886b443a20703747ad9a99e26c1502b7..22601e48c3607fca53c91ea00b17551c791302bd 100644 --- a/src/tfs/src/tdisk.c +++ b/src/tfs/src/tdisk.c @@ -27,7 +27,7 @@ SDisk *tfsNewDisk(int level, int id, const char *dir) { pDisk->level = level; pDisk->id = id; - strncpy(pDisk->dir, dir, TSDB_FILENAME_LEN); + tstrncpy(pDisk->dir, dir, TSDB_FILENAME_LEN); return pDisk; } @@ -52,6 +52,7 @@ int tfsUpdateDiskInfo(SDisk *pDisk) { } pDisk->dmeta.size = diskSize.tsize; + pDisk->dmeta.used = diskSize.used; pDisk->dmeta.free = diskSize.avail; return code; diff --git a/src/tfs/src/tfs.c b/src/tfs/src/tfs.c index 7b7c9b6127db0f1c8cabab35254ba4a128e05f05..f78535b8ed5bd17cb232fbcbc73f9831db099547 100644 --- a/src/tfs/src/tfs.c +++ b/src/tfs/src/tfs.c @@ -134,6 +134,7 @@ void tfsUpdateInfo(SFSMeta *pFSMeta) { tfsUpdateTierInfo(pTier, &tierMeta); pFSMeta->tsize += tierMeta.size; pFSMeta->avail += tierMeta.free; + pFSMeta->used += tierMeta.used; } tfsLock(); @@ -186,7 +187,7 @@ void tfsInitFile(TFILE *pf, int level, int id, const char *bname) { pf->level = level; pf->id = id; - strncpy(pf->rname, bname, TSDB_FILENAME_LEN); + tstrncpy(pf->rname, bname, TSDB_FILENAME_LEN); char tmpName[TMPNAME_LEN] = {0}; snprintf(tmpName, TMPNAME_LEN, "%s/%s", DISK_DIR(pDisk), bname); @@ -229,15 +230,15 @@ void *tfsDecodeFile(void *buf, TFILE *pf) { void tfsbasename(const TFILE *pf, char *dest) { char tname[TSDB_FILENAME_LEN] = "\0"; - strncpy(tname, pf->aname, TSDB_FILENAME_LEN); - strncpy(dest, basename(tname), TSDB_FILENAME_LEN); + tstrncpy(tname, pf->aname, TSDB_FILENAME_LEN); + tstrncpy(dest, basename(tname), TSDB_FILENAME_LEN); } void tfsdirname(const TFILE *pf, char *dest) { char tname[TSDB_FILENAME_LEN] = "\0"; - strncpy(tname, pf->aname, TSDB_FILENAME_LEN); - strncpy(dest, dirname(tname), TSDB_FILENAME_LEN); + tstrncpy(tname, pf->aname, TSDB_FILENAME_LEN); + tstrncpy(dest, dirname(tname), TSDB_FILENAME_LEN); } // DIR APIs ==================================== @@ -343,7 +344,7 @@ TDIR *tfsOpendir(const char *rname) { } tfsInitDiskIter(&(tdir->iter)); - strncpy(tdir->dirname, rname, TSDB_FILENAME_LEN); + tstrncpy(tdir->dirname, rname, TSDB_FILENAME_LEN); if (tfsOpendirImpl(tdir) < 0) { free(tdir); @@ -585,6 +586,7 @@ void taosGetDisk() { if (tscEmbedded) { tfsUpdateInfo(&fsMeta); tsTotalDataDirGB = (float)(fsMeta.tsize / unit); + tsUsedDataDirGB = (float)(fsMeta.used / unit); tsAvailDataDirGB = (float)(fsMeta.avail / unit); } diff --git a/src/tfs/src/ttier.c b/src/tfs/src/ttier.c index 2dce0c31949a145bdafd111a63e96c2b83a7140c..3b19797acf67f36a31c30dccefc0c985512f510b 100644 --- a/src/tfs/src/ttier.c +++ b/src/tfs/src/ttier.c @@ -100,6 +100,7 @@ void tfsUpdateTierInfo(STier *pTier, STierMeta *pTierMeta) { continue; } pTierMeta->size += DISK_SIZE(DISK_AT_TIER(pTier, id)); + pTierMeta->used += DISK_USED_SIZE(DISK_AT_TIER(pTier, id)); pTierMeta->free += DISK_FREE_SIZE(DISK_AT_TIER(pTier, id)); pTierMeta->nAvailDisks++; } @@ -166,4 +167,4 @@ void tfsPosNextId(STier *pTier) { } pTier->nextid = nextid; -} \ No newline at end of file +} diff --git a/src/tsdb/inc/tsdbFile.h b/src/tsdb/inc/tsdbFile.h index f1e2422e45b195e3874518132051ded67a776449..792efcdb2e0cc0245203d91e80369205cab74d56 100644 --- a/src/tsdb/inc/tsdbFile.h +++ b/src/tsdb/inc/tsdbFile.h @@ -334,7 +334,7 @@ static FORCE_INLINE int tsdbOpenDFileSet(SDFileSet* pSet, int flags) { static FORCE_INLINE void tsdbRemoveDFileSet(SDFileSet* pSet) { for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) { - tsdbRemoveDFile(TSDB_DFILE_IN_SET(pSet, ftype)); + (void)tsdbRemoveDFile(TSDB_DFILE_IN_SET(pSet, ftype)); } } diff --git a/src/tsdb/inc/tsdbMemTable.h b/src/tsdb/inc/tsdbMemTable.h index bd64ed4a5238b3b8b60716d8732d59d27218c639..6046274af40b855ac25dba6e220bf3bcfdc1dcca 100644 --- a/src/tsdb/inc/tsdbMemTable.h +++ b/src/tsdb/inc/tsdbMemTable.h @@ -31,29 +31,14 @@ typedef struct { SSkipListIterator *pIter; } SCommitIter; -typedef struct { +struct STableData { uint64_t uid; TSKEY keyFirst; TSKEY keyLast; int64_t numOfRows; SSkipList* pData; T_REF_DECLARE() -} STableData; - -typedef struct { - T_REF_DECLARE() - SRWLatch latch; - TSKEY keyFirst; - TSKEY keyLast; - int64_t numOfRows; - int32_t maxTables; - STableData** tData; - SList* actList; - SList* extraBuffList; - SList* bufBlockList; - int64_t pointsAdd; // TODO - int64_t storageAdd; // TODO -} SMemTable; +}; enum { TSDB_UPDATE_META, TSDB_DROP_META }; @@ -77,8 +62,8 @@ typedef struct { int tsdbRefMemTable(STsdbRepo* pRepo, SMemTable* pMemTable); int tsdbUnRefMemTable(STsdbRepo* pRepo, SMemTable* pMemTable); -int tsdbTakeMemSnapshot(STsdbRepo* pRepo, SMemTable** pMem, SMemTable** pIMem, SArray* pATable); -void tsdbUnTakeMemSnapShot(STsdbRepo* pRepo, SMemTable* pMem, SMemTable* pIMem); +int tsdbTakeMemSnapshot(STsdbRepo* pRepo, SMemSnapshot* pSnapshot, SArray* pATable); +void tsdbUnTakeMemSnapShot(STsdbRepo* pRepo, SMemSnapshot* pSnapshot); void* tsdbAllocBytes(STsdbRepo* pRepo, int bytes); int tsdbAsyncCommit(STsdbRepo* pRepo); int tsdbLoadDataFromCache(STable* pTable, SSkipListIterator* pIter, TSKEY maxKey, int maxRowsToRead, SDataCols* pCols, diff --git a/src/tsdb/src/tsdbCommit.c b/src/tsdb/src/tsdbCommit.c index a1ed0796a6e628a55ebe81fd87396ada990b7e73..02dd2d1ca40a04dd1102f884bae528916b522272 100644 --- a/src/tsdb/src/tsdbCommit.c +++ b/src/tsdb/src/tsdbCommit.c @@ -164,7 +164,7 @@ static int tsdbCommitMeta(STsdbRepo *pRepo) { tsdbError("vgId:%d failed to update META record, uid %" PRIu64 " since %s", REPO_ID(pRepo), pAct->uid, tstrerror(terrno)); tsdbCloseMFile(&mf); - tsdbApplyMFileChange(&mf, pOMFile); + (void)tsdbApplyMFileChange(&mf, pOMFile); // TODO: need to reload metaCache return -1; } @@ -304,7 +304,7 @@ static int tsdbCommitTSData(STsdbRepo *pRepo) { SDFileSet *pSet = NULL; int fid; - memset(&commith, 0, sizeof(SMemTable *)); + memset(&commith, 0, sizeof(commith)); if (pMem->numOfRows <= 0) { // No memory data, just apply retention on each file on disk @@ -399,9 +399,9 @@ static void tsdbEndCommit(STsdbRepo *pRepo, int eno) { if (pRepo->appH.notifyStatus) pRepo->appH.notifyStatus(pRepo->appH.appH, TSDB_STATUS_COMMIT_OVER, eno); SMemTable *pIMem = pRepo->imem; - tsdbLockRepo(pRepo); + (void)tsdbLockRepo(pRepo); pRepo->imem = NULL; - tsdbUnlockRepo(pRepo); + (void)tsdbUnlockRepo(pRepo); tsdbUnRefMemTable(pRepo, pIMem); tsem_post(&(pRepo->readyToCommit)); } @@ -1136,12 +1136,12 @@ static int tsdbMoveBlock(SCommitH *pCommith, int bidx) { } static int tsdbCommitAddBlock(SCommitH *pCommith, const SBlock *pSupBlock, const SBlock *pSubBlocks, int nSubBlocks) { - if (taosArrayPush(pCommith->aSupBlk, pSupBlock) < 0) { + if (taosArrayPush(pCommith->aSupBlk, pSupBlock) == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; return -1; } - if (pSubBlocks && taosArrayPushBatch(pCommith->aSubBlk, pSubBlocks, nSubBlocks) < 0) { + if (pSubBlocks && taosArrayPushBatch(pCommith->aSubBlk, pSubBlocks, nSubBlocks) == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; return -1; } @@ -1379,7 +1379,7 @@ static int tsdbSetAndOpenCommitFile(SCommitH *pCommith, SDFileSet *pSet, int fid tstrerror(terrno)); tsdbCloseDFileSet(pWSet); - tsdbRemoveDFile(pWHeadf); + (void)tsdbRemoveDFile(pWHeadf); if (pCommith->isRFileSet) { tsdbCloseAndUnsetFSet(&(pCommith->readh)); return -1; diff --git a/src/tsdb/src/tsdbFS.c b/src/tsdb/src/tsdbFS.c index cbff4fbeaa6907c83b5836d6039cbfc23a62168b..a9e74cb229df24800bd920186113669164ca7dc7 100644 --- a/src/tsdb/src/tsdbFS.c +++ b/src/tsdb/src/tsdbFS.c @@ -380,7 +380,7 @@ static int tsdbSaveFSStatus(SFSStatus *pStatus, int vid) { if (taosWrite(fd, pBuf, fsheader.len) < fsheader.len) { terrno = TAOS_SYSTEM_ERROR(errno); close(fd); - remove(tfname); + (void)remove(tfname); taosTZfree(pBuf); return -1; } @@ -413,7 +413,7 @@ static void tsdbApplyFSTxnOnDisk(SFSStatus *pFrom, SFSStatus *pTo) { sizeTo = taosArrayGetSize(pTo->df); // Apply meta file change - tsdbApplyMFileChange(pFrom->pmf, pTo->pmf); + (void)tsdbApplyMFileChange(pFrom->pmf, pTo->pmf); // Apply SDFileSet change if (ifrom >= sizeFrom) { @@ -853,7 +853,7 @@ static int tsdbScanRootDir(STsdbRepo *pRepo) { continue; } - tfsremove(pf); + (void)tfsremove(pf); tsdbDebug("vgId:%d invalid file %s is removed", REPO_ID(pRepo), TFILE_NAME(pf)); } @@ -879,7 +879,7 @@ static int tsdbScanDataDir(STsdbRepo *pRepo) { tfsbasename(pf, bname); if (!tsdbIsTFileInFS(pfs, pf)) { - tfsremove(pf); + (void)tfsremove(pf); tsdbDebug("vgId:%d invalid file %s is removed", REPO_ID(pRepo), TFILE_NAME(pf)); } } @@ -939,7 +939,7 @@ static int tsdbRestoreMeta(STsdbRepo *pRepo) { if (strcmp(bname, tsdbTxnFname[TSDB_TXN_TEMP_FILE]) == 0) { // Skip current.t file tsdbInfo("vgId:%d file %s exists, remove it", REPO_ID(pRepo), TFILE_NAME(pf)); - tfsremove(pf); + (void)tfsremove(pf); continue; } @@ -1045,7 +1045,7 @@ static int tsdbRestoreDFileSet(STsdbRepo *pRepo) { int code = regexec(®ex, bname, 0, NULL, 0); if (code == 0) { - if (taosArrayPush(fArray, (void *)pf) < 0) { + if (taosArrayPush(fArray, (void *)pf) == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; tfsClosedir(tdir); taosArrayDestroy(fArray); @@ -1055,7 +1055,7 @@ static int tsdbRestoreDFileSet(STsdbRepo *pRepo) { } else if (code == REG_NOMATCH) { // Not match tsdbInfo("vgId:%d invalid file %s exists, remove it", REPO_ID(pRepo), TFILE_NAME(pf)); - tfsremove(pf); + (void)tfsremove(pf); continue; } else { // Has other error diff --git a/src/tsdb/src/tsdbFile.c b/src/tsdb/src/tsdbFile.c index 8124a0e3b5984eecee1f0934a385be56d5bd3b61..ac33096aaeb2536a70b5226ce1b5bdb8856903b8 100644 --- a/src/tsdb/src/tsdbFile.c +++ b/src/tsdb/src/tsdbFile.c @@ -523,7 +523,7 @@ static int tsdbApplyDFileChange(SDFile *from, SDFile *to) { tsdbRollBackDFile(to); } } else { - tsdbRemoveDFile(from); + (void)tsdbRemoveDFile(from); } } } diff --git a/src/tsdb/src/tsdbMemTable.c b/src/tsdb/src/tsdbMemTable.c index 6818f2ed14c278bd5d203d0570f52772c159dcde..20ec426018a39e554fb03e9bb11399dbce1f3fcc 100644 --- a/src/tsdb/src/tsdbMemTable.c +++ b/src/tsdb/src/tsdbMemTable.c @@ -124,88 +124,80 @@ int tsdbUnRefMemTable(STsdbRepo *pRepo, SMemTable *pMemTable) { return 0; } -int tsdbTakeMemSnapshot(STsdbRepo *pRepo, SMemTable **pMem, SMemTable **pIMem, SArray *pATable) { - SMemTable *tmem; +int tsdbTakeMemSnapshot(STsdbRepo *pRepo, SMemSnapshot *pSnapshot, SArray *pATable) { + memset(pSnapshot, 0, sizeof(*pSnapshot)); - // Get snap object if (tsdbLockRepo(pRepo) < 0) return -1; - tmem = pRepo->mem; - *pIMem = pRepo->imem; - tsdbRefMemTable(pRepo, tmem); - tsdbRefMemTable(pRepo, *pIMem); + pSnapshot->omem = pRepo->mem; + pSnapshot->imem = pRepo->imem; + tsdbRefMemTable(pRepo, pRepo->mem); + tsdbRefMemTable(pRepo, pRepo->imem); if (tsdbUnlockRepo(pRepo) < 0) return -1; - // Copy mem objects and ref needed STableData - if (tmem) { - taosRLockLatch(&(tmem->latch)); + if (pSnapshot->omem) { + taosRLockLatch(&(pSnapshot->omem->latch)); - *pMem = (SMemTable *)calloc(1, sizeof(**pMem)); - if (*pMem == NULL) { - terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; - taosRUnLockLatch(&(tmem->latch)); - tsdbUnRefMemTable(pRepo, tmem); - tsdbUnRefMemTable(pRepo, *pIMem); - *pMem = NULL; - *pIMem = NULL; - return -1; - } + pSnapshot->mem = &(pSnapshot->mtable); - (*pMem)->tData = (STableData **)calloc(tmem->maxTables, sizeof(STableData *)); - if ((*pMem)->tData == NULL) { + pSnapshot->mem->tData = (STableData **)calloc(pSnapshot->omem->maxTables, sizeof(STableData *)); + if (pSnapshot->mem->tData == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; - taosRUnLockLatch(&(tmem->latch)); - free(*pMem); - tsdbUnRefMemTable(pRepo, tmem); - tsdbUnRefMemTable(pRepo, *pIMem); - *pMem = NULL; - *pIMem = NULL; + taosRUnLockLatch(&(pSnapshot->omem->latch)); + tsdbUnRefMemTable(pRepo, pSnapshot->omem); + tsdbUnRefMemTable(pRepo, pSnapshot->imem); + pSnapshot->mem = NULL; + pSnapshot->imem = NULL; + pSnapshot->omem = NULL; return -1; } - (*pMem)->keyFirst = tmem->keyFirst; - (*pMem)->keyLast = tmem->keyLast; - (*pMem)->numOfRows = tmem->numOfRows; - (*pMem)->maxTables = tmem->maxTables; + pSnapshot->mem->keyFirst = pSnapshot->omem->keyFirst; + pSnapshot->mem->keyLast = pSnapshot->omem->keyLast; + pSnapshot->mem->numOfRows = pSnapshot->omem->numOfRows; + pSnapshot->mem->maxTables = pSnapshot->omem->maxTables; for (size_t i = 0; i < taosArrayGetSize(pATable); i++) { STable * pTable = *(STable **)taosArrayGet(pATable, i); int32_t tid = TABLE_TID(pTable); - STableData *pTableData = (tid < tmem->maxTables) ? tmem->tData[tid] : NULL; + STableData *pTableData = (tid < pSnapshot->omem->maxTables) ? pSnapshot->omem->tData[tid] : NULL; if ((pTableData == NULL) || (TABLE_UID(pTable) != pTableData->uid)) continue; - (*pMem)->tData[tid] = tmem->tData[tid]; - T_REF_INC(tmem->tData[tid]); + pSnapshot->mem->tData[tid] = pTableData; + T_REF_INC(pTableData); } - taosRUnLockLatch(&(tmem->latch)); + taosRUnLockLatch(&(pSnapshot->omem->latch)); } - tsdbUnRefMemTable(pRepo, tmem); - - tsdbDebug("vgId:%d take memory snapshot, pMem %p pIMem %p", REPO_ID(pRepo), *pMem, *pIMem); + tsdbDebug("vgId:%d take memory snapshot, pMem %p pIMem %p", REPO_ID(pRepo), pSnapshot->omem, pSnapshot->imem); return 0; } -void tsdbUnTakeMemSnapShot(STsdbRepo *pRepo, SMemTable *pMem, SMemTable *pIMem) { - tsdbDebug("vgId:%d untake memory snapshot, pMem %p pIMem %p", REPO_ID(pRepo), pMem, pIMem); +void tsdbUnTakeMemSnapShot(STsdbRepo *pRepo, SMemSnapshot *pSnapshot) { + tsdbDebug("vgId:%d untake memory snapshot, pMem %p pIMem %p", REPO_ID(pRepo), pSnapshot->omem, pSnapshot->imem); - if (pMem != NULL) { - for (size_t i = 0; i < pMem->maxTables; i++) { - STableData *pTableData = pMem->tData[i]; + if (pSnapshot->mem) { + ASSERT(pSnapshot->omem != NULL); + + for (size_t i = 0; i < pSnapshot->mem->maxTables; i++) { + STableData *pTableData = pSnapshot->mem->tData[i]; if (pTableData) { tsdbFreeTableData(pTableData); } } - free(pMem->tData); - free(pMem); - } + tfree(pSnapshot->mem->tData); - if (pIMem != NULL) { - tsdbUnRefMemTable(pRepo, pIMem); + tsdbUnRefMemTable(pRepo, pSnapshot->omem); } + + tsdbUnRefMemTable(pRepo, pSnapshot->imem); + + pSnapshot->mem = NULL; + pSnapshot->imem = NULL; + pSnapshot->omem = NULL; } void *tsdbAllocBytes(STsdbRepo *pRepo, int bytes) { diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index cdde2bc91f430273a65aa3ae2ba09bc42771a024..824f69608e8c9d2d00e3219d54b484304827e8ae 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -213,9 +213,9 @@ void *tsdbGetTableTagVal(const void* pTable, int32_t colId, int16_t type, int16_ char *val = tdGetKVRowValOfCol(((STable*)pTable)->tagVal, colId); assert(type == pCol->type && bytes == pCol->bytes); - if (val != NULL && IS_VAR_DATA_TYPE(type)) { - assert(varDataLen(val) < pCol->bytes); - } + // if (val != NULL && IS_VAR_DATA_TYPE(type)) { + // assert(varDataLen(val) < pCol->bytes); + // } return val; } diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 0bf533d027db284a12ae155dc494fd8f9f35a5f1..648b6d3617a53b004d93add220d007fa228f7076 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -194,7 +194,7 @@ static void tsdbMayTakeMemSnapshot(STsdbQueryHandle* pQueryHandle, SArray* psTab SMemRef* pMemRef = pQueryHandle->pMemRef; if (pQueryHandle->pMemRef->ref++ == 0) { - tsdbTakeMemSnapshot(pQueryHandle->pTsdb, (SMemTable**)&(pMemRef->mem), (SMemTable**)&(pMemRef->imem), psTable); + tsdbTakeMemSnapshot(pQueryHandle->pTsdb, &(pMemRef->snapshot), psTable); } taosArrayDestroy(psTable); @@ -208,9 +208,7 @@ static void tsdbMayUnTakeMemSnapshot(STsdbQueryHandle* pQueryHandle) { } if (--pMemRef->ref == 0) { - tsdbUnTakeMemSnapShot(pQueryHandle->pTsdb, pMemRef->mem, pMemRef->imem); - pMemRef->mem = NULL; - pMemRef->imem = NULL; + tsdbUnTakeMemSnapShot(pQueryHandle->pTsdb, &(pMemRef->snapshot)); } pQueryHandle->pMemRef = NULL; @@ -229,10 +227,10 @@ int64_t tsdbGetNumOfRowsInMemTable(TsdbQueryHandleT* pHandle) { if (pMemRef == NULL) { return rows; } STableData* pMem = NULL; - STableData* pIMem = NULL; + STableData* pIMem = NULL; - SMemTable *pMemT = (SMemTable *)(pMemRef->mem); - SMemTable *pIMemT = (SMemTable *)(pMemRef->imem); + SMemTable* pMemT = pMemRef->snapshot.mem; + SMemTable* pIMemT = pMemRef->snapshot.imem; if (pMemT && pCheckInfo->tableId.tid < pMemT->maxTables) { pMem = pMemT->tData[pCheckInfo->tableId.tid]; @@ -605,7 +603,7 @@ static bool initTableMemIterator(STsdbQueryHandle* pHandle, STableCheckInfo* pCh int32_t order = pHandle->order; // no data in buffer, abort - if (pHandle->pMemRef->mem == NULL && pHandle->pMemRef->imem == NULL) { + if (pHandle->pMemRef->snapshot.mem == NULL && pHandle->pMemRef->snapshot.imem == NULL) { return false; } @@ -614,8 +612,8 @@ static bool initTableMemIterator(STsdbQueryHandle* pHandle, STableCheckInfo* pCh STableData* pMem = NULL; STableData* pIMem = NULL; - SMemTable* pMemT = pHandle->pMemRef->mem; - SMemTable* pIMemT = pHandle->pMemRef->imem; + SMemTable* pMemT = pHandle->pMemRef->snapshot.mem; + SMemTable* pIMemT = pHandle->pMemRef->snapshot.imem; if (pMemT && pCheckInfo->tableId.tid < pMemT->maxTables) { pMem = pMemT->tData[pCheckInfo->tableId.tid]; @@ -844,6 +842,10 @@ static int32_t getFileIdFromKey(TSKEY key, int32_t daysPerFile, int32_t precisio return INT32_MIN; } + if (key < 0) { + key -= (daysPerFile * tsMsPerDay[precision]); + } + int64_t fid = (int64_t)(key / (daysPerFile * tsMsPerDay[precision])); // set the starting fileId if (fid < 0L && llabs(fid) > INT32_MAX) { // data value overflow for INT32 fid = INT32_MIN; @@ -1021,6 +1023,14 @@ static int32_t doLoadFileDataBlock(STsdbQueryHandle* pQueryHandle, SBlock* pBloc pBlock->numOfRows = pCols->numOfRows; + // Convert from TKEY to TSKEY for primary timestamp column if current block has timestamp before 1970-01-01T00:00:00Z + if(pBlock->keyFirst < 0 && colIds[0] == PRIMARYKEY_TIMESTAMP_COL_INDEX) { + int64_t* src = pCols->cols[0].pData; + for(int32_t i = 0; i < pBlock->numOfRows; ++i) { + src[i] = tdGetKey(src[i]); + } + } + int64_t elapsedTime = (taosGetTimestampUs() - st); pQueryHandle->cost.blockLoadTime += elapsedTime; @@ -1277,13 +1287,7 @@ int32_t doCopyRowsFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t capacity } if (pColInfo->info.colId == src->colId) { - - if (pColInfo->info.type == TSDB_DATA_TYPE_TIMESTAMP) { - for (int32_t n = 0; n < num; n++) { - TKEY tkey = *(TKEY *)((char*)src->pData + bytes * start + n * sizeof(TKEY)); - *(TSKEY *)(pData + n * sizeof(TSKEY)) = tdGetKey(tkey); - } - } else if (pColInfo->info.type != TSDB_DATA_TYPE_BINARY && pColInfo->info.type != TSDB_DATA_TYPE_NCHAR) { + if (pColInfo->info.type != TSDB_DATA_TYPE_BINARY && pColInfo->info.type != TSDB_DATA_TYPE_NCHAR) { memmove(pData, (char*)src->pData + bytes * start, bytes * num); } else { // handle the var-string char* dst = pData; diff --git a/src/tsdb/src/tsdbReadImpl.c b/src/tsdb/src/tsdbReadImpl.c index 572706d45e6a085f44ffd0a089dc28256255e33e..7212ae1636400b0ce45ef27306356f658fb3f90d 100644 --- a/src/tsdb/src/tsdbReadImpl.c +++ b/src/tsdb/src/tsdbReadImpl.c @@ -139,7 +139,7 @@ int tsdbLoadBlockIdx(SReadH *pReadh) { ptr = tsdbDecodeSBlockIdx(ptr, &blkIdx); ASSERT(ptr != NULL); - if (taosArrayPush(pReadh->aBlkIdx, (void *)(&blkIdx)) < 0) { + if (taosArrayPush(pReadh->aBlkIdx, (void *)(&blkIdx)) == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; return -1; } diff --git a/src/tsdb/src/tsdbSync.c b/src/tsdb/src/tsdbSync.c index 6b8483e4a66df75db529b05db9a29e800e01427a..cef561aebea002649e8458057882094a7e42d9b4 100644 --- a/src/tsdb/src/tsdbSync.c +++ b/src/tsdb/src/tsdbSync.c @@ -152,14 +152,14 @@ static int32_t tsdbSyncSendMeta(SSyncH *pSynch) { return -1; } - int32_t writeLen = (int32_t)mf.info.size; - tsdbInfo("vgId:%d, metafile:%s will be sent, size:%d", REPO_ID(pRepo), mf.f.aname, writeLen); + int64_t writeLen = mf.info.size; + tsdbInfo("vgId:%d, metafile:%s will be sent, size:%" PRId64, REPO_ID(pRepo), mf.f.aname, writeLen); - int32_t ret = (int32_t)taosSendFile(pSynch->socketFd, TSDB_FILE_FD(&mf), 0, writeLen); + int64_t ret = taosSendFile(pSynch->socketFd, TSDB_FILE_FD(&mf), 0, writeLen); if (ret != writeLen) { terrno = TAOS_SYSTEM_ERROR(errno); - tsdbError("vgId:%d, failed to send metafile since %s, ret:%d writeLen:%d", REPO_ID(pRepo), tstrerror(terrno), ret, - writeLen); + tsdbError("vgId:%d, failed to send metafile since %s, ret:%" PRId64 " writeLen:%" PRId64, REPO_ID(pRepo), + tstrerror(terrno), ret, writeLen); tsdbCloseMFile(&mf); return -1; } @@ -217,18 +217,18 @@ static int32_t tsdbSyncRecvMeta(SSyncH *pSynch) { tsdbInfo("vgId:%d, metafile:%s is created", REPO_ID(pRepo), mf.f.aname); - int32_t readLen = (int32_t)pSynch->pmf->info.size; - int32_t ret = taosCopyFds(pSynch->socketFd, TSDB_FILE_FD(&mf), readLen); + int64_t readLen = pSynch->pmf->info.size; + int64_t ret = taosCopyFds(pSynch->socketFd, TSDB_FILE_FD(&mf), readLen); if (ret != readLen) { terrno = TAOS_SYSTEM_ERROR(errno); - tsdbError("vgId:%d, failed to recv metafile since %s, ret:%d readLen:%d", REPO_ID(pRepo), tstrerror(terrno), ret, - readLen); + tsdbError("vgId:%d, failed to recv metafile since %s, ret:%" PRId64 " readLen:%" PRId64, REPO_ID(pRepo), + tstrerror(terrno), ret, readLen); tsdbCloseMFile(&mf); tsdbRemoveMFile(&mf); return -1; } - tsdbInfo("vgId:%d, metafile is received, size:%d", REPO_ID(pRepo), readLen); + tsdbInfo("vgId:%d, metafile is received, size:%" PRId64, REPO_ID(pRepo), readLen); mf.info = pSynch->pmf->info; tsdbCloseMFile(&mf); @@ -463,12 +463,12 @@ static int32_t tsdbSyncRecvDFileSetArray(SSyncH *pSynch) { tsdbInfo("vgId:%d, file:%s will be received, osize:%" PRIu64 " rsize:%" PRIu64, REPO_ID(pRepo), pDFile->f.aname, pDFile->info.size, pRDFile->info.size); - int32_t writeLen = (int32_t)pRDFile->info.size; - int32_t ret = taosCopyFds(pSynch->socketFd, pDFile->fd, writeLen); + int64_t writeLen = pRDFile->info.size; + int64_t ret = taosCopyFds(pSynch->socketFd, pDFile->fd, writeLen); if (ret != writeLen) { terrno = TAOS_SYSTEM_ERROR(errno); - tsdbError("vgId:%d, failed to recv file:%s since %s, ret:%d writeLen:%d", REPO_ID(pRepo), pDFile->f.aname, - tstrerror(terrno), ret, writeLen); + tsdbError("vgId:%d, failed to recv file:%s since %s, ret:%" PRId64 " writeLen:%" PRId64, REPO_ID(pRepo), + pDFile->f.aname, tstrerror(terrno), ret, writeLen); tsdbCloseDFileSet(&fset); tsdbRemoveDFileSet(&fset); return -1; @@ -476,7 +476,7 @@ static int32_t tsdbSyncRecvDFileSetArray(SSyncH *pSynch) { // Update new file info pDFile->info = pRDFile->info; - tsdbInfo("vgId:%d, file:%s is received, size:%d", REPO_ID(pRepo), pDFile->f.aname, writeLen); + tsdbInfo("vgId:%d, file:%s is received, size:%" PRId64, REPO_ID(pRepo), pDFile->f.aname, writeLen); } tsdbCloseDFileSet(&fset); @@ -575,14 +575,14 @@ static int32_t tsdbSyncSendDFileSet(SSyncH *pSynch, SDFileSet *pSet) { return -1; } - int32_t writeLen = (int32_t)df.info.size; - tsdbInfo("vgId:%d, file:%s will be sent, size:%d", REPO_ID(pRepo), df.f.aname, writeLen); + int64_t writeLen = df.info.size; + tsdbInfo("vgId:%d, file:%s will be sent, size:%" PRId64, REPO_ID(pRepo), df.f.aname, writeLen); - int32_t ret = (int32_t)taosSendFile(pSynch->socketFd, TSDB_FILE_FD(&df), 0, writeLen); + int64_t ret = taosSendFile(pSynch->socketFd, TSDB_FILE_FD(&df), 0, writeLen); if (ret != writeLen) { terrno = TAOS_SYSTEM_ERROR(errno); - tsdbError("vgId:%d, failed to send file:%s since %s, ret:%d writeLen:%d", REPO_ID(pRepo), df.f.aname, - tstrerror(terrno), ret, writeLen); + tsdbError("vgId:%d, failed to send file:%s since %s, ret:%" PRId64 " writeLen:%" PRId64, REPO_ID(pRepo), + df.f.aname, tstrerror(terrno), ret, writeLen); tsdbCloseDFile(&df); return -1; } @@ -677,13 +677,13 @@ static int32_t tsdbRecvDFileSetInfo(SSyncH *pSynch) { static int tsdbReload(STsdbRepo *pRepo, bool isMfChanged) { // TODO: may need to stop and restart stream - if (isMfChanged) { - tsdbCloseMeta(pRepo); - tsdbFreeMeta(pRepo->tsdbMeta); - pRepo->tsdbMeta = tsdbNewMeta(REPO_CFG(pRepo)); - tsdbOpenMeta(pRepo); - tsdbLoadMetaCache(pRepo, true); - } + // if (isMfChanged) { + tsdbCloseMeta(pRepo); + tsdbFreeMeta(pRepo->tsdbMeta); + pRepo->tsdbMeta = tsdbNewMeta(REPO_CFG(pRepo)); + tsdbOpenMeta(pRepo); + tsdbLoadMetaCache(pRepo, true); + // } tsdbUnRefMemTable(pRepo, pRepo->mem); tsdbUnRefMemTable(pRepo, pRepo->imem); diff --git a/src/util/inc/tchecksum.h b/src/util/inc/tchecksum.h index 495aaf33e8fca3594c45f1cfe6fc6acc59fa59d5..12ca3a54432187ea5af0ac24208e81d5028359bb 100644 --- a/src/util/inc/tchecksum.h +++ b/src/util/inc/tchecksum.h @@ -47,7 +47,6 @@ static FORCE_INLINE int taosCalcChecksumAppend(TSCKSUM csi, uint8_t *stream, uin } static FORCE_INLINE int taosCheckChecksum(const uint8_t *stream, uint32_t ssize, TSCKSUM checksum) { - if (ssize < 0) return 0; return (checksum == (*crc32c)(0, stream, (size_t)ssize)); } diff --git a/src/util/inc/tidpool.h b/src/util/inc/tidpool.h index bf352516310a1356f37359ab3052814d726ab8f0..e4439439ced6522e26c8db4a560c50f5b0cb8a16 100644 --- a/src/util/inc/tidpool.h +++ b/src/util/inc/tidpool.h @@ -34,7 +34,7 @@ void taosIdPoolCleanUp(void *handle); int taosIdPoolNumOfUsed(void *handle); -void taosIdPoolMarkStatus(void *handle, int id); +bool taosIdPoolMarkStatus(void *handle, int id); #ifdef __cplusplus } diff --git a/src/util/inc/tsocket.h b/src/util/inc/tsocket.h index 35b591b61e007dcf6d4edc39810a60454f37c07a..b4f55169594589b83c299694723cb234bd21ed7d 100644 --- a/src/util/inc/tsocket.h +++ b/src/util/inc/tsocket.h @@ -28,7 +28,7 @@ int32_t taosReadn(SOCKET sock, char *buffer, int32_t len); int32_t taosWriteMsg(SOCKET fd, void *ptr, int32_t nbytes); int32_t taosReadMsg(SOCKET fd, void *ptr, int32_t nbytes); int32_t taosNonblockwrite(SOCKET fd, char *ptr, int32_t nbytes); -int32_t taosCopyFds(SOCKET sfd, int32_t dfd, int64_t len); +int64_t taosCopyFds(SOCKET sfd, int32_t dfd, int64_t len); int32_t taosSetNonblocking(SOCKET sock, int32_t on); SOCKET taosOpenUdpSocket(uint32_t localIp, uint16_t localPort); diff --git a/src/util/src/terror.c b/src/util/src/terror.c index 1a92b1671994eace566eb4fdfa06905ce8272885..fc600c82602784edb89ccb45414f1cd859baa1bb 100644 --- a/src/util/src/terror.c +++ b/src/util/src/terror.c @@ -206,6 +206,8 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_DB_OPTION_KEEP, "Invalid database opti TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_TOPIC, "Invalid topic name") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_TOPIC_OPTION, "Invalid topic option") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_TOPIC_PARTITONS, "Invalid topic partitons num, valid range: [1, 1000]") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOPIC_ALREADY_EXIST, "Topic already exists") // dnode TAOS_DEFINE_ERROR(TSDB_CODE_DND_MSG_NOT_PROCESSED, "Message not processed") diff --git a/src/util/src/tidpool.c b/src/util/src/tidpool.c index 53d81bb5422e5c1b3b7384a97186a93940d26408..bd3f7745430a20bd0ba4250436e43e6524d1b431 100644 --- a/src/util/src/tidpool.c +++ b/src/util/src/tidpool.c @@ -104,10 +104,16 @@ void taosIdPoolCleanUp(void *handle) { int taosIdPoolNumOfUsed(void *handle) { id_pool_t *pIdPool = handle; - return pIdPool->maxId - pIdPool->numOfFree; + + pthread_mutex_lock(&pIdPool->mutex); + int ret = pIdPool->maxId - pIdPool->numOfFree; + pthread_mutex_unlock(&pIdPool->mutex); + + return ret; } -void taosIdPoolMarkStatus(void *handle, int id) { +bool taosIdPoolMarkStatus(void *handle, int id) { + bool ret = false; id_pool_t *pIdPool = handle; pthread_mutex_lock(&pIdPool->mutex); @@ -115,9 +121,13 @@ void taosIdPoolMarkStatus(void *handle, int id) { if (!pIdPool->freeList[slot]) { pIdPool->freeList[slot] = true; pIdPool->numOfFree--; + ret = true; + } else { + ret = false; } pthread_mutex_unlock(&pIdPool->mutex); + return ret; } int taosUpdateIdPool(id_pool_t *handle, int maxId) { @@ -147,6 +157,11 @@ int taosUpdateIdPool(id_pool_t *handle, int maxId) { } int taosIdPoolMaxSize(void *handle) { - id_pool_t *pIdPool = (id_pool_t*)handle; - return pIdPool->maxId; + id_pool_t *pIdPool = (id_pool_t *)handle; + + pthread_mutex_lock(&pIdPool->mutex); + int ret = pIdPool->maxId; + pthread_mutex_unlock(&pIdPool->mutex); + + return ret; } \ No newline at end of file diff --git a/src/util/src/tsocket.c b/src/util/src/tsocket.c index e07587686774cb0fa6c7682daca59b400a9451ec..b33cdb8b807f545943e3676a96098818e54b31dd 100644 --- a/src/util/src/tsocket.c +++ b/src/util/src/tsocket.c @@ -465,36 +465,36 @@ void tinet_ntoa(char *ipstr, uint32_t ip) { #define COPY_SIZE 32768 // sendfile shall be used -int32_t taosCopyFds(SOCKET sfd, int32_t dfd, int64_t len) { +int64_t taosCopyFds(SOCKET sfd, int32_t dfd, int64_t len) { int64_t leftLen; - int32_t readLen, writeLen; + int64_t readLen, writeLen; char temp[COPY_SIZE]; leftLen = len; while (leftLen > 0) { if (leftLen < COPY_SIZE) - readLen = (int32_t)leftLen; + readLen = leftLen; else readLen = COPY_SIZE; // 4K - int32_t retLen = taosReadMsg(sfd, temp, (int32_t)readLen); + int64_t retLen = taosReadMsg(sfd, temp, (int32_t)readLen); if (readLen != retLen) { - uError("read error, readLen:%d retLen:%d len:%" PRId64 " leftLen:%" PRId64 ", reason:%s", readLen, retLen, len, - leftLen, strerror(errno)); + uError("read error, readLen:%" PRId64 " retLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s", + readLen, retLen, len, leftLen, strerror(errno)); return -1; } - writeLen = taosWriteMsg(dfd, temp, readLen); + writeLen = taosWriteMsg(dfd, temp, (int32_t)readLen); if (readLen != writeLen) { - uError("copy error, readLen:%d writeLen:%d len:%" PRId64 " leftLen:%" PRId64 ", reason:%s", readLen, writeLen, - len, leftLen, strerror(errno)); + uError("copy error, readLen:%" PRId64 " writeLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s", + readLen, writeLen, len, leftLen, strerror(errno)); return -1; } leftLen -= readLen; } - return (int32_t)len; + return len; } diff --git a/src/vnode/inc/vnodeInt.h b/src/vnode/inc/vnodeInt.h index 91ddf5076b0540613cdac7047f0a1ea0cdd21c0b..4aa07196a79513c476072b58d62787bd7a5a966d 100644 --- a/src/vnode/inc/vnodeInt.h +++ b/src/vnode/inc/vnodeInt.h @@ -40,7 +40,7 @@ typedef struct { int32_t queuedWMsg; int32_t queuedRMsg; int32_t flowctrlLevel; - int32_t sequence; // for topic + int64_t sequence; // for topic int8_t status; int8_t role; int8_t accessState; diff --git a/src/vnode/inc/vnodeSync.h b/src/vnode/inc/vnodeSync.h index c9ac25c2274d81cd08c52a77cd3cc76a27c7a0d5..75d7ffbabda514f3d280c712fbd531aedbc3e0d7 100644 --- a/src/vnode/inc/vnodeSync.h +++ b/src/vnode/inc/vnodeSync.h @@ -30,8 +30,9 @@ void vnodeStopSyncFile(int32_t vgId, uint64_t fversion); void vnodeConfirmForard(int32_t vgId, void *wparam, int32_t code); int32_t vnodeWriteToCache(int32_t vgId, void *wparam, int32_t qtype, void *rparam); int32_t vnodeGetVersion(int32_t vgId, uint64_t *fver, uint64_t *wver); +int32_t vnodeResetVersion(int32_t vgId, uint64_t fver); -void vnodeConfirmForward(void *pVnode, uint64_t version, int32_t code); +void vnodeConfirmForward(void *pVnode, uint64_t version, int32_t code, bool force); #ifdef __cplusplus } diff --git a/src/vnode/src/vnodeMain.c b/src/vnode/src/vnodeMain.c index ac9536d243dbd2613d42c8b9a5b054ce862df061..ded39e67cc37d7733f4e7aaa9998b4578e05c122 100644 --- a/src/vnode/src/vnodeMain.c +++ b/src/vnode/src/vnodeMain.c @@ -110,31 +110,78 @@ int32_t vnodeDrop(int32_t vgId) { } static int32_t vnodeAlterImp(SVnodeObj *pVnode, SCreateVnodeMsg *pVnodeCfg) { + STsdbCfg tsdbCfg = pVnode->tsdbCfg; + SSyncCfg syncCfg = pVnode->syncCfg; + int32_t dbCfgVersion = pVnode->dbCfgVersion; + int32_t vgCfgVersion = pVnode->vgCfgVersion; + int32_t code = vnodeWriteCfg(pVnodeCfg); if (code != TSDB_CODE_SUCCESS) { - return code; + pVnode->dbCfgVersion = dbCfgVersion; + pVnode->vgCfgVersion = vgCfgVersion; + pVnode->syncCfg = syncCfg; + pVnode->tsdbCfg = tsdbCfg; + return code; } code = vnodeReadCfg(pVnode); if (code != TSDB_CODE_SUCCESS) { - return code; + pVnode->dbCfgVersion = dbCfgVersion; + pVnode->vgCfgVersion = vgCfgVersion; + pVnode->syncCfg = syncCfg; + pVnode->tsdbCfg = tsdbCfg; + return code; } code = walAlter(pVnode->wal, &pVnode->walCfg); if (code != TSDB_CODE_SUCCESS) { + pVnode->dbCfgVersion = dbCfgVersion; + pVnode->vgCfgVersion = vgCfgVersion; + pVnode->syncCfg = syncCfg; + pVnode->tsdbCfg = tsdbCfg; return code; } - code = syncReconfig(pVnode->sync, &pVnode->syncCfg); - if (code != TSDB_CODE_SUCCESS) { - return code; - } + bool tsdbCfgChanged = (memcmp(&tsdbCfg, &pVnode->tsdbCfg, sizeof(STsdbCfg)) != 0); + bool syncCfgChanged = (memcmp(&syncCfg, &pVnode->syncCfg, sizeof(SSyncCfg)) != 0); - if (pVnode->tsdb) { - code = tsdbConfigRepo(pVnode->tsdb, &pVnode->tsdbCfg); + vDebug("vgId:%d, tsdbchanged:%d syncchanged:%d while alter vnode", pVnode->vgId, tsdbCfgChanged, syncCfgChanged); + + if (/*tsdbCfgChanged || */syncCfgChanged) { + // vnode in non-ready state and still needs to return success instead of TSDB_CODE_VND_INVALID_STATUS + // dbCfgVersion can be corrected by status msg + if (!vnodeSetUpdatingStatus(pVnode)) { + vDebug("vgId:%d, vnode is not ready, do alter operation later", pVnode->vgId); + pVnode->dbCfgVersion = dbCfgVersion; + pVnode->vgCfgVersion = vgCfgVersion; + pVnode->syncCfg = syncCfg; + pVnode->tsdbCfg = tsdbCfg; + return TSDB_CODE_SUCCESS; + } + + code = syncReconfig(pVnode->sync, &pVnode->syncCfg); if (code != TSDB_CODE_SUCCESS) { + pVnode->dbCfgVersion = dbCfgVersion; + pVnode->vgCfgVersion = vgCfgVersion; + pVnode->syncCfg = syncCfg; + pVnode->tsdbCfg = tsdbCfg; + vnodeSetReadyStatus(pVnode); return code; } + + if (pVnode->tsdb) { + code = tsdbConfigRepo(pVnode->tsdb, &pVnode->tsdbCfg); + if (code != TSDB_CODE_SUCCESS) { + pVnode->dbCfgVersion = dbCfgVersion; + pVnode->vgCfgVersion = vgCfgVersion; + pVnode->syncCfg = syncCfg; + pVnode->tsdbCfg = tsdbCfg; + vnodeSetReadyStatus(pVnode); + return code; + } + } + + vnodeSetReadyStatus(pVnode); } return 0; @@ -142,21 +189,16 @@ static int32_t vnodeAlterImp(SVnodeObj *pVnode, SCreateVnodeMsg *pVnodeCfg) { int32_t vnodeAlter(void *vparam, SCreateVnodeMsg *pVnodeCfg) { SVnodeObj *pVnode = vparam; - if (pVnode->dbCfgVersion == pVnodeCfg->cfg.dbCfgVersion && pVnode->vgCfgVersion == pVnodeCfg->cfg.vgCfgVersion) { - vDebug("vgId:%d, dbCfgVersion:%d and vgCfgVersion:%d not change", pVnode->vgId, pVnode->dbCfgVersion, - pVnode->vgCfgVersion); - return TSDB_CODE_SUCCESS; - } - // vnode in non-ready state and still needs to return success instead of TSDB_CODE_VND_INVALID_STATUS - // dbCfgVersion can be corrected by status msg - if (!vnodeSetUpdatingStatus(pVnode)) { - vDebug("vgId:%d, vnode is not ready, do alter operation later", pVnode->vgId); + vDebug("vgId:%d, current dbCfgVersion:%d vgCfgVersion:%d, input dbCfgVersion:%d vgCfgVersion:%d", pVnode->vgId, + pVnode->dbCfgVersion, pVnode->vgCfgVersion, pVnodeCfg->cfg.dbCfgVersion, pVnodeCfg->cfg.vgCfgVersion); + + if (pVnode->dbCfgVersion == pVnodeCfg->cfg.dbCfgVersion && pVnode->vgCfgVersion == pVnodeCfg->cfg.vgCfgVersion) { + vDebug("vgId:%d, cfg not change", pVnode->vgId); return TSDB_CODE_SUCCESS; } int32_t code = vnodeAlterImp(pVnode, pVnodeCfg); - vnodeSetReadyStatus(pVnode); if (code != 0) { vError("vgId:%d, failed to alter vnode, code:0x%x", pVnode->vgId, code); @@ -305,6 +347,7 @@ int32_t vnodeOpen(int32_t vgId) { syncInfo.startSyncFileFp = vnodeStartSyncFile; syncInfo.stopSyncFileFp = vnodeStopSyncFile; syncInfo.getVersionFp = vnodeGetVersion; + syncInfo.resetVersionFp = vnodeResetVersion; syncInfo.sendFileFp = tsdbSyncSend; syncInfo.recvFileFp = tsdbSyncRecv; syncInfo.pTsdb = pVnode->tsdb; @@ -439,7 +482,7 @@ static int32_t vnodeProcessTsdbStatus(void *arg, int32_t status, int32_t eno) { if (status == TSDB_STATUS_COMMIT_START) { pVnode->isCommiting = 1; pVnode->cversion = pVnode->version; - vDebug("vgId:%d, start commit, fver:%" PRIu64 " vver:%" PRIu64, pVnode->vgId, pVnode->fversion, pVnode->version); + vInfo("vgId:%d, start commit, fver:%" PRIu64 " vver:%" PRIu64, pVnode->vgId, pVnode->fversion, pVnode->version); if (!vnodeInInitStatus(pVnode)) { return walRenew(pVnode->wal); } @@ -450,7 +493,7 @@ static int32_t vnodeProcessTsdbStatus(void *arg, int32_t status, int32_t eno) { pVnode->isCommiting = 0; pVnode->isFull = 0; pVnode->fversion = pVnode->cversion; - vDebug("vgId:%d, commit over, fver:%" PRIu64 " vver:%" PRIu64, pVnode->vgId, pVnode->fversion, pVnode->version); + vInfo("vgId:%d, commit over, fver:%" PRIu64 " vver:%" PRIu64, pVnode->vgId, pVnode->fversion, pVnode->version); if (!vnodeInInitStatus(pVnode)) { walRemoveOneOldFile(pVnode->wal); } diff --git a/src/vnode/src/vnodeMgmt.c b/src/vnode/src/vnodeMgmt.c index 8469ab12c1ef5833e73058c167afb2777ac76ba9..71d9bc07f50b6a8cba06d68b9b06b24f4dadcf83 100644 --- a/src/vnode/src/vnodeMgmt.c +++ b/src/vnode/src/vnodeMgmt.c @@ -128,7 +128,7 @@ static void vnodeBuildVloadMsg(SVnodeObj *pVnode, SStatusMsg *pStatus) { int64_t compStorage = 0; int64_t pointsWritten = 0; - if (!vnodeInReadyStatus(pVnode)) return; + if (vnodeInClosingStatus(pVnode)) return; if (pStatus->openVnodes >= TSDB_MAX_VNODES) return; if (pVnode->tsdb) { @@ -194,4 +194,4 @@ void vnodeSetAccess(SVgroupAccess *pAccess, int32_t numOfVnodes) { vnodeRelease(pVnode); } } -} \ No newline at end of file +} diff --git a/src/vnode/src/vnodeStatus.c b/src/vnode/src/vnodeStatus.c index 68898435303daa8e0ac60a84cd54f4794515103e..c482d1fd1a44497b2ba3ff8482d4d1f66bb11ff5 100644 --- a/src/vnode/src/vnodeStatus.c +++ b/src/vnode/src/vnodeStatus.c @@ -109,6 +109,8 @@ bool vnodeSetResetStatus(SVnodeObj* pVnode) { taosMsleep(1); } + vInfo("vgId:%d, set to reset status", pVnode->vgId); + // release local resources only after cutting off outside connections qQueryMgmtNotifyClosed(pVnode->qMgmt); vnodeWaitReadCompleted(pVnode); @@ -153,6 +155,18 @@ bool vnodeInReadyOrUpdatingStatus(SVnodeObj* pVnode) { return in; } +bool vnodeInClosingStatus(SVnodeObj* pVnode) { + bool in = false; + pthread_mutex_lock(&pVnode->statusMutex); + + if (pVnode->status == TAOS_VN_STATUS_CLOSING) { + in = true; + } + + pthread_mutex_unlock(&pVnode->statusMutex); + return in; +} + bool vnodeInResetStatus(SVnodeObj* pVnode) { bool in = false; pthread_mutex_lock(&pVnode->statusMutex); diff --git a/src/vnode/src/vnodeSync.c b/src/vnode/src/vnodeSync.c index 627783c391d45b37830cb2b6d851fa6dd3261819..929dd1592610b03a41027781d66470b13756174a 100644 --- a/src/vnode/src/vnodeSync.c +++ b/src/vnode/src/vnodeSync.c @@ -91,7 +91,7 @@ void vnodeStartSyncFile(int32_t vgId) { return; } - vDebug("vgId:%d, datafile will be synced", vgId); + vInfo("vgId:%d, datafile will be synced", vgId); vnodeSetResetStatus(pVnode); vnodeRelease(pVnode); @@ -147,7 +147,7 @@ int32_t vnodeGetVersion(int32_t vgId, uint64_t *fver, uint64_t *wver) { int32_t code = 0; if (pVnode->isCommiting) { - vDebug("vgId:%d, vnode is commiting while get version", vgId); + vInfo("vgId:%d, vnode is commiting while get version", vgId); code = -1; } else { *fver = pVnode->fversion; @@ -158,7 +158,23 @@ int32_t vnodeGetVersion(int32_t vgId, uint64_t *fver, uint64_t *wver) { return code; } -void vnodeConfirmForward(void *vparam, uint64_t version, int32_t code) { - SVnodeObj *pVnode = vparam; - syncConfirmForward(pVnode->sync, version, code); +int32_t vnodeResetVersion(int32_t vgId, uint64_t fver) { + SVnodeObj *pVnode = vnodeAcquire(vgId); + if (pVnode == NULL) { + vError("vgId:%d, vnode not found while reset version", vgId); + return -1; + } + + pVnode->fversion = fver; + pVnode->version = fver; + walResetVersion(pVnode->wal, fver); + vInfo("vgId:%d, version reset to %" PRIu64, vgId, fver); + + vnodeRelease(pVnode); + return 0; } + +void vnodeConfirmForward(void *vparam, uint64_t version, int32_t code, bool force) { + SVnodeObj *pVnode = vparam; + syncConfirmForward(pVnode->sync, version, code, force); +} \ No newline at end of file diff --git a/src/vnode/src/vnodeWrite.c b/src/vnode/src/vnodeWrite.c index a1d4f50010f1cd3825146dbc2506d53ad3e17c09..e318978a11186a86dff79a5aaea234b9719ce979 100644 --- a/src/vnode/src/vnodeWrite.c +++ b/src/vnode/src/vnodeWrite.c @@ -24,7 +24,7 @@ #include "dnode.h" #include "vnodeStatus.h" -#define MAX_QUEUED_MSG_NUM 10000 +#define MAX_QUEUED_MSG_NUM 100000 extern void * tsDnodeTmr; static int32_t (*vnodeProcessWriteMsgFp[TSDB_MSG_TYPE_MAX])(SVnodeObj *, void *pCont, SRspRet *); @@ -89,7 +89,8 @@ int32_t vnodeProcessWrite(void *vparam, void *wparam, int32_t qtype, void *rpara // forward to peers, even it is WAL/FWD, it shall be called to update version in sync int32_t syncCode = 0; - syncCode = syncForwardToPeer(pVnode->sync, pHead, pWrite, qtype); + bool force = (pWrite == NULL ? false : pWrite->pHead.msgType != TSDB_MSG_TYPE_SUBMIT); + syncCode = syncForwardToPeer(pVnode->sync, pHead, pWrite, qtype, force); if (syncCode < 0) return syncCode; // write into WAL @@ -141,7 +142,7 @@ static int32_t vnodeProcessSubmitMsg(SVnodeObj *pVnode, void *pCont, SRspRet *pR vTrace("vgId:%d, submit msg is processed", pVnode->vgId); if (pVnode->dbType == TSDB_DB_TYPE_TOPIC && pVnode->role == TAOS_SYNC_ROLE_MASTER) { - tpUpdateTs(&pVnode->sequence, pCont); + tpUpdateTs(pVnode->vgId, &pVnode->sequence, pCont); } // save insert result into item diff --git a/src/wal/src/walWrite.c b/src/wal/src/walWrite.c index aeb49830299eb0dcddfbd39a7a838fdc5d45b081..4368ddd7d35c444c0b6e32fb5897801bba6e615d 100644 --- a/src/wal/src/walWrite.c +++ b/src/wal/src/walWrite.c @@ -446,3 +446,16 @@ uint64_t walGetVersion(twalh param) { return pWal->version; } + +// Wal version in slave (dnode1) must be reset. +// Because after the data file is recovered from peer (dnode2), the new file version in dnode1 may become smaller than origin. +// Some new wal record cannot be written to the wal file in dnode1 for wal version not reset, then fversion and the record in wal file may inconsistent, +// At this time, if dnode2 down, dnode1 switched to master. After dnode2 start and restore data from dnode1, data loss will occur + +void walResetVersion(twalh param, uint64_t newVer) { + SWal *pWal = param; + if (pWal == 0) return; + wInfo("vgId:%d, version reset from %" PRIu64 " to %" PRIu64, pWal->vgId, pWal->version, newVer); + + pWal->version = newVer; +} \ No newline at end of file diff --git a/tests/pytest/cluster/clusterEnvSetup/Dockerfile b/tests/pytest/cluster/clusterEnvSetup/Dockerfile index c9c4d79be981e45609e040bf5835e275fc446260..437dbc65e6430deb20faa16fc78ddc07005c15ac 100644 --- a/tests/pytest/cluster/clusterEnvSetup/Dockerfile +++ b/tests/pytest/cluster/clusterEnvSetup/Dockerfile @@ -28,6 +28,8 @@ RUN ulimit -c unlimited COPY --from=builder /root/bin/taosd /usr/bin COPY --from=builder /root/bin/tarbitrator /usr/bin +COPY --from=builder /root/bin/taosdemo /usr/bin +COPY --from=builder /root/bin/taosdump /usr/bin COPY --from=builder /root/bin/taos /usr/bin COPY --from=builder /root/cfg/taos.cfg /etc/taos/ COPY --from=builder /root/lib/libtaos.so.* /usr/lib/libtaos.so.1 diff --git a/tests/pytest/cluster/clusterEnvSetup/basic.py b/tests/pytest/cluster/clusterEnvSetup/basic.py index d9b8e9ce4a7bc144839334332268ac0f09f78f0d..dc7e07fd5cea3473270afa6cb2ddbfba6c2402e4 100644 --- a/tests/pytest/cluster/clusterEnvSetup/basic.py +++ b/tests/pytest/cluster/clusterEnvSetup/basic.py @@ -18,13 +18,15 @@ import argparse class BuildDockerCluser: - def __init__(self, hostName, user, password, configDir, numOfNodes, clusterVersion): + def __init__(self, hostName, user, password, configDir, numOfNodes, clusterVersion, dockerDir, removeFlag): self.hostName = hostName self.user = user self.password = password self.configDir = configDir self.numOfNodes = numOfNodes - self.clusterVersion = clusterVersion + self.clusterVersion = clusterVersion + self.dockerDir = dockerDir + self.removeFlag = removeFlag def getConnection(self): self.conn = taos.connect( @@ -42,14 +44,17 @@ class BuildDockerCluser: print("start arbitrator") os.system("docker exec -d $(docker ps|grep tdnode1|awk '{print $1}') tarbitrator") - def run(self): - if self.numOfNodes < 2 or self.numOfNodes > 5: - print("the number of nodes must be between 2 and 5") - exit(0) - os.system("./buildClusterEnv.sh -n %d -v %s" % (self.numOfNodes, self.clusterVersion)) + def run(self): + if self.numOfNodes < 2 or self.numOfNodes > 10: + print("the number of nodes must be between 2 and 10") + exit(0) + print("remove Flag value %s" % self.removeFlag) + if self.removeFlag == False: + os.system("./cleanClusterEnv.sh -d %s" % self.dockerDir) + os.system("./buildClusterEnv.sh -n %d -v %s -d %s" % (self.numOfNodes, self.clusterVersion, self.dockerDir)) self.getConnection() self.createDondes() - self.startArbitrator() + self.startArbitrator() parser = argparse.ArgumentParser() parser.add_argument( @@ -91,10 +96,24 @@ parser.add_argument( '-v', '--version', action='store', - default='2.0.14.1', + default='2.0.18.1', type=str, - help='the version of the cluster to be build, Default is 2.0.14.1') + help='the version of the cluster to be build, Default is 2.0.17.1') +parser.add_argument( + '-d', + '--docker-dir', + action='store', + default='/data', + type=str, + help='the data dir for docker, default is /data') +parser.add_argument( + '--flag', + action='store_true', + help='remove docker containers flag, default: True') args = parser.parse_args() -cluster = BuildDockerCluser(args.host, args.user, args.password, args.config_dir, args.num_of_nodes, args.version) -cluster.run() \ No newline at end of file +cluster = BuildDockerCluser(args.host, args.user, args.password, args.config_dir, args.num_of_nodes, args.version, args.docker_dir, args.flag) +cluster.run() + +# usage 1: python3 basic.py -n 2 --flag (flag is True) +# usage 2: python3 basic.py -n 2 (flag should be False when it is not specified) \ No newline at end of file diff --git a/tests/pytest/cluster/clusterEnvSetup/buildClusterEnv.sh b/tests/pytest/cluster/clusterEnvSetup/buildClusterEnv.sh index 968cdd1c1c81b9f6dba68bc2cca542038ada8606..0057a970ca096d15e17792805e469dd3180b7d83 100755 --- a/tests/pytest/cluster/clusterEnvSetup/buildClusterEnv.sh +++ b/tests/pytest/cluster/clusterEnvSetup/buildClusterEnv.sh @@ -1,18 +1,20 @@ #!/bin/bash echo "Executing buildClusterEnv.sh" -DOCKER_DIR=/data CURR_DIR=`pwd` +IN_TDINTERNAL="community" -if [ $# != 4 ]; then +if [ $# != 6 ]; then echo "argument list need input : " echo " -n numOfNodes" - echo " -v version" + echo " -v version" + echo " -d docker dir" exit 1 fi NUM_OF_NODES= VERSION= -while getopts "n:v:" arg +DOCKER_DIR= +while getopts "n:v:d:" arg do case $arg in n) @@ -20,6 +22,9 @@ do ;; v) VERSION=$OPTARG + ;; + d) + DOCKER_DIR=$OPTARG ;; ?) echo "unkonwn argument" @@ -28,32 +33,31 @@ do done function addTaoscfg { - for i in {1..5} + for((i=1;i<=$NUM_OF_NODES;i++)) do - touch /data/node$i/cfg/taos.cfg - echo 'firstEp tdnode1:6030' > /data/node$i/cfg/taos.cfg - echo 'fqdn tdnode'$i >> /data/node$i/cfg/taos.cfg - echo 'arbitrator tdnode1:6042' >> /data/node$i/cfg/taos.cfg + touch $DOCKER_DIR/node$i/cfg/taos.cfg + echo 'firstEp tdnode1:6030' > $DOCKER_DIR/node$i/cfg/taos.cfg + echo 'fqdn tdnode'$i >> $DOCKER_DIR/node$i/cfg/taos.cfg + echo 'arbitrator tdnode1:6042' >> $DOCKER_DIR/node$i/cfg/taos.cfg done } function createDIR { - for i in {1..5} + for((i=1;i<=$NUM_OF_NODES;i++)) do - mkdir -p /data/node$i/data - mkdir -p /data/node$i/log - mkdir -p /data/node$i/cfg - mkdir -p /data/node$i/core + mkdir -p $DOCKER_DIR/node$i/data + mkdir -p $DOCKER_DIR/node$i/log + mkdir -p $DOCKER_DIR/node$i/cfg + mkdir -p $DOCKER_DIR/node$i/core done } -function cleanEnv { - for i in {1..5} - do - echo /data/node$i/data/* - rm -rf /data/node$i/data/* - echo /data/node$i/log/* - rm -rf /data/node$i/log/* +function cleanEnv { + echo "Clean up docker environment" + for((i=1;i<=$NUM_OF_NODES;i++)) + do + rm -rf $DOCKER_DIR/node$i/data/* + rm -rf $DOCKER_DIR/node$i/log/* done } @@ -65,23 +69,48 @@ function prepareBuild { fi if [ ! -e $DOCKER_DIR/TDengine-server-$VERSION-Linux-x64.tar.gz ] || [ ! -e $DOCKER_DIR/TDengine-arbitrator-$VERSION-Linux-x64.tar.gz ]; then - cd $CURR_DIR/../../../../packaging + cd $CURR_DIR/../../../../packaging + echo $CURR_DIR + echo $IN_TDINTERNAL echo "generating TDeninger packages" - ./release.sh -v edge -n $VERSION >> /dev/null - - if [ ! -e $CURR_DIR/../../../../release/TDengine-server-$VERSION-Linux-x64.tar.gz ]; then - echo "no TDengine install package found" - exit 1 + if [[ "$CURR_DIR" == *"$IN_TDINTERNAL"* ]]; then + pwd + ./release.sh -v cluster -n $VERSION >> /dev/null 2>&1 + else + pwd + ./release.sh -v edge -n $VERSION >> /dev/null 2>&1 fi - if [ ! -e $CURR_DIR/../../../../release/TDengine-arbitrator-$VERSION-Linux-x64.tar.gz ]; then - echo "no arbitrator install package found" - exit 1 + if [[ "$CURR_DIR" == *"$IN_TDINTERNAL"* ]]; then + if [ ! -e $CURR_DIR/../../../../release/TDengine-enterprise-server-$VERSION-Linux-x64.tar.gz ]; then + echo "no TDengine install package found" + exit 1 + fi + + if [ ! -e $CURR_DIR/../../../../release/TDengine-enterprise-arbitrator-$VERSION-Linux-x64.tar.gz ]; then + echo "no arbitrator install package found" + exit 1 + fi + else + if [ ! -e $CURR_DIR/../../../../release/TDengine-server-$VERSION-Linux-x64.tar.gz ]; then + echo "no TDengine install package found" + exit 1 + fi + + if [ ! -e $CURR_DIR/../../../../release/TDengine-arbitrator-$VERSION-Linux-x64.tar.gz ]; then + echo "no arbitrator install package found" + exit 1 + fi fi cd $CURR_DIR/../../../../release - mv TDengine-server-$VERSION-Linux-x64.tar.gz $DOCKER_DIR - mv TDengine-arbitrator-$VERSION-Linux-x64.tar.gz $DOCKER_DIR + if [[ "$CURR_DIR" == *"$IN_TDINTERNAL"* ]]; then + mv TDengine-enterprise-server-$VERSION-Linux-x64.tar.gz $DOCKER_DIR + mv TDengine-enterprise-arbitrator-$VERSION-Linux-x64.tar.gz $DOCKER_DIR + else + mv TDengine-server-$VERSION-Linux-x64.tar.gz $DOCKER_DIR + mv TDengine-arbitrator-$VERSION-Linux-x64.tar.gz $DOCKER_DIR + fi fi rm -rf $DOCKER_DIR/*.yml @@ -96,23 +125,31 @@ function clusterUp { cd $DOCKER_DIR - if [ $NUM_OF_NODES -eq 2 ]; then - echo "create 2 dnodes" - PACKAGE=TDengine-server-$VERSION-Linux-x64.tar.gz DIR=TDengine-server-$VERSION DIR2=TDengine-arbitrator-$VERSION VERSION=$VERSION docker-compose up -d - fi - - if [ $NUM_OF_NODES -eq 3 ]; then - PACKAGE=TDengine-server-$VERSION-Linux-x64.tar.gz DIR=TDengine-server-$VERSION DIR2=TDengine-arbitrator-$VERSION VERSION=$VERSION docker-compose -f docker-compose.yml -f node3.yml up -d - fi - - if [ $NUM_OF_NODES -eq 4 ]; then - PACKAGE=TDengine-server-$VERSION-Linux-x64.tar.gz DIR=TDengine-server-$VERSION DIR2=TDengine-arbitrator-$VERSION VERSION=$VERSION docker-compose -f docker-compose.yml -f node3.yml -f node4.yml up -d + if [[ "$CURR_DIR" == *"$IN_TDINTERNAL"* ]]; then + docker_run="PACKAGE=TDengine-enterprise-server-$VERSION-Linux-x64.tar.gz TARBITRATORPKG=TDengine-enterprise-arbitrator-$VERSION-Linux-x64.tar.gz DIR=TDengine-enterprise-server-$VERSION DIR2=TDengine-enterprise-arbitrator-$VERSION VERSION=$VERSION DATADIR=$DOCKER_DIR docker-compose -f docker-compose.yml " + else + docker_run="PACKAGE=TDengine-server-$VERSION-Linux-x64.tar.gz TARBITRATORPKG=TDengine-arbitrator-$VERSION-Linux-x64.tar.gz DIR=TDengine-server-$VERSION DIR2=TDengine-arbitrator-$VERSION VERSION=$VERSION DATADIR=$DOCKER_DIR docker-compose -f docker-compose.yml " fi - if [ $NUM_OF_NODES -eq 5 ]; then - PACKAGE=TDengine-server-$VERSION-Linux-x64.tar.gz DIR=TDengine-server-$VERSION DIR2=TDengine-arbitrator-$VERSION VERSION=$VERSION docker-compose -f docker-compose.yml -f node3.yml -f node4.yml -f node5.yml up -d + if [ $NUM_OF_NODES -ge 2 ];then + echo "create $NUM_OF_NODES dnodes" + for((i=3;i<=$NUM_OF_NODES;i++)) + do + if [ ! -f node$i.yml ];then + echo "node$i.yml not exist" + cp node3.yml node$i.yml + sed -i "s/td2.0-node3/td2.0-node$i/g" node$i.yml + sed -i "s/'tdnode3'/'tdnode$i'/g" node$i.yml + sed -i "s#/node3/#/node$i/#g" node$i.yml + sed -i "s#hostname: tdnode3#hostname: tdnode$i#g" node$i.yml + sed -i "s#ipv4_address: 172.27.0.9#ipv4_address: 172.27.0.`expr $i + 6`#g" node$i.yml + fi + docker_run=$docker_run" -f node$i.yml " + done + docker_run=$docker_run" up -d" fi - + echo $docker_run |sh + echo "docker compose finish" } diff --git a/tests/pytest/cluster/clusterEnvSetup/cleanClusterEnv.sh b/tests/pytest/cluster/clusterEnvSetup/cleanClusterEnv.sh new file mode 100755 index 0000000000000000000000000000000000000000..675cae5fef850947c2c53899ef1863dc00b55422 --- /dev/null +++ b/tests/pytest/cluster/clusterEnvSetup/cleanClusterEnv.sh @@ -0,0 +1,39 @@ +#!/bin/bash +echo "Executing cleanClusterEnv.sh" +CURR_DIR=`pwd` + +if [ $# != 2 ]; then + echo "argument list need input : " + echo " -d docker dir" + exit 1 +fi + +DOCKER_DIR= +while getopts "d:" arg +do + case $arg in + d) + DOCKER_DIR=$OPTARG + ;; + ?) + echo "unkonwn argument" + ;; + esac +done + +function removeDockerContainers { + cd $DOCKER_DIR + docker-compose down --remove-orphans +} + +function cleanEnv { + echo "Clean up docker environment" + for i in {1..10} + do + rm -rf $DOCKER_DIR/node$i/data/* + rm -rf $DOCKER_DIR/node$i/log/* + done +} + +removeDockerContainers +cleanEnv \ No newline at end of file diff --git a/tests/pytest/cluster/clusterEnvSetup/docker-compose.yml b/tests/pytest/cluster/clusterEnvSetup/docker-compose.yml index cb35abd9a1497c92dee10e1e6fb95027fb21710c..d241062a2dd50fa82f934d9e915cddeb74505248 100644 --- a/tests/pytest/cluster/clusterEnvSetup/docker-compose.yml +++ b/tests/pytest/cluster/clusterEnvSetup/docker-compose.yml @@ -9,6 +9,7 @@ services: - TARBITRATORPKG=${TARBITRATORPKG} - EXTRACTDIR=${DIR} - EXTRACTDIR2=${DIR2} + - DATADIR=${DATADIR} image: 'tdengine:${VERSION}' container_name: 'tdnode1' cap_add: @@ -29,22 +30,27 @@ services: - "tdnode3:172.27.0.9" - "tdnode4:172.27.0.10" - "tdnode5:172.27.0.11" + - "tdnode6:172.27.0.12" + - "tdnode7:172.27.0.13" + - "tdnode8:172.27.0.14" + - "tdnode9:172.27.0.15" + - "tdnode10:172.27.0.16" volumes: # bind data directory - type: bind - source: /data/node1/data + source: ${DATADIR}/node1/data target: /var/lib/taos # bind log directory - type: bind - source: /data/node1/log + source: ${DATADIR}/node1/log target: /var/log/taos # bind configuration - type: bind - source: /data/node1/cfg + source: ${DATADIR}/node1/cfg target: /etc/taos # bind core dump path - type: bind - source: /data/node1/core + source: ${DATADIR}/node1/core target: /coredump - type: bind source: /data @@ -60,7 +66,10 @@ services: context: . args: - PACKAGE=${PACKAGE} + - TARBITRATORPKG=${TARBITRATORPKG} - EXTRACTDIR=${DIR} + - EXTRACTDIR2=${DIR2} + - DATADIR=${DATADIR} image: 'tdengine:${VERSION}' container_name: 'tdnode2' cap_add: @@ -84,22 +93,22 @@ services: volumes: # bind data directory - type: bind - source: /data/node2/data + source: ${DATADIR}/node2/data target: /var/lib/taos # bind log directory - type: bind - source: /data/node2/log + source: ${DATADIR}/node2/log target: /var/log/taos # bind configuration - type: bind - source: /data/node2/cfg + source: ${DATADIR}/node2/cfg target: /etc/taos # bind core dump path - type: bind - source: /data/node2/core + source: ${DATADIR}/node2/core target: /coredump - type: bind - source: /data + source: ${DATADIR} target: /root hostname: tdnode2 networks: diff --git a/tests/pytest/cluster/clusterEnvSetup/node3.yml b/tests/pytest/cluster/clusterEnvSetup/node3.yml index 4f4f3a6f991f0ffff51265fee4c5a3b8941b5d85..18f1b37c1c029f50cc6e66e662ec2a42bc475c5e 100644 --- a/tests/pytest/cluster/clusterEnvSetup/node3.yml +++ b/tests/pytest/cluster/clusterEnvSetup/node3.yml @@ -6,7 +6,10 @@ services: context: . args: - PACKAGE=${PACKAGE} + - TARBITRATORPKG=${TARBITRATORPKG} - EXTRACTDIR=${DIR} + - EXTRACTDIR2=${DIR2} + - DATADIR=${DATADIR} image: 'tdengine:${VERSION}' container_name: 'tdnode3' cap_add: @@ -23,29 +26,34 @@ services: sysctl -p && exec my-main-application" extra_hosts: - - "tdnode1:172.27.0.7" - "tdnode2:172.27.0.8" + - "tdnode3:172.27.0.9" - "tdnode4:172.27.0.10" - "tdnode5:172.27.0.11" + - "tdnode6:172.27.0.12" + - "tdnode7:172.27.0.13" + - "tdnode8:172.27.0.14" + - "tdnode9:172.27.0.15" + - "tdnode10:172.27.0.16" volumes: # bind data directory - type: bind - source: /data/node3/data + source: ${DATADIR}/node3/data target: /var/lib/taos # bind log directory - type: bind - source: /data/node3/log + source: ${DATADIR}/node3/log target: /var/log/taos # bind configuration - type: bind - source: /data/node3/cfg + source: ${DATADIR}/node3/cfg target: /etc/taos # bind core dump path - type: bind - source: /data/node3/core + source: ${DATADIR}/node3/core target: /coredump - type: bind - source: /data + source: ${DATADIR} target: /root hostname: tdnode3 networks: diff --git a/tests/pytest/cluster/clusterEnvSetup/node4.yml b/tests/pytest/cluster/clusterEnvSetup/node4.yml index c82a174cb883b14c885de7c5e8f19d98263b22b7..f542c22c4537dd6dc2c529dff39ba93c5c0ec3a4 100644 --- a/tests/pytest/cluster/clusterEnvSetup/node4.yml +++ b/tests/pytest/cluster/clusterEnvSetup/node4.yml @@ -6,7 +6,10 @@ services: context: . args: - PACKAGE=${PACKAGE} + - TARBITRATORPKG=${TARBITRATORPKG} - EXTRACTDIR=${DIR} + - EXTRACTDIR2=${DIR2} + - DATADIR=${DATADIR} image: 'tdengine:${VERSION}' container_name: 'tdnode4' cap_add: @@ -27,26 +30,31 @@ services: - "tdnode3:172.27.0.9" - "tdnode4:172.27.0.10" - "tdnode5:172.27.0.11" + - "tdnode6:172.27.0.12" + - "tdnode7:172.27.0.13" + - "tdnode8:172.27.0.14" + - "tdnode9:172.27.0.15" + - "tdnode10:172.27.0.16" volumes: # bind data directory - type: bind - source: /data/node4/data + source: ${DATADIR}/node4/data target: /var/lib/taos # bind log directory - type: bind - source: /data/node4/log + source: ${DATADIR}/node4/log target: /var/log/taos # bind configuration - type: bind - source: /data/node4/cfg + source: ${DATADIR}/node4/cfg target: /etc/taos - # bind core dump path + # bind core dump path - type: bind - source: /data/node4/core + source: ${DATADIR}/node4/core target: /coredump - type: bind - source: /data - target: /root + source: ${DATADIR} + target: /root hostname: tdnode4 networks: taos_update_net: diff --git a/tests/pytest/cluster/clusterEnvSetup/node5.yml b/tests/pytest/cluster/clusterEnvSetup/node5.yml index 2e37e47512430ac99244f6b2f0e2d309a2145edc..dd5941ac769273031c98bca3248adcf633240088 100644 --- a/tests/pytest/cluster/clusterEnvSetup/node5.yml +++ b/tests/pytest/cluster/clusterEnvSetup/node5.yml @@ -6,7 +6,10 @@ services: context: . args: - PACKAGE=${PACKAGE} + - TARBITRATORPKG=${TARBITRATORPKG} - EXTRACTDIR=${DIR} + - EXTRACTDIR2=${DIR2} + - DATADIR=${DATADIR} image: 'tdengine:${VERSION}' container_name: 'tdnode5' cap_add: @@ -27,25 +30,30 @@ services: - "tdnode3:172.27.0.9" - "tdnode4:172.27.0.10" - "tdnode5:172.27.0.11" + - "tdnode6:172.27.0.12" + - "tdnode7:172.27.0.13" + - "tdnode8:172.27.0.14" + - "tdnode9:172.27.0.15" + - "tdnode10:172.27.0.16" volumes: # bind data directory - type: bind - source: /data/node5/data + source: ${DATADIR}/node5/data target: /var/lib/taos # bind log directory - type: bind - source: /data/node5/log + source: ${DATADIR}/node5/log target: /var/log/taos # bind configuration - type: bind - source: /data/node5/cfg + source: ${DATADIR}/node5/cfg target: /etc/taos # bind core dump path - type: bind - source: /data/node5/core + source: ${DATADIR}/node5/core target: /coredump - type: bind - source: /data + source: ${DATADIR} target: /root hostname: tdnode5 networks: diff --git a/tests/pytest/fulltest.sh b/tests/pytest/fulltest.sh index b8552925b7e6ce710829b7df0a39ead1a25c17f7..5037f2c399bdc1f1a291dac774e1fde1ab2cb6ed 100755 --- a/tests/pytest/fulltest.sh +++ b/tests/pytest/fulltest.sh @@ -1,18 +1,15 @@ #!/bin/bash ulimit -c unlimited +#======================p1-start=============== python3 ./test.py -f insert/basic.py python3 ./test.py -f insert/int.py -python3 ./test.py -f insert/unsignedInt.py python3 ./test.py -f insert/float.py python3 ./test.py -f insert/bigint.py -python3 ./test.py -f insert/unsignedBigint.py python3 ./test.py -f insert/bool.py python3 ./test.py -f insert/double.py python3 ./test.py -f insert/smallint.py -python3 ./test.py -f insert/unsignedSmallint.py python3 ./test.py -f insert/tinyint.py -python3 ./test.py -f insert/unsignedTinyint.py python3 ./test.py -f insert/date.py python3 ./test.py -f insert/binary.py python3 ./test.py -f insert/nchar.py @@ -23,10 +20,8 @@ python3 ./test.py -f insert/randomNullCommit.py python3 insert/retentionpolicy.py python3 ./test.py -f insert/alterTableAndInsert.py python3 ./test.py -f insert/insertIntoTwoTables.py -#python3 ./test.py -f insert/before_1970.py -python3 ./test.py -f insert/metadataUpdate.py +python3 ./test.py -f insert/before_1970.py python3 bug2265.py -python3 ./test.py -f insert/boundary2.py #table python3 ./test.py -f table/alter_wal0.py @@ -71,7 +66,7 @@ python3 ./test.py -f tag_lite/int.py python3 ./test.py -f tag_lite/set.py python3 ./test.py -f tag_lite/smallint.py python3 ./test.py -f tag_lite/tinyint.py -python3 ./test.py -f tag_lite/alter_tag.py + #python3 ./test.py -f dbmgmt/database-name-boundary.py python3 ./test.py -f import_merge/importBlock1HO.py @@ -142,6 +137,26 @@ python3 ./test.py -f import_merge/importTPORestart.py python3 ./test.py -f import_merge/importTRestart.py python3 ./test.py -f import_merge/importInsertThenImport.py python3 ./test.py -f import_merge/importCSV.py +#======================p1-end=============== +#======================p2-start=============== +# update +python3 ./test.py -f update/allow_update.py +python3 ./test.py -f update/allow_update-0.py +python3 ./test.py -f update/append_commit_data.py +python3 ./test.py -f update/append_commit_last-0.py +python3 ./test.py -f update/append_commit_last.py +python3 ./test.py -f update/merge_commit_data.py + +python3 ./test.py -f update/merge_commit_data2.py +python3 ./test.py -f update/merge_commit_data2_update0.py +python3 ./test.py -f update/merge_commit_last-0.py +python3 ./test.py -f update/merge_commit_last.py +python3 ./test.py -f update/bug_td2279.py + +#======================p2-end=============== +#======================p3-start=============== + + # user python3 ./test.py -f user/user_create.py python3 ./test.py -f user/pass_len.py @@ -155,7 +170,6 @@ python3 ./test.py -f query/filterCombo.py python3 ./test.py -f query/queryNormal.py python3 ./test.py -f query/queryError.py python3 ./test.py -f query/filterAllIntTypes.py -python3 ./test.py -f query/filterAllUnsignedIntTypes.py python3 ./test.py -f query/filterFloatAndDouble.py python3 ./test.py -f query/filterOtherTypes.py python3 ./test.py -f query/querySort.py @@ -182,8 +196,6 @@ python3 ./test.py -f query/bug2119.py python3 ./test.py -f query/isNullTest.py python3 ./test.py -f query/queryWithTaosdKilled.py python3 ./test.py -f query/floatCompare.py -python3 ./test.py -f query/queryGroupbySort.py -python3 ./test.py -f query/queryBetweenAnd.py #stream python3 ./test.py -f stream/metric_1.py @@ -199,8 +211,6 @@ python3 ./test.py -f stream/table_n.py #alter table python3 ./test.py -f alter/alter_table_crash.py -python3 ./test.py -f alter/alter_table.py -python3 ./test.py -f alter/alter_debugFlag.py # client python3 ./test.py -f client/client.py @@ -213,6 +223,38 @@ python3 testCompress.py python3 testNoCompress.py python3 testMinTablesPerVnode.py + +python3 queryCount.py +python3 ./test.py -f query/queryGroupbyWithInterval.py +python3 client/twoClients.py +python3 test.py -f query/queryInterval.py +python3 test.py -f query/queryFillTest.py + +# tools +python3 test.py -f tools/taosdemoTest.py +python3 test.py -f tools/taosdemoTestWithoutMetric.py +python3 test.py -f tools/taosdemoTestWithJson.py +python3 test.py -f tools/taosdemoTestLimitOffset.py +python3 test.py -f tools/taosdumpTest.py +python3 test.py -f tools/taosdemoTest2.py +python3 test.py -f tools/taosdemoTestSampleData.py +python3 test.py -f tools/taosdemoTestInterlace.py + +# subscribe +python3 test.py -f subscribe/singlemeter.py +#python3 test.py -f subscribe/stability.py +python3 test.py -f subscribe/supertable.py + + +#======================p3-end=============== +#======================p4-start=============== + +python3 ./test.py -f update/merge_commit_data-0.py +# wal +python3 ./test.py -f wal/addOldWalTest.py + +# function +python3 ./test.py -f functions/all_null_value.py # functions python3 ./test.py -f functions/function_avg.py -r 1 python3 ./test.py -f functions/function_bottom.py -r 1 @@ -232,44 +274,24 @@ python3 ./test.py -f functions/function_sum.py -r 1 python3 ./test.py -f functions/function_top.py -r 1 python3 ./test.py -f functions/function_twa.py -r 1 python3 ./test.py -f functions/function_twa_test2.py -python3 ./test.py -f functions/all_null_value.py -python3 ./test.py -f functions/function_percentile2.py -python3 queryCount.py -python3 ./test.py -f query/queryGroupbyWithInterval.py -python3 client/twoClients.py -python3 ./test.py -f query/queryInterval.py -python3 ./test.py -f query/queryFillTest.py -python3 ./test.py -f query/last_row_cache.py +python3 ./test.py -f functions/function_stddev_td2555.py +python3 ./test.py -f insert/metadataUpdate.py python3 ./test.py -f query/last_cache.py +python3 ./test.py -f query/last_row_cache.py +python3 ./test.py -f account/account_create.py +python3 ./test.py -f alter/alter_table.py +python3 ./test.py -f query/queryGroupbySort.py -# tools -python3 test.py -f tools/taosdemoTest.py -python3 test.py -f tools/taosdumpTest.py -python3 test.py -f tools/lowaTest.py -python3 test.py -f tools/taosdemoTest2.py - -# subscribe -python3 test.py -f subscribe/singlemeter.py -#python3 test.py -f subscribe/stability.py -python3 test.py -f subscribe/supertable.py - - -# update -python3 ./test.py -f update/allow_update.py -python3 ./test.py -f update/allow_update-0.py -python3 ./test.py -f update/append_commit_data.py -python3 ./test.py -f update/append_commit_last-0.py -python3 ./test.py -f update/append_commit_last.py -python3 ./test.py -f update/merge_commit_data.py -python3 ./test.py -f update/merge_commit_data-0.py -python3 ./test.py -f update/merge_commit_data2.py -python3 ./test.py -f update/merge_commit_data2_update0.py -python3 ./test.py -f update/merge_commit_last-0.py -python3 ./test.py -f update/merge_commit_last.py -python3 ./test.py -f update/bug_td2279.py +python3 ./test.py -f insert/unsignedInt.py +python3 ./test.py -f insert/unsignedBigint.py +python3 ./test.py -f insert/unsignedSmallint.py +python3 ./test.py -f insert/unsignedTinyint.py +python3 ./test.py -f query/filterAllUnsignedIntTypes.py -# wal -python3 ./test.py -f wal/addOldWalTest.py +python3 ./test.py -f functions/function_percentile2.py +python3 ./test.py -f insert/boundary2.py +python3 ./test.py -f alter/alter_debugFlag.py +python3 ./test.py -f query/queryBetweenAnd.py +python3 ./test.py -f tag_lite/alter_tag.py -# account -python3 ./test.py -f account/account_create.py \ No newline at end of file +#======================p4-end=============== diff --git a/tests/pytest/functions/function_operations.py b/tests/pytest/functions/function_operations.py index e703147b6722f848263f170b89ce9f972f7a2435..162aa3eb658a60615c9f20de0c363f9066096f0c 100644 --- a/tests/pytest/functions/function_operations.py +++ b/tests/pytest/functions/function_operations.py @@ -92,14 +92,16 @@ class TDTestCase: col_list = [ 'col1' , 'col2' , 'col3' , 'col4' , 'col5' , 'col6' , 'col7' , 'col8' , 'col9' , 'col11' , 'col12' , 'col13' , 'col14' , '1' , '1.1' , 'NULL' ] op_list = [ '+' , '-' , '*' , '/' , '%' ] err_list = [ 'col7' , 'col8' , 'col9' , 'NULL' ] + order_lsit = [ ' order by ts ', ' order by ts desc ', ' order by ts asc '] for i in col_list : for j in col_list : for k in op_list : - sql = " select %s %s %s from test1 " % ( i , k , j ) - if i in err_list or j in err_list: - tdSql.error(sql) - else: - tdSql.query(sql) + for l in order_lsit : + sql = " select %s %s %s from test1 %s" % ( i , k , j , l ) + if i in err_list or j in err_list: + tdSql.error(sql) + else: + tdSql.query(sql) def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/pytest/functions/function_percentile2.py b/tests/pytest/functions/function_percentile2.py index 8a2b280c7df15f5626285671bf6f0432f730d10a..227a3cbe0307a8a198fed2e981eba2890f1e5664 100644 --- a/tests/pytest/functions/function_percentile2.py +++ b/tests/pytest/functions/function_percentile2.py @@ -28,13 +28,13 @@ class TDTestCase: def run(self): tdSql.prepare() - tdSql.execute("create table test(ts timestamp, col1 int, col2 float)") + tdSql.execute("create table test(ts timestamp, col1 int, col2 float, col3 double)") for i in range(1000): sql = "insert into test values" batchSize = int (self.rowNum / 1000) for j in range (batchSize): currTime = self.ts + batchSize * i + j - sql += "(%d, 1, 2.37)" % currTime + sql += "(%d, 1, 2.37, 3.1415926)" % currTime tdSql.execute(sql) tdSql.query("select percentile(col1, 20) from test") @@ -43,12 +43,18 @@ class TDTestCase: tdSql.query("select percentile(col2, 20) from test") tdSql.checkData(0, 0, 2.3699998) + tdSql.query("select percentile(col3, 20) from test") + tdSql.checkData(0, 0, 3.1415926) + tdSql.query("select apercentile(col1, 20) from test") tdSql.checkData(0, 0, 1) tdSql.query("select apercentile(col2, 20) from test") tdSql.checkData(0, 0, 2.3699998) + tdSql.query("select apercentile(col3, 20) from test") + tdSql.checkData(0, 0, 3.1415926) + def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/pytest/functions/function_stddev.py b/tests/pytest/functions/function_stddev.py index 6e4ee694222247b884c2d40526d644e22cb2260f..3ff2b82bf6b326ed4d07a5a51027c9e266c2fd72 100644 --- a/tests/pytest/functions/function_stddev.py +++ b/tests/pytest/functions/function_stddev.py @@ -113,6 +113,16 @@ class TDTestCase: for i in range(13): tdSql.query('select stddev(c4) from s group by t%s' % str(i+1) ) + #add for td-3223 + for i in range(13): + if i == 1 or i == 5 or i == 6 or i == 7 or i == 9 or i == 8 :continue + tdSql.query('select stddev(c%d),stddev(c%d) from s group by c%d' %( i+1 , i+1 , i+1 ) ) + + #add for TD-3318 + tdSql.execute('create table t1(ts timestamp, k int, b binary(12));') + tdSql.execute("insert into t1 values(now, 1, 'abc');") + tdLog.info("select stddev(k) from t1 where b <> 'abc' interval(1s);") + tdSql.query("select stddev(k) from t1 where b <> 'abc' interval(1s);") def stop(self): diff --git a/tests/pytest/handle_crash_gen_val_log.sh b/tests/pytest/handle_crash_gen_val_log.sh index 502c859dad85a8fcceee7e0efaaa46ab9bded02a..55c10639d7af941eda21cf33cbf7050c95fe3539 100755 --- a/tests/pytest/handle_crash_gen_val_log.sh +++ b/tests/pytest/handle_crash_gen_val_log.sh @@ -16,7 +16,7 @@ TOP_DIR=`pwd` TAOSD_DIR=`find . -name "taosd"|grep -v community|head -n1` nohup $TAOSD_DIR >/dev/null & cd - -./crash_gen.sh --valgrind -p -t 10 -s 500 -b 4 +./crash_gen.sh --valgrind -p -t 10 -s 1000 -b 4 pidof taosd|xargs kill -9 grep 'start to execute\|ERROR SUMMARY' valgrind.err|grep -v 'grep'|uniq|tee crash_gen_mem_err.log diff --git a/tests/pytest/pytest_1.sh b/tests/pytest/pytest_1.sh deleted file mode 100755 index e6638cbb171ab3d8dc38c13f5767ff2f09c522bb..0000000000000000000000000000000000000000 --- a/tests/pytest/pytest_1.sh +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/bash -ulimit -c unlimited - -python3 ./test.py -f insert/basic.py -python3 ./test.py -f insert/int.py -python3 ./test.py -f insert/float.py -python3 ./test.py -f insert/bigint.py -python3 ./test.py -f insert/bool.py -python3 ./test.py -f insert/double.py -python3 ./test.py -f insert/smallint.py -python3 ./test.py -f insert/tinyint.py -python3 ./test.py -f insert/date.py -python3 ./test.py -f insert/binary.py -python3 ./test.py -f insert/nchar.py -#python3 ./test.py -f insert/nchar-boundary.py -python3 ./test.py -f insert/nchar-unicode.py -python3 ./test.py -f insert/multi.py -python3 ./test.py -f insert/randomNullCommit.py -python3 insert/retentionpolicy.py -python3 ./test.py -f insert/alterTableAndInsert.py -python3 ./test.py -f insert/insertIntoTwoTables.py -python3 ./test.py -f insert/before_1970.py -python3 bug2265.py - -#table -python3 ./test.py -f table/alter_wal0.py -python3 ./test.py -f table/column_name.py -python3 ./test.py -f table/column_num.py -python3 ./test.py -f table/db_table.py -python3 ./test.py -f table/create_sensitive.py -#python3 ./test.py -f table/tablename-boundary.py -python3 ./test.py -f table/max_table_length.py -python3 ./test.py -f table/alter_column.py -python3 ./test.py -f table/boundary.py -python3 ./test.py -f table/create.py -python3 ./test.py -f table/del_stable.py - - -# tag -python3 ./test.py -f tag_lite/filter.py -python3 ./test.py -f tag_lite/create-tags-boundary.py -python3 ./test.py -f tag_lite/3.py -python3 ./test.py -f tag_lite/4.py -python3 ./test.py -f tag_lite/5.py -python3 ./test.py -f tag_lite/6.py -python3 ./test.py -f tag_lite/add.py -python3 ./test.py -f tag_lite/bigint.py -python3 ./test.py -f tag_lite/binary_binary.py -python3 ./test.py -f tag_lite/binary.py -python3 ./test.py -f tag_lite/bool_binary.py -python3 ./test.py -f tag_lite/bool_int.py -python3 ./test.py -f tag_lite/bool.py -python3 ./test.py -f tag_lite/change.py -python3 ./test.py -f tag_lite/column.py -python3 ./test.py -f tag_lite/commit.py -python3 ./test.py -f tag_lite/create.py -python3 ./test.py -f tag_lite/datatype.py -python3 ./test.py -f tag_lite/datatype-without-alter.py -python3 ./test.py -f tag_lite/delete.py -python3 ./test.py -f tag_lite/double.py -python3 ./test.py -f tag_lite/float.py -python3 ./test.py -f tag_lite/int_binary.py -python3 ./test.py -f tag_lite/int_float.py -python3 ./test.py -f tag_lite/int.py -python3 ./test.py -f tag_lite/set.py -python3 ./test.py -f tag_lite/smallint.py -python3 ./test.py -f tag_lite/tinyint.py - -#python3 ./test.py -f dbmgmt/database-name-boundary.py - -python3 ./test.py -f import_merge/importBlock1HO.py -python3 ./test.py -f import_merge/importBlock1HPO.py -python3 ./test.py -f import_merge/importBlock1H.py -python3 ./test.py -f import_merge/importBlock1S.py -python3 ./test.py -f import_merge/importBlock1Sub.py -python3 ./test.py -f import_merge/importBlock1TO.py -python3 ./test.py -f import_merge/importBlock1TPO.py -python3 ./test.py -f import_merge/importBlock1T.py -python3 ./test.py -f import_merge/importBlock2HO.py -python3 ./test.py -f import_merge/importBlock2HPO.py -python3 ./test.py -f import_merge/importBlock2H.py -python3 ./test.py -f import_merge/importBlock2S.py -python3 ./test.py -f import_merge/importBlock2Sub.py -python3 ./test.py -f import_merge/importBlock2TO.py -python3 ./test.py -f import_merge/importBlock2TPO.py -python3 ./test.py -f import_merge/importBlock2T.py -python3 ./test.py -f import_merge/importBlockbetween.py -python3 ./test.py -f import_merge/importCacheFileHO.py -python3 ./test.py -f import_merge/importCacheFileHPO.py -python3 ./test.py -f import_merge/importCacheFileH.py -python3 ./test.py -f import_merge/importCacheFileS.py -python3 ./test.py -f import_merge/importCacheFileSub.py -python3 ./test.py -f import_merge/importCacheFileTO.py -python3 ./test.py -f import_merge/importCacheFileTPO.py -python3 ./test.py -f import_merge/importCacheFileT.py -python3 ./test.py -f import_merge/importDataH2.py -python3 ./test.py -f import_merge/importDataHO2.py -python3 ./test.py -f import_merge/importDataHO.py -python3 ./test.py -f import_merge/importDataHPO.py -python3 ./test.py -f import_merge/importDataLastHO.py -python3 ./test.py -f import_merge/importDataLastHPO.py -python3 ./test.py -f import_merge/importDataLastH.py -python3 ./test.py -f import_merge/importDataLastS.py -python3 ./test.py -f import_merge/importDataLastSub.py -python3 ./test.py -f import_merge/importDataLastTO.py -python3 ./test.py -f import_merge/importDataLastTPO.py -python3 ./test.py -f import_merge/importDataLastT.py -python3 ./test.py -f import_merge/importDataS.py -python3 ./test.py -f import_merge/importDataSub.py -python3 ./test.py -f import_merge/importDataTO.py -python3 ./test.py -f import_merge/importDataTPO.py -python3 ./test.py -f import_merge/importDataT.py -python3 ./test.py -f import_merge/importHeadOverlap.py -python3 ./test.py -f import_merge/importHeadPartOverlap.py -python3 ./test.py -f import_merge/importHead.py -python3 ./test.py -f import_merge/importHORestart.py -python3 ./test.py -f import_merge/importHPORestart.py -python3 ./test.py -f import_merge/importHRestart.py -python3 ./test.py -f import_merge/importLastHO.py -python3 ./test.py -f import_merge/importLastHPO.py -python3 ./test.py -f import_merge/importLastH.py -python3 ./test.py -f import_merge/importLastS.py -python3 ./test.py -f import_merge/importLastSub.py -python3 ./test.py -f import_merge/importLastTO.py -python3 ./test.py -f import_merge/importLastTPO.py -python3 ./test.py -f import_merge/importLastT.py -python3 ./test.py -f import_merge/importSpan.py -python3 ./test.py -f import_merge/importSRestart.py -python3 ./test.py -f import_merge/importSubRestart.py -python3 ./test.py -f import_merge/importTailOverlap.py -python3 ./test.py -f import_merge/importTailPartOverlap.py -python3 ./test.py -f import_merge/importTail.py -python3 ./test.py -f import_merge/importToCommit.py -python3 ./test.py -f import_merge/importTORestart.py -python3 ./test.py -f import_merge/importTPORestart.py -python3 ./test.py -f import_merge/importTRestart.py -python3 ./test.py -f import_merge/importInsertThenImport.py -python3 ./test.py -f import_merge/importCSV.py \ No newline at end of file diff --git a/tests/pytest/pytest_2.sh b/tests/pytest/pytest_2.sh deleted file mode 100755 index d152ed85fb9e138a6b9d62574bcc8a5119973448..0000000000000000000000000000000000000000 --- a/tests/pytest/pytest_2.sh +++ /dev/null @@ -1,16 +0,0 @@ - - -# update -python3 ./test.py -f update/allow_update.py -python3 ./test.py -f update/allow_update-0.py -python3 ./test.py -f update/append_commit_data.py -python3 ./test.py -f update/append_commit_last-0.py -python3 ./test.py -f update/append_commit_last.py -python3 ./test.py -f update/merge_commit_data.py - -python3 ./test.py -f update/merge_commit_data2.py -python3 ./test.py -f update/merge_commit_data2_update0.py -python3 ./test.py -f update/merge_commit_last-0.py -python3 ./test.py -f update/merge_commit_last.py -python3 ./test.py -f update/bug_td2279.py - diff --git a/tests/pytest/pytest_3.sh b/tests/pytest/pytest_3.sh deleted file mode 100755 index a40cbb0d558e30943e29ea55f2274a96df2a3e6d..0000000000000000000000000000000000000000 --- a/tests/pytest/pytest_3.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/bash -ulimit -c unlimited - - -python3 ./test.py -f insert/randomNullCommit.py - -# user -python3 ./test.py -f user/user_create.py -python3 ./test.py -f user/pass_len.py - -# stable -python3 ./test.py -f stable/query_after_reset.py - -#query -python3 ./test.py -f query/filter.py -python3 ./test.py -f query/filterCombo.py -python3 ./test.py -f query/queryNormal.py -python3 ./test.py -f query/queryError.py -python3 ./test.py -f query/filterAllIntTypes.py -python3 ./test.py -f query/filterFloatAndDouble.py -python3 ./test.py -f query/filterOtherTypes.py -python3 ./test.py -f query/querySort.py -python3 ./test.py -f query/queryJoin.py -python3 ./test.py -f query/select_last_crash.py -python3 ./test.py -f query/queryNullValueTest.py -python3 ./test.py -f query/queryInsertValue.py -python3 ./test.py -f query/queryConnection.py -python3 ./test.py -f query/queryCountCSVData.py -python3 ./test.py -f query/natualInterval.py -python3 ./test.py -f query/bug1471.py -#python3 ./test.py -f query/dataLossTest.py -python3 ./test.py -f query/bug1874.py -python3 ./test.py -f query/bug1875.py -python3 ./test.py -f query/bug1876.py -python3 ./test.py -f query/bug2218.py -python3 ./test.py -f query/bug2117.py -python3 ./test.py -f query/bug2118.py -python3 ./test.py -f query/bug2143.py -python3 ./test.py -f query/sliding.py -python3 ./test.py -f query/unionAllTest.py -python3 ./test.py -f query/bug2281.py -python3 ./test.py -f query/bug2119.py -python3 ./test.py -f query/isNullTest.py -python3 ./test.py -f query/queryWithTaosdKilled.py -python3 ./test.py -f query/floatCompare.py - -#stream -python3 ./test.py -f stream/metric_1.py -python3 ./test.py -f stream/metric_n.py -python3 ./test.py -f stream/new.py -python3 ./test.py -f stream/stream1.py -python3 ./test.py -f stream/stream2.py -#python3 ./test.py -f stream/parser.py -python3 ./test.py -f stream/history.py -python3 ./test.py -f stream/sys.py -python3 ./test.py -f stream/table_1.py -python3 ./test.py -f stream/table_n.py - -#alter table -python3 ./test.py -f alter/alter_table_crash.py - -# client -python3 ./test.py -f client/client.py -python3 ./test.py -f client/version.py -python3 ./test.py -f client/alterDatabase.py -python3 ./test.py -f client/noConnectionErrorTest.py - -# Misc -python3 testCompress.py -python3 testNoCompress.py -python3 testMinTablesPerVnode.py - - -python3 queryCount.py -python3 ./test.py -f query/queryGroupbyWithInterval.py -python3 client/twoClients.py -python3 test.py -f query/queryInterval.py -python3 test.py -f query/queryFillTest.py - -# tools -python3 test.py -f tools/taosdemoTest.py -python3 test.py -f tools/taosdemoTestWithoutMetric.py -python3 test.py -f tools/taosdumpTest.py -python3 test.py -f tools/lowaTest.py -#python3 test.py -f tools/taosdemoTest2.py - -# subscribe -python3 test.py -f subscribe/singlemeter.py -#python3 test.py -f subscribe/stability.py -python3 test.py -f subscribe/supertable.py - diff --git a/tests/pytest/pytest_4.sh b/tests/pytest/pytest_4.sh deleted file mode 100755 index dada90c709a967df37693d7398692c6d7fc12039..0000000000000000000000000000000000000000 --- a/tests/pytest/pytest_4.sh +++ /dev/null @@ -1,39 +0,0 @@ -python3 ./test.py -f update/merge_commit_data-0.py -# wal -python3 ./test.py -f wal/addOldWalTest.py - -# function -python3 ./test.py -f functions/all_null_value.py -# functions -python3 ./test.py -f functions/function_avg.py -r 1 -python3 ./test.py -f functions/function_bottom.py -r 1 -python3 ./test.py -f functions/function_count.py -r 1 -python3 ./test.py -f functions/function_diff.py -r 1 -python3 ./test.py -f functions/function_first.py -r 1 -python3 ./test.py -f functions/function_last.py -r 1 -python3 ./test.py -f functions/function_last_row.py -r 1 -python3 ./test.py -f functions/function_leastsquares.py -r 1 -python3 ./test.py -f functions/function_max.py -r 1 -python3 ./test.py -f functions/function_min.py -r 1 -python3 ./test.py -f functions/function_operations.py -r 1 -python3 ./test.py -f functions/function_percentile.py -r 1 -python3 ./test.py -f functions/function_spread.py -r 1 -python3 ./test.py -f functions/function_stddev.py -r 1 -python3 ./test.py -f functions/function_sum.py -r 1 -python3 ./test.py -f functions/function_top.py -r 1 -python3 ./test.py -f functions/function_twa.py -r 1 -python3 ./test.py -f functions/function_twa_test2.py -python3 ./test.py -f functions/function_stddev_td2555.py -python3 ./test.py -f insert/metadataUpdate.py -python3 ./test.py -f tools/taosdemoTest2.py -python3 ./test.py -f query/last_cache.py -python3 ./test.py -f query/last_row_cache.py -python3 ./test.py -f account/account_create.py -python3 ./test.py -f alter/alter_table.py -python3 ./test.py -f query/queryGroupbySort.py - -python3 ./test.py -f insert/unsignedInt.py -python3 ./test.py -f insert/unsignedBigint.py -python3 ./test.py -f insert/unsignedSmallint.py -python3 ./test.py -f insert/unsignedTinyint.py -python3 ./test.py -f query/filterAllUnsignedIntTypes.py \ No newline at end of file diff --git a/tests/pytest/query/filter.py b/tests/pytest/query/filter.py index f107985f150a05cdd38a7fa1453d59d35c8a903a..6d2ffbc8b10992628fec381e60fd11a68c69fe27 100644 --- a/tests/pytest/query/filter.py +++ b/tests/pytest/query/filter.py @@ -28,18 +28,18 @@ class TDTestCase: print("==============step1") tdSql.execute( - "create table if not exists st (ts timestamp, tagtype int, name nchar(16)) tags(dev nchar(50))") + "create table if not exists st (ts timestamp, tagtype int, name nchar(16), col4 binary(16)) tags(dev nchar(50), tag2 binary(16))") tdSql.execute( - 'CREATE TABLE if not exists dev_001 using st tags("dev_01")') + 'CREATE TABLE if not exists dev_001 using st tags("dev_01", "tag_01")') tdSql.execute( - 'CREATE TABLE if not exists dev_002 using st tags("dev_02")') + 'CREATE TABLE if not exists dev_002 using st tags("dev_02", "tag_02")') print("==============step2") tdSql.execute( - """INSERT INTO dev_001(ts, tagtype, name) VALUES('2020-05-13 10:00:00.000', 1, 'first'),('2020-05-13 10:00:00.001', 2, 'second'), - ('2020-05-13 10:00:00.002', 3, 'third') dev_002 VALUES('2020-05-13 10:00:00.003', 1, 'first'), ('2020-05-13 10:00:00.004', 2, 'second'), - ('2020-05-13 10:00:00.005', 3, 'third')""") + """INSERT INTO dev_001 VALUES('2020-05-13 10:00:00.000', 1, 'first', 'binary1'),('2020-05-13 10:00:00.001', 2, 'second', 'binary2'), + ('2020-05-13 10:00:00.002', 3, 'third' , 'binary3') dev_002 VALUES('2020-05-13 10:00:00.003', 1, 'first', 'binary4'), ('2020-05-13 10:00:00.004', 2, 'second', 'binary5'), + ('2020-05-13 10:00:00.005', 3, 'third', 'binary6')""") # > for timestamp type tdSql.query("select * from db.st where ts > '2020-05-13 10:00:00.002'") @@ -85,6 +85,12 @@ class TDTestCase: tdSql.query("select * from db.st where name = 'first'") tdSql.checkRows(2) + tdSql.query("select * from db.st where col4 = 1231231") + tdSql.checkRows(0) + + tdSql.query("select * from db.st where name = 1231231") + tdSql.checkRows(0) + # <> for timestamp type tdSql.query("select * from db.st where ts <> '2020-05-13 10:00:00.002'") # tdSql.checkRows(4) @@ -105,6 +111,13 @@ class TDTestCase: tdSql.query("select * from db.st where name like '_econd'") tdSql.checkRows(2) + # for tag + tdSql.query("select * from db.st where dev=1") + tdSql.checkRows(0) + + tdSql.query("select * from db.st where tag2=1") + tdSql.checkRows(0) + def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/pytest/query/queryNormal.py b/tests/pytest/query/queryNormal.py index 13393117d642ec1fbdf839d59429428ffee79a27..4e3f9dd3bdd6376ac1069c4e084944a577ce4a70 100644 --- a/tests/pytest/query/queryNormal.py +++ b/tests/pytest/query/queryNormal.py @@ -94,8 +94,9 @@ class TDTestCase: tdSql.query("select * from stb1 limit 2 offset 3") tdSql.checkRows(1) - # query ... alias for table ---- bug - tdSql.error("select t.ts from tb1 t") + # query ... alias for table + tdSql.query("select t.ts from tb1 t") + tdSql.checkRows(2) # query ... tbname tdSql.query("select tbname from stb1") diff --git a/tests/pytest/tools/insert-interlace.json b/tests/pytest/tools/insert-interlace.json new file mode 100644 index 0000000000000000000000000000000000000000..a2ff2c001cf5aad24d2ecd7d9766f5ee62d6f3a5 --- /dev/null +++ b/tests/pytest/tools/insert-interlace.json @@ -0,0 +1,58 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 5000, + "rows_per_tbl": 50, + "num_of_records_per_req": 100, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "db", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 16, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb", + "child_table_exists":"no", + "childtable_count": 9, + "childtable_prefix": "stb_", + "auto_create_table": "no", + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 250, + "multi_thread_write_one_tbl": "no", + "rows_per_tbl": 80, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}], + "tags": [{"type": "INT", "count":1}] + }] + }] +} diff --git a/tests/pytest/tools/insert-tblimit-tboffset.json b/tests/pytest/tools/insert-tblimit-tboffset.json new file mode 100644 index 0000000000000000000000000000000000000000..f3d3e864baaa5429248f57a6dd1ea6b5bc314bfb --- /dev/null +++ b/tests/pytest/tools/insert-tblimit-tboffset.json @@ -0,0 +1,59 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "num_of_records_per_req": 100, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "db", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 16, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb", + "child_table_exists":"no", + "childtable_count": 100, + "childtable_prefix": "stb_", + "auto_create_table": "no", + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 1000, + "childtable_limit": 33, + "childtable_offset": 33, + "multi_thread_write_one_tbl": "no", + "number_of_tbl_in_one_sql": 0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":10}, {"type": "BINARY", "len": 16, "count":3}, {"type": "BINARY", "len": 32, "count":6}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":5}] + }] + }] +} diff --git a/tests/pytest/tools/insert-tblimit-tboffset0.json b/tests/pytest/tools/insert-tblimit-tboffset0.json new file mode 100644 index 0000000000000000000000000000000000000000..7dcb2e052745e545d1693d97ce28350d00745e55 --- /dev/null +++ b/tests/pytest/tools/insert-tblimit-tboffset0.json @@ -0,0 +1,59 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "num_of_records_per_req": 100, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "db", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 16, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb", + "child_table_exists":"no", + "childtable_count": 100, + "childtable_prefix": "stb_", + "auto_create_table": "no", + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 1000, + "childtable_limit": 20, + "childtable_offset": 0, + "multi_thread_write_one_tbl": "no", + "number_of_tbl_in_one_sql": 0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":10}, {"type": "BINARY", "len": 16, "count":3}, {"type": "BINARY", "len": 32, "count":6}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":5}] + }] + }] +} diff --git a/tests/pytest/tools/insert-tblimit1-tboffset.json b/tests/pytest/tools/insert-tblimit1-tboffset.json new file mode 100644 index 0000000000000000000000000000000000000000..a33dc22d5d5e2c88c9b6220fbe53390dfcd4f1ce --- /dev/null +++ b/tests/pytest/tools/insert-tblimit1-tboffset.json @@ -0,0 +1,59 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "num_of_records_per_req": 100, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "db", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 16, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb", + "child_table_exists":"no", + "childtable_count": 100, + "childtable_prefix": "stb_", + "auto_create_table": "no", + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 1000, + "childtable_limit": 1, + "childtable_offset": 50, + "multi_thread_write_one_tbl": "no", + "number_of_tbl_in_one_sql": 0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}], + "tags": [{"type": "TINYINT", "count":1}] + }] + }] +} diff --git a/tests/pytest/tools/insert.json b/tests/pytest/tools/insert.json index c3fa78076b2a25f73ebc50f6a35bcc5afddb246d..996b91ed06f283fdcd968df9cafc4f58583cbb8d 100644 --- a/tests/pytest/tools/insert.json +++ b/tests/pytest/tools/insert.json @@ -1,50 +1,45 @@ { "filetype":"insert", "cfgdir": "/etc/taos", - "host": "127.0.0.1", - "port": 6030, - "user": "root", - "password": "taosdata", - "thread_count": 1, - "databases": [{ - "dbinfo": { - "name": "db01", - "replica": 1, - "days": 10, - "cache": 16, - "blocks": 8, - "precision": "ms", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 2, + "num_of_records_per_req": 10, + "thread_count_create_tbl": 4, + "databases": [{ + "dbinfo": { + "name": "db01", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 16, + "blocks": 8, + "precision": "ms", "update": 0, - "maxtablesPerVnode": 1000 - }, - "super_tables": [{ - "name": "stb01", - "childtable_count": 100, - "childtable_prefix": "stb01_", - "auto_create_table": "no", - "data_source": "rand", - "insert_mode": "taosc", - "insert_rate": 0, - "insert_rows": 1000, - "timestamp_step": 1000, - "start_timestamp": "2020-10-01 00:00:00.000", - "sample_format": "csv", - "sample_file": "/home/data/sample.csv", - "tags_file": "", - "columns": [{ - "type": "SMALLINT" - }, { - "type": "BOOL" - }, { - "type": "BINARY", - "len": 6 - }], - "tags": [{ - "type": "INT" - },{ - "type": "BINARY", - "len": 4 - }] - }] - }] + "maxtablesPerVnode": 1000 + }, + "super_tables": [{ + "name": "stb01", + "childtable_count": 3, + "childtable_prefix": "stb01_", + "auto_create_table": "no", + "data_source": "rand", + "insert_mode": "taosc", + "insert_rate": 0, + "insert_rows": 20, + "timestamp_step": 1000, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "/home/data/sample.csv", + "tags_file": "", + "columns": [{ + "type": "INT" + }], + "tags": [{ + "type": "INT" + }] + }] + }] } diff --git a/tests/pytest/tools/sampledata.csv b/tests/pytest/tools/sampledata.csv new file mode 100644 index 0000000000000000000000000000000000000000..01e79c32a8c99c557f0757da7cb6d65b3414466d --- /dev/null +++ b/tests/pytest/tools/sampledata.csv @@ -0,0 +1,3 @@ +1 +2 +3 diff --git a/tests/pytest/tools/taosdemo-sampledata.json b/tests/pytest/tools/taosdemo-sampledata.json new file mode 100644 index 0000000000000000000000000000000000000000..473c977773a097fd040b3821c3df806da8ef9c02 --- /dev/null +++ b/tests/pytest/tools/taosdemo-sampledata.json @@ -0,0 +1,39 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 10, + "confirm_parameter_prompt": "no", + "databases": [{ + "dbinfo": { + "name": "db", + "drop": "yes" + }, + "super_tables": [{ + "name": "stb", + "child_table_exists":"no", + "childtable_count": 20, + "childtable_limit": 10, + "childtable_offset": 0, + "childtable_prefix": "t_", + "auto_create_table": "no", + "data_source": "sample", + "insert_mode": "taosc", + "insert_rate": 0, + "insert_rows": 20, + "multi_thread_write_one_tbl": "no", + "number_of_tbl_in_one_sql": 0, + "max_sql_len": 1048000, + "timestamp_step": 1000, + "start_timestamp": "2020-1-1 00:00:00", + "sample_format": "csv", + "sample_file": "./tools/sampledata.csv", + "columns": [{"type": "INT"}], + "tags": [{"type": "INT", "count":1}] + }] + }] + +} diff --git a/tests/pytest/tools/taosdemoTest.py b/tests/pytest/tools/taosdemoTest.py index c450570d2446a236ad8fa98c0817d2e31bcae795..2ce9228c54b925b55b202dcbd151fb8c9de2e4fc 100644 --- a/tests/pytest/tools/taosdemoTest.py +++ b/tests/pytest/tools/taosdemoTest.py @@ -63,7 +63,7 @@ class TDTestCase: tdSql.checkRows(2) tdSql.query( - "select apercentile(col1, 1) from test.meters interval(10s)") + "select apercentile(col1, 1) from test.meters interval(100s)") tdSql.checkRows(1) tdSql.error("select loc, count(loc) from test.meters") diff --git a/tests/pytest/tools/taosdemoTestInterlace.py b/tests/pytest/tools/taosdemoTestInterlace.py new file mode 100644 index 0000000000000000000000000000000000000000..953bfff90fd7f114ad1c78425a80e1eaae75c43e --- /dev/null +++ b/tests/pytest/tools/taosdemoTestInterlace.py @@ -0,0 +1,78 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import os +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import * +import subprocess + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + self.numberOfTables = 10000 + self.numberOfRecords = 100 + + def getBuildPath(self): + selfPath = os.path.dirname(os.path.realpath(__file__)) + + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] + else: + projPath = selfPath[:selfPath.find("tests")] + + for root, dirs, files in os.walk(projPath): + if ("taosd" in files): + rootRealPath = os.path.dirname(os.path.realpath(root)) + if ("packaging" not in rootRealPath): + buildPath = root[:len(root) - len("/build/bin")] + break + return buildPath + + def run(self): + tdSql.prepare() + buildPath = self.getBuildPath() + if (buildPath == ""): + tdLog.exit("taosd not found!") + else: + tdLog.info("taosd found in %s" % buildPath) + binPath = buildPath + "/build/bin/" + taosdemoCmd = "%staosdemo -f tools/insert-interlace.json -pp 2>&1 | grep sleep | wc -l" % binPath + sleepTimes = subprocess.check_output( + taosdemoCmd, shell=True).decode("utf-8") + print("sleep times: %d" % int(sleepTimes)) + + if (int(sleepTimes) != 16): + caller = inspect.getframeinfo(inspect.stack()[0][0]) + tdLog.exit( + "%s(%d) failed: expected sleep times 16, actual %d" % + (caller.filename, caller.lineno, int(sleepTimes))) + + tdSql.execute("use db") + tdSql.query("select count(tbname) from db.stb") + tdSql.checkData(0, 0, 9) + tdSql.query("select count(*) from db.stb") + tdSql.checkData(0, 0, 2250) + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/tools/taosdemoTestLimitOffset.py b/tests/pytest/tools/taosdemoTestLimitOffset.py new file mode 100644 index 0000000000000000000000000000000000000000..bce41e1c75817c2939d4c1104419771483a9a689 --- /dev/null +++ b/tests/pytest/tools/taosdemoTestLimitOffset.py @@ -0,0 +1,86 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import os +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import * + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + self.numberOfTables = 10000 + self.numberOfRecords = 100 + + def getBuildPath(self): + selfPath = os.path.dirname(os.path.realpath(__file__)) + + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] + else: + projPath = selfPath[:selfPath.find("tests")] + + for root, dirs, files in os.walk(projPath): + if ("taosd" in files): + rootRealPath = os.path.dirname(os.path.realpath(root)) + if ("packaging" not in rootRealPath): + buildPath = root[:len(root)-len("/build/bin")] + break + return buildPath + + def run(self): + tdSql.prepare() + buildPath = self.getBuildPath() + if (buildPath == ""): + tdLog.exit("taosd not found!") + else: + tdLog.info("taosd found in %s" % buildPath) + binPath = buildPath+ "/build/bin/" + os.system("%staosdemo -f tools/insert-tblimit-tboffset.json" % binPath) + + tdSql.execute("use db") + tdSql.query("select count(tbname) from db.stb") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from db.stb") + tdSql.checkData(0, 0, 33000) + + os.system("%staosdemo -f tools/insert-tblimit-tboffset0.json" % binPath) + + tdSql.execute("reset query cache") + tdSql.execute("use db") + tdSql.query("select count(tbname) from db.stb") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from db.stb") + tdSql.checkData(0, 0, 20000) + + os.system("%staosdemo -f tools/insert-tblimit1-tboffset.json" % binPath) + + tdSql.execute("reset query cache") + tdSql.execute("use db") + tdSql.query("select count(tbname) from db.stb") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from db.stb") + tdSql.checkData(0, 0, 1000) + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/tools/taosdemoTestSampleData.py b/tests/pytest/tools/taosdemoTestSampleData.py new file mode 100644 index 0000000000000000000000000000000000000000..893c53984d87aa729111a840831c6f5343087085 --- /dev/null +++ b/tests/pytest/tools/taosdemoTestSampleData.py @@ -0,0 +1,68 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import os +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import * + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + self.numberOfTables = 10000 + self.numberOfRecords = 100 + + def getBuildPath(self): + selfPath = os.path.dirname(os.path.realpath(__file__)) + + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] + else: + projPath = selfPath[:selfPath.find("tests")] + + for root, dirs, files in os.walk(projPath): + if ("taosd" in files): + rootRealPath = os.path.dirname(os.path.realpath(root)) + if ("packaging" not in rootRealPath): + buildPath = root[:len(root)-len("/build/bin")] + break + return buildPath + + def run(self): + tdSql.prepare() + buildPath = self.getBuildPath() + if (buildPath == ""): + tdLog.exit("taosd not found!") + else: + tdLog.info("taosd found in %s" % buildPath) + binPath = buildPath+ "/build/bin/" + os.system("%staosdemo -f tools/taosdemo-sampledata.json" % binPath) + + tdSql.execute("use db") + tdSql.query("select count(tbname) from db.stb") + tdSql.checkData(0, 0, 20) + tdSql.query("select count(*) from db.stb") + tdSql.checkData(0, 0, 200) + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/tools/lowaTest.py b/tests/pytest/tools/taosdemoTestWithJson.py similarity index 94% rename from tests/pytest/tools/lowaTest.py rename to tests/pytest/tools/taosdemoTestWithJson.py index ad8b5925bd99b9c5918421eb277cea6e5ed100a7..f57af9ce5c7ce890a0a93c6081702d93954af138 100644 --- a/tests/pytest/tools/lowaTest.py +++ b/tests/pytest/tools/taosdemoTestWithJson.py @@ -24,9 +24,6 @@ class TDTestCase: tdLog.debug("start to execute %s" % __file__) tdSql.init(conn.cursor(), logSql) - self.numberOfTables = 10000 - self.numberOfRecords = 100 - def getBuildPath(self): selfPath = os.path.dirname(os.path.realpath(__file__)) @@ -55,7 +52,7 @@ class TDTestCase: tdSql.execute("use db01") tdSql.query("select count(*) from stb01") - tdSql.checkData(0, 0, 100000) + tdSql.checkData(0, 0, 60) def stop(self): tdSql.close() diff --git a/tests/script/general/db/topic1.sim b/tests/script/general/db/topic1.sim index cdfb8ea2ec33a5322ab34de6d2688ef0dc1fc64f..e17a4996f569450116a8050cc4e32905463cea4d 100644 --- a/tests/script/general/db/topic1.sim +++ b/tests/script/general/db/topic1.sim @@ -167,7 +167,7 @@ sql_error show t1.stables; sql_error show t1.tables; sql_error create topic t1 partitions -1; -sql_error create topic t1 partitions 0; +#sql_error create topic t1 partitions 0; sql_error create topic t1 partitions 10001; print =============step3 create with db para @@ -718,7 +718,7 @@ sql_error alter database t1 partitions 1000 sql_error alter database t1 partitions 10000 sql_error alter topic t1 partitions -1 -sql_error alter topic t1 partitions 0 +#sql_error alter topic t1 partitions 0 sql_error alter database t1 partitions 10000 sql alter topic t1 partitions 1 @@ -842,4 +842,41 @@ if $rows != 10 then return -1 endi +sql drop topic t1 + +print ============== create same name topic +sql create database d2 +sql create topic t2 + +sql_error create topic d2 +sql_error create topic if not exists d2 +sql_error create topic t2 +sql create topic if not exists t2 +sql_error create topic t2 partitions 5; +sql_error create topic t2 partitions 6; +sql_error create topic t2 partitions 3; + +sql_error alter topic t3 partitions 1 +sql_error alter topic d2 partitions 1 +#sql_error alter topic t2 partitions 0 +sql_error alter topic t2 partitions 10000 + +sql_error drop topic d2 +sql_error drop topic d3 +sql drop database d2 +sql drop database t2 + +print ============== create partitons 0 +sql create topic t2 partitions 0 +sql show t2.stables; +if $rows != 0 then + return -1 +endi +sql show t2.tables; +if $rows != 0 then + return -1 +endi + +sql drop topic t2 + system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/general/parser/create_mt.sim b/tests/script/general/parser/create_mt.sim index 830b72f93f45835be1d21622dd595a4bbbb4f0dc..ae1629dce9861d7540bda4b6d4014e32ce2ce52d 100644 --- a/tests/script/general/parser/create_mt.sim +++ b/tests/script/general/parser/create_mt.sim @@ -126,8 +126,7 @@ $tb_ = table $tbs = tables $db_ = database $dbs = databases -$mt_ = metric -$mts = metrics +$ses = session $int = int $bint = bigint $binary = binary @@ -145,8 +144,7 @@ sql_error create table $mt (ts timestamp, col1 int) tags ( $tb_ int) sql_error create table $mt (ts timestamp, col1 int) tags ( $tbs int) sql_error create table $mt (ts timestamp, col1 int) tags ( $db_ int) sql_error create table $mt (ts timestamp, col1 int) tags ( $dbs int) -sql_error create table $mt (ts timestamp, col1 int) tags ( $mt_ int) -sql_error create table $mt (ts timestamp, col1 int) tags ( $mts int) +sql_error create table $mt (ts timestamp, col1 int) tags ( $ses int) sql_error create table $mt (ts timestamp, col1 int) tags ( $int int) sql_error create table $mt (ts timestamp, col1 int) tags ( $bint int) sql_error create table $mt (ts timestamp, col1 int) tags ( $binary int) diff --git a/tests/script/general/parser/create_tb.sim b/tests/script/general/parser/create_tb.sim index d30a1392ef74deea0f57807e2828d4dc3f6930a3..eb6e4f71c3f752d0e54ba275f2e8f04dc5b08e65 100644 --- a/tests/script/general/parser/create_tb.sim +++ b/tests/script/general/parser/create_tb.sim @@ -90,8 +90,7 @@ $tb_ = table $tbs = tables $db_ = database $dbs = databases -$mt_ = metric -$mts = metrics +$ses = session $int = int $bint = bigint $binary = binary @@ -105,9 +104,8 @@ $nchar = nchar sql_error create table $tb (ts timestamp, $tb_ int) sql_error create table $tb (ts timestamp, $tbs int) sql_error create table $tb (ts timestamp, $db_ int) -sql_error create table $tb (ts timestamp, $dbs int) -sql_error create table $tb (ts timestamp, $mt_ int) -sql_error create table $tb (ts timestamp, $mts int) +sql_error create table $tb (ts timestamp, $dbs int) +sql_error create table $tb (ts timestamp, $ses int) sql_error create table $tb (ts timestamp, $int int) sql_error create table $tb (ts timestamp, $bint int) sql_error create table $tb (ts timestamp, $binary int) diff --git a/tests/script/general/parser/join.sim b/tests/script/general/parser/join.sim index 73f83f1c9e2af21e49099ffd73a6b1e9d040b2eb..2c14a86c3a6532088d0dce584199c0d5ffbed6fd 100644 --- a/tests/script/general/parser/join.sim +++ b/tests/script/general/parser/join.sim @@ -448,7 +448,7 @@ endi sql select first(join_tb0.c8),first(join_tb0.c9) from join_tb1 , join_tb0 where join_tb1.ts = join_tb0.ts and join_tb1.ts <= 100002 and join_tb0.c7 = true #====================group by========================================= - +print =================>"group by not supported" diff --git a/tests/script/general/parser/join_manyblocks.sim b/tests/script/general/parser/join_manyblocks.sim new file mode 100644 index 0000000000000000000000000000000000000000..fddd59c0a148975fd1bb6d63dbfb01ab46baa376 --- /dev/null +++ b/tests/script/general/parser/join_manyblocks.sim @@ -0,0 +1,93 @@ +system sh/stop_dnodes.sh + +system sh/deploy.sh -n dnode1 -i 1 +system sh/cfg.sh -n dnode1 -c walLevel -v 1 +system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 + +system sh/exec.sh -n dnode1 -s start +sql connect +sleep 100 + +$dbPrefix = join_m_db +$tbPrefix = join_tb +$mtPrefix = join_mt +$tbNum = 3 +$rowNum = 20000 +$totalNum = $tbNum * $rowNum + +print =============== join_manyBlocks.sim +$i = 0 +$db = $dbPrefix . $i +$mt = $mtPrefix . $i + +$tstart = 100000 + +sql drop database if exists $db -x step1 +step1: +sql create database if not exists $db keep 36500 + +sql use $db +sql create table $mt (ts timestamp, c1 int, c2 float, c3 bigint, c4 smallint, c5 tinyint, c6 double, c7 bool, c8 binary(10), c9 nchar(9)) TAGS(t1 int, t2 binary(12)) + +$mt1 = $mtPrefix . 1 . $i +sql create table $mt1 (ts timestamp, c1 int, c2 float, c3 bigint, c4 smallint, c5 tinyint, c6 double, c7 bool, c8 binary(10), c9 nchar(9)) TAGS(t1 int, t2 binary(12), t3 int) + +$i = 0 +$tbPrefix1 = join_1_tb + +$i = 0 +while $i < $tbNum + $tb = $tbPrefix . $i + $tg2 = ' . abc + $tg2 = $tg2 . ' + sql create table $tb using $mt tags( $i , $tg2 ) + + $tb1 = $tbPrefix1 . $i + $c = $i + $t3 = $i + 1 + + $binary = ' . abc + $binary = $binary . $i + $binary = $binary . ' + + print $binary + sql create table $tb1 using $mt1 tags( $i , $binary , $t3 ) + + $x = 0 + while $x < $rowNum + $ms = $x . m + $c = $x / 100 + $c = $c * 100 + $c = $x - $c + + $binary = ' . binary + $binary = $binary . $c + $binary = $binary . ' + + $nchar = ' . nchar + $nchar = $nchar . $c + $nchar = $nchar . ' + + sql insert into $tb values ($tstart , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) $tb1 values ($tstart , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) + + $tstart = $tstart + 1 + $x = $x + 1 + endw + + $i = $i + 1 + $tstart = 100000 +endw + +sleep 100 + +print ===============join_manyblocks.sim +print ==============> td-3313 +sql select join_mt0.ts,join_mt0.ts,join_mt0.t1 from join_mt0, join_mt1 where join_mt0.ts=join_mt1.ts and join_mt0.t1=join_mt1.t1; + +print $row +if $row != 60000 then + print expect 60000, actual: $row + return -1 +endi + +print ======= second tags join diff --git a/tests/script/general/parser/sliding.sim b/tests/script/general/parser/sliding.sim index be33c905a1786b8c56d21aa973e6eb1fb8698ad6..b2695ff95f27c5fe6ba27c9b977c96b48a5e5801 100644 --- a/tests/script/general/parser/sliding.sim +++ b/tests/script/general/parser/sliding.sim @@ -469,11 +469,12 @@ if $data25 != 33 then endi sql select count(*),stddev(c1),count(c1),first(c2),last(c3) from sliding_tb0 where ts>'2000-1-1 00:00:00' and ts<'2000-1-1 00:00:01.002' and c2 >= 0 interval(30s) sliding(10s) order by ts desc limit 1000; -if $row != 1 then +if $row != 3 then return -1 endi -if $data00 != @99-12-31 23:59:40.000@ then +if $data00 != @00-01-01 00:00:00.000@ then + print expect 00-01-01 00:00:00.000, actual: $data00 return -1 endi @@ -489,7 +490,28 @@ if $data03 != 33 then return -1 endi -print check boundary check crash at client side +if $data10 != @99-12-31 23:59:50.000@ then + return -1 +endi + +if $data11 != 33 then + return -1 +endi +if $data12 != 9.521904571 then + return -1 +endi + +if $data20 != @99-12-31 23:59:40.000@ then + return -1 +endi +if $data21 != 33 then + return -1 +endi +if $data22 != 9.521904571 then + return -1 +endi + +print ====================>check boundary check crash at client side sql select count(*) from sliding_mt0 where ts>now and ts < now-1h; print ========================query on super table diff --git a/tests/script/general/parser/testSuite.sim b/tests/script/general/parser/testSuite.sim index c2ce5df12e9e4d60824950f21ac8afb9d64b5235..f05474d15804fba661f650d69632c454415eba64 100644 --- a/tests/script/general/parser/testSuite.sim +++ b/tests/script/general/parser/testSuite.sim @@ -1,112 +1,58 @@ run general/parser/alter.sim -sleep 100 run general/parser/alter1.sim -sleep 100 run general/parser/alter_stable.sim -sleep 100 run general/parser/auto_create_tb.sim -sleep 100 run general/parser/auto_create_tb_drop_tb.sim -sleep 100 run general/parser/col_arithmetic_operation.sim -sleep 100 run general/parser/columnValue.sim -sleep 100 run general/parser/commit.sim -sleep 100 run general/parser/create_db.sim -sleep 100 run general/parser/create_mt.sim -sleep 100 run general/parser/create_tb.sim -sleep 100 run general/parser/dbtbnameValidate.sim -sleep 100 run general/parser/fill.sim -sleep 100 run general/parser/fill_stb.sim -sleep 100 #run general/parser/fill_us.sim # -sleep 100 run general/parser/first_last.sim -sleep 100 run general/parser/import_commit1.sim -sleep 100 run general/parser/import_commit2.sim -sleep 100 run general/parser/import_commit3.sim -sleep 100 #run general/parser/import_file.sim -sleep 100 run general/parser/insert_tb.sim -sleep 100 run general/parser/tags_dynamically_specifiy.sim -sleep 100 run general/parser/interp.sim -sleep 100 run general/parser/lastrow.sim -sleep 100 run general/parser/limit.sim -sleep 100 run general/parser/limit1.sim -sleep 100 run general/parser/limit1_tblocks100.sim -sleep 100 run general/parser/limit2.sim -sleep 100 run general/parser/mixed_blocks.sim -sleep 100 run general/parser/nchar.sim -sleep 100 run general/parser/null_char.sim -sleep 100 run general/parser/selectResNum.sim -sleep 100 run general/parser/select_across_vnodes.sim -sleep 100 run general/parser/select_from_cache_disk.sim -sleep 100 run general/parser/set_tag_vals.sim -sleep 100 run general/parser/single_row_in_tb.sim -sleep 100 run general/parser/slimit.sim -sleep 100 run general/parser/slimit1.sim -sleep 100 run general/parser/slimit_alter_tags.sim -sleep 100 run general/parser/tbnameIn.sim -sleep 100 run general/parser/slimit_alter_tags.sim # persistent failed -sleep 100 run general/parser/join.sim -sleep 100 run general/parser/join_multivnode.sim -sleep 100 +run general/parser/join_manyblocks.sim run general/parser/projection_limit_offset.sim -sleep 100 run general/parser/select_with_tags.sim -sleep 100 run general/parser/groupby.sim -sleep 100 run general/parser/tags_filter.sim -sleep 100 run general/parser/topbot.sim -sleep 100 run general/parser/union.sim -sleep 100 run general/parser/constCol.sim -sleep 100 run general/parser/where.sim -sleep 100 run general/parser/timestamp.sim -sleep 100 run general/parser/sliding.sim -sleep 100 run general/parser/function.sim -sleep 100 run general/parser/stableOp.sim -sleep 100 run general/parser/slimit_alter_tags.sim diff --git a/tests/script/general/parser/topbot.sim b/tests/script/general/parser/topbot.sim index 80a122238ec70136daa444b78764f5881563451d..e23bbf6724ea7b95a759764ac80cc2dbcdb73398 100644 --- a/tests/script/general/parser/topbot.sim +++ b/tests/script/general/parser/topbot.sim @@ -316,4 +316,13 @@ if $data13 != @20-02-02 01:01:01.000@ then return -1 endi +print ===============================>td-3361 +sql create table ttm1(ts timestamp, k int) tags(a nchar(12)); +sql create table ttm1_t1 using ttm1 tags('abcdef') +sql insert into ttm1_t1 values(now, 1) +sql select * from ttm1 where a=123456789012 +if $row != 0 then + return -1 +endi + system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file diff --git a/tests/script/general/parser/where.sim b/tests/script/general/parser/where.sim index ace1ca6f5bf1f62ecc78c676da4a9b4624f12a5c..157c41ce58ddf4775c0715f35ccd77e46a7dd221 100644 --- a/tests/script/general/parser/where.sim +++ b/tests/script/general/parser/where.sim @@ -350,5 +350,13 @@ if $rows != 0 then return -1 endi +print ==========================>td-3318 +sql create table tu(ts timestamp, k int, b binary(12)) +sql insert into tu values(now, 1, 'abc') +sql select stddev(k) from tu where b <>'abc' interval(1s) +if $rows != 0 then + return -1 +endi + system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file diff --git a/tests/script/general/table/delete_writing.sim b/tests/script/general/table/delete_writing.sim index b7350f26a70bc18023cfff6497ffddc2d5b8ced8..5351d13d80ad732b2a58953f72b3c62086b1090b 100644 --- a/tests/script/general/table/delete_writing.sim +++ b/tests/script/general/table/delete_writing.sim @@ -41,7 +41,7 @@ while $x < 15 sql create table db.tb (ts timestamp, i int) - sleep 2000 + sleep 1000 $x = $x + 1 endw diff --git a/tests/script/issue/TD-3300.sim b/tests/script/issue/TD-3300.sim new file mode 100644 index 0000000000000000000000000000000000000000..0745ceb8490567b508397b3e99d4748dc41c8971 --- /dev/null +++ b/tests/script/issue/TD-3300.sim @@ -0,0 +1,556 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/deploy.sh -n dnode2 -i 2 +system sh/deploy.sh -n dnode3 -i 3 +system sh/deploy.sh -n dnode4 -i 4 + +system sh/cfg.sh -n dnode1 -c numOfMnodes -v 1 +system sh/cfg.sh -n dnode2 -c numOfMnodes -v 1 +system sh/cfg.sh -n dnode3 -c numOfMnodes -v 1 +system sh/cfg.sh -n dnode4 -c numOfMnodes -v 1 + +system sh/cfg.sh -n dnode1 -c role -v 1 +system sh/cfg.sh -n dnode2 -c role -v 2 +system sh/cfg.sh -n dnode3 -c role -v 2 +system sh/cfg.sh -n dnode4 -c role -v 2 + +system sh/cfg.sh -n dnode1 -c arbitrator -v $arbitrator +system sh/cfg.sh -n dnode2 -c arbitrator -v $arbitrator +system sh/cfg.sh -n dnode3 -c arbitrator -v $arbitrator +system sh/cfg.sh -n dnode4 -c arbitrator -v $arbitrator + +print ============== step0: start tarbitrator +system sh/exec_tarbitrator.sh -s start + +print ============== step1: start dnode1, only deploy mnode +system sh/exec.sh -n dnode1 -s start +sql connect + +print ============== step2: start dnode2/dnode3 +system sh/exec.sh -n dnode2 -s start +system sh/exec.sh -n dnode3 -s start +sql create dnode $hostname2 +sql create dnode $hostname3 + +$x = 0 +step2: + $x = $x + 1 + sleep 1000 + if $x == 10 then + return -1 + endi + +sql show dnodes +print dnode1 $data4_1 +print dnode2 $data4_2 +print dnode3 $data4_3 + +if $data4_1 != ready then + goto step2 +endi +if $data4_2 != ready then + goto step2 +endi +if $data4_3 != ready then + goto step2 +endi + +sleep 1000 + +print ============== step3 +sql create database db replica 2 +sql use db + +sql create table stb (ts timestamp, c1 int, c2 int) tags(t1 int) +sql create table t1 using stb tags(1) +sql insert into t1 values(1577980800000, 1, 5) +sql insert into t1 values(1577980800001, 2, 4) +sql insert into t1 values(1577980800002, 3, 3) +sql insert into t1 values(1577980800003, 4, 2) +sql insert into t1 values(1577980800004, 5, 1) + +sql show db.vgroups +if $data04 != 3 then + return -1 +endi +if $data06 != 2 then + return -1 +endi +if $data05 != master then + return -1 +endi +if $data07 != slave then + return -1 +endi + +sql select * from t1 +if $rows != 5 then + return -1 +endi + +system sh/exec.sh -n dnode2 -s stop -x SIGKILL +system sh/exec.sh -n dnode3 -s stop -x SIGKILL + +print ============== step4 +system sh/exec.sh -n dnode2 -s start +system sh/exec.sh -n dnode3 -s start + +$x = 0 +step4: + $x = $x + 1 + sleep 1000 + if $x == 10 then + return -1 + endi + +sql show dnodes +print dnode1 $data4_1 +print dnode2 $data4_2 +print dnode3 $data4_3 + +if $data4_1 != ready then + goto step4 +endi +if $data4_2 != ready then + goto step4 +endi +if $data4_3 != ready then + goto step4 +endi + +sql show db.vgroups +if $data04 != 3 then + goto step4 +endi +if $data06 != 2 then + goto step4 +endi +if $data05 != master then + goto step4 +endi +if $data07 != slave then + goto step4 +endi + +sql create table t2 using stb tags(1) +sql insert into t2 values(1577980800000, 1, 5) +sql insert into t2 values(1577980800001, 2, 4) +sql insert into t2 values(1577980800002, 3, 3) +sql insert into t2 values(1577980800003, 4, 2) +sql insert into t2 values(1577980800004, 5, 1) + +sql select * from t2 +if $rows != 5 then + return -1 +endi + +print ============== step5 +system sh/exec.sh -n dnode3 -s stop -x SIGKILL + +$x = 0 +step5: + $x = $x + 1 + sleep 1000 + if $x == 10 then + return -1 + endi + +sql show dnodes +print dnode1 $data4_1 +print dnode2 $data4_2 +print dnode3 $data4_3 + +if $data4_1 != ready then + goto step5 +endi +if $data4_2 != ready then + goto step5 +endi +if $data4_3 != offline then + goto step5 +endi + +sql select * from t1 +if $rows != 5 then + return -1 +endi +sql select * from t2 +if $rows != 5 then + return -1 +endi + +sql show db.vgroups +if $data04 != 3 then + goto step5 +endi +if $data06 != 2 then + goto step5 +endi +if $data05 != offline then + goto step5 +endi +if $data07 != master then + goto step5 +endi + +print ============== step6 +sql create table t3 using stb tags(1) +sql insert into t3 values(1577980800000, 1, 5) +sql insert into t3 values(1577980800001, 2, 4) +sql insert into t3 values(1577980800002, 3, 3) +sql insert into t3 values(1577980800003, 4, 2) +sql insert into t3 values(1577980800004, 5, 1) +sql insert into t3 values(1577980800010, 11, 5) +sql insert into t3 values(1577980800011, 12, 4) +sql insert into t3 values(1577980800012, 13, 3) +sql insert into t3 values(1577980800013, 14, 2) +sql insert into t3 values(1577980800014, 15, 1) + +sql select * from t1 +if $rows != 5 then + return -1 +endi +sql select * from t2 +if $rows != 5 then + return -1 +endi +sql select * from t3 +if $rows != 10 then + return -1 +endi + +system sh/exec.sh -n dnode3 -s start + +$x = 0 +step6: + $x = $x + 1 + sleep 1000 + if $x == 10 then + return -1 + endi + +sql show dnodes +print dnode1 $data4_1 +print dnode2 $data4_2 +print dnode3 $data4_3 + +if $data4_1 != ready then + goto step6 +endi +if $data4_2 != ready then + goto step6 +endi +if $data4_3 != ready then + goto step6 +endi + +sql show db.vgroups +if $data04 != 3 then + goto step6 +endi +if $data06 != 2 then + goto step6 +endi +if $data05 != slave then + goto step6 +endi +if $data07 != master then + goto step6 +endi + +sql select * from t1 +if $rows != 5 then + return -1 +endi +sql select * from t2 +if $rows != 5 then + return -1 +endi +sql select * from t3 +if $rows != 10 then + return -1 +endi + +print ============== step7 +sql create table t4 using stb tags(1) +sql insert into t4 values(1577980800000, 1, 5) +sql insert into t4 values(1577980800001, 2, 4) +sql insert into t4 values(1577980800002, 3, 3) +sql insert into t4 values(1577980800003, 4, 2) +sql insert into t4 values(1577980800004, 5, 1) +sql insert into t4 values(1577980800010, 11, 5) +sql insert into t4 values(1577980800011, 12, 4) +sql insert into t4 values(1577980800012, 13, 3) +sql insert into t4 values(1577980800013, 14, 2) +sql insert into t4 values(1577980800014, 15, 1) +sql insert into t4 values(1577980800020, 21, 5) +sql insert into t4 values(1577980800021, 22, 4) +sql insert into t4 values(1577980800022, 23, 3) +sql insert into t4 values(1577980800023, 24, 2) +sql insert into t4 values(1577980800024, 25, 1) + +sql select * from t1 +if $rows != 5 then + return -1 +endi +sql select * from t2 +if $rows != 5 then + return -1 +endi +sql select * from t3 +if $rows != 10 then + return -1 +endi +sql select * from t4 +if $rows != 15 then + return -1 +endi + +system sh/exec.sh -n dnode2 -s stop -x SIGKILL +$x = 0 +step7: + $x = $x + 1 + sleep 1000 + if $x == 10 then + return -1 + endi + +sql show dnodes +print dnode1 $data4_1 +print dnode2 $data4_2 +print dnode3 $data4_3 + +if $data4_1 != ready then + goto step7 +endi +if $data4_2 != offline then + goto step7 +endi +if $data4_3 != ready then + goto step7 +endi + +sql show db.vgroups +if $data04 != 3 then + goto step7 +endi +if $data06 != 2 then + goto step7 +endi +if $data05 != master then + goto step7 +endi +if $data07 != offline then + goto step7 +endi + +sql select * from t1 +if $rows != 5 then + return -1 +endi +sql select * from t2 +if $rows != 5 then + return -1 +endi +sql select * from t3 +if $rows != 10 then + return -1 +endi +sql select * from t4 +if $rows != 15 then + return -1 +endi + +print ============== step8 +sql create table t5 using stb tags(1) +sql insert into t5 values(1577980800000, 1, 5) +sql insert into t5 values(1577980800001, 2, 4) +sql insert into t5 values(1577980800002, 3, 3) +sql insert into t5 values(1577980800003, 4, 2) +sql insert into t5 values(1577980800004, 5, 1) +sql insert into t5 values(1577980800010, 11, 5) + +sql select * from t1 +if $rows != 5 then + return -1 +endi +sql select * from t2 +if $rows != 5 then + return -1 +endi +sql select * from t3 +if $rows != 10 then + return -1 +endi +sql select * from t4 +if $rows != 15 then + return -1 +endi +sql select * from t5 +if $rows != 6 then + return -1 +endi + +system sh/exec.sh -n dnode2 -s start +$x = 0 +step8: + $x = $x + 1 + sleep 1000 + if $x == 10 then + return -1 + endi + +sql show dnodes +print dnode1 $data4_1 +print dnode2 $data4_2 +print dnode3 $data4_3 + +if $data4_1 != ready then + goto step8 +endi +if $data4_2 != ready then + goto step8 +endi +if $data4_3 != ready then + goto step8 +endi + +sql show db.vgroups +if $data04 != 3 then + goto step8 +endi +if $data06 != 2 then + goto step8 +endi +if $data05 != master then + goto step8 +endi +if $data07 != slave then + goto step8 +endi + +sql select * from t1 +if $rows != 5 then + return -1 +endi +sql select * from t2 +if $rows != 5 then + return -1 +endi +sql select * from t3 +if $rows != 10 then + return -1 +endi +sql select * from t4 +if $rows != 15 then + return -1 +endi +sql select * from t5 +if $rows != 6 then + return -1 +endi + +print ============== step9 +sql create table t6 using stb tags(1) +sql insert into t6 values(1577980800000, 1, 5) +sql insert into t6 values(1577980800001, 2, 4) +sql insert into t6 values(1577980800002, 3, 3) +sql insert into t6 values(1577980800003, 4, 2) +sql insert into t6 values(1577980800004, 5, 1) +sql insert into t6 values(1577980800010, 11, 5) +sql insert into t6 values(1577980800011, 12, 4) + +sql select * from t1 +if $rows != 5 then + return -1 +endi +sql select * from t2 +if $rows != 5 then + return -1 +endi +sql select * from t3 +if $rows != 10 then + return -1 +endi +sql select * from t4 +if $rows != 15 then + return -1 +endi +sql select * from t5 +if $rows != 6 then + return -1 +endi +sql select * from t6 +if $rows != 7 then + return -1 +endi + +system sh/exec.sh -n dnode3 -s stop -x SIGKILL +$x = 0 +step9: + $x = $x + 1 + sleep 1000 + if $x == 10 then + return -1 + endi + +sql show dnodes +print dnode1 $data4_1 +print dnode2 $data4_2 +print dnode3 $data4_3 + +if $data4_1 != ready then + goto step9 +endi +if $data4_2 != ready then + goto step9 +endi +if $data4_3 != offline then + goto step9 +endi + +print ============== 2 +sql show db.vgroups + +if $data04 != 3 then + goto step7 +endi +if $data06 != 2 then + goto step7 +endi +if $data05 != offline then + goto step7 +endi +if $data07 != master then + goto step7 +endi + +print ============== 3 +sql select * from t1 +if $rows != 5 then + return -1 +endi +sql select * from t2 +if $rows != 5 then + return -1 +endi +sql select * from t3 +if $rows != 10 then + return -1 +endi +sql select * from t4 +if $rows != 15 then + return -1 +endi +sql select * from t5 +if $rows != 6 then + return -1 +endi +sql select * from t6 +if $rows != 7 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop +system sh/exec.sh -n dnode2 -s stop +system sh/exec.sh -n dnode3 -s stop diff --git a/tests/script/jenkins/basic.txt b/tests/script/jenkins/basic.txt index fc56e34dca875e61cd3fc611a6757ea76e9901c9..ce770aee56c9ddb7b3a6b866e4317d09c463c8d6 100644 --- a/tests/script/jenkins/basic.txt +++ b/tests/script/jenkins/basic.txt @@ -1,76 +1,7 @@ cd ../../../debug; cmake .. cd ../../../debug; make -./test.sh -f issue/TD-2677.sim -./test.sh -f issue/TD-2680.sim -./test.sh -f issue/TD-2713.sim - -./test.sh -f general/alter/cached_schema_after_alter.sim -./test.sh -f general/alter/count.sim -./test.sh -f general/alter/dnode.sim -./test.sh -f general/alter/import.sim -./test.sh -f general/alter/insert1.sim -./test.sh -f general/alter/insert2.sim -./test.sh -f general/alter/metrics.sim -./test.sh -f general/alter/table.sim - -./test.sh -f general/cache/new_metrics.sim -./test.sh -f general/cache/restart_metrics.sim -./test.sh -f general/cache/restart_table.sim - -./test.sh -f general/connection/connection.sim - -./test.sh -f general/column/commit.sim -./test.sh -f general/column/metrics.sim -./test.sh -f general/column/table.sim - -./test.sh -f general/compress/commitlog.sim -./test.sh -f general/compress/compress.sim -./test.sh -f general/compress/compress2.sim -./test.sh -f general/compress/uncompress.sim - -./test.sh -f general/compute/avg.sim -./test.sh -f general/compute/bottom.sim -./test.sh -f general/compute/count.sim -./test.sh -f general/compute/diff.sim -./test.sh -f general/compute/diff2.sim -./test.sh -f general/compute/first.sim -./test.sh -f general/compute/interval.sim -./test.sh -f general/compute/last.sim -./test.sh -f general/compute/leastsquare.sim -./test.sh -f general/compute/max.sim -./test.sh -f general/compute/min.sim -./test.sh -f general/compute/null.sim -./test.sh -f general/compute/percentile.sim -./test.sh -f general/compute/stddev.sim -./test.sh -f general/compute/sum.sim -./test.sh -f general/compute/top.sim - -./test.sh -f general/db/alter_option.sim -./test.sh -f general/db/alter_tables_d2.sim -./test.sh -f general/db/alter_tables_v1.sim -./test.sh -f general/db/alter_tables_v4.sim -./test.sh -f general/db/alter_vgroups.sim -./test.sh -f general/db/basic.sim -./test.sh -f general/db/basic1.sim -./test.sh -f general/db/basic2.sim -./test.sh -f general/db/basic3.sim -./test.sh -f general/db/basic4.sim -./test.sh -f general/db/basic5.sim -./test.sh -f general/db/delete_reuse1.sim -./test.sh -f general/db/delete_reuse2.sim -./test.sh -f general/db/delete_reusevnode.sim -./test.sh -f general/db/delete_reusevnode2.sim -./test.sh -f general/db/delete_writing1.sim -./test.sh -f general/db/delete_writing2.sim -./test.sh -f general/db/delete.sim -./test.sh -f general/db/len.sim -./test.sh -f general/db/repeat.sim -./test.sh -f general/db/tables.sim -./test.sh -f general/db/vnodes.sim -./test.sh -f general/db/topic1.sim -./test.sh -f general/db/topic2.sim -./test.sh -f general/db/nosuchfile.sim +#======================b1-start=============== ./test.sh -f general/field/2.sim ./test.sh -f general/field/3.sim @@ -96,11 +27,6 @@ cd ../../../debug; make ./test.sh -f general/http/grafana_bug.sim ./test.sh -f general/http/grafana.sim -./test.sh -f general/import/basic.sim -./test.sh -f general/import/commit.sim -./test.sh -f general/import/large.sim -./test.sh -f general/import/replica1.sim - ./test.sh -f general/insert/basic.sim ./test.sh -f general/insert/insert_drop.sim ./test.sh -f general/insert/query_block1_memory.sim @@ -160,45 +86,12 @@ cd ../../../debug; make ./test.sh -f general/parser/repeatAlter.sim ./test.sh -f general/parser/union.sim ./test.sh -f general/parser/topbot.sim +./test.sh -f general/db/nosuchfile.sim ./test.sh -f general/parser/function.sim -./test.sh -f general/parser/select_distinct_tag.sim +./test.sh -f unique/cluster/vgroup100.sim -./test.sh -f general/stable/disk.sim -./test.sh -f general/stable/dnode3.sim -./test.sh -f general/stable/metrics.sim -./test.sh -f general/stable/refcount.sim -./test.sh -f general/stable/show.sim -./test.sh -f general/stable/values.sim -./test.sh -f general/stable/vnode3.sim - -./test.sh -f general/table/autocreate.sim -./test.sh -f general/table/basic1.sim -./test.sh -f general/table/basic2.sim -./test.sh -f general/table/basic3.sim -./test.sh -f general/table/bigint.sim -./test.sh -f general/table/binary.sim -./test.sh -f general/table/bool.sim -./test.sh -f general/table/column_name.sim -./test.sh -f general/table/column_num.sim -./test.sh -f general/table/column_value.sim -./test.sh -f general/table/column2.sim -./test.sh -f general/table/date.sim -./test.sh -f general/table/db.table.sim -./test.sh -f general/table/delete_reuse1.sim -./test.sh -f general/table/delete_reuse2.sim -./test.sh -f general/table/delete_writing.sim -./test.sh -f general/table/describe.sim -./test.sh -f general/table/double.sim -./test.sh -f general/table/fill.sim -./test.sh -f general/table/float.sim -./test.sh -f general/table/int.sim -./test.sh -f general/table/limit.sim -./test.sh -f general/table/smallint.sim -./test.sh -f general/table/table_len.sim -./test.sh -f general/table/table.sim -./test.sh -f general/table/tinyint.sim -./test.sh -f general/table/vgroup.sim -./test.sh -f general/table/createmulti.sim +#======================b1-end=============== +#======================b2-start=============== ./test.sh -f general/tag/3.sim ./test.sh -f general/tag/4.sim @@ -225,6 +118,9 @@ cd ../../../debug; make ./test.sh -f general/tag/set.sim ./test.sh -f general/tag/smallint.sim ./test.sh -f general/tag/tinyint.sim +./test.sh -f general/wal/sync.sim +./test.sh -f general/wal/kill.sim +./test.sh -f general/wal/maxtables.sim ./test.sh -f general/user/authority.sim ./test.sh -f general/user/monitor.sim @@ -245,10 +141,6 @@ cd ../../../debug; make ./test.sh -f general/vector/table_query.sim ./test.sh -f general/vector/table_time.sim -./test.sh -f general/wal/sync.sim -./test.sh -f general/wal/kill.sim -./test.sh -f general/wal/maxtables.sim - ./test.sh -f unique/account/account_create.sim ./test.sh -f unique/account/account_delete.sim ./test.sh -f unique/account/account_len.sim @@ -261,91 +153,15 @@ cd ../../../debug; make ./test.sh -f unique/account/user_create.sim ./test.sh -f unique/account/user_len.sim -./test.sh -f unique/big/balance.sim ./test.sh -f unique/big/maxvnodes.sim ./test.sh -f unique/big/tcp.sim ./test.sh -f unique/cluster/alter.sim -./test.sh -f unique/cluster/balance1.sim -./test.sh -f unique/cluster/balance2.sim -./test.sh -f unique/cluster/balance3.sim ./test.sh -f unique/cluster/cache.sim -./test.sh -f unique/cluster/vgroup100.sim - -./test.sh -f unique/column/replica3.sim - -./test.sh -f unique/db/commit.sim -./test.sh -f unique/db/delete.sim -./test.sh -f unique/db/delete_part.sim -./test.sh -f unique/db/replica_add12.sim -./test.sh -f unique/db/replica_add13.sim -./test.sh -f unique/db/replica_add23.sim -./test.sh -f unique/db/replica_reduce21.sim -./test.sh -f unique/db/replica_reduce32.sim -./test.sh -f unique/db/replica_reduce31.sim -./test.sh -f unique/db/replica_part.sim - -./test.sh -f unique/dnode/alternativeRole.sim -./test.sh -f unique/dnode/monitor.sim -./test.sh -f unique/dnode/monitor_bug.sim -./test.sh -f unique/dnode/simple.sim -./test.sh -f unique/dnode/balance1.sim -./test.sh -f unique/dnode/balance2.sim -./test.sh -f unique/dnode/balance3.sim -./test.sh -f unique/dnode/balancex.sim -./test.sh -f unique/dnode/data1.sim -./test.sh -f unique/dnode/m2.sim -./test.sh -f unique/dnode/m3.sim -./test.sh -f unique/dnode/lossdata.sim -./test.sh -f unique/dnode/offline1.sim -./test.sh -f unique/dnode/offline2.sim -./test.sh -f unique/dnode/offline3.sim -./test.sh -f unique/dnode/reason.sim -./test.sh -f unique/dnode/remove1.sim -./test.sh -f unique/dnode/remove2.sim -./test.sh -f unique/dnode/vnode_clean.sim - -./test.sh -f unique/http/admin.sim -./test.sh -f unique/http/opentsdb.sim - -./test.sh -f unique/import/replica2.sim -./test.sh -f unique/import/replica3.sim - -./test.sh -f unique/stable/balance_replica1.sim -./test.sh -f unique/stable/dnode2_stop.sim -./test.sh -f unique/stable/dnode2.sim -./test.sh -f unique/stable/dnode3.sim -./test.sh -f unique/stable/replica2_dnode4.sim -./test.sh -f unique/stable/replica2_vnode3.sim -./test.sh -f unique/stable/replica3_dnode6.sim -./test.sh -f unique/stable/replica3_vnode3.sim - -./test.sh -f unique/mnode/mgmt20.sim -./test.sh -f unique/mnode/mgmt21.sim -./test.sh -f unique/mnode/mgmt22.sim -./test.sh -f unique/mnode/mgmt23.sim -./test.sh -f unique/mnode/mgmt24.sim -./test.sh -f unique/mnode/mgmt25.sim -./test.sh -f unique/mnode/mgmt26.sim -./test.sh -f unique/mnode/mgmt30.sim -./test.sh -f unique/mnode/mgmt33.sim -./test.sh -f unique/mnode/mgmt34.sim -./test.sh -f unique/mnode/mgmtr2.sim -./test.sh -f unique/vnode/many.sim -./test.sh -f unique/vnode/replica2_basic2.sim -./test.sh -f unique/vnode/replica2_repeat.sim -./test.sh -f unique/vnode/replica3_basic.sim -./test.sh -f unique/vnode/replica3_repeat.sim -./test.sh -f unique/vnode/replica3_vgroup.sim -./test.sh -f general/stream/metrics_del.sim -./test.sh -f general/stream/metrics_replica1_vnoden.sim -./test.sh -f general/stream/restart_stream.sim -./test.sh -f general/stream/stream_3.sim -./test.sh -f general/stream/stream_restart.sim -./test.sh -f general/stream/table_del.sim -./test.sh -f general/stream/table_replica1_vnoden.sim +#======================b2-end=============== +#======================b3-start=============== ./test.sh -f unique/arbitrator/check_cluster_cfg_para.sim #./test.sh -f unique/arbitrator/dn2_mn1_cache_file_sync.sim @@ -367,7 +183,7 @@ cd ../../../debug; make ./test.sh -f unique/arbitrator/dn3_mn1_r3_vnode_delDir.sim ./test.sh -f unique/arbitrator/dn3_mn1_vnode_nomaster.sim ./test.sh -f unique/arbitrator/dn3_mn2_killDnode.sim -./test.sh -f unique/arbitrator/insert_duplicationTs.sim + ./test.sh -f unique/arbitrator/offline_replica2_alterTable_online.sim ./test.sh -f unique/arbitrator/offline_replica2_alterTag_online.sim ./test.sh -f unique/arbitrator/offline_replica2_createTable_online.sim @@ -394,7 +210,220 @@ cd ../../../debug; make ./test.sh -f unique/migrate/mn2_vn2_repl2_rmMnodeVnodeDir_stopAll_starAll.sim ./test.sh -f unique/migrate/mn2_vn2_repl2_rmVnodeDir.sim +./test.sh -f unique/stable/balance_replica1.sim +./test.sh -f unique/stable/dnode2_stop.sim +./test.sh -f unique/stable/dnode2.sim +./test.sh -f unique/stable/dnode3.sim +./test.sh -f unique/stable/replica2_dnode4.sim +./test.sh -f unique/stable/replica2_vnode3.sim +./test.sh -f unique/stable/replica3_dnode6.sim +./test.sh -f unique/stable/replica3_vnode3.sim + +#======================b3-end=============== +#======================b4-start=============== + +./test.sh -f unique/http/admin.sim +./test.sh -f unique/http/opentsdb.sim + +./test.sh -f unique/import/replica2.sim +./test.sh -f unique/import/replica3.sim + +./test.sh -f general/alter/cached_schema_after_alter.sim +./test.sh -f general/alter/count.sim +./test.sh -f general/alter/dnode.sim +./test.sh -f general/alter/import.sim +./test.sh -f general/alter/insert1.sim +./test.sh -f general/alter/insert2.sim +./test.sh -f general/alter/metrics.sim +./test.sh -f general/alter/table.sim + +./test.sh -f general/cache/new_metrics.sim +./test.sh -f general/cache/restart_metrics.sim +./test.sh -f general/cache/restart_table.sim + +./test.sh -f general/connection/connection.sim + +./test.sh -f general/column/commit.sim +./test.sh -f general/column/metrics.sim +./test.sh -f general/column/table.sim + +./test.sh -f general/compress/commitlog.sim +./test.sh -f general/compress/compress.sim +./test.sh -f general/compress/compress2.sim +./test.sh -f general/compress/uncompress.sim + +./test.sh -f general/stable/disk.sim +./test.sh -f general/stable/dnode3.sim +./test.sh -f general/stable/metrics.sim +./test.sh -f general/stable/refcount.sim +./test.sh -f general/stable/show.sim +./test.sh -f general/stable/values.sim +./test.sh -f general/stable/vnode3.sim + +./test.sh -f unique/column/replica3.sim +./test.sh -f issue/TD-2713.sim +./test.sh -f general/parser/select_distinct_tag.sim +./test.sh -f unique/mnode/mgmt30.sim +./test.sh -f issue/TD-2677.sim +./test.sh -f issue/TD-2680.sim +./test.sh -f unique/dnode/lossdata.sim + +#======================b4-end=============== +#======================b5-start=============== + +./test.sh -f unique/dnode/alternativeRole.sim +./test.sh -f unique/dnode/balance1.sim +./test.sh -f unique/dnode/balance2.sim +./test.sh -f unique/dnode/balance3.sim +./test.sh -f unique/dnode/balancex.sim +./test.sh -f unique/dnode/offline1.sim +./test.sh -f unique/dnode/offline2.sim + +./test.sh -f general/stream/metrics_del.sim +./test.sh -f general/stream/metrics_replica1_vnoden.sim +./test.sh -f general/stream/restart_stream.sim +./test.sh -f general/stream/stream_3.sim +./test.sh -f general/stream/stream_restart.sim +./test.sh -f general/stream/table_del.sim +./test.sh -f general/stream/table_replica1_vnoden.sim + ./test.sh -f general/connection/test_old_data.sim ./test.sh -f unique/dnode/datatrans_3node.sim ./test.sh -f unique/dnode/datatrans_3node_2.sim +./test.sh -f general/db/alter_tables_d2.sim +./test.sh -f general/db/alter_tables_v1.sim +./test.sh -f general/db/alter_tables_v4.sim + +#======================b5-end=============== +#======================b6-start=============== + +./test.sh -f unique/dnode/reason.sim +./test.sh -f unique/dnode/remove1.sim +./test.sh -f unique/dnode/remove2.sim +./test.sh -f unique/dnode/vnode_clean.sim + +./test.sh -f unique/db/commit.sim +./test.sh -f unique/db/delete.sim +./test.sh -f unique/db/delete_part.sim +./test.sh -f unique/db/replica_add12.sim +./test.sh -f unique/db/replica_add13.sim +./test.sh -f unique/db/replica_add23.sim +./test.sh -f unique/db/replica_reduce21.sim +./test.sh -f unique/db/replica_reduce32.sim +./test.sh -f unique/db/replica_reduce31.sim +./test.sh -f unique/db/replica_part.sim + +./test.sh -f unique/vnode/many.sim +./test.sh -f unique/vnode/replica2_basic2.sim +./test.sh -f unique/vnode/replica2_repeat.sim +./test.sh -f unique/vnode/replica3_basic.sim +./test.sh -f unique/vnode/replica3_repeat.sim +./test.sh -f unique/vnode/replica3_vgroup.sim + +./test.sh -f unique/dnode/monitor.sim +./test.sh -f unique/dnode/monitor_bug.sim +./test.sh -f unique/dnode/simple.sim +./test.sh -f unique/dnode/data1.sim +./test.sh -f unique/dnode/m2.sim +./test.sh -f unique/dnode/m3.sim +./test.sh -f unique/dnode/offline3.sim +./test.sh -f general/wal/kill.sim +./test.sh -f general/wal/maxtables.sim + +./test.sh -f general/import/basic.sim +./test.sh -f general/import/commit.sim +./test.sh -f general/import/large.sim +./test.sh -f general/import/replica1.sim +./test.sh -f unique/cluster/balance1.sim +./test.sh -f unique/cluster/balance2.sim +./test.sh -f unique/cluster/balance3.sim + +#======================b6-end=============== +#======================b7-start=============== + +./test.sh -f general/compute/avg.sim +./test.sh -f general/compute/bottom.sim +./test.sh -f general/compute/count.sim +./test.sh -f general/compute/diff.sim +./test.sh -f general/compute/diff2.sim +./test.sh -f general/compute/first.sim +./test.sh -f general/compute/interval.sim +./test.sh -f general/compute/last.sim +./test.sh -f general/compute/leastsquare.sim +./test.sh -f general/compute/max.sim +./test.sh -f general/compute/min.sim +./test.sh -f general/compute/null.sim +./test.sh -f general/compute/percentile.sim +./test.sh -f general/compute/stddev.sim +./test.sh -f general/compute/sum.sim +./test.sh -f general/compute/top.sim + +./test.sh -f general/db/alter_option.sim +./test.sh -f general/db/alter_vgroups.sim +./test.sh -f general/db/basic.sim +./test.sh -f general/db/basic1.sim +./test.sh -f general/db/basic2.sim +./test.sh -f general/db/basic3.sim +./test.sh -f general/db/basic4.sim +./test.sh -f general/db/basic5.sim +./test.sh -f general/db/delete_reuse1.sim +./test.sh -f general/db/delete_reuse2.sim +./test.sh -f general/db/delete_reusevnode.sim +./test.sh -f general/db/delete_reusevnode2.sim +./test.sh -f general/db/delete_writing1.sim +./test.sh -f general/db/delete_writing2.sim +./test.sh -f general/db/delete.sim +./test.sh -f general/db/len.sim +./test.sh -f general/db/repeat.sim +./test.sh -f general/db/tables.sim +./test.sh -f general/db/vnodes.sim +./test.sh -f general/db/topic1.sim +./test.sh -f general/db/topic2.sim +./test.sh -f general/table/autocreate.sim +./test.sh -f general/table/basic1.sim +./test.sh -f general/table/basic2.sim +./test.sh -f general/table/basic3.sim +./test.sh -f general/table/bigint.sim +./test.sh -f general/table/binary.sim +./test.sh -f general/table/bool.sim +./test.sh -f general/table/column_name.sim +./test.sh -f general/table/column_num.sim +./test.sh -f general/table/column_value.sim +./test.sh -f general/table/column2.sim +./test.sh -f general/table/date.sim +./test.sh -f general/table/db.table.sim +./test.sh -f general/table/delete_reuse1.sim +./test.sh -f general/table/delete_reuse2.sim +./test.sh -f general/table/delete_writing.sim +./test.sh -f general/table/describe.sim +./test.sh -f general/table/double.sim +./test.sh -f general/table/fill.sim +./test.sh -f general/table/float.sim +./test.sh -f general/table/int.sim +./test.sh -f general/table/limit.sim +./test.sh -f general/table/smallint.sim +./test.sh -f general/table/table_len.sim +./test.sh -f general/table/table.sim +./test.sh -f general/table/tinyint.sim +./test.sh -f general/table/vgroup.sim +./test.sh -f general/table/createmulti.sim + +./test.sh -f unique/mnode/mgmt20.sim +./test.sh -f unique/mnode/mgmt21.sim +./test.sh -f unique/mnode/mgmt22.sim +./test.sh -f unique/mnode/mgmt23.sim +./test.sh -f unique/mnode/mgmt24.sim +./test.sh -f unique/mnode/mgmt25.sim +./test.sh -f unique/mnode/mgmt26.sim +./test.sh -f unique/mnode/mgmt33.sim +./test.sh -f unique/mnode/mgmt34.sim +./test.sh -f unique/mnode/mgmtr2.sim + +./test.sh -f unique/arbitrator/insert_duplicationTs.sim +./test.sh -f general/parser/join_manyblocks.sim +./test.sh -f general/parser/stableOp.sim +./test.sh -f general/parser/timestamp.sim +./test.sh -f general/parser/sliding.sim +./test.sh -f unique/big/balance.sim +#======================b7-end=============== diff --git a/tests/script/jenkins/basic_1.txt b/tests/script/jenkins/basic_1.txt deleted file mode 100644 index ae72e76b2f6c444e84fdaee3818200983796ace3..0000000000000000000000000000000000000000 --- a/tests/script/jenkins/basic_1.txt +++ /dev/null @@ -1,85 +0,0 @@ -./test.sh -f general/field/2.sim -./test.sh -f general/field/3.sim -./test.sh -f general/field/4.sim -./test.sh -f general/field/5.sim -./test.sh -f general/field/6.sim -./test.sh -f general/field/bigint.sim -./test.sh -f general/field/binary.sim -./test.sh -f general/field/bool.sim -./test.sh -f general/field/single.sim -./test.sh -f general/field/smallint.sim -./test.sh -f general/field/tinyint.sim - -./test.sh -f general/http/autocreate.sim -./test.sh -f general/http/chunked.sim -./test.sh -f general/http/gzip.sim -./test.sh -f general/http/restful.sim -./test.sh -f general/http/restful_insert.sim -./test.sh -f general/http/restful_limit.sim -./test.sh -f general/http/restful_full.sim -./test.sh -f general/http/prepare.sim -./test.sh -f general/http/telegraf.sim -./test.sh -f general/http/grafana_bug.sim -./test.sh -f general/http/grafana.sim - -./test.sh -f general/insert/basic.sim -./test.sh -f general/insert/insert_drop.sim -./test.sh -f general/insert/query_block1_memory.sim -./test.sh -f general/insert/query_block2_memory.sim -./test.sh -f general/insert/query_block1_file.sim -./test.sh -f general/insert/query_block2_file.sim -./test.sh -f general/insert/query_file_memory.sim -./test.sh -f general/insert/query_multi_file.sim -./test.sh -f general/insert/tcp.sim - -./test.sh -f general/parser/alter.sim -./test.sh -f general/parser/alter1.sim -./test.sh -f general/parser/alter_stable.sim -./test.sh -f general/parser/auto_create_tb.sim -./test.sh -f general/parser/auto_create_tb_drop_tb.sim -./test.sh -f general/parser/col_arithmetic_operation.sim -./test.sh -f general/parser/columnValue.sim -./test.sh -f general/parser/commit.sim -./test.sh -f general/parser/create_db.sim -./test.sh -f general/parser/create_mt.sim -./test.sh -f general/parser/create_tb.sim -./test.sh -f general/parser/dbtbnameValidate.sim -./test.sh -f general/parser/import_commit1.sim -./test.sh -f general/parser/import_commit2.sim -./test.sh -f general/parser/import_commit3.sim -./test.sh -f general/parser/insert_tb.sim -./test.sh -f general/parser/first_last.sim -./test.sh -f general/parser/lastrow.sim -./test.sh -f general/parser/nchar.sim -./test.sh -f general/parser/null_char.sim -./test.sh -f general/parser/single_row_in_tb.sim -./test.sh -f general/parser/select_from_cache_disk.sim -./test.sh -f general/parser/mixed_blocks.sim -./test.sh -f general/parser/selectResNum.sim -./test.sh -f general/parser/limit.sim -./test.sh -f general/parser/limit1.sim -./test.sh -f general/parser/limit1_tblocks100.sim -./test.sh -f general/parser/select_across_vnodes.sim -./test.sh -f general/parser/slimit1.sim -./test.sh -f general/parser/tbnameIn.sim -./test.sh -f general/parser/projection_limit_offset.sim -./test.sh -f general/parser/limit2.sim -./test.sh -f general/parser/fill.sim -./test.sh -f general/parser/fill_stb.sim -./test.sh -f general/parser/where.sim -./test.sh -f general/parser/slimit.sim -./test.sh -f general/parser/select_with_tags.sim -./test.sh -f general/parser/interp.sim -./test.sh -f general/parser/tags_dynamically_specifiy.sim -./test.sh -f general/parser/groupby.sim -./test.sh -f general/parser/set_tag_vals.sim -./test.sh -f general/parser/tags_filter.sim -./test.sh -f general/parser/slimit_alter_tags.sim -./test.sh -f general/parser/join.sim -./test.sh -f general/parser/join_multivnode.sim -./test.sh -f general/parser/binary_escapeCharacter.sim -./test.sh -f general/parser/repeatAlter.sim -./test.sh -f general/parser/union.sim -./test.sh -f general/parser/topbot.sim -./test.sh -f general/db/nosuchfile.sim -./test.sh -f general/parser/function.sim \ No newline at end of file diff --git a/tests/script/jenkins/basic_2.txt b/tests/script/jenkins/basic_2.txt deleted file mode 100644 index 5a2a6f4062e9f35f9ef77222383ecfc800ea7574..0000000000000000000000000000000000000000 --- a/tests/script/jenkins/basic_2.txt +++ /dev/null @@ -1,74 +0,0 @@ -cd ../../../debug; cmake .. -cd ../../../debug; make - -./test.sh -f general/tag/3.sim -./test.sh -f general/tag/4.sim -./test.sh -f general/tag/5.sim -./test.sh -f general/tag/6.sim -./test.sh -f general/tag/add.sim -./test.sh -f general/tag/bigint.sim -./test.sh -f general/tag/binary_binary.sim -./test.sh -f general/tag/binary.sim -./test.sh -f general/tag/bool_binary.sim -./test.sh -f general/tag/bool_int.sim -./test.sh -f general/tag/bool.sim -./test.sh -f general/tag/change.sim -./test.sh -f general/tag/column.sim -./test.sh -f general/tag/commit.sim -./test.sh -f general/tag/create.sim -./test.sh -f general/tag/delete.sim -./test.sh -f general/tag/double.sim -./test.sh -f general/tag/filter.sim -./test.sh -f general/tag/float.sim -./test.sh -f general/tag/int_binary.sim -./test.sh -f general/tag/int_float.sim -./test.sh -f general/tag/int.sim -./test.sh -f general/tag/set.sim -./test.sh -f general/tag/smallint.sim -./test.sh -f general/tag/tinyint.sim -./test.sh -f general/wal/sync.sim -./test.sh -f general/wal/kill.sim -./test.sh -f general/wal/maxtables.sim - -./test.sh -f general/user/authority.sim -./test.sh -f general/user/monitor.sim -./test.sh -f general/user/pass_alter.sim -./test.sh -f general/user/pass_len.sim -./test.sh -f general/user/user_create.sim -./test.sh -f general/user/user_len.sim - -./test.sh -f general/vector/metrics_field.sim -./test.sh -f general/vector/metrics_mix.sim -./test.sh -f general/vector/metrics_query.sim -./test.sh -f general/vector/metrics_tag.sim -./test.sh -f general/vector/metrics_time.sim -./test.sh -f general/vector/multi.sim -./test.sh -f general/vector/single.sim -./test.sh -f general/vector/table_field.sim -./test.sh -f general/vector/table_mix.sim -./test.sh -f general/vector/table_query.sim -./test.sh -f general/vector/table_time.sim - -./test.sh -f unique/account/account_create.sim -./test.sh -f unique/account/account_delete.sim -./test.sh -f unique/account/account_len.sim -./test.sh -f unique/account/authority.sim -./test.sh -f unique/account/basic.sim -./test.sh -f unique/account/paras.sim -./test.sh -f unique/account/pass_alter.sim -./test.sh -f unique/account/pass_len.sim -./test.sh -f unique/account/usage.sim -./test.sh -f unique/account/user_create.sim -./test.sh -f unique/account/user_len.sim - -./test.sh -f unique/big/balance.sim -./test.sh -f unique/big/maxvnodes.sim -./test.sh -f unique/big/tcp.sim - -./test.sh -f unique/cluster/alter.sim -./test.sh -f unique/cluster/balance1.sim -./test.sh -f unique/cluster/balance2.sim -./test.sh -f unique/cluster/balance3.sim -./test.sh -f unique/cluster/cache.sim -./test.sh -f unique/cluster/vgroup100.sim - diff --git a/tests/script/jenkins/basic_3.txt b/tests/script/jenkins/basic_3.txt deleted file mode 100644 index f53b1b763a45659ce498f863a3843d27ef4b233d..0000000000000000000000000000000000000000 --- a/tests/script/jenkins/basic_3.txt +++ /dev/null @@ -1,58 +0,0 @@ - -./test.sh -f unique/arbitrator/check_cluster_cfg_para.sim -#./test.sh -f unique/arbitrator/dn2_mn1_cache_file_sync.sim -./test.sh -f unique/arbitrator/dn3_mn1_full_createTableFail.sim -./test.sh -f unique/arbitrator/dn3_mn1_multiCreateDropTable.sim -#./test.sh -f unique/arbitrator/dn3_mn1_nw_disable_timeout_autoDropDnode.sim -#./test.sh -f unique/arbitrator/dn3_mn1_replica2_wal1_AddDelDnode.sim -./test.sh -f unique/arbitrator/dn3_mn1_replica_change_dropDnod.sim -./test.sh -f unique/arbitrator/dn3_mn1_replica_change.sim -#./test.sh -f unique/arbitrator/dn3_mn1_stopDnode_timeout.sim -# lower the priority while file corruption -#./test.sh -f unique/arbitrator/dn3_mn1_vnode_change.sim -#./test.sh -f unique/arbitrator/dn3_mn1_vnode_corruptFile_offline.sim -#./test.sh -f unique/arbitrator/dn3_mn1_vnode_corruptFile_online.sim -#./test.sh -f unique/arbitrator/dn3_mn1_vnode_createErrData_online.sim -./test.sh -f unique/arbitrator/dn3_mn1_vnode_noCorruptFile_offline.sim -./test.sh -f unique/arbitrator/dn3_mn1_vnode_delDir.sim -./test.sh -f unique/arbitrator/dn3_mn1_r2_vnode_delDir.sim -./test.sh -f unique/arbitrator/dn3_mn1_r3_vnode_delDir.sim -./test.sh -f unique/arbitrator/dn3_mn1_vnode_nomaster.sim -./test.sh -f unique/arbitrator/dn3_mn2_killDnode.sim - -./test.sh -f unique/arbitrator/offline_replica2_alterTable_online.sim -./test.sh -f unique/arbitrator/offline_replica2_alterTag_online.sim -./test.sh -f unique/arbitrator/offline_replica2_createTable_online.sim -./test.sh -f unique/arbitrator/offline_replica2_dropDb_online.sim -./test.sh -f unique/arbitrator/offline_replica2_dropTable_online.sim -./test.sh -f unique/arbitrator/offline_replica3_alterTable_online.sim -./test.sh -f unique/arbitrator/offline_replica3_alterTag_online.sim -./test.sh -f unique/arbitrator/offline_replica3_createTable_online.sim -./test.sh -f unique/arbitrator/offline_replica3_dropDb_online.sim -./test.sh -f unique/arbitrator/offline_replica3_dropTable_online.sim -./test.sh -f unique/arbitrator/replica_changeWithArbitrator.sim -./test.sh -f unique/arbitrator/sync_replica2_alterTable_add.sim -./test.sh -f unique/arbitrator/sync_replica2_alterTable_drop.sim - -./test.sh -f unique/arbitrator/sync_replica2_dropDb.sim -./test.sh -f unique/arbitrator/sync_replica2_dropTable.sim -./test.sh -f unique/arbitrator/sync_replica3_alterTable_add.sim -./test.sh -f unique/arbitrator/sync_replica3_alterTable_drop.sim -./test.sh -f unique/arbitrator/sync_replica3_dropDb.sim -./test.sh -f unique/arbitrator/sync_replica3_dropTable.sim - -./test.sh -f unique/migrate/mn2_vn2_repl2_rmMnodeDir.sim -./test.sh -f unique/migrate/mn2_vn2_repl2_rmMnodeVnodeDir.sim -./test.sh -f unique/migrate/mn2_vn2_repl2_rmMnodeVnodeDir_stopAll_starAll.sim -./test.sh -f unique/migrate/mn2_vn2_repl2_rmVnodeDir.sim - -./test.sh -f unique/stable/balance_replica1.sim -./test.sh -f unique/stable/dnode2_stop.sim -./test.sh -f unique/stable/dnode2.sim -./test.sh -f unique/stable/dnode3.sim -./test.sh -f unique/stable/replica2_dnode4.sim -./test.sh -f unique/stable/replica2_vnode3.sim -./test.sh -f unique/stable/replica3_dnode6.sim -./test.sh -f unique/stable/replica3_vnode3.sim - - diff --git a/tests/script/jenkins/basic_4.txt b/tests/script/jenkins/basic_4.txt deleted file mode 100644 index 5a7d23df719f737d0c5a3c85acfd3875b87872ab..0000000000000000000000000000000000000000 --- a/tests/script/jenkins/basic_4.txt +++ /dev/null @@ -1,46 +0,0 @@ - -./test.sh -f unique/http/admin.sim -./test.sh -f unique/http/opentsdb.sim - -./test.sh -f unique/import/replica2.sim -./test.sh -f unique/import/replica3.sim - -./test.sh -f general/alter/cached_schema_after_alter.sim -./test.sh -f general/alter/count.sim -./test.sh -f general/alter/dnode.sim -./test.sh -f general/alter/import.sim -./test.sh -f general/alter/insert1.sim -./test.sh -f general/alter/insert2.sim -./test.sh -f general/alter/metrics.sim -./test.sh -f general/alter/table.sim - -./test.sh -f general/cache/new_metrics.sim -./test.sh -f general/cache/restart_metrics.sim -./test.sh -f general/cache/restart_table.sim - -./test.sh -f general/connection/connection.sim - -./test.sh -f general/column/commit.sim -./test.sh -f general/column/metrics.sim -./test.sh -f general/column/table.sim - -./test.sh -f general/compress/commitlog.sim -./test.sh -f general/compress/compress.sim -./test.sh -f general/compress/compress2.sim -./test.sh -f general/compress/uncompress.sim - -./test.sh -f general/stable/disk.sim -./test.sh -f general/stable/dnode3.sim -./test.sh -f general/stable/metrics.sim -./test.sh -f general/stable/refcount.sim -./test.sh -f general/stable/show.sim -./test.sh -f general/stable/values.sim -./test.sh -f general/stable/vnode3.sim - -./test.sh -f unique/column/replica3.sim -./test.sh -f issue/TD-2713.sim -./test.sh -f general/parser/select_distinct_tag.sim -./test.sh -f unique/mnode/mgmt30.sim -./test.sh -f issue/TD-2677.sim -./test.sh -f issue/TD-2680.sim -./test.sh -f unique/dnode/lossdata.sim \ No newline at end of file diff --git a/tests/script/jenkins/basic_5.txt b/tests/script/jenkins/basic_5.txt deleted file mode 100644 index f89be9499e7a672a3c72646614552a43d1537463..0000000000000000000000000000000000000000 --- a/tests/script/jenkins/basic_5.txt +++ /dev/null @@ -1,19 +0,0 @@ -./test.sh -f unique/dnode/alternativeRole.sim -./test.sh -f unique/dnode/balance1.sim -./test.sh -f unique/dnode/balance2.sim -./test.sh -f unique/dnode/balance3.sim -./test.sh -f unique/dnode/balancex.sim -./test.sh -f unique/dnode/offline1.sim -./test.sh -f unique/dnode/offline2.sim - -./test.sh -f general/stream/metrics_del.sim -./test.sh -f general/stream/metrics_replica1_vnoden.sim -./test.sh -f general/stream/restart_stream.sim -./test.sh -f general/stream/stream_3.sim -./test.sh -f general/stream/stream_restart.sim -./test.sh -f general/stream/table_del.sim -./test.sh -f general/stream/table_replica1_vnoden.sim - -./test.sh -f general/connection/test_old_data.sim -./test.sh -f unique/dnode/datatrans_3node.sim -./test.sh -f unique/dnode/datatrans_3node_2.sim \ No newline at end of file diff --git a/tests/script/jenkins/basic_6.txt b/tests/script/jenkins/basic_6.txt deleted file mode 100644 index 9156360a9f548ba17d9b96d297e839e6b74aaa55..0000000000000000000000000000000000000000 --- a/tests/script/jenkins/basic_6.txt +++ /dev/null @@ -1,37 +0,0 @@ -./test.sh -f unique/dnode/reason.sim -./test.sh -f unique/dnode/remove1.sim -./test.sh -f unique/dnode/remove2.sim -./test.sh -f unique/dnode/vnode_clean.sim - -./test.sh -f unique/db/commit.sim -./test.sh -f unique/db/delete.sim -./test.sh -f unique/db/delete_part.sim -./test.sh -f unique/db/replica_add12.sim -./test.sh -f unique/db/replica_add13.sim -./test.sh -f unique/db/replica_add23.sim -./test.sh -f unique/db/replica_reduce21.sim -./test.sh -f unique/db/replica_reduce32.sim -./test.sh -f unique/db/replica_reduce31.sim -./test.sh -f unique/db/replica_part.sim - -./test.sh -f unique/vnode/many.sim -./test.sh -f unique/vnode/replica2_basic2.sim -./test.sh -f unique/vnode/replica2_repeat.sim -./test.sh -f unique/vnode/replica3_basic.sim -./test.sh -f unique/vnode/replica3_repeat.sim -./test.sh -f unique/vnode/replica3_vgroup.sim - -./test.sh -f unique/dnode/monitor.sim -./test.sh -f unique/dnode/monitor_bug.sim -./test.sh -f unique/dnode/simple.sim -./test.sh -f unique/dnode/data1.sim -./test.sh -f unique/dnode/m2.sim -./test.sh -f unique/dnode/m3.sim -./test.sh -f unique/dnode/offline3.sim -./test.sh -f general/wal/kill.sim -./test.sh -f general/wal/maxtables.sim - -./test.sh -f general/import/basic.sim -./test.sh -f general/import/commit.sim -./test.sh -f general/import/large.sim -./test.sh -f general/import/replica1.sim \ No newline at end of file diff --git a/tests/script/jenkins/basic_7.txt b/tests/script/jenkins/basic_7.txt deleted file mode 100644 index d951e0a48d33f457ae8aa53dc0577f6187e4ddee..0000000000000000000000000000000000000000 --- a/tests/script/jenkins/basic_7.txt +++ /dev/null @@ -1,83 +0,0 @@ - -./test.sh -f general/compute/avg.sim -./test.sh -f general/compute/bottom.sim -./test.sh -f general/compute/count.sim -./test.sh -f general/compute/diff.sim -./test.sh -f general/compute/diff2.sim -./test.sh -f general/compute/first.sim -./test.sh -f general/compute/interval.sim -./test.sh -f general/compute/last.sim -./test.sh -f general/compute/leastsquare.sim -./test.sh -f general/compute/max.sim -./test.sh -f general/compute/min.sim -./test.sh -f general/compute/null.sim -./test.sh -f general/compute/percentile.sim -./test.sh -f general/compute/stddev.sim -./test.sh -f general/compute/sum.sim -./test.sh -f general/compute/top.sim - -./test.sh -f general/db/alter_option.sim -./test.sh -f general/db/alter_tables_d2.sim -./test.sh -f general/db/alter_tables_v1.sim -./test.sh -f general/db/alter_tables_v4.sim -./test.sh -f general/db/alter_vgroups.sim -./test.sh -f general/db/basic.sim -./test.sh -f general/db/basic1.sim -./test.sh -f general/db/basic2.sim -./test.sh -f general/db/basic3.sim -./test.sh -f general/db/basic4.sim -./test.sh -f general/db/basic5.sim -./test.sh -f general/db/delete_reuse1.sim -./test.sh -f general/db/delete_reuse2.sim -./test.sh -f general/db/delete_reusevnode.sim -./test.sh -f general/db/delete_reusevnode2.sim -./test.sh -f general/db/delete_writing1.sim -./test.sh -f general/db/delete_writing2.sim -./test.sh -f general/db/delete.sim -./test.sh -f general/db/len.sim -./test.sh -f general/db/repeat.sim -./test.sh -f general/db/tables.sim -./test.sh -f general/db/vnodes.sim -./test.sh -f general/db/topic1.sim -./test.sh -f general/db/topic2.sim -./test.sh -f general/table/autocreate.sim -./test.sh -f general/table/basic1.sim -./test.sh -f general/table/basic2.sim -./test.sh -f general/table/basic3.sim -./test.sh -f general/table/bigint.sim -./test.sh -f general/table/binary.sim -./test.sh -f general/table/bool.sim -./test.sh -f general/table/column_name.sim -./test.sh -f general/table/column_num.sim -./test.sh -f general/table/column_value.sim -./test.sh -f general/table/column2.sim -./test.sh -f general/table/date.sim -./test.sh -f general/table/db.table.sim -./test.sh -f general/table/delete_reuse1.sim -./test.sh -f general/table/delete_reuse2.sim -./test.sh -f general/table/delete_writing.sim -./test.sh -f general/table/describe.sim -./test.sh -f general/table/double.sim -./test.sh -f general/table/fill.sim -./test.sh -f general/table/float.sim -./test.sh -f general/table/int.sim -./test.sh -f general/table/limit.sim -./test.sh -f general/table/smallint.sim -./test.sh -f general/table/table_len.sim -./test.sh -f general/table/table.sim -./test.sh -f general/table/tinyint.sim -./test.sh -f general/table/vgroup.sim -./test.sh -f general/table/createmulti.sim - -./test.sh -f unique/mnode/mgmt20.sim -./test.sh -f unique/mnode/mgmt21.sim -./test.sh -f unique/mnode/mgmt22.sim -./test.sh -f unique/mnode/mgmt23.sim -./test.sh -f unique/mnode/mgmt24.sim -./test.sh -f unique/mnode/mgmt25.sim -./test.sh -f unique/mnode/mgmt26.sim -./test.sh -f unique/mnode/mgmt33.sim -./test.sh -f unique/mnode/mgmt34.sim -./test.sh -f unique/mnode/mgmtr2.sim - -./test.sh -f unique/arbitrator/insert_duplicationTs.sim \ No newline at end of file diff --git a/tests/test-all.sh b/tests/test-all.sh index db9d6523a0eced09407f958e0adee9a4a8087bf1..b5e23c1506ed6d7deb7e9acaf7d3f3c182861ba6 100755 --- a/tests/test-all.sh +++ b/tests/test-all.sh @@ -24,13 +24,19 @@ function stopTaosd { function dohavecore(){ corefile=`find $corepath -mmin 1` + core_file=`echo $corefile|cut -d " " -f2` + echo $core_file + proc=`echo $corefile|cut -d "_" -f3` if [ -n "$corefile" ];then - echo 'taosd or taos has generated core' - if [[ $1 == 1 ]];then - exit 8 - fi + echo 'taosd or taos has generated core' + tar -zcPf $corepath'taos_'`date "+%Y_%m_%d_%H_%M_%S"`.tar.gz /usr/local/taos/ + if [[ $1 == 1 ]];then + echo '\n'|gdb /usr/local/taos/bin/$proc $core_file -ex "bt 10" -ex quit + exit 8 + fi fi } + function runSimCaseOneByOne { while read -r line; do if [[ $line =~ ^./test.sh* ]] || [[ $line =~ ^run* ]]; then @@ -61,7 +67,11 @@ function runSimCaseOneByOne { done < $1 } function runSimCaseOneByOnefq { - while read -r line; do + + start=`sed -n "/$1-start/=" jenkins/basic.txt` + end=`sed -n "/$1-end/=" jenkins/basic.txt` + for ((i=$start;i<=$end;i++)) ; do + line=`sed -n "$i"p jenkins/basic.txt` if [[ $line =~ ^./test.sh* ]] || [[ $line =~ ^run* ]]; then case=`echo $line | grep sim$ |awk '{print $NF}'` @@ -69,32 +79,36 @@ function runSimCaseOneByOnefq { date +%F\ %T | tee -a out.log if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]]; then echo -n $case - ./test.sh -f $case > /dev/null 2>&1 && \ + ./test.sh -f $case > ../../../sim/case.log 2>&1 && \ ( grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \ ( grep -q 'script.*success.*m$' ../../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \ - echo -e "${RED} failed${NC}" | tee -a out.log + ( echo -e "${RED} failed${NC}" | tee -a out.log && echo '=====================log=====================' && cat ../../../sim/case.log ) else echo -n $case - ./test.sh -f $case > /dev/null 2>&1 && \ + ./test.sh -f $case > ../../sim/case.log 2>&1 && \ ( grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \ ( grep -q 'script.*success.*m$' ../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \ - echo -e "${RED} failed${NC}" | tee -a out.log + ( echo -e "${RED} failed${NC}" | tee -a out.log && echo '=====================log=====================' && cat ../../sim/case.log ) fi out_log=`tail -1 out.log ` if [[ $out_log =~ 'failed' ]];then if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]]; then cp -r ../../../sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S"` + rm -rf ../../../sim/case.log else cp -r ../../sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S" ` + rm -rf ../../sim/case.log fi exit 8 fi end_time=`date +%s` echo execution time of $case was `expr $end_time - $start_time`s. | tee -a out.log - dohavecore 1 + dohavecore $2 fi - done < $1 + done + rm -rf ../../../sim/case.log + rm -rf ../../sim/case.log } function runPyCaseOneByOne { @@ -126,8 +140,17 @@ function runPyCaseOneByOne { fi done < $1 } -function runPyCaseOneByOnefq { - while read -r line; do +function runPyCaseOneByOnefq() { + cd $tests_dir/pytest + if [[ $1 =~ full ]] ; then + start=1 + end=`sed -n '$=' fulltest.sh` + else + start=`sed -n "/$1-start/=" fulltest.sh` + end=`sed -n "/$1-end/=" fulltest.sh` + fi + for ((i=$start;i<=$end;i++)) ; do + line=`sed -n "$i"p fulltest.sh` if [[ $line =~ ^python.* ]]; then if [[ $line != *sleep* ]]; then @@ -139,22 +162,26 @@ function runPyCaseOneByOnefq { start_time=`date +%s` date +%F\ %T | tee -a pytest-out.log echo -n $case - $line > /dev/null 2>&1 && \ + $line > ../../sim/case.log 2>&1 && \ echo -e "${GREEN} success${NC}" | tee -a pytest-out.log || \ - echo -e "${RED} failed${NC}" | tee -a pytest-out.log + echo -e "${RED} failed${NC}" | tee -a pytest-out.log end_time=`date +%s` out_log=`tail -1 pytest-out.log ` if [[ $out_log =~ 'failed' ]];then cp -r ../../sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S" ` + echo '=====================log=====================' + cat ../../sim/case.log + rm -rf ../../sim/case.log exit 8 fi echo execution time of $case was `expr $end_time - $start_time`s. | tee -a pytest-out.log else $line > /dev/null 2>&1 fi - dohavecore 1 + dohavecore $2 fi - done < $1 + done + rm -rf ../../sim/case.log } totalFailed=0 @@ -176,38 +203,38 @@ if [ "$2" != "jdbc" ] && [ "$2" != "python" ] && [ "$2" != "unit" ]; then runSimCaseOneByOne jenkins/basic.txt elif [ "$1" == "b1" ]; then echo "### run TSIM b1 test ###" - runSimCaseOneByOne jenkins/basic_1.txt - runSimCaseOneByOne jenkins/basic_4.txt - runSimCaseOneByOne jenkins/basic_5.txt - runSimCaseOneByOne jenkins/basic_6.txt - runSimCaseOneByOne jenkins/basic_7.txt + runSimCaseOneByOnefq b1 0 + runSimCaseOneByOnefq b4 0 + runSimCaseOneByOnefq b5 0 + runSimCaseOneByOnefq b6 0 + runSimCaseOneByOnefq b7 0 elif [ "$1" == "b2" ]; then echo "### run TSIM b2 test ###" - runSimCaseOneByOne jenkins/basic_2.txt + runSimCaseOneByOnefq b2 0 elif [ "$1" == "b3" ]; then echo "### run TSIM b3 test ###" - runSimCaseOneByOne jenkins/basic_3.txt + runSimCaseOneByOnefq b3 0 elif [ "$1" == "b1fq" ]; then echo "### run TSIM b1 test ###" - runSimCaseOneByOnefq jenkins/basic_1.txt + runSimCaseOneByOnefq b1 1 elif [ "$1" == "b2fq" ]; then echo "### run TSIM b2 test ###" - runSimCaseOneByOnefq jenkins/basic_2.txt + runSimCaseOneByOnefq b2 1 elif [ "$1" == "b3fq" ]; then echo "### run TSIM b3 test ###" - runSimCaseOneByOnefq jenkins/basic_3.txt + runSimCaseOneByOnefq b3 1 elif [ "$1" == "b4fq" ]; then echo "### run TSIM b4 test ###" - runSimCaseOneByOnefq jenkins/basic_4.txt + runSimCaseOneByOnefq b4 1 elif [ "$1" == "b5fq" ]; then echo "### run TSIM b5 test ###" - runSimCaseOneByOnefq jenkins/basic_5.txt + runSimCaseOneByOnefq b5 1 elif [ "$1" == "b6fq" ]; then echo "### run TSIM b6 test ###" - runSimCaseOneByOnefq jenkins/basic_6.txt + runSimCaseOneByOnefq b6 1 elif [ "$1" == "b7fq" ]; then echo "### run TSIM b7 test ###" - runSimCaseOneByOnefq jenkins/basic_7.txt + runSimCaseOneByOnefq b7 1 elif [ "$1" == "smoke" ] || [ -z "$1" ]; then echo "### run TSIM smoke test ###" runSimCaseOneByOne basicSuite.sim @@ -268,19 +295,19 @@ if [ "$2" != "sim" ] && [ "$2" != "jdbc" ] && [ "$2" != "unit" ]; then runPyCaseOneByOne fulltest.sh elif [ "$1" == "pytestfq" ]; then echo "### run Python full test ###" - runPyCaseOneByOnefq fulltest.sh + runPyCaseOneByOnefq full 0 elif [ "$1" == "p1" ]; then echo "### run Python_1 test ###" - runPyCaseOneByOnefq pytest_1.sh + runPyCaseOneByOnefq p1 1 elif [ "$1" == "p2" ]; then echo "### run Python_2 test ###" - runPyCaseOneByOnefq pytest_2.sh + runPyCaseOneByOnefq p2 1 elif [ "$1" == "p3" ]; then echo "### run Python_3 test ###" - runPyCaseOneByOnefq pytest_3.sh + runPyCaseOneByOnefq p3 1 elif [ "$1" == "p4" ]; then echo "### run Python_4 test ###" - runPyCaseOneByOnefq pytest_4.sh + runPyCaseOneByOnefq p4 1 elif [ "$1" == "b2" ] || [ "$1" == "b3" ]; then exit $(($totalFailed + $totalPyFailed)) elif [ "$1" == "smoke" ] || [ -z "$1" ]; then