diff --git a/.drone.yml b/.drone.yml index f7ee4e976f..b520f308ba 100644 --- a/.drone.yml +++ b/.drone.yml @@ -25,15 +25,14 @@ steps: - master --- kind: pipeline -name: test_arm64 +name: test_arm64_bionic platform: os: linux arch: arm64 - steps: - name: build - image: gcc + image: arm64v8/ubuntu:bionic commands: - apt-get update - apt-get install -y cmake build-essential @@ -48,9 +47,87 @@ steps: branch: - develop - master + - 2.0 --- kind: pipeline -name: test_arm +name: test_arm64_focal + +platform: + os: linux + arch: arm64 + +steps: +- name: build + image: arm64v8/ubuntu:focal + commands: + - echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections + - apt-get update + - apt-get install -y -qq cmake build-essential + - mkdir debug + - cd debug + - cmake .. -DCPUTYPE=aarch64 > /dev/null + - make + trigger: + event: + - pull_request + when: + branch: + - develop + - master + - 2.0 +--- +kind: pipeline +name: test_arm64_centos7 + +platform: + os: linux + arch: arm64 + +steps: +- name: build + image: arm64v8/centos:7 + commands: + - yum install -y gcc gcc-c++ make cmake git + - mkdir debug + - cd debug + - cmake .. -DCPUTYPE=aarch64 > /dev/null + - make + trigger: + event: + - pull_request + when: + branch: + - develop + - master + - 2.0 +--- +kind: pipeline +name: test_arm64_centos8 + +platform: + os: linux + arch: arm64 + +steps: +- name: build + image: arm64v8/centos:8 + commands: + - dnf install -y gcc gcc-c++ make cmake epel-release git libarchive + - mkdir debug + - cd debug + - cmake .. -DCPUTYPE=aarch64 > /dev/null + - make + trigger: + event: + - pull_request + when: + branch: + - develop + - master + - 2.0 +--- +kind: pipeline +name: test_arm_bionic platform: os: linux @@ -73,7 +150,6 @@ steps: branch: - develop - master - --- kind: pipeline name: build_trusty @@ -174,25 +250,3 @@ steps: - develop - master ---- -kind: pipeline -name: goodbye - -platform: - os: linux - arch: amd64 - -steps: -- name: 64-bit - image: alpine - commands: - - echo 64-bit is good. - when: - branch: - - develop - - master - - -depends_on: -- test_arm64 -- test_amd64 \ No newline at end of file diff --git a/alert/app/app.go b/alert/app/app.go index 760f93d839..68a6aa4059 100644 --- a/alert/app/app.go +++ b/alert/app/app.go @@ -1,3 +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 . + */ + package app import ( diff --git a/alert/app/expr/expr.go b/alert/app/expr/expr.go index 42cb506f0e..dec6ce71a3 100644 --- a/alert/app/expr/expr.go +++ b/alert/app/expr/expr.go @@ -1,3 +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 . + */ + package expr import ( diff --git a/alert/app/expr/expr_test.go b/alert/app/expr/expr_test.go index 0228268771..db2d5bf22a 100644 --- a/alert/app/expr/expr_test.go +++ b/alert/app/expr/expr_test.go @@ -1,3 +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 . + */ + package expr import "testing" diff --git a/alert/app/expr/funcs.go b/alert/app/expr/funcs.go index 97ed0e1c64..3535e0d014 100644 --- a/alert/app/expr/funcs.go +++ b/alert/app/expr/funcs.go @@ -1,3 +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 . + */ + package expr import ( diff --git a/alert/app/expr/funcs_test.go b/alert/app/expr/funcs_test.go index b960888b25..68d4c24703 100644 --- a/alert/app/expr/funcs_test.go +++ b/alert/app/expr/funcs_test.go @@ -1,3 +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 . + */ + package expr import ( diff --git a/alert/app/route.go b/alert/app/route.go index 0fec3bab34..467e7b38c4 100644 --- a/alert/app/route.go +++ b/alert/app/route.go @@ -1,3 +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 . + */ + package app import ( diff --git a/alert/app/rule.go b/alert/app/rule.go index 236e5bd755..e318edab2a 100644 --- a/alert/app/rule.go +++ b/alert/app/rule.go @@ -1,3 +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 . + */ + package app import ( diff --git a/alert/app/rule_test.go b/alert/app/rule_test.go index 0adf100e9c..2b732f7153 100644 --- a/alert/app/rule_test.go +++ b/alert/app/rule_test.go @@ -1,3 +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 . + */ + package app import ( diff --git a/alert/cmd/alert/main.go b/alert/cmd/alert/main.go index 1bd185b580..5a5e5c6df6 100644 --- a/alert/cmd/alert/main.go +++ b/alert/cmd/alert/main.go @@ -1,3 +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 . + */ + package main import ( diff --git a/alert/models/models.go b/alert/models/models.go index 5d6de5572c..57b2737c62 100644 --- a/alert/models/models.go +++ b/alert/models/models.go @@ -1,3 +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 . + */ + package models import ( diff --git a/alert/models/rule.go b/alert/models/rule.go index 53d45f45da..759f9aad80 100644 --- a/alert/models/rule.go +++ b/alert/models/rule.go @@ -1,3 +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 . + */ + package models import "time" diff --git a/alert/utils/config.go b/alert/utils/config.go index 71b9dd16e1..7ee6306891 100644 --- a/alert/utils/config.go +++ b/alert/utils/config.go @@ -1,3 +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 . + */ + package utils import ( diff --git a/alert/utils/log/log.go b/alert/utils/log/log.go index 5f49c213ae..c7e2c56973 100644 --- a/alert/utils/log/log.go +++ b/alert/utils/log/log.go @@ -1,3 +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 . + */ + package log import ( diff --git a/cmake/version.inc b/cmake/version.inc index 7c0a824c9c..ffceecf492 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.1.5.0") + SET(TD_VER_NUMBER "2.1.6.0") ENDIF () IF (DEFINED VERCOMPATIBLE) diff --git a/documentation20/cn/09.connections/docs.md b/documentation20/cn/09.connections/docs.md index b47f297ae0..7a13270830 100644 --- a/documentation20/cn/09.connections/docs.md +++ b/documentation20/cn/09.connections/docs.md @@ -3,17 +3,17 @@ ## Grafana -TDengine能够与开源数据可视化系统[Grafana](https://www.grafana.com/)快速集成搭建数据监测报警系统,整个过程无需任何代码开发,TDengine中数据表中内容可以在仪表盘(DashBoard)上进行可视化展现。 +TDengine 能够与开源数据可视化系统 [Grafana](https://www.grafana.com/)快速集成搭建数据监测报警系统,整个过程无需任何代码开发,TDengine 中数据表中内容可以在仪表盘(DashBoard)上进行可视化展现。 ### 安装Grafana -目前TDengine支持Grafana 5.2.4以上的版本。用户可以根据当前的操作系统,到Grafana官网下载安装包,并执行安装。下载地址如下:https://grafana.com/grafana/download。 +目前 TDengine 支持 Grafana 6.2 以上的版本。用户可以根据当前的操作系统,到 Grafana 官网下载安装包,并执行安装。下载地址如下:https://grafana.com/grafana/download。 ### 配置Grafana -TDengine的Grafana插件在安装包的/usr/local/taos/connector/grafanaplugin目录下。 +TDengine 的 Grafana 插件在安装包的 /usr/local/taos/connector/grafanaplugin 目录下。 -以CentOS 7.2操作系统为例,将grafanaplugin目录拷贝到/var/lib/grafana/plugins目录下,重新启动grafana即可。 +以 CentOS 7.2 操作系统为例,将 grafanaplugin 目录拷贝到 /var/lib/grafana/plugins 目录下,重新启动 grafana 即可。 ```bash sudo cp -rf /usr/local/taos/connector/grafanaplugin /var/lib/grafana/plugins/tdengine diff --git a/documentation20/cn/11.administrator/docs.md b/documentation20/cn/11.administrator/docs.md index b37916d790..2eb4ac50cc 100644 --- a/documentation20/cn/11.administrator/docs.md +++ b/documentation20/cn/11.administrator/docs.md @@ -427,7 +427,7 @@ TDengine启动后,会自动创建一个监测数据库log,并自动将服务 COMPACT VNODES IN (vg_id1, vg_id2, ...) ``` -COMPACT 命令对指定的一个或多个 VGroup 启动碎片重整,系统会通过任务队列尽快安排重整操作的具体执行。COMPACT 指令所需的 VGroup id,可以通过 `SHOW VGROUPS;` 指令的输出结果获取;而且在 `SHOW VGROUPS;` 中会有一个 compacting 列,值为 1 时表示对应的 VGroup 正在进行碎片重整,为 0 时则表示并没有处于重整状态。 +COMPACT 命令对指定的一个或多个 VGroup 启动碎片重整,系统会通过任务队列尽快安排重整操作的具体执行。COMPACT 指令所需的 VGroup id,可以通过 `SHOW VGROUPS;` 指令的输出结果获取;而且在 `SHOW VGROUPS;` 中会有一个 compacting 列,值为 2 时表示对应的 VGroup 处于排队等待进行重整的状态,值为 1 时表示正在进行碎片重整,为 0 时则表示并没有处于重整状态(未要求进行重整或已经完成重整)。 需要注意的是,碎片重整操作会大幅消耗磁盘 I/O。因此在重整进行期间,有可能会影响节点的写入和查询性能,甚至在极端情况下导致短时间的阻写。 diff --git a/documentation20/cn/12.taos-sql/docs.md b/documentation20/cn/12.taos-sql/docs.md index 97b89f3446..ed5c282da1 100644 --- a/documentation20/cn/12.taos-sql/docs.md +++ b/documentation20/cn/12.taos-sql/docs.md @@ -182,7 +182,7 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传 - **批量创建数据表** ```mysql - CREATE TABLE [IF NOT EXISTS] tb_name1 USING stb_name TAGS (tag_value1, ...) tb_name2 USING stb_name TAGS (tag_value2, ...) ...; + CREATE TABLE [IF NOT EXISTS] tb_name1 USING stb_name TAGS (tag_value1, ...) [IF NOT EXISTS] tb_name2 USING stb_name TAGS (tag_value2, ...) ...; ``` 以更快的速度批量创建大量数据表(服务器端 2.0.14 及以上版本)。 diff --git a/documentation20/en/12.taos-sql/docs.md b/documentation20/en/12.taos-sql/docs.md index 2f344b4529..dfa1742c99 100644 --- a/documentation20/en/12.taos-sql/docs.md +++ b/documentation20/en/12.taos-sql/docs.md @@ -165,7 +165,7 @@ Note: - **Create tables in batches** ```mysql - CREATE TABLE [IF NOT EXISTS] tb_name1 USING stb_name TAGS (tag_value1, ...) tb_name2 USING stb_name TAGS (tag_value2, ...) ...; + CREATE TABLE [IF NOT EXISTS] tb_name1 USING stb_name TAGS (tag_value1, ...) [IF NOT EXISTS] tb_name2 USING stb_name TAGS (tag_value2, ...) ...; ``` Create a large number of data tables in batches faster. (Server side 2.0. 14 and above) diff --git a/importSampleData/app/main.go b/importSampleData/app/main.go index 5fee49734d..e45e33e159 100644 --- a/importSampleData/app/main.go +++ b/importSampleData/app/main.go @@ -1,3 +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 . + */ + package main import ( diff --git a/importSampleData/import/import_config.go b/importSampleData/import/import_config.go index fdaeeab7da..68587a3519 100644 --- a/importSampleData/import/import_config.go +++ b/importSampleData/import/import_config.go @@ -1,3 +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 . + */ + package dataimport import ( diff --git a/packaging/cfg/taos.cfg b/packaging/cfg/taos.cfg index bbe6eae419..3ae4e9941e 100644 --- a/packaging/cfg/taos.cfg +++ b/packaging/cfg/taos.cfg @@ -144,6 +144,9 @@ keepColumnName 1 # max length of an SQL # maxSQLLength 65480 +# max length of WildCards +# maxWildCardsLength 100 + # the maximum number of records allowed for super table time sorting # maxNumOfOrderedRes 100000 diff --git a/packaging/docker/dockerManifest.sh b/packaging/docker/dockerManifest.sh index 9c5a618f34..98abe4e099 100755 --- a/packaging/docker/dockerManifest.sh +++ b/packaging/docker/dockerManifest.sh @@ -44,7 +44,8 @@ echo "version=${version}" #docker manifest rm tdengine/tdengine #docker manifest rm tdengine/tdengine:${version} if [ "$verType" == "beta" ]; then - docker manifest rm tdengine/tdengine:latest + docker manifest inspect tdengine/tdengine-beta:latest + docker manifest rm tdengine/tdengine-beta:latest docker manifest create -a tdengine/tdengine-beta:${version} tdengine/tdengine-amd64-beta:${version} tdengine/tdengine-aarch64-beta:${version} tdengine/tdengine-aarch32-beta:${version} docker manifest create -a tdengine/tdengine-beta:latest tdengine/tdengine-amd64-beta:latest tdengine/tdengine-aarch64-beta:latest tdengine/tdengine-aarch32-beta:latest docker login -u tdengine -p ${passWord} #replace the docker registry username and password @@ -52,6 +53,7 @@ if [ "$verType" == "beta" ]; then docker manifest push tdengine/tdengine-beta:${version} elif [ "$verType" == "stable" ]; then + docker manifest inspect tdengine/tdengine:latest docker manifest rm tdengine/tdengine:latest docker manifest create -a tdengine/tdengine:${version} tdengine/tdengine-amd64:${version} tdengine/tdengine-aarch64:${version} tdengine/tdengine-aarch32:${version} docker manifest create -a tdengine/tdengine:latest tdengine/tdengine-amd64:latest tdengine/tdengine-aarch64:latest tdengine/tdengine-aarch32:latest diff --git a/packaging/tools/makepkg.sh b/packaging/tools/makepkg.sh index 1064f0b0e5..e9266ec80d 100755 --- a/packaging/tools/makepkg.sh +++ b/packaging/tools/makepkg.sh @@ -35,7 +35,7 @@ fi if [ "$pagMode" == "lite" ]; then strip ${build_dir}/bin/taosd strip ${build_dir}/bin/taos - bin_files="${build_dir}/bin/taosd ${build_dir}/bin/taos ${script_dir}/remove.sh" + bin_files="${build_dir}/bin/taosd ${build_dir}/bin/taos ${script_dir}/remove.sh ${script_dir}/startPre.sh" else bin_files="${build_dir}/bin/taosd ${build_dir}/bin/taos ${build_dir}/bin/taosdump ${build_dir}/bin/taosdemo ${build_dir}/bin/tarbitrator\ ${script_dir}/remove.sh ${script_dir}/set_core.sh ${script_dir}/startPre.sh ${script_dir}/taosd-dump-cfg.gdb" diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index aef706311d..c04fa3298b 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,6 +1,6 @@ name: tdengine base: core18 -version: '2.1.5.0' +version: '2.1.6.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.1.5.0 + - usr/lib/libtaos.so.2.1.6.0 - usr/lib/libtaos.so.1 - usr/lib/libtaos.so diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h index 401da65908..b74fe29a61 100644 --- a/src/client/inc/tscUtil.h +++ b/src/client/inc/tscUtil.h @@ -61,6 +61,7 @@ typedef struct SJoinSupporter { uint64_t uid; // query table uid SArray* colList; // previous query information, no need to use this attribute, and the corresponding attribution SArray* exprList; + SArray* colCond; SFieldInfo fieldsInfo; STagCond tagCond; SGroupbyExpr groupInfo; // group by info @@ -244,8 +245,9 @@ SCond* tsGetSTableQueryCond(STagCond* pCond, uint64_t uid); void tsSetSTableQueryCond(STagCond* pTagCond, uint64_t uid, SBufferWriter* bw); int32_t tscTagCondCopy(STagCond* dest, const STagCond* src); +int32_t tscColCondCopy(SArray** dest, const SArray* src, uint64_t uid, int16_t tidx); void tscTagCondRelease(STagCond* pCond); - +void tscColCondRelease(SArray** pCond); void tscGetSrcColumnInfo(SSrcColumnInfo* pColInfo, SQueryInfo* pQueryInfo); bool tscShouldBeFreed(SSqlObj* pSql); @@ -355,6 +357,7 @@ char* strdup_throw(const char* str); bool vgroupInfoIdentical(SNewVgroupInfo *pExisted, SVgroupMsg* src); SNewVgroupInfo createNewVgroupInfo(SVgroupMsg *pVgroupMsg); +STblCond* tsGetTableFilter(SArray* filters, uint64_t uid, int16_t idx); void tscRemoveCachedTableMeta(STableMetaInfo* pTableMetaInfo, uint64_t id); diff --git a/src/client/src/tscAsync.c b/src/client/src/tscAsync.c index 1c198fb8c6..eaad783331 100644 --- a/src/client/src/tscAsync.c +++ b/src/client/src/tscAsync.c @@ -339,6 +339,11 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) { const char* msg = (sub->cmd.command == TSDB_SQL_STABLEVGROUP)? "vgroup-list":"multi-tableMeta"; if (code != TSDB_CODE_SUCCESS) { tscError("0x%"PRIx64" get %s failed, code:%s", pSql->self, msg, tstrerror(code)); + if (code == TSDB_CODE_RPC_FQDN_ERROR) { + size_t sz = strlen(tscGetErrorMsgPayload(&sub->cmd)); + tscAllocPayload(&pSql->cmd, (int)sz + 1); + memcpy(tscGetErrorMsgPayload(&pSql->cmd), tscGetErrorMsgPayload(&sub->cmd), sz); + } goto _error; } diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 8f8ed6ae5e..d6df43af68 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -39,6 +39,7 @@ #include "ttokendef.h" #include "qScript.h" #include "ttype.h" +#include "qFilter.h" #define DEFAULT_PRIMARY_TIMESTAMP_COL_NAME "_c0" @@ -87,7 +88,6 @@ static uint8_t convertRelationalOperator(SStrToken *pToken); static int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pSelNodeList, 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 twQuery); @@ -141,6 +141,7 @@ static int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlE static bool validateDebugFlag(int32_t v); static int32_t checkQueryRangeForFill(SSqlCmd* pCmd, SQueryInfo* pQueryInfo); static int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo); +static tSqlExpr* extractExprForSTable(SSqlCmd* pCmd, tSqlExpr** pExpr, SQueryInfo* pQueryInfo, int32_t tableIndex); static bool isTimeWindowQuery(SQueryInfo* pQueryInfo) { return pQueryInfo->interval.interval > 0 || pQueryInfo->sessionWindow.gap > 0; @@ -184,6 +185,9 @@ bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType, if (var->nType != TSDB_DATA_TYPE_BOOL && !IS_SIGNED_NUMERIC_TYPE(var->nType)) { break; } + if (colType == TSDB_DATA_TYPE_BOOL && (var->i64 > 1 ||var->i64 < 0)) { + break; + } tbufWriteInt64(&bw, var->i64); } else if (IS_UNSIGNED_NUMERIC_TYPE(colType)) { if (IS_SIGNED_NUMERIC_TYPE(var->nType) || IS_UNSIGNED_NUMERIC_TYPE(var->nType)) { @@ -3218,9 +3222,8 @@ int32_t setShowInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { pCmd->command = TSDB_SQL_SHOW; const char* msg1 = "invalid name"; - const char* msg2 = "pattern filter string too long"; + const char* msg2 = "wildcard string should be less than %d characters"; const char* msg3 = "database name too long"; - const char* msg4 = "invalid ip address"; const char* msg5 = "database name is empty"; const char* msg6 = "pattern string is empty"; @@ -3262,23 +3265,19 @@ int32_t setShowInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); } - if (!tscValidateTableNameLength(pCmd->payloadLen)) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); + if (pPattern->n > tsMaxWildCardsLen){ + char tmp[64] = {0}; + sprintf(tmp, msg2, tsMaxWildCardsLen); + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), tmp); } } } else if (showType == TSDB_MGMT_TABLE_VNODES) { if (pShowInfo->prefix.type == 0) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "No specified ip of dnode"); + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "No specified dnode ep"); } - // show vnodes may be ip addr of dnode in payload - SStrToken* pDnodeIp = &pShowInfo->prefix; - if (pDnodeIp->n >= TSDB_IPv4ADDR_LEN) { // ip addr is too long - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); - } - - if (!validateIpAddress(pDnodeIp->z, pDnodeIp->n)) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4); + if (pShowInfo->prefix.type == TK_STRING) { + pShowInfo->prefix.n = strdequote(pShowInfo->prefix.z); } } return TSDB_CODE_SUCCESS; @@ -3331,16 +3330,6 @@ static int32_t setCompactVnodeInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { return TSDB_CODE_SUCCESS; } -bool validateIpAddress(const char* ip, size_t size) { - char tmp[128] = {0}; // buffer to build null-terminated string - assert(size < 128); - - strncpy(tmp, ip, size); - - in_addr_t epAddr = taosInetAddr(tmp); - - return epAddr != INADDR_NONE; -} int32_t tscTansformFuncForSTableQuery(SQueryInfo* pQueryInfo) { STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); @@ -3751,8 +3740,8 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, 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, bufLen * TSDB_NCHAR_SIZE); + // bufLen + 1 is larger than the actual nchar string length + pColumnFilter->pz = (int64_t)calloc(1, (bufLen + 1) * 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; @@ -3858,51 +3847,40 @@ static int32_t tablenameCondToString(tSqlExpr* pExpr, SStringBuilder* sb) { } enum { - TSQL_EXPR_TS = 0, - TSQL_EXPR_TAG = 1, - TSQL_EXPR_COLUMN = 2, - TSQL_EXPR_TBNAME = 3, + TSQL_EXPR_TS = 1, + TSQL_EXPR_TAG = 2, + TSQL_EXPR_COLUMN = 4, + TSQL_EXPR_TBNAME = 8, + TSQL_EXPR_JOIN = 16, }; -static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnIndex* pIndex, tSqlExpr* pExpr, int32_t sqlOptr) { +#define GET_MIXED_TYPE(t) (((t) >= TSQL_EXPR_JOIN) || ((t) > TSQL_EXPR_COLUMN && (t) < TSQL_EXPR_TBNAME) || ((t) == (TSQL_EXPR_TS|TSQL_EXPR_TAG))) + +static int32_t checkColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnIndex* pIndex, tSqlExpr* pExpr, int32_t sqlOptr) { STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, pIndex->tableIndex); STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, pIndex->columnIndex); - + int32_t ret = 0; const char* msg1 = "non binary column not support like operator"; const char* msg2 = "binary column not support this operator"; const char* msg3 = "bool column not support this operator"; const char* msg4 = "primary key not support this operator"; SColumn* pColumn = tscColumnListInsert(pQueryInfo->colList, pIndex->columnIndex, pTableMeta->id.uid, pSchema); - SColumnFilterInfo* pColFilter = NULL; + pColumn->info.flist.numOfFilters++; + /* * in case of TK_AND filter condition, we first find the corresponding column and build the query condition together * the already existed condition. */ - if (sqlOptr == TK_AND) { - // this is a new filter condition on this column - if (pColumn->info.flist.numOfFilters == 0) { - pColFilter = addColumnFilterInfo(&pColumn->info.flist); - } else { // update the existed column filter information, find the filter info here - pColFilter = &pColumn->info.flist.filterInfo[0]; - } - - if (pColFilter == NULL) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - } else if (sqlOptr == TK_OR) { - // TODO fixme: failed to invalid the filter expression: "col1 = 1 OR col2 = 2" - pColFilter = addColumnFilterInfo(&pColumn->info.flist); - if (pColFilter == NULL) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - } else { // error; + if (sqlOptr != TK_AND && sqlOptr != TK_OR) { return TSDB_CODE_TSC_INVALID_OPERATION; } + SColumnFilterInfo* pColFilter = calloc(1, sizeof(SColumnFilterInfo)); + pColFilter->filterstr = ((pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) ? 1 : 0); @@ -3913,17 +3891,20 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC && pExpr->tokenId != TK_NOTNULL && pExpr->tokenId != TK_LIKE && pExpr->tokenId != TK_IN) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); + goto _err_ret; } } else { if (pExpr->tokenId == TK_LIKE) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); + goto _err_ret; } if (pSchema->type == TSDB_DATA_TYPE_BOOL) { int32_t t = pExpr->tokenId; if (t != TK_EQ && t != TK_NE && t != TK_NOTNULL && t != TK_ISNULL && t != TK_IN) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); + goto _err_ret; } } } @@ -3935,7 +3916,12 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC } STableComInfo tinfo = tscGetTableInfo(pTableMeta); - return doExtractColumnFilterInfo(pCmd, pQueryInfo, tinfo.precision, pColFilter, pSchema->type, pExpr); + ret = doExtractColumnFilterInfo(pCmd, pQueryInfo, tinfo.precision, pColFilter, pSchema->type, pExpr); + +_err_ret: + freeColumnFilterInfo(pColFilter, 1); + + return ret; } static int32_t getTablenameCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pTableCond, SStringBuilder* sb) { @@ -3972,7 +3958,61 @@ 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 getColQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr) { + int32_t ret = TSDB_CODE_SUCCESS; + + for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { + tSqlExpr* p1 = extractExprForSTable(pCmd, pExpr, pQueryInfo, i); + if (p1 == NULL) { // no query condition on this table + continue; + } + + tExprNode* p = NULL; + + SArray* colList = taosArrayInit(10, sizeof(SColIndex)); + ret = exprTreeFromSqlExpr(pCmd, &p, p1, pQueryInfo, colList, NULL); + taosArrayDestroy(colList); + + SBufferWriter bw = tbufInitWriter(NULL, false); + + TRY(0) { + exprTreeToBinary(&bw, p); + } CATCH(code) { + tbufCloseWriter(&bw); + UNUSED(code); + // TODO: more error handling + } END_TRY + + // add to required table column list + STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, i); + int64_t uid = pTableMetaInfo->pTableMeta->id.uid; + + STblCond cond = { + .uid = uid, + .idx = i, + .len = (int32_t)(tbufTell(&bw)), + .cond = tbufGetData(&bw, true) + }; + + if (pQueryInfo->colCond == NULL) { + pQueryInfo->colCond = taosArrayInit(2, sizeof(SCond)); + } + + taosArrayPush(pQueryInfo->colCond, &cond); + + tSqlExprDestroy(p1); + tExprTreeDestroy(p, NULL); + + if (ret) { + break; + } + } + + return ret; +} + + +static int32_t checkColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, int32_t relOptr) { if (pExpr == NULL) { pQueryInfo->onlyHasTagCond &= true; return TSDB_CODE_SUCCESS; @@ -3980,19 +4020,19 @@ static int32_t getColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSq pQueryInfo->onlyHasTagCond &= false; if (!tSqlExprIsParentOfLeaf(pExpr)) { // internal node - int32_t ret = getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pLeft, pExpr->tokenId); + int32_t ret = checkColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pLeft, pExpr->tokenId); if (ret != TSDB_CODE_SUCCESS) { return ret; } - return getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pRight, pExpr->tokenId); + return checkColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pRight, pExpr->tokenId); } else { // handle leaf node SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (getColumnIndexByName(&pExpr->pLeft->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_OPERATION; } - return extractColumnFilterInfo(pCmd, pQueryInfo, &index, pExpr, relOptr); + return checkColumnFilterInfo(pCmd, pQueryInfo, &index, pExpr, relOptr); } } @@ -4259,6 +4299,10 @@ static bool isValidExpr(tSqlExpr* pLeft, tSqlExpr* pRight, int32_t optr) { return false; } + if (pLeft->tokenId >= TK_BOOL && pLeft->tokenId <= TK_BINARY && (optr == TK_NOTNULL || optr == TK_ISNULL)) { + return false; + } + return true; } @@ -4378,7 +4422,18 @@ static int32_t setExprToCond(tSqlExpr** parent, tSqlExpr* pExpr, const char* msg return TSDB_CODE_SUCCESS; } -static int32_t validateNullExpr(tSqlExpr* pExpr, char* msgBuf) { +static int32_t setNormalExprToCond(tSqlExpr** parent, tSqlExpr* pExpr, int32_t parentOptr) { + if (*parent != NULL) { + *parent = tSqlExprCreate((*parent), pExpr, parentOptr); + } else { + *parent = pExpr; + } + + return TSDB_CODE_SUCCESS; +} + + +static int32_t validateNullExpr(tSqlExpr* pExpr, STableMeta* pTableMeta, int32_t index, char* msgBuf) { const char* msg = "only support is [not] null"; tSqlExpr* pRight = pExpr->pRight; @@ -4386,20 +4441,43 @@ static int32_t validateNullExpr(tSqlExpr* pExpr, char* msgBuf) { return invalidOperationMsg(msgBuf, msg); } + if (pRight->tokenId == TK_STRING) { + SSchema* pSchema = tscGetTableSchema(pTableMeta); + if (IS_VAR_DATA_TYPE(pSchema[index].type)) { + return TSDB_CODE_SUCCESS; + } + + char *v = strndup(pRight->exprToken.z, pRight->exprToken.n); + int32_t len = strRmquote(v, pRight->exprToken.n); + if (len > 0) { + uint32_t type = 0; + tGetToken(v, &type); + + if (type == TK_NULL) { + free(v); + return invalidOperationMsg(msgBuf, msg); + } + } + + free(v); + } + return TSDB_CODE_SUCCESS; } // check for like expression static int32_t validateLikeExpr(tSqlExpr* pExpr, STableMeta* pTableMeta, int32_t index, char* msgBuf) { - const char* msg1 = "wildcard string should be less than 20 characters"; - const char* msg2 = "illegal column name"; + const char* msg1 = "wildcard string should be less than %d characters"; + const char* msg2 = "illegal column type for like"; tSqlExpr* pLeft = pExpr->pLeft; tSqlExpr* pRight = pExpr->pRight; if (pExpr->tokenId == TK_LIKE) { - if (pRight->value.nLen > TSDB_PATTERN_STRING_MAX_LEN) { - return invalidOperationMsg(msgBuf, msg1); + if (pRight->value.nLen > tsMaxWildCardsLen) { + char tmp[64] = {0}; + sprintf(tmp, msg1, tsMaxWildCardsLen); + return invalidOperationMsg(msgBuf, tmp); } SSchema* pSchema = tscGetTableSchema(pTableMeta); @@ -4411,11 +4489,23 @@ static int32_t validateLikeExpr(tSqlExpr* pExpr, STableMeta* pTableMeta, int32_t return TSDB_CODE_SUCCESS; } +int32_t handleNeOptr(tSqlExpr** rexpr, tSqlExpr* expr) { + tSqlExpr* left = tSqlExprClone(expr); + tSqlExpr* right = expr; + + left->tokenId = TK_LT; + right->tokenId = TK_GT; + + *rexpr = tSqlExprCreate(left, right, TK_OR); + + return TSDB_CODE_SUCCESS; +} + + static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr, - int32_t* type, int32_t parentOptr) { + int32_t* type, int32_t* tbIdx, int32_t parentOptr, tSqlExpr** columnExpr, tSqlExpr** tsExpr) { const char* msg1 = "table query cannot use tags filter"; const char* msg2 = "illegal column name"; - const char* msg3 = "only one query time range allowed"; const char* msg4 = "too many join tables"; const char* msg5 = "not support ordinary column join"; const char* msg6 = "only one query condition on tbname allowed"; @@ -4431,13 +4521,15 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); } + *tbIdx = index.tableIndex; + assert(tSqlExprIsParentOfLeaf(*pExpr)); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; // validate the null expression - int32_t code = validateNullExpr(*pExpr, tscGetErrorMsgPayload(pCmd)); + int32_t code = validateNullExpr(*pExpr, pTableMeta, index.columnIndex, tscGetErrorMsgPayload(pCmd)); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -4504,12 +4596,24 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql * since this expression is used to set the join query type */ tSqlExprDestroy(*pExpr); + if (type) { + *type |= TSQL_EXPR_JOIN; + } } else { - ret = setExprToCond(&pCondExpr->pTimewindow, *pExpr, msg3, parentOptr, pQueryInfo->msg); + tSqlExpr *rexpr = NULL; + if ((*pExpr)->tokenId == TK_NE) { + handleNeOptr(&rexpr, *pExpr); + } else { + rexpr = *pExpr; + } + + ret = setNormalExprToCond(tsExpr, rexpr, parentOptr); + if (type) { + *type |= TSQL_EXPR_TS; + } } *pExpr = NULL; // remove this expression - *type = TSQL_EXPR_TS; } else if (index.columnIndex >= tscGetNumOfColumns(pTableMeta) || index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { // query on tags, check for tag query condition if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) { @@ -4534,7 +4638,9 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); } - *type = TSQL_EXPR_TBNAME; + if (type) { + *type |= TSQL_EXPR_TAG; + } *pExpr = NULL; } else { if (pRight != NULL && pRight->tokenId == TK_ID) { // join on tag columns for stable query @@ -4545,23 +4651,41 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql pQueryInfo->type |= TSDB_QUERY_TYPE_JOIN_QUERY; ret = setExprToCond(&pCondExpr->pJoinExpr, *pExpr, NULL, parentOptr, pQueryInfo->msg); *pExpr = NULL; + if (type) { + *type |= TSQL_EXPR_JOIN; + } } else { // do nothing // ret = setExprToCond(pCmd, &pCondExpr->pTagCond, // *pExpr, NULL, parentOptr); + tSqlExpr *rexpr = NULL; + if ((*pExpr)->tokenId == TK_NE && (pSchema->type != TSDB_DATA_TYPE_BINARY && pSchema->type != TSDB_DATA_TYPE_NCHAR && pSchema->type != TSDB_DATA_TYPE_BOOL)) { + handleNeOptr(&rexpr, *pExpr); + *pExpr = rexpr; + } + + if (type) { + *type |= TSQL_EXPR_TAG; + } } - - *type = TSQL_EXPR_TAG; } - } else { // query on other columns - *type = TSQL_EXPR_COLUMN; - + if (type) { + *type |= TSQL_EXPR_COLUMN; + } + if (pRight->tokenId == TK_ID) { // other column cannot be served as the join column return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); } - ret = setExprToCond(&pCondExpr->pColumnCond, *pExpr, NULL, parentOptr, pQueryInfo->msg); + tSqlExpr *rexpr = NULL; + if ((*pExpr)->tokenId == TK_NE && (pSchema->type != TSDB_DATA_TYPE_BINARY && pSchema->type != TSDB_DATA_TYPE_NCHAR && pSchema->type != TSDB_DATA_TYPE_BOOL)) { + handleNeOptr(&rexpr, *pExpr); + } else { + rexpr = *pExpr; + } + + ret = setNormalExprToCond(columnExpr, rexpr, parentOptr); *pExpr = NULL; // remove it from expr tree } @@ -4569,12 +4693,20 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql } int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr, - int32_t* type, int32_t parentOptr) { + int32_t* type, int32_t* tbIdx, int32_t parentOptr, tSqlExpr** columnExpr, tSqlExpr** tsExpr) { if (pExpr == NULL) { return TSDB_CODE_SUCCESS; } - const char* msg1 = "query condition between different columns must use 'AND'"; + tSqlExpr *columnLeft = NULL; + tSqlExpr *columnRight = NULL; + tSqlExpr *tsLeft = NULL; + tSqlExpr *tsRight = NULL; + + int32_t ret = 0; + + const char* msg1 = "query condition between columns/tags/timestamp/join fields must use 'AND'"; + const char* msg2 = "query condition between tables must use 'AND'"; if ((*pExpr)->flags & (1 << EXPR_FLAG_TS_ERROR)) { return TSDB_CODE_TSC_INVALID_OPERATION; @@ -4587,48 +4719,94 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr return TSDB_CODE_TSC_INVALID_OPERATION; } - int32_t leftType = -1; - int32_t rightType = -1; + int32_t leftType = 0; + int32_t rightType = 0; + int32_t leftTbIdx = 0; + int32_t rightTbIdx = 0; if (!tSqlExprIsParentOfLeaf(*pExpr)) { - int32_t ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, &leftType, (*pExpr)->tokenId); + ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, type ? &leftType : NULL, &leftTbIdx, (*pExpr)->tokenId, &columnLeft, &tsLeft); if (ret != TSDB_CODE_SUCCESS) { - return ret; + goto err_ret; } - ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, pCondExpr, &rightType, (*pExpr)->tokenId); + ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, pCondExpr, type ? &rightType : NULL, &rightTbIdx, (*pExpr)->tokenId, &columnRight, &tsRight); if (ret != TSDB_CODE_SUCCESS) { - return ret; + goto err_ret; } /* * if left child and right child do not belong to the same group, the sub * expression is not valid for parent node, it must be TK_AND operator. */ - if (leftType != rightType) { - if ((*pExpr)->tokenId == TK_OR && (leftType + rightType != TSQL_EXPR_TBNAME + TSQL_EXPR_TAG)) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); - } + if (type != NULL && ((leftType != rightType) || GET_MIXED_TYPE(leftType)) && ((*pExpr)->tokenId == TK_OR)) { + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); + goto err_ret; } - *type = rightType; + if (((leftTbIdx != rightTbIdx) || (leftTbIdx == -1 || rightTbIdx == -1)) && ((*pExpr)->tokenId == TK_OR)) { + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); + goto err_ret; + } + + if (columnLeft && columnRight) { + setNormalExprToCond(&columnLeft, columnRight, (*pExpr)->tokenId); + + *columnExpr = columnLeft; + } else { + *columnExpr = columnLeft ? columnLeft : columnRight; + } + + if (tsLeft && tsRight) { + setNormalExprToCond(&tsLeft, tsRight, (*pExpr)->tokenId); + + *tsExpr = tsLeft; + } else { + *tsExpr = tsLeft ? tsLeft : tsRight; + } + + if (type) { + *type = leftType|rightType; + } + *tbIdx = (leftTbIdx == rightTbIdx) ? leftTbIdx : -1; + return TSDB_CODE_SUCCESS; } exchangeExpr(*pExpr); if (pLeft->tokenId == TK_ID && pRight->tokenId == TK_TIMESTAMP && (pRight->flags & (1 << EXPR_FLAG_TIMESTAMP_VAR))) { - return TSDB_CODE_TSC_INVALID_OPERATION; + ret = TSDB_CODE_TSC_INVALID_OPERATION; + goto err_ret; } if ((pLeft->flags & (1 << EXPR_FLAG_TS_ERROR)) || (pRight->flags & (1 << EXPR_FLAG_TS_ERROR))) { - return TSDB_CODE_TSC_INVALID_OPERATION; + ret = TSDB_CODE_TSC_INVALID_OPERATION; + goto err_ret; } - return handleExprInQueryCond(pCmd, pQueryInfo, pExpr, pCondExpr, type, parentOptr); + ret = handleExprInQueryCond(pCmd, pQueryInfo, pExpr, pCondExpr, type, tbIdx, parentOptr, columnExpr, tsExpr); + if (ret) { + goto err_ret; + } + + return TSDB_CODE_SUCCESS; + +err_ret: + + tSqlExprDestroy(columnLeft); + tSqlExprDestroy(columnRight); + tSqlExprDestroy(tsLeft); + tSqlExprDestroy(tsRight); + return ret; } static void doExtractExprForSTable(SSqlCmd* pCmd, tSqlExpr** pExpr, SQueryInfo* pQueryInfo, tSqlExpr** pOut, int32_t tableIndex) { + if (*pExpr == NULL) { + *pOut = NULL; + return; + } + if (tSqlExprIsParentOfLeaf(*pExpr)) { tSqlExpr* pLeft = (*pExpr)->pLeft; @@ -4750,38 +4928,73 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, return TSDB_CODE_SUCCESS; } -static bool validateFilterExpr(SQueryInfo* pQueryInfo) { - SArray* pColList = pQueryInfo->colList; +int32_t mergeTimeRange(SSqlCmd* pCmd, STimeWindow* res, STimeWindow* win, int32_t optr) { + const char* msg0 = "only one time stamp window allowed"; + +#define SET_EMPTY_RANGE(w) do { (w)->skey = INT64_MAX; (w)->ekey = INT64_MIN; } while (0) +#define IS_EMPTY_RANGE(w) ((w)->skey == INT64_MAX && (w)->ekey == INT64_MIN) - size_t num = taosArrayGetSize(pColList); - - for (int32_t i = 0; i < num; ++i) { - SColumn* pCol = taosArrayGetP(pColList, i); - - for (int32_t j = 0; j < pCol->info.flist.numOfFilters; ++j) { - SColumnFilterInfo* pColFilter = &pCol->info.flist.filterInfo[j]; - int32_t lowerOptr = pColFilter->lowerRelOptr; - int32_t upperOptr = pColFilter->upperRelOptr; - - if ((lowerOptr == TSDB_RELATION_GREATER_EQUAL || lowerOptr == TSDB_RELATION_GREATER) && - (upperOptr == TSDB_RELATION_LESS_EQUAL || upperOptr == TSDB_RELATION_LESS)) { - continue; - } - - // there must be at least two range, not support yet. - if (lowerOptr * upperOptr != TSDB_RELATION_INVALID) { - return false; - } + if (optr == TSDB_RELATION_AND) { + if (res->skey > win->ekey || win->skey > res->ekey) { + SET_EMPTY_RANGE(res); + return TSDB_CODE_SUCCESS; } + + if (res->skey < win->skey) { + res->skey = win->skey; + } + + if (res->ekey > win->ekey) { + res->ekey = win->ekey; + } + + return TSDB_CODE_SUCCESS; } - return true; + if (res->skey > win->ekey || win->skey > res->ekey) { + if (IS_EMPTY_RANGE(res)) { + res->skey = win->skey; + res->ekey = win->ekey; + return TSDB_CODE_SUCCESS; + } + + if (IS_EMPTY_RANGE(win)) { + return TSDB_CODE_SUCCESS; + } + + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg0); + } + + if (res->skey > win->skey) { + res->skey = win->skey; + } + + if (res->ekey < win->ekey) { + res->ekey = win->ekey; + } + + return TSDB_CODE_SUCCESS; } -static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) { - const char* msg0 = "invalid timestamp"; - const char* msg1 = "only one time stamp window allowed"; +static int32_t createTimeRangeExpr(tSqlExpr** pExpr, STimeWindow* win, uint32_t tokenId) { + *pExpr = calloc(1, sizeof(tSqlExpr)); + + (*pExpr)->type = SQL_NODE_VALUE; + (*pExpr)->tokenId = tokenId; + (*pExpr)->value.nType = TSDB_DATA_TYPE_VALUE_ARRAY; + (*pExpr)->value.nLen = 2; + (*pExpr)->value.arr = taosArrayInit(2, sizeof(int64_t)); + + taosArrayPush((*pExpr)->value.arr, &win->skey); + taosArrayPush((*pExpr)->value.arr, &win->ekey); + + return TSDB_CODE_SUCCESS; +} + +static int32_t convertTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) { + const char* msg0 = "invalid timestamp or operator for timestamp"; int32_t code = 0; + STimeWindow win = {.skey = INT64_MIN, .ekey = INT64_MAX}; if (pExpr == NULL) { pQueryInfo->onlyHasTagCond &= true; @@ -4791,16 +5004,15 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlE if (!tSqlExprIsParentOfLeaf(pExpr)) { - if (pExpr->tokenId == TK_OR) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); - } + code = convertTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pLeft); + if (code) { + return code; + } - code = getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pLeft); - if (code) { - return code; - } - - return getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pRight); + code = convertTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pRight); + if (code) { + return code; + } } else { SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (getColumnIndexByName(&pExpr->pLeft->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) { @@ -4812,19 +5024,13 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlE tSqlExpr* pRight = pExpr->pRight; - STimeWindow win = {.skey = INT64_MIN, .ekey = INT64_MAX}; if (getTimeRange(&win, pRight, pExpr->tokenId, tinfo.precision) != TSDB_CODE_SUCCESS) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg0); } - // update the timestamp query range - if (pQueryInfo->window.skey < win.skey) { - pQueryInfo->window.skey = win.skey; - } + createTimeRangeExpr(&pExpr->pRight, &win, pRight->tokenId); - if (pQueryInfo->window.ekey > win.ekey) { - pQueryInfo->window.ekey = win.ekey; - } + tSqlExprDestroy(pRight); } return TSDB_CODE_SUCCESS; @@ -4990,7 +5196,7 @@ static int32_t validateTagCondExpr(SSqlCmd* pCmd, tExprNode *p) { 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) { int32_t ret = TSDB_CODE_SUCCESS; if (pCondExpr->pTagCond == NULL) { @@ -4998,7 +5204,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, &pCondExpr->pTagCond, pQueryInfo, i); if (p1 == NULL) { // no query condition on this table continue; } @@ -5007,6 +5213,10 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE SArray* colList = taosArrayInit(10, sizeof(SColIndex)); ret = exprTreeFromSqlExpr(pCmd, &p, p1, pQueryInfo, colList, NULL); + //if (ret == TSDB_CODE_SUCCESS) { + // ret = filterInitFromTree(p, &pQueryInfo->tagFilter, (int32_t)taosArrayGetSize(colList)); + //} + SBufferWriter bw = tbufInitWriter(NULL, false); TRY(0) { @@ -5033,14 +5243,14 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE } tsSetSTableQueryCond(&pQueryInfo->tagCond, uid, &bw); - tSqlExprCompact(pExpr); + tSqlExprCompact(&pCondExpr->pTagCond); if (ret == TSDB_CODE_SUCCESS) { ret = validateTagCondExpr(pCmd, p); } tSqlExprDestroy(p1); - tExprTreeDestroy(p, NULL); + tExprTreeDestroy(p, NULL); //TODO taosArrayDestroy(colList); if (pQueryInfo->tagCond.pCond != NULL && taosArrayGetSize(pQueryInfo->tagCond.pCond) > 0 && !UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { @@ -5052,7 +5262,6 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE } } - pCondExpr->pTagCond = NULL; return ret; } @@ -5151,6 +5360,46 @@ int32_t mergeJoinNodes(SQueryInfo* pQueryInfo, SSqlObj* pSql) { return TSDB_CODE_SUCCESS; } +static int32_t getQueryTimeRange(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr) { + int32_t ret = TSDB_CODE_SUCCESS; + + if (*pExpr == NULL) { + return ret; + } + + //multiple tables's query time range mixed together + + tExprNode* p = NULL; + SFilterInfo *filter = NULL; + + SArray* colList = taosArrayInit(10, sizeof(SColIndex)); + ret = exprTreeFromSqlExpr(pCmd, &p, *pExpr, pQueryInfo, colList, NULL); + taosArrayDestroy(colList); + + if (ret != TSDB_CODE_SUCCESS) { + goto _ret; + } + + ret = filterInitFromTree(p, &filter, FI_OPTION_NO_REWRITE|FI_OPTION_TIMESTAMP); + if (ret != TSDB_CODE_SUCCESS) { + goto _ret; + } + + ret = filterGetTimeRange(filter, &pQueryInfo->window); + + filterFreeInfo(filter); + +_ret: + tExprTreeDestroy(p, NULL); + + if (ret) { + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), tstrerror(ret)); + } + + return ret; +} + + int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql) { if (pExpr == NULL) { @@ -5158,7 +5407,7 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq } const char* msg1 = "invalid expression"; - const char* msg2 = "invalid filter expression"; +// const char* msg2 = "invalid filter expression"; int32_t ret = TSDB_CODE_SUCCESS; @@ -5171,14 +5420,30 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq } int32_t type = 0; - if ((ret = getQueryCondExpr(&pSql->cmd, pQueryInfo, pExpr, &condExpr, &type, (*pExpr)->tokenId)) != TSDB_CODE_SUCCESS) { + int32_t tbIdx = 0; + int32_t *etype = &type; + +#if 0 + //DISABLE PARENT CONDITION GROUP TYPE CHECK + if (taosArrayGetSize(pQueryInfo->pUpstream) > 0) { + etype = NULL; + } +#endif + + if ((ret = getQueryCondExpr(&pSql->cmd, pQueryInfo, pExpr, &condExpr, etype, &tbIdx, (*pExpr)->tokenId, &condExpr.pColumnCond, &condExpr.pTimewindow)) != TSDB_CODE_SUCCESS) { goto PARSE_WHERE_EXIT; } + if (taosArrayGetSize(pQueryInfo->pUpstream) > 0 && condExpr.pTimewindow != NULL) { + setNormalExprToCond(&condExpr.pColumnCond, condExpr.pTimewindow, TK_AND); + condExpr.pTimewindow = NULL; + } + tSqlExprCompact(pExpr); // after expression compact, the expression tree is only include tag query condition condExpr.pTagCond = (*pExpr); + *pExpr = NULL; // 1. check if it is a join query if ((ret = validateJoinExpr(&pSql->cmd, pQueryInfo, &condExpr)) != TSDB_CODE_SUCCESS) { @@ -5186,14 +5451,18 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq } // 2. get the query time range - if ((ret = getTimeRangeFromExpr(&pSql->cmd, pQueryInfo, condExpr.pTimewindow)) != TSDB_CODE_SUCCESS) { - return ret; + if ((ret = convertTimeRangeFromExpr(&pSql->cmd, pQueryInfo, condExpr.pTimewindow)) != TSDB_CODE_SUCCESS) { + goto PARSE_WHERE_EXIT; + } + + if ((ret = getQueryTimeRange(&pSql->cmd, pQueryInfo, &condExpr.pTimewindow)) != TSDB_CODE_SUCCESS) { + goto PARSE_WHERE_EXIT; } // 3. get the tag query condition - if ((ret = getTagQueryCondExpr(&pSql->cmd, pQueryInfo, &condExpr, pExpr)) != TSDB_CODE_SUCCESS) { - return ret; + if ((ret = getTagQueryCondExpr(&pSql->cmd, pQueryInfo, &condExpr)) != TSDB_CODE_SUCCESS) { + goto PARSE_WHERE_EXIT; } // 4. get the table name query condition @@ -5202,16 +5471,15 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq } // 5. other column query condition - if ((ret = getColumnQueryCondInfo(&pSql->cmd, pQueryInfo, condExpr.pColumnCond, TK_AND)) != TSDB_CODE_SUCCESS) { + if ((ret = checkColumnQueryCondInfo(&pSql->cmd, pQueryInfo, condExpr.pColumnCond, TK_AND)) != TSDB_CODE_SUCCESS) { goto PARSE_WHERE_EXIT; } - if (taosArrayGetSize(pQueryInfo->pUpstream) > 0 ) { - if ((ret = getColumnQueryCondInfo(&pSql->cmd, pQueryInfo, condExpr.pTimewindow, TK_AND)) != TSDB_CODE_SUCCESS) { - goto PARSE_WHERE_EXIT; - } + if ((ret = getColQueryCondExpr(&pSql->cmd, pQueryInfo, &condExpr.pColumnCond)) != TSDB_CODE_SUCCESS) { + goto PARSE_WHERE_EXIT; } + // 6. join condition if ((ret = getJoinCondInfo(&pSql->cmd, pQueryInfo, condExpr.pJoinExpr)) != TSDB_CODE_SUCCESS) { goto PARSE_WHERE_EXIT; @@ -5226,10 +5494,10 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq goto PARSE_WHERE_EXIT; } - if (!validateFilterExpr(pQueryInfo)) { - ret = invalidOperationMsg(tscGetErrorMsgPayload(&pSql->cmd), msg2); - goto PARSE_WHERE_EXIT; - } + //if (!validateFilterExpr(pQueryInfo)) { + // ret = invalidOperationMsg(tscGetErrorMsgPayload(&pSql->cmd), msg2); + // goto PARSE_WHERE_EXIT; + //} //doAddJoinTagsColumnsIntoTagList(&pSql->cmd, pQueryInfo, &condExpr); if (condExpr.tsJoin) { @@ -5260,7 +5528,7 @@ int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t t * filter primary ts filter expression like: * where ts in ('2015-12-12 4:8:12') */ - if (pRight->tokenId == TK_SET || optr == TK_IN) { + if (pRight->tokenId == TK_SET || optr == TK_IN || optr == TK_NE) { return TSDB_CODE_TSC_INVALID_OPERATION; } @@ -7557,6 +7825,8 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) { const char* msg6 = "from missing in subclause"; const char* msg7 = "time interval is required"; const char* msg8 = "the first column should be primary timestamp column"; + const char* msg9 = "Continuous query do not support sub query"; + const char* msg10 = "illegal number of columns"; SSqlCmd* pCmd = &pSql->cmd; SQueryInfo* pQueryInfo = tscGetQueryInfo(pCmd); @@ -7577,7 +7847,11 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) { if (pFromInfo == NULL || taosArrayGetSize(pFromInfo->list) == 0) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); } - + + if (pFromInfo->type == SQL_NODE_FROM_SUBQUERY){ + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg9); + } + SRelElementPair* p1 = taosArrayGet(pFromInfo->list, 0); SStrToken srcToken = {.z = p1->tableName.z, .n = p1->tableName.n, .type = TK_STRING}; if (tscValidateName(&srcToken) != TSDB_CODE_SUCCESS) { @@ -7639,7 +7913,9 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) { return TSDB_CODE_TSC_INVALID_OPERATION; } - pCmd->numOfCols = pQueryInfo->fieldsInfo.numOfOutput; + if (pQueryInfo->fieldsInfo.numOfOutput <= 1) { + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg10); + } if (validateSqlFunctionInStreamSql(pCmd, pQueryInfo) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_OPERATION; @@ -8680,12 +8956,8 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf SExprInfo* pExpr1 = tscExprGet(pQueryInfo, 0); if (pExpr1->base.functionId != TSDB_FUNC_TID_TAG) { - int32_t numOfCols = (int32_t)taosArrayGetSize(pQueryInfo->colList); - for (int32_t i = 0; i < numOfCols; ++i) { - SColumn* pCols = taosArrayGetP(pQueryInfo->colList, i); - if (pCols->info.flist.numOfFilters > 0) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); - } + if ((pQueryInfo->colCond && taosArrayGetSize(pQueryInfo->colCond) > 0) || IS_TSWINDOW_SPECIFIED(pQueryInfo->window)) { + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); } } } @@ -8787,6 +9059,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryInfo* pQueryInfo, SArray* pCols, uint64_t *uid) { tExprNode* pLeft = NULL; tExprNode* pRight= NULL; + SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (pSqlExpr->pLeft != NULL) { int32_t ret = exprTreeFromSqlExpr(pCmd, &pLeft, pSqlExpr->pLeft, pQueryInfo, pCols, uid); @@ -8854,13 +9127,13 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pS } } } else if (pSqlExpr->type == SQL_NODE_TABLE_COLUMN) { // column name, normal column arithmetic expression - SColumnIndex index = COLUMN_INDEX_INITIALIZER; int32_t ret = getColumnIndexByName(&pSqlExpr->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)); if (ret != TSDB_CODE_SUCCESS) { return ret; } - STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, 0)->pTableMeta; + pQueryInfo->curTableIdx = index.tableIndex; + STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, index.tableIndex)->pTableMeta; int32_t numOfColumns = tscGetNumOfColumns(pTableMeta); *pExpr = calloc(1, sizeof(tExprNode)); @@ -8883,12 +9156,16 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pS return TSDB_CODE_SUCCESS; } else if (pSqlExpr->tokenId == TK_SET) { int32_t colType = -1; - STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, 0)->pTableMeta; - if (pCols != NULL && taosArrayGetSize(pCols) > 0) { - SColIndex* idx = taosArrayGet(pCols, taosArrayGetSize(pCols) - 1); - SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, idx->colIndex); - if (pSchema != NULL) { - colType = pSchema->type; + STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, pQueryInfo->curTableIdx)->pTableMeta; + if (pCols != NULL) { + size_t colSize = taosArrayGetSize(pCols); + + if (colSize > 0) { + SColIndex* idx = taosArrayGet(pCols, colSize - 1); + SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, idx->colIndex); + if (pSchema != NULL) { + colType = pSchema->type; + } } } tVariant *pVal; @@ -8897,7 +9174,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pS } else if (colType == TSDB_DATA_TYPE_FLOAT || colType == TSDB_DATA_TYPE_DOUBLE) { colType = TSDB_DATA_TYPE_DOUBLE; } - STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); + STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, pQueryInfo->curTableIdx); STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta); if (serializeExprListToVariant(pSqlExpr->Expr.paramList, &pVal, colType, tinfo.precision) == false) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "not support filter expression"); @@ -8936,7 +9213,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pS // NOTE: binary|nchar data allows the >|< type filter if ((*pExpr)->_node.optr != TSDB_RELATION_EQUAL && (*pExpr)->_node.optr != TSDB_RELATION_NOT_EQUAL) { if (pRight != NULL && pRight->nodeType == TSQL_NODE_VALUE) { - if (pRight->pVal->nType == TSDB_DATA_TYPE_BOOL) { + if (pRight->pVal->nType == TSDB_DATA_TYPE_BOOL && pLeft->pSchema->type == TSDB_DATA_TYPE_BOOL) { return TSDB_CODE_TSC_INVALID_OPERATION; } } @@ -8991,3 +9268,4 @@ void normalizeSqlNode(SSqlNode* pSqlNode, const char* dbName) { #endif + diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 69c3357230..11c458e9bc 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -501,6 +501,15 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) { pRes->code = rpcMsg->code; } rpcMsg->code = (pRes->code == TSDB_CODE_SUCCESS) ? (int32_t)pRes->numOfRows : pRes->code; + if (pRes->code == TSDB_CODE_RPC_FQDN_ERROR) { + if (pEpSet) { + char buf[TSDB_FQDN_LEN + 64] = {0}; + tscAllocPayload(pCmd, sizeof(buf)); + sprintf(tscGetErrorMsgPayload(pCmd), "%s\"%s\"", tstrerror(pRes->code),pEpSet->fqdn[(pEpSet->inUse)%(pEpSet->numOfEps)]); + } else { + sprintf(tscGetErrorMsgPayload(pCmd), "%s", tstrerror(pRes->code)); + } + } (*pSql->fp)(pSql->param, pSql, rpcMsg->code); } @@ -675,7 +684,7 @@ static int32_t tscEstimateQueryMsgSize(SSqlObj *pSql) { SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd); int32_t srcColListSize = (int32_t)(taosArrayGetSize(pQueryInfo->colList) * sizeof(SColumnInfo)); - int32_t srcColFilterSize = tscGetColFilterSerializeLen(pQueryInfo); + int32_t srcColFilterSize = 0; int32_t srcTagFilterSize = tscGetTagFilterSerializeLen(pQueryInfo); size_t numOfExprs = tscNumOfExprs(pQueryInfo); @@ -686,6 +695,7 @@ static int32_t tscEstimateQueryMsgSize(SSqlObj *pSql) { int32_t tableSerialize = 0; STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); + STableMeta * pTableMeta = pTableMetaInfo->pTableMeta; if (pTableMetaInfo->pVgroupTables != NULL) { size_t numOfGroups = taosArrayGetSize(pTableMetaInfo->pVgroupTables); @@ -698,8 +708,15 @@ static int32_t tscEstimateQueryMsgSize(SSqlObj *pSql) { tableSerialize = totalTables * sizeof(STableIdInfo); } - return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + srcColFilterSize + srcTagFilterSize + - exprSize + tsBufSize + tableSerialize + sqlLen + 4096 + pQueryInfo->bufLen; + if (pQueryInfo->colCond && taosArrayGetSize(pQueryInfo->colCond) > 0) { + STblCond *pCond = tsGetTableFilter(pQueryInfo->colCond, pTableMeta->id.uid, 0); + if (pCond != NULL && pCond->cond != NULL) { + srcColFilterSize = pCond->len; + } + } + + return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + srcColFilterSize + srcTagFilterSize + exprSize + tsBufSize + + tableSerialize + sqlLen + 4096 + pQueryInfo->bufLen; } static char *doSerializeTableInfo(SQueryTableMsg *pQueryMsg, SSqlObj *pSql, STableMetaInfo *pTableMetaInfo, char *pMsg, @@ -957,10 +974,21 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { pQueryMsg->tableCols[i].colId = htons(pCol->colId); pQueryMsg->tableCols[i].bytes = htons(pCol->bytes); pQueryMsg->tableCols[i].type = htons(pCol->type); - pQueryMsg->tableCols[i].flist.numOfFilters = htons(pCol->flist.numOfFilters); + //pQueryMsg->tableCols[i].flist.numOfFilters = htons(pCol->flist.numOfFilters); + pQueryMsg->tableCols[i].flist.numOfFilters = 0; // append the filter information after the basic column information - serializeColFilterInfo(pCol->flist.filterInfo, pCol->flist.numOfFilters, &pMsg); + //serializeColFilterInfo(pCol->flist.filterInfo, pCol->flist.numOfFilters, &pMsg); + } + + if (pQueryInfo->colCond && taosArrayGetSize(pQueryInfo->colCond) > 0 && !onlyQueryTags(&query) ) { + STblCond *pCond = tsGetTableFilter(pQueryInfo->colCond, pTableMeta->id.uid, 0); + if (pCond != NULL && pCond->cond != NULL) { + pQueryMsg->colCondLen = htons(pCond->len); + memcpy(pMsg, pCond->cond, pCond->len); + + pMsg += pCond->len; + } } for (int32_t i = 0; i < query.numOfOutput; ++i) { @@ -1035,7 +1063,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { SCond *pCond = tsGetSTableQueryCond(pTagCond, pTableMeta->id.uid); if (pCond != NULL && pCond->cond != NULL) { - pQueryMsg->tagCondLen = htonl(pCond->len); + pQueryMsg->tagCondLen = htons(pCond->len); memcpy(pMsg, pCond->cond, pCond->len); pMsg += pCond->len; diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index 6f3d5c3a63..5f55e1c50d 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -196,6 +196,11 @@ TAOS *taos_connect_internal(const char *ip, const char *user, const char *pass, if (pSql->res.code != TSDB_CODE_SUCCESS) { terrno = pSql->res.code; + if (terrno ==TSDB_CODE_RPC_FQDN_ERROR) { + printf("taos connect failed, reason: %s\n\n", taos_errstr(pSql)); + } else { + printf("taos connect failed, reason: %s.\n\n", tstrerror(terrno)); + } taos_free_result(pSql); taos_close(pObj); return NULL; @@ -643,7 +648,7 @@ char *taos_errstr(TAOS_RES *tres) { return (char*) tstrerror(terrno); } - if (hasAdditionalErrorInfo(pSql->res.code, &pSql->cmd)) { + if (hasAdditionalErrorInfo(pSql->res.code, &pSql->cmd) || pSql->res.code == TSDB_CODE_RPC_FQDN_ERROR) { return pSql->cmd.payload; } else { return (char*)tstrerror(pSql->res.code); diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index e1cb79b357..693391c44b 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -796,6 +796,7 @@ static void issueTsCompQuery(SSqlObj* pSql, SJoinSupporter* pSupporter, SSqlObj* STimeWindow window = pQueryInfo->window; tscInitQueryInfo(pQueryInfo); + pQueryInfo->colCond = pSupporter->colCond; pQueryInfo->window = window; TSDB_QUERY_CLEAR_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY); TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_MULTITABLE_QUERY); @@ -1883,6 +1884,9 @@ int32_t tscCreateJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { // return the tableId & tag SColumnIndex colIndex = {0}; + pSupporter->colCond = pNewQueryInfo->colCond; + pNewQueryInfo->colCond = NULL; + STagCond* pTagCond = &pSupporter->tagCond; assert(pTagCond->joinInfo.hasJoin); @@ -2319,6 +2323,11 @@ int32_t tscHandleFirstRoundStableQuery(SSqlObj *pSql) { goto _error; } + if (tscColCondCopy(&pNewQueryInfo->colCond, pQueryInfo->colCond, pTableMetaInfo->pTableMeta->id.uid, 0) != 0) { + terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; + goto _error; + } + pNewQueryInfo->window = pQueryInfo->window; pNewQueryInfo->interval = pQueryInfo->interval; pNewQueryInfo->sessionWindow = pQueryInfo->sessionWindow; diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index a6712778ba..4857265d17 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -62,11 +62,11 @@ int32_t converToStr(char *str, int type, void *buf, int32_t bufSize, int32_t *le break; case TSDB_DATA_TYPE_FLOAT: - n = sprintf(str, "%f", GET_FLOAT_VAL(buf)); + n = sprintf(str, "%e", GET_FLOAT_VAL(buf)); break; case TSDB_DATA_TYPE_DOUBLE: - n = sprintf(str, "%f", GET_DOUBLE_VAL(buf)); + n = sprintf(str, "%e", GET_DOUBLE_VAL(buf)); break; case TSDB_DATA_TYPE_BINARY: @@ -82,6 +82,22 @@ int32_t converToStr(char *str, int type, void *buf, int32_t bufSize, int32_t *le n = bufSize + 2; break; + case TSDB_DATA_TYPE_UTINYINT: + n = sprintf(str, "%d", *(uint8_t*)buf); + break; + + case TSDB_DATA_TYPE_USMALLINT: + n = sprintf(str, "%d", *(uint16_t*)buf); + break; + + case TSDB_DATA_TYPE_UINT: + n = sprintf(str, "%u", *(uint32_t*)buf); + break; + + case TSDB_DATA_TYPE_UBIGINT: + n = sprintf(str, "%" PRIu64, *(uint64_t*)buf); + break; + default: tscError("unsupported type:%d", type); return TSDB_CODE_TSC_INVALID_VALUE; @@ -118,6 +134,24 @@ SCond* tsGetSTableQueryCond(STagCond* pTagCond, uint64_t uid) { return NULL; } +STblCond* tsGetTableFilter(SArray* filters, uint64_t uid, int16_t idx) { + if (filters == NULL) { + return NULL; + } + + size_t size = taosArrayGetSize(filters); + for (int32_t i = 0; i < size; ++i) { + STblCond* cond = taosArrayGet(filters, i); + + if (uid == cond->uid && (idx >= 0 && cond->idx == idx)) { + return cond; + } + } + + return NULL; +} + + void tsSetSTableQueryCond(STagCond* pTagCond, uint64_t uid, SBufferWriter* bw) { if (tbufTell(bw) == 0) { return; @@ -753,8 +787,7 @@ typedef struct SDummyInputInfo { SSDataBlock *block; STableQueryInfo *pTableQueryInfo; SSqlObj *pSql; // refactor: remove it - int32_t numOfFilterCols; - SSingleColumnFilterInfo *pFilterInfo; + SFilterInfo *pFilterInfo; } SDummyInputInfo; typedef struct SJoinStatus { @@ -770,38 +803,7 @@ typedef struct SJoinOperatorInfo { SRspResultInfo resultInfo; // todo refactor, add this info for each operator } SJoinOperatorInfo; -static void converNcharFilterColumn(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, int32_t rows, bool *gotNchar) { - for (int32_t i = 0; i < numOfFilterCols; ++i) { - if (pFilterInfo[i].info.type == TSDB_DATA_TYPE_NCHAR) { - pFilterInfo[i].pData2 = pFilterInfo[i].pData; - pFilterInfo[i].pData = malloc(rows * pFilterInfo[i].info.bytes); - int32_t bufSize = pFilterInfo[i].info.bytes - VARSTR_HEADER_SIZE; - for (int32_t j = 0; j < rows; ++j) { - char* dst = (char *)pFilterInfo[i].pData + j * pFilterInfo[i].info.bytes; - char* src = (char *)pFilterInfo[i].pData2 + j * pFilterInfo[i].info.bytes; - int32_t len = 0; - taosMbsToUcs4(varDataVal(src), varDataLen(src), varDataVal(dst), bufSize, &len); - varDataLen(dst) = len; - } - *gotNchar = true; - } - } -} - -static void freeNcharFilterColumn(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols) { - for (int32_t i = 0; i < numOfFilterCols; ++i) { - if (pFilterInfo[i].info.type == TSDB_DATA_TYPE_NCHAR) { - if (pFilterInfo[i].pData2) { - tfree(pFilterInfo[i].pData); - pFilterInfo[i].pData = pFilterInfo[i].pData2; - pFilterInfo[i].pData2 = NULL; - } - } - } -} - - -static void doSetupSDataBlock(SSqlRes* pRes, SSDataBlock* pBlock, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols) { +static void doSetupSDataBlock(SSqlRes* pRes, SSDataBlock* pBlock, SFilterInfo* pFilterInfo) { int32_t offset = 0; char* pData = pRes->data; @@ -817,14 +819,16 @@ static void doSetupSDataBlock(SSqlRes* pRes, SSDataBlock* pBlock, SSingleColumnF } // filter data if needed - if (numOfFilterCols > 0) { - doSetFilterColumnInfo(pFilterInfo, numOfFilterCols, pBlock); + if (pFilterInfo) { + //doSetFilterColumnInfo(pFilterInfo, numOfFilterCols, pBlock); + doSetFilterColInfo(pFilterInfo, pBlock); bool gotNchar = false; - converNcharFilterColumn(pFilterInfo, numOfFilterCols, pBlock->info.rows, &gotNchar); + filterConverNcharColumns(pFilterInfo, pBlock->info.rows, &gotNchar); int8_t* p = calloc(pBlock->info.rows, sizeof(int8_t)); - bool all = doFilterDataBlock(pFilterInfo, numOfFilterCols, pBlock->info.rows, p); + //bool all = doFilterDataBlock(pFilterInfo, numOfFilterCols, pBlock->info.rows, p); + bool all = filterExecute(pFilterInfo, pBlock->info.rows, p); if (gotNchar) { - freeNcharFilterColumn(pFilterInfo, numOfFilterCols); + filterFreeNcharColumns(pFilterInfo); } if (!all) { doCompactSDataBlock(pBlock, pBlock->info.rows, p); @@ -862,7 +866,7 @@ SSDataBlock* doGetDataBlock(void* param, bool* newgroup) { pBlock->info.rows = pRes->numOfRows; if (pRes->numOfRows != 0) { - doSetupSDataBlock(pRes, pBlock, pInput->pFilterInfo, pInput->numOfFilterCols); + doSetupSDataBlock(pRes, pBlock, pInput->pFilterInfo); *newgroup = false; return pBlock; } @@ -877,7 +881,7 @@ SSDataBlock* doGetDataBlock(void* param, bool* newgroup) { } pBlock->info.rows = pRes->numOfRows; - doSetupSDataBlock(pRes, pBlock, pInput->pFilterInfo, pInput->numOfFilterCols); + doSetupSDataBlock(pRes, pBlock, pInput->pFilterInfo); *newgroup = false; return pBlock; } @@ -920,25 +924,40 @@ SSDataBlock* doDataBlockJoin(void* param, bool* newgroup) { if (pOperator->status == OP_EXEC_DONE) { return pJoinInfo->pRes; } - + SJoinStatus* st0 = &pJoinInfo->status[0]; SColumnInfoData* p0 = taosArrayGet(st0->pBlock->pDataBlock, 0); int64_t* ts0 = (int64_t*) p0->pData; + if (st0->index >= st0->pBlock->info.rows) { + continue; + } + bool prefixEqual = true; while(1) { prefixEqual = true; for (int32_t i = 1; i < pJoinInfo->numOfUpstream; ++i) { SJoinStatus* st = &pJoinInfo->status[i]; + ts0 = (int64_t*) p0->pData; SColumnInfoData* p = taosArrayGet(st->pBlock->pDataBlock, 0); int64_t* ts = (int64_t*)p->pData; + if (st->index >= st->pBlock->info.rows || st0->index >= st0->pBlock->info.rows) { + fetchNextBlockIfCompleted(pOperator, newgroup); + if (pOperator->status == OP_EXEC_DONE) { + return pJoinInfo->pRes; + } + + prefixEqual = false; + break; + } + if (ts[st->index] < ts0[st0->index]) { // less than the first prefixEqual = false; - if ((++(st->index)) >= st->pBlock->info.rows) { + if ((++(st->index)) >= st->pBlock->info.rows) { fetchNextBlockIfCompleted(pOperator, newgroup); if (pOperator->status == OP_EXEC_DONE) { return pJoinInfo->pRes; @@ -1053,22 +1072,21 @@ static void destroyDummyInputOperator(void* param, int32_t numOfOutput) { pInfo->block = destroyOutputBuf(pInfo->block); pInfo->pSql = NULL; - doDestroyFilterInfo(pInfo->pFilterInfo, pInfo->numOfFilterCols); + filterFreeInfo(pInfo->pFilterInfo); cleanupResultRowInfo(&pInfo->pTableQueryInfo->resInfo); tfree(pInfo->pTableQueryInfo); } // todo this operator servers as the adapter for Operator tree and SqlRes result, remove it later -SOperatorInfo* createDummyInputOperator(SSqlObj* pSql, SSchema* pSchema, int32_t numOfCols, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols) { +SOperatorInfo* createDummyInputOperator(SSqlObj* pSql, SSchema* pSchema, int32_t numOfCols, SFilterInfo* pFilters) { assert(numOfCols > 0); STimeWindow win = {.skey = INT64_MIN, .ekey = INT64_MAX}; SDummyInputInfo* pInfo = calloc(1, sizeof(SDummyInputInfo)); pInfo->pSql = pSql; - pInfo->pFilterInfo = pFilterInfo; - pInfo->numOfFilterCols = numOfFilterCols; + pInfo->pFilterInfo = pFilters; pInfo->pTableQueryInfo = createTmpTableQueryInfo(win); pInfo->block = calloc(numOfCols, sizeof(SSDataBlock)); @@ -1156,6 +1174,7 @@ void convertQueryResult(SSqlRes* pRes, SQueryInfo* pQueryInfo, uint64_t objId, b pRes->completed = (pRes->numOfRows == 0); } +/* static void createInputDataFilterInfo(SQueryInfo* px, int32_t numOfCol1, int32_t* numOfFilterCols, SSingleColumnFilterInfo** pFilterInfo) { SColumnInfo* tableCols = calloc(numOfCol1, sizeof(SColumnInfo)); for(int32_t i = 0; i < numOfCol1; ++i) { @@ -1173,6 +1192,7 @@ static void createInputDataFilterInfo(SQueryInfo* px, int32_t numOfCol1, int32_t tfree(tableCols); } +*/ void handleDownstreamOperator(SSqlObj** pSqlObjList, int32_t numOfUpstream, SQueryInfo* px, SSqlObj* pSql) { SSqlRes* pOutput = &pSql->res; @@ -1201,11 +1221,17 @@ void handleDownstreamOperator(SSqlObj** pSqlObjList, int32_t numOfUpstream, SQue // if it is a join query, create join operator here int32_t numOfCol1 = pTableMeta->tableInfo.numOfColumns; - int32_t numOfFilterCols = 0; - SSingleColumnFilterInfo* pFilterInfo = NULL; - createInputDataFilterInfo(px, numOfCol1, &numOfFilterCols, &pFilterInfo); + SFilterInfo *pFilters = NULL; + STblCond *pCond = NULL; + if (px->colCond) { + pCond = tsGetTableFilter(px->colCond, pTableMeta->id.uid, 0); + if (pCond && pCond->cond) { + createQueryFilter(pCond->cond, pCond->len, &pFilters); + } + //createInputDataFlterInfo(px, numOfCol1, &numOfFilterCols, &pFilterInfo); + } - SOperatorInfo* pSourceOperator = createDummyInputOperator(pSqlObjList[0], pSchema, numOfCol1, pFilterInfo, numOfFilterCols); + SOperatorInfo* pSourceOperator = createDummyInputOperator(pSqlObjList[0], pSchema, numOfCol1, pFilters); pOutput->precision = pSqlObjList[0]->res.precision; @@ -1222,15 +1248,21 @@ void handleDownstreamOperator(SSqlObj** pSqlObjList, int32_t numOfUpstream, SQue for(int32_t i = 1; i < px->numOfTables; ++i) { STableMeta* pTableMeta1 = tscGetMetaInfo(px, i)->pTableMeta; + numOfCol1 = pTableMeta1->tableInfo.numOfColumns; + SFilterInfo *pFilters1 = NULL; SSchema* pSchema1 = tscGetTableSchema(pTableMeta1); int32_t n = pTableMeta1->tableInfo.numOfColumns; - int32_t numOfFilterCols1 = 0; - SSingleColumnFilterInfo* pFilterInfo1 = NULL; - createInputDataFilterInfo(px, numOfCol1, &numOfFilterCols1, &pFilterInfo1); + if (px->colCond) { + pCond = tsGetTableFilter(px->colCond, pTableMeta1->id.uid, i); + if (pCond && pCond->cond) { + createQueryFilter(pCond->cond, pCond->len, &pFilters1); + } + //createInputDataFilterInfo(px, numOfCol1, &numOfFilterCols1, &pFilterInfo1); + } - p[i] = createDummyInputOperator(pSqlObjList[i], pSchema1, n, pFilterInfo1, numOfFilterCols1); + p[i] = createDummyInputOperator(pSqlObjList[i], pSchema1, n, pFilters1); memcpy(&schema[offset], pSchema1, n * sizeof(SSchema)); offset += n; } @@ -2258,6 +2290,11 @@ int32_t tscGetResRowLength(SArray* pExprList) { } static void destroyFilterInfo(SColumnFilterList* pFilterList) { + if (pFilterList->filterInfo == NULL) { + pFilterList->numOfFilters = 0; + return; + } + for(int32_t i = 0; i < pFilterList->numOfFilters; ++i) { if (pFilterList->filterInfo[i].filterstr) { tfree(pFilterList->filterInfo[i].pz); @@ -2960,6 +2997,64 @@ int32_t tscTagCondCopy(STagCond* dest, const STagCond* src) { return 0; } +int32_t tscColCondCopy(SArray** dest, const SArray* src, uint64_t uid, int16_t tidx) { + if (src == NULL) { + return 0; + } + + size_t s = taosArrayGetSize(src); + *dest = taosArrayInit(s, sizeof(SCond)); + + for (int32_t i = 0; i < s; ++i) { + STblCond* pCond = taosArrayGet(src, i); + STblCond c = {0}; + + if (tidx > 0) { + if (!(pCond->uid == uid && pCond->idx == tidx)) { + continue; + } + + c.idx = 0; + } else { + c.idx = pCond->idx; + } + + c.len = pCond->len; + c.uid = pCond->uid; + + if (pCond->len > 0) { + assert(pCond->cond != NULL); + c.cond = malloc(c.len); + if (c.cond == NULL) { + return -1; + } + + memcpy(c.cond, pCond->cond, c.len); + } + + taosArrayPush(*dest, &c); + } + + return 0; +} + +void tscColCondRelease(SArray** pCond) { + if (*pCond == NULL) { + return; + } + + size_t s = taosArrayGetSize(*pCond); + for (int32_t i = 0; i < s; ++i) { + STblCond* p = taosArrayGet(*pCond, i); + tfree(p->cond); + } + + taosArrayDestroy(*pCond); + + *pCond = NULL; +} + + void tscTagCondRelease(STagCond* pTagCond) { free(pTagCond->tbnameCond.cond); @@ -3152,6 +3247,7 @@ int32_t tscAddQueryInfo(SSqlCmd* pCmd) { static void freeQueryInfoImpl(SQueryInfo* pQueryInfo) { tscTagCondRelease(&pQueryInfo->tagCond); + tscColCondRelease(&pQueryInfo->colCond); tscFieldInfoClear(&pQueryInfo->fieldsInfo); tscExprDestroy(pQueryInfo->exprList); @@ -3242,6 +3338,11 @@ int32_t tscQueryInfoCopy(SQueryInfo* pQueryInfo, const SQueryInfo* pSrc) { goto _error; } + if (tscColCondCopy(&pQueryInfo->colCond, pSrc->colCond, 0, -1) != 0) { + code = TSDB_CODE_TSC_OUT_OF_MEMORY; + goto _error; + } + if (pSrc->fillType != TSDB_FILL_NONE) { pQueryInfo->fillVal = calloc(1, pSrc->fieldsInfo.numOfOutput * sizeof(int64_t)); if (pQueryInfo->fillVal == NULL) { @@ -3634,6 +3735,11 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, __async_cb_func_t goto _error; } + if (tscColCondCopy(&pNewQueryInfo->colCond, pQueryInfo->colCond, pTableMetaInfo->pTableMeta->id.uid, tableIndex) != 0) { + terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; + goto _error; + } + if (pQueryInfo->fillType != TSDB_FILL_NONE) { //just make memory memory sanitizer happy //refactor later diff --git a/src/common/inc/tdataformat.h b/src/common/inc/tdataformat.h index fb6bab0cf2..1637c4832b 100644 --- a/src/common/inc/tdataformat.h +++ b/src/common/inc/tdataformat.h @@ -328,11 +328,10 @@ static FORCE_INLINE void dataColReset(SDataCol *pDataCol) { pDataCol->len = 0; } int tdAllocMemForCol(SDataCol *pCol, int maxPoints); void dataColInit(SDataCol *pDataCol, STColumn *pCol, int maxPoints); -void dataColAppendVal(SDataCol *pCol, const void *value, int numOfRows, int maxPoints); +int dataColAppendVal(SDataCol *pCol, const void *value, int numOfRows, int maxPoints); void dataColSetOffset(SDataCol *pCol, int nEle); bool isNEleNull(SDataCol *pCol, int nEle); -void dataColSetNEleNull(SDataCol *pCol, int nEle, int maxPoints); // Get the data pointer from a column-wised data static FORCE_INLINE const void *tdGetColDataOfRow(SDataCol *pCol, int row) { @@ -357,13 +356,11 @@ static FORCE_INLINE int32_t dataColGetNEleLen(SDataCol *pDataCol, int rows) { } typedef struct { - int maxRowSize; - int maxCols; // max number of columns - int maxPoints; // max number of points - - int numOfRows; - int numOfCols; // Total number of cols - int sversion; // TODO: set sversion + int maxCols; // max number of columns + int maxPoints; // max number of points + int numOfRows; + int numOfCols; // Total number of cols + int sversion; // TODO: set sversion SDataCol *cols; } SDataCols; @@ -407,7 +404,7 @@ static FORCE_INLINE TSKEY dataColsKeyLast(SDataCols *pCols) { } } -SDataCols *tdNewDataCols(int maxRowSize, int maxCols, int maxRows); +SDataCols *tdNewDataCols(int maxCols, int maxRows); void tdResetDataCols(SDataCols *pCols); int tdInitDataCols(SDataCols *pCols, STSchema *pSchema); SDataCols *tdDupDataCols(SDataCols *pCols, bool keepData); diff --git a/src/common/inc/tglobal.h b/src/common/inc/tglobal.h index 7290db6ec9..25d1c90ec5 100644 --- a/src/common/inc/tglobal.h +++ b/src/common/inc/tglobal.h @@ -70,6 +70,7 @@ extern int8_t tsKeepOriginalColumnName; // client extern int32_t tsMaxSQLStringLen; +extern int32_t tsMaxWildCardsLen; extern int8_t tsTscEnableRecordSql; extern int32_t tsMaxNumOfOrderedResults; extern int32_t tsMinSlidingTime; diff --git a/src/common/inc/tvariant.h b/src/common/inc/tvariant.h index 21b7fd8223..c69a662846 100644 --- a/src/common/inc/tvariant.h +++ b/src/common/inc/tvariant.h @@ -53,6 +53,8 @@ int32_t tVariantToString(tVariant *pVar, char *dst); int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix); +int32_t tVariantDumpEx(tVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix, bool *converted, char *extInfo); + int32_t tVariantTypeSetType(tVariant *pVariant, char type); #ifdef __cplusplus diff --git a/src/common/src/tdataformat.c b/src/common/src/tdataformat.c index 3f0ab7f93e..c793d241f6 100644 --- a/src/common/src/tdataformat.c +++ b/src/common/src/tdataformat.c @@ -19,10 +19,10 @@ #include "wchar.h" #include "tarray.h" +static void dataColSetNEleNull(SDataCol *pCol, int nEle); static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limit1, SDataCols *src2, int *iter2, int limit2, int tRows, bool forceSetNull); -//TODO: change caller to use return val int tdAllocMemForCol(SDataCol *pCol, int maxPoints) { int spaceNeeded = pCol->bytes * maxPoints; if(IS_VAR_DATA_TYPE(pCol->type)) { @@ -31,7 +31,7 @@ int tdAllocMemForCol(SDataCol *pCol, int maxPoints) { if(pCol->spaceSize < spaceNeeded) { void* ptr = realloc(pCol->pData, spaceNeeded); if(ptr == NULL) { - uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)pCol->spaceSize, + uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)spaceNeeded, strerror(errno)); return -1; } else { @@ -239,20 +239,19 @@ void dataColInit(SDataCol *pDataCol, STColumn *pCol, int maxPoints) { pDataCol->len = 0; } // value from timestamp should be TKEY here instead of TSKEY -void dataColAppendVal(SDataCol *pCol, const void *value, int numOfRows, int maxPoints) { +int dataColAppendVal(SDataCol *pCol, const void *value, int numOfRows, int maxPoints) { ASSERT(pCol != NULL && value != NULL); if (isAllRowsNull(pCol)) { if (isNull(value, pCol->type)) { // all null value yet, just return - return; + return 0; } + if(tdAllocMemForCol(pCol, maxPoints) < 0) return -1; if (numOfRows > 0) { // Find the first not null value, fill all previouse values as NULL - dataColSetNEleNull(pCol, numOfRows, maxPoints); - } else { - tdAllocMemForCol(pCol, maxPoints); + dataColSetNEleNull(pCol, numOfRows); } } @@ -268,12 +267,21 @@ void dataColAppendVal(SDataCol *pCol, const void *value, int numOfRows, int maxP memcpy(POINTER_SHIFT(pCol->pData, pCol->len), value, pCol->bytes); pCol->len += pCol->bytes; } + return 0; +} + +static FORCE_INLINE const void *tdGetColDataOfRowUnsafe(SDataCol *pCol, int row) { + if (IS_VAR_DATA_TYPE(pCol->type)) { + return POINTER_SHIFT(pCol->pData, pCol->dataOff[row]); + } else { + return POINTER_SHIFT(pCol->pData, TYPE_BYTES[pCol->type] * row); + } } bool isNEleNull(SDataCol *pCol, int nEle) { if(isAllRowsNull(pCol)) return true; for (int i = 0; i < nEle; i++) { - if (!isNull(tdGetColDataOfRow(pCol, i), pCol->type)) return false; + if (!isNull(tdGetColDataOfRowUnsafe(pCol, i), pCol->type)) return false; } return true; } @@ -290,9 +298,7 @@ static FORCE_INLINE void dataColSetNullAt(SDataCol *pCol, int index) { } } -void dataColSetNEleNull(SDataCol *pCol, int nEle, int maxPoints) { - tdAllocMemForCol(pCol, maxPoints); - +static void dataColSetNEleNull(SDataCol *pCol, int nEle) { if (IS_VAR_DATA_TYPE(pCol->type)) { pCol->len = 0; for (int i = 0; i < nEle; i++) { @@ -318,7 +324,7 @@ void dataColSetOffset(SDataCol *pCol, int nEle) { } } -SDataCols *tdNewDataCols(int maxRowSize, int maxCols, int maxRows) { +SDataCols *tdNewDataCols(int maxCols, int maxRows) { SDataCols *pCols = (SDataCols *)calloc(1, sizeof(SDataCols)); if (pCols == NULL) { uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)sizeof(SDataCols), strerror(errno)); @@ -326,6 +332,9 @@ SDataCols *tdNewDataCols(int maxRowSize, int maxCols, int maxRows) { } pCols->maxPoints = maxRows; + pCols->maxCols = maxCols; + pCols->numOfRows = 0; + pCols->numOfCols = 0; if (maxCols > 0) { pCols->cols = (SDataCol *)calloc(maxCols, sizeof(SDataCol)); @@ -342,13 +351,8 @@ SDataCols *tdNewDataCols(int maxRowSize, int maxCols, int maxRows) { pCols->cols[i].pData = NULL; pCols->cols[i].dataOff = NULL; } - - pCols->maxCols = maxCols; } - pCols->maxRowSize = maxRowSize; - - return pCols; } @@ -357,8 +361,9 @@ int tdInitDataCols(SDataCols *pCols, STSchema *pSchema) { int oldMaxCols = pCols->maxCols; if (schemaNCols(pSchema) > oldMaxCols) { pCols->maxCols = schemaNCols(pSchema); - pCols->cols = (SDataCol *)realloc(pCols->cols, sizeof(SDataCol) * pCols->maxCols); - if (pCols->cols == NULL) return -1; + void* ptr = (SDataCol *)realloc(pCols->cols, sizeof(SDataCol) * pCols->maxCols); + if (ptr == NULL) return -1; + pCols->cols = ptr; for(i = oldMaxCols; i < pCols->maxCols; i++) { pCols->cols[i].pData = NULL; pCols->cols[i].dataOff = NULL; @@ -366,10 +371,6 @@ int tdInitDataCols(SDataCols *pCols, STSchema *pSchema) { } } - if (schemaTLen(pSchema) > pCols->maxRowSize) { - pCols->maxRowSize = schemaTLen(pSchema); - } - tdResetDataCols(pCols); pCols->numOfCols = schemaNCols(pSchema); @@ -398,7 +399,7 @@ SDataCols *tdFreeDataCols(SDataCols *pCols) { } SDataCols *tdDupDataCols(SDataCols *pDataCols, bool keepData) { - SDataCols *pRet = tdNewDataCols(pDataCols->maxRowSize, pDataCols->maxCols, pDataCols->maxPoints); + SDataCols *pRet = tdNewDataCols(pDataCols->maxCols, pDataCols->maxPoints); if (pRet == NULL) return NULL; pRet->numOfCols = pDataCols->numOfCols; @@ -413,7 +414,10 @@ SDataCols *tdDupDataCols(SDataCols *pDataCols, bool keepData) { if (keepData) { if (pDataCols->cols[i].len > 0) { - tdAllocMemForCol(&pRet->cols[i], pRet->maxPoints); + if(tdAllocMemForCol(&pRet->cols[i], pRet->maxPoints) < 0) { + tdFreeDataCols(pRet); + return NULL; + } pRet->cols[i].len = pDataCols->cols[i].len; memcpy(pRet->cols[i].pData, pDataCols->cols[i].pData, pDataCols->cols[i].len); if (IS_VAR_DATA_TYPE(pRet->cols[i].type)) { @@ -584,9 +588,12 @@ static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, i if ((key1 > key2) || (key1 == key2 && !TKEY_IS_DELETED(tkey2))) { for (int i = 0; i < src2->numOfCols; i++) { ASSERT(target->cols[i].type == src2->cols[i].type); - if (src2->cols[i].len > 0 && (forceSetNull || (!forceSetNull && !isNull(src2->cols[i].pData, src2->cols[i].type)))) { + if (src2->cols[i].len > 0 && !isNull(src2->cols[i].pData, src2->cols[i].type)) { dataColAppendVal(&(target->cols[i]), tdGetColDataOfRow(src2->cols + i, *iter2), target->numOfRows, target->maxPoints); + } else if(!forceSetNull && key1 == key2 && src1->cols[i].len > 0) { + dataColAppendVal(&(target->cols[i]), tdGetColDataOfRow(src1->cols + i, *iter1), target->numOfRows, + target->maxPoints); } } target->numOfRows++; diff --git a/src/common/src/texpr.c b/src/common/src/texpr.c index 973b88fef9..ebdb33fd5b 100644 --- a/src/common/src/texpr.c +++ b/src/common/src/texpr.c @@ -118,7 +118,7 @@ void tExprTreeDestroy(tExprNode *pNode, void (*fp)(void *)) { } else if (pNode->nodeType == TSQL_NODE_VALUE) { tVariantDestroy(pNode->pVal); } else if (pNode->nodeType == TSQL_NODE_COL) { - free(pNode->pSchema); + tfree(pNode->pSchema); } free(pNode); @@ -435,7 +435,7 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) { expr->_node.optr = TSDB_RELATION_IN; tVariant* pVal = exception_calloc(1, sizeof(tVariant)); right->pVal = pVal; - pVal->nType = TSDB_DATA_TYPE_ARRAY; + pVal->nType = TSDB_DATA_TYPE_POINTER_ARRAY; pVal->arr = taosArrayInit(2, POINTER_BYTES); const char* cond = tbnameCond + QUERY_COND_REL_PREFIX_IN_LEN; @@ -502,6 +502,183 @@ void buildFilterSetFromBinary(void **q, const char *buf, int32_t len) { *q = (void *)pObj; } +void convertFilterSetFromBinary(void **q, const char *buf, int32_t len, uint32_t tType) { + SBufferReader br = tbufInitReader(buf, len, false); + uint32_t sType = tbufReadUint32(&br); + SHashObj *pObj = taosHashInit(256, taosGetDefaultHashFunction(tType), true, false); + + taosHashSetEqualFp(pObj, taosGetDefaultEqualFunction(tType)); + + int dummy = -1; + tVariant tmpVar = {0}; + size_t t = 0; + int32_t sz = tbufReadInt32(&br); + void *pvar = NULL; + int64_t val = 0; + int32_t bufLen = 0; + if (IS_NUMERIC_TYPE(sType)) { + bufLen = 60; // The maximum length of string that a number is converted to. + } else { + bufLen = 128; + } + + char *tmp = calloc(1, bufLen * TSDB_NCHAR_SIZE); + + for (int32_t i = 0; i < sz; i++) { + switch (sType) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_TINYINT: { + *(uint8_t *)&val = (uint8_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_SMALLINT: { + *(uint16_t *)&val = (uint16_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_INT: { + *(uint32_t *)&val = (uint32_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_BIGINT: { + *(uint64_t *)&val = (uint64_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_DOUBLE: { + *(double *)&val = tbufReadDouble(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_FLOAT: { + *(float *)&val = (float)tbufReadDouble(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_BINARY: { + pvar = (char *)tbufReadBinary(&br, &t); + break; + } + case TSDB_DATA_TYPE_NCHAR: { + pvar = (char *)tbufReadBinary(&br, &t); + break; + } + default: + taosHashCleanup(pObj); + *q = NULL; + return; + } + + tVariantCreateFromBinary(&tmpVar, (char *)pvar, t, sType); + + if (bufLen < t) { + tmp = realloc(tmp, t * TSDB_NCHAR_SIZE); + bufLen = (int32_t)t; + } + + switch (tType) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_TINYINT: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto err_ret; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_SMALLINT: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto err_ret; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_INT: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto err_ret; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_BIGINT: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto err_ret; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_DOUBLE: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto err_ret; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_FLOAT: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto err_ret; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_BINARY: { + if (tVariantDump(&tmpVar, tmp, tType, true)) { + goto err_ret; + } + t = varDataLen(tmp); + pvar = varDataVal(tmp); + break; + } + case TSDB_DATA_TYPE_NCHAR: { + if (tVariantDump(&tmpVar, tmp, tType, true)) { + goto err_ret; + } + t = varDataLen(tmp); + pvar = varDataVal(tmp); + break; + } + default: + goto err_ret; + } + + taosHashPut(pObj, (char *)pvar, t, &dummy, sizeof(dummy)); + tVariantDestroy(&tmpVar); + memset(&tmpVar, 0, sizeof(tmpVar)); + } + + *q = (void *)pObj; + pObj = NULL; + +err_ret: + tVariantDestroy(&tmpVar); + taosHashCleanup(pObj); + tfree(tmp); +} + + tExprNode* exprdup(tExprNode* pNode) { if (pNode == NULL) { return NULL; diff --git a/src/common/src/tglobal.c b/src/common/src/tglobal.c index a58303e9fc..3c904dc034 100644 --- a/src/common/src/tglobal.c +++ b/src/common/src/tglobal.c @@ -25,6 +25,7 @@ #include "tutil.h" #include "tlocale.h" #include "ttimezone.h" +#include "tcompare.h" // cluster char tsFirst[TSDB_EP_LEN] = {0}; @@ -75,6 +76,7 @@ int32_t tsCompressMsgSize = -1; // client int32_t tsMaxSQLStringLen = TSDB_MAX_ALLOWED_SQL_LEN; +int32_t tsMaxWildCardsLen = TSDB_PATTERN_STRING_MAX_LEN; int8_t tsTscEnableRecordSql = 0; // the maximum number of results for projection query on super table that are returned from @@ -984,6 +986,16 @@ static void doInitGlobalConfig(void) { cfg.unitType = TAOS_CFG_UTYPE_BYTE; taosInitConfigOption(cfg); + cfg.option = "maxWildCardsLength"; + cfg.ptr = &tsMaxWildCardsLen; + cfg.valType = TAOS_CFG_VTYPE_INT32; + cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_CLIENT | TSDB_CFG_CTYPE_B_SHOW; + cfg.minValue = 0; + cfg.maxValue = TSDB_MAX_ALLOWED_SQL_LEN; + cfg.ptrLength = 0; + cfg.unitType = TAOS_CFG_UTYPE_BYTE; + taosInitConfigOption(cfg); + cfg.option = "maxNumOfOrderedRes"; cfg.ptr = &tsMaxNumOfOrderedResults; cfg.valType = TAOS_CFG_VTYPE_INT32; @@ -1531,6 +1543,7 @@ static void doInitGlobalConfig(void) { cfg.unitType = TAOS_CFG_UTYPE_NONE; taosInitConfigOption(cfg); + assert(tsGlobalConfigNum <= TSDB_CFG_MAX_NUM); #ifdef TD_TSZ // lossy compress cfg.option = "lossyColumns"; diff --git a/src/common/src/tname.c b/src/common/src/tname.c index 40433d1f00..532333651d 100644 --- a/src/common/src/tname.c +++ b/src/common/src/tname.c @@ -61,7 +61,7 @@ bool tscValidateTableNameLength(size_t len) { // TODO refactor SColumnFilterInfo* tFilterInfoDup(const SColumnFilterInfo* src, int32_t numOfFilters) { - if (numOfFilters == 0) { + if (numOfFilters == 0 || src == NULL) { assert(src == NULL); return NULL; } diff --git a/src/common/src/ttypes.c b/src/common/src/ttypes.c index eeffe49adc..13c4160e7f 100644 --- a/src/common/src/ttypes.c +++ b/src/common/src/ttypes.c @@ -372,21 +372,21 @@ static void getStatics_nchr(const void *pData, int32_t numOfRow, int64_t *min, i } tDataTypeDescriptor tDataTypes[15] = { - {TSDB_DATA_TYPE_NULL, 6,1, "NOTYPE", NULL, NULL, NULL}, - {TSDB_DATA_TYPE_BOOL, 4, CHAR_BYTES, "BOOL", tsCompressBool, tsDecompressBool, getStatics_bool}, - {TSDB_DATA_TYPE_TINYINT, 7, CHAR_BYTES, "TINYINT", tsCompressTinyint, tsDecompressTinyint, getStatics_i8}, - {TSDB_DATA_TYPE_SMALLINT, 8, SHORT_BYTES, "SMALLINT", tsCompressSmallint, tsDecompressSmallint, getStatics_i16}, - {TSDB_DATA_TYPE_INT, 3, INT_BYTES, "INT", tsCompressInt, tsDecompressInt, getStatics_i32}, - {TSDB_DATA_TYPE_BIGINT, 6, LONG_BYTES, "BIGINT", tsCompressBigint, tsDecompressBigint, getStatics_i64}, - {TSDB_DATA_TYPE_FLOAT, 5, FLOAT_BYTES, "FLOAT", tsCompressFloat, tsDecompressFloat, getStatics_f}, - {TSDB_DATA_TYPE_DOUBLE, 6, DOUBLE_BYTES, "DOUBLE", tsCompressDouble, tsDecompressDouble, getStatics_d}, - {TSDB_DATA_TYPE_BINARY, 6, 0, "BINARY", tsCompressString, tsDecompressString, getStatics_bin}, - {TSDB_DATA_TYPE_TIMESTAMP, 9, LONG_BYTES, "TIMESTAMP", tsCompressTimestamp, tsDecompressTimestamp, getStatics_i64}, - {TSDB_DATA_TYPE_NCHAR, 5, 8, "NCHAR", tsCompressString, tsDecompressString, getStatics_nchr}, - {TSDB_DATA_TYPE_UTINYINT, 16, CHAR_BYTES, "TINYINT UNSIGNED", tsCompressTinyint, tsDecompressTinyint, getStatics_u8}, - {TSDB_DATA_TYPE_USMALLINT, 17, SHORT_BYTES, "SMALLINT UNSIGNED", tsCompressSmallint, tsDecompressSmallint, getStatics_u16}, - {TSDB_DATA_TYPE_UINT, 12, INT_BYTES, "INT UNSIGNED", tsCompressInt, tsDecompressInt, getStatics_u32}, - {TSDB_DATA_TYPE_UBIGINT, 15, LONG_BYTES, "BIGINT UNSIGNED", tsCompressBigint, tsDecompressBigint, getStatics_u64}, + {TSDB_DATA_TYPE_NULL, 6, 1, "NOTYPE", 0, 0, NULL, NULL, NULL}, + {TSDB_DATA_TYPE_BOOL, 4, CHAR_BYTES, "BOOL", false, true, tsCompressBool, tsDecompressBool, getStatics_bool}, + {TSDB_DATA_TYPE_TINYINT, 7, CHAR_BYTES, "TINYINT", INT8_MIN, INT8_MAX, tsCompressTinyint, tsDecompressTinyint, getStatics_i8}, + {TSDB_DATA_TYPE_SMALLINT, 8, SHORT_BYTES, "SMALLINT", INT16_MIN, INT16_MAX, tsCompressSmallint, tsDecompressSmallint, getStatics_i16}, + {TSDB_DATA_TYPE_INT, 3, INT_BYTES, "INT", INT32_MIN, INT32_MAX, tsCompressInt, tsDecompressInt, getStatics_i32}, + {TSDB_DATA_TYPE_BIGINT, 6, LONG_BYTES, "BIGINT", INT64_MIN, INT64_MAX, tsCompressBigint, tsDecompressBigint, getStatics_i64}, + {TSDB_DATA_TYPE_FLOAT, 5, FLOAT_BYTES, "FLOAT", 0, 0, tsCompressFloat, tsDecompressFloat, getStatics_f}, + {TSDB_DATA_TYPE_DOUBLE, 6, DOUBLE_BYTES, "DOUBLE", 0, 0, tsCompressDouble, tsDecompressDouble, getStatics_d}, + {TSDB_DATA_TYPE_BINARY, 6, 0, "BINARY", 0, 0, tsCompressString, tsDecompressString, getStatics_bin}, + {TSDB_DATA_TYPE_TIMESTAMP, 9, LONG_BYTES, "TIMESTAMP", INT64_MIN, INT64_MAX, tsCompressTimestamp, tsDecompressTimestamp, getStatics_i64}, + {TSDB_DATA_TYPE_NCHAR, 5, 8, "NCHAR", 0, 0, tsCompressString, tsDecompressString, getStatics_nchr}, + {TSDB_DATA_TYPE_UTINYINT, 16, CHAR_BYTES, "TINYINT UNSIGNED", 0, UINT8_MAX, tsCompressTinyint, tsDecompressTinyint, getStatics_u8}, + {TSDB_DATA_TYPE_USMALLINT, 17, SHORT_BYTES, "SMALLINT UNSIGNED", 0, UINT16_MAX, tsCompressSmallint, tsDecompressSmallint, getStatics_u16}, + {TSDB_DATA_TYPE_UINT, 12, INT_BYTES, "INT UNSIGNED", 0, UINT32_MAX, tsCompressInt, tsDecompressInt, getStatics_u32}, + {TSDB_DATA_TYPE_UBIGINT, 15, LONG_BYTES, "BIGINT UNSIGNED", 0, UINT64_MAX, tsCompressBigint, tsDecompressBigint, getStatics_u64}, }; char tTokenTypeSwitcher[13] = { @@ -405,6 +405,32 @@ char tTokenTypeSwitcher[13] = { TSDB_DATA_TYPE_NCHAR, // TK_NCHAR }; +float floatMin = -FLT_MAX, floatMax = FLT_MAX; +double doubleMin = -DBL_MAX, doubleMax = DBL_MAX; + +FORCE_INLINE void* getDataMin(int32_t type) { + switch (type) { + case TSDB_DATA_TYPE_FLOAT: + return &floatMin; + case TSDB_DATA_TYPE_DOUBLE: + return &doubleMin; + default: + return &tDataTypes[type].minValue; + } +} + +FORCE_INLINE void* getDataMax(int32_t type) { + switch (type) { + case TSDB_DATA_TYPE_FLOAT: + return &floatMax; + case TSDB_DATA_TYPE_DOUBLE: + return &doubleMax; + default: + return &tDataTypes[type].maxValue; + } +} + + bool isValidDataType(int32_t type) { return type >= TSDB_DATA_TYPE_NULL && type <= TSDB_DATA_TYPE_UBIGINT; } @@ -566,6 +592,53 @@ void assignVal(char *val, const char *src, int32_t len, int32_t type) { } } +void operateVal(void *dst, void *s1, void *s2, int32_t optr, int32_t type) { + if (optr == TSDB_BINARY_OP_ADD) { + switch (type) { + case TSDB_DATA_TYPE_TINYINT: + *((int8_t *)dst) = GET_INT8_VAL(s1) + GET_INT8_VAL(s2); + break; + case TSDB_DATA_TYPE_UTINYINT: + *((uint8_t *)dst) = GET_UINT8_VAL(s1) + GET_UINT8_VAL(s2); + break; + case TSDB_DATA_TYPE_SMALLINT: + *((int16_t *)dst) = GET_INT16_VAL(s1) + GET_INT16_VAL(s2); + break; + case TSDB_DATA_TYPE_USMALLINT: + *((uint16_t *)dst) = GET_UINT16_VAL(s1) + GET_UINT16_VAL(s2); + break; + case TSDB_DATA_TYPE_INT: + *((int32_t *)dst) = GET_INT32_VAL(s1) + GET_INT32_VAL(s2); + break; + case TSDB_DATA_TYPE_UINT: + *((uint32_t *)dst) = GET_UINT32_VAL(s1) + GET_UINT32_VAL(s2); + break; + case TSDB_DATA_TYPE_BIGINT: + *((int64_t *)dst) = GET_INT64_VAL(s1) + GET_INT64_VAL(s2); + break; + case TSDB_DATA_TYPE_UBIGINT: + *((uint64_t *)dst) = GET_UINT64_VAL(s1) + GET_UINT64_VAL(s2); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + *((int64_t *)dst) = GET_INT64_VAL(s1) + GET_INT64_VAL(s2); + break; + case TSDB_DATA_TYPE_FLOAT: + SET_FLOAT_VAL(dst, GET_FLOAT_VAL(s1) + GET_FLOAT_VAL(s2)); + break; + case TSDB_DATA_TYPE_DOUBLE: + SET_DOUBLE_VAL(dst, GET_DOUBLE_VAL(s1) + GET_DOUBLE_VAL(s2)); + break; + default: { + assert(0); + break; + } + } + } else { + assert(0); + } +} + + void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size, void* buf) { switch (type) { case TSDB_DATA_TYPE_INT: diff --git a/src/common/src/tvariant.c b/src/common/src/tvariant.c index 9e0f7ffc74..a491df6f98 100644 --- a/src/common/src/tvariant.c +++ b/src/common/src/tvariant.c @@ -23,6 +23,13 @@ #include "tutil.h" #include "tvariant.h" +#define SET_EXT_INFO(converted, res, minv, maxv, exti) do { \ + if (converted == NULL || exti == NULL || *converted == false) { break; } \ + if ((res) < (minv)) { *exti = -1; break; } \ + if ((res) > (maxv)) { *exti = 1; break; } \ + assert(0); \ + } while (0) + void tVariantCreate(tVariant *pVar, SStrToken *token) { int32_t ret = 0; int32_t type = token->type; @@ -184,7 +191,7 @@ void tVariantDestroy(tVariant *pVar) { } // NOTE: this is only for string array - if (pVar->nType == TSDB_DATA_TYPE_ARRAY) { + if (pVar->nType == TSDB_DATA_TYPE_POINTER_ARRAY) { size_t num = taosArrayGetSize(pVar->arr); for(size_t i = 0; i < num; i++) { void* p = taosArrayGetP(pVar->arr, i); @@ -192,6 +199,9 @@ void tVariantDestroy(tVariant *pVar) { } taosArrayDestroy(pVar->arr); pVar->arr = NULL; + } else if (pVar->nType == TSDB_DATA_TYPE_VALUE_ARRAY) { + taosArrayDestroy(pVar->arr); + pVar->arr = NULL; } } @@ -220,7 +230,7 @@ void tVariantAssign(tVariant *pDst, const tVariant *pSrc) { if (IS_NUMERIC_TYPE(pSrc->nType) || (pSrc->nType == TSDB_DATA_TYPE_BOOL)) { pDst->i64 = pSrc->i64; - } else if (pSrc->nType == TSDB_DATA_TYPE_ARRAY) { // this is only for string array + } else if (pSrc->nType == TSDB_DATA_TYPE_POINTER_ARRAY) { // this is only for string array size_t num = taosArrayGetSize(pSrc->arr); pDst->arr = taosArrayInit(num, sizeof(char*)); for(size_t i = 0; i < num; i++) { @@ -228,9 +238,18 @@ void tVariantAssign(tVariant *pDst, const tVariant *pSrc) { char* n = strdup(p); taosArrayPush(pDst->arr, &n); } + } else if (pSrc->nType == TSDB_DATA_TYPE_VALUE_ARRAY) { + size_t num = taosArrayGetSize(pSrc->arr); + pDst->arr = taosArrayInit(num, sizeof(int64_t)); + pDst->nLen = pSrc->nLen; + assert(pSrc->nLen == num); + for(size_t i = 0; i < num; i++) { + int64_t *p = taosArrayGet(pSrc->arr, i); + taosArrayPush(pDst->arr, p); + } } - if (pDst->nType != TSDB_DATA_TYPE_ARRAY) { + if (pDst->nType != TSDB_DATA_TYPE_POINTER_ARRAY && pDst->nType != TSDB_DATA_TYPE_VALUE_ARRAY) { pDst->nLen = tDataTypes[pDst->nType].bytes; } } @@ -450,7 +469,7 @@ static FORCE_INLINE int32_t convertToDouble(char *pStr, int32_t len, double *val return 0; } -static FORCE_INLINE int32_t convertToInteger(tVariant *pVariant, int64_t *result, int32_t type, bool issigned, bool releaseVariantPtr) { +static FORCE_INLINE int32_t convertToInteger(tVariant *pVariant, int64_t *result, int32_t type, bool issigned, bool releaseVariantPtr, bool *converted) { if (pVariant->nType == TSDB_DATA_TYPE_NULL) { setNull((char *)result, type, tDataTypes[type].bytes); return 0; @@ -540,6 +559,10 @@ static FORCE_INLINE int32_t convertToInteger(tVariant *pVariant, int64_t *result } } + if (converted) { + *converted = true; + } + bool code = false; uint64_t ui = 0; @@ -602,6 +625,18 @@ static int32_t convertToBool(tVariant *pVariant, int64_t *pDest) { * to column type defined in schema */ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix) { + return tVariantDumpEx(pVariant, payload, type, includeLengthPrefix, NULL, NULL); +} + +/* + * transfer data from variant serve as the implicit data conversion: from input sql string pVariant->nType + * to column type defined in schema + */ +int32_t tVariantDumpEx(tVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix, bool *converted, char *extInfo) { + if (converted) { + *converted = false; + } + if (pVariant == NULL || (pVariant->nType != 0 && !isValidDataType(pVariant->nType))) { return -1; } @@ -620,7 +655,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_TINYINT: { - if (convertToInteger(pVariant, &result, type, true, false) < 0) { + if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) { + SET_EXT_INFO(converted, result, INT8_MIN + 1, INT8_MAX, extInfo); return -1; } *((int8_t *)payload) = (int8_t) result; @@ -628,7 +664,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_UTINYINT: { - if (convertToInteger(pVariant, &result, type, false, false) < 0) { + if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) { + SET_EXT_INFO(converted, result, 0, UINT8_MAX - 1, extInfo); return -1; } *((uint8_t *)payload) = (uint8_t) result; @@ -636,7 +673,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_SMALLINT: { - if (convertToInteger(pVariant, &result, type, true, false) < 0) { + if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) { + SET_EXT_INFO(converted, result, INT16_MIN + 1, INT16_MAX, extInfo); return -1; } *((int16_t *)payload) = (int16_t)result; @@ -644,7 +682,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_USMALLINT: { - if (convertToInteger(pVariant, &result, type, false, false) < 0) { + if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) { + SET_EXT_INFO(converted, result, 0, UINT16_MAX - 1, extInfo); return -1; } *((uint16_t *)payload) = (uint16_t)result; @@ -652,7 +691,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_INT: { - if (convertToInteger(pVariant, &result, type, true, false) < 0) { + if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) { + SET_EXT_INFO(converted, result, INT32_MIN + 1, INT32_MAX, extInfo); return -1; } *((int32_t *)payload) = (int32_t)result; @@ -660,7 +700,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_UINT: { - if (convertToInteger(pVariant, &result, type, false, false) < 0) { + if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) { + SET_EXT_INFO(converted, result, 0, UINT32_MAX - 1, extInfo); return -1; } *((uint32_t *)payload) = (uint32_t)result; @@ -668,7 +709,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_BIGINT: { - if (convertToInteger(pVariant, &result, type, true, false) < 0) { + if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) { + SET_EXT_INFO(converted, (int64_t)result, INT64_MIN + 1, INT64_MAX, extInfo); return -1; } *((int64_t *)payload) = (int64_t)result; @@ -676,7 +718,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_UBIGINT: { - if (convertToInteger(pVariant, &result, type, false, false) < 0) { + if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) { + SET_EXT_INFO(converted, (uint64_t)result, 0, UINT64_MAX - 1, extInfo); return -1; } *((uint64_t *)payload) = (uint64_t)result; @@ -696,11 +739,37 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu return -1; } + if (converted) { + *converted = true; + } + + if (value > FLT_MAX || value < -FLT_MAX) { + SET_EXT_INFO(converted, value, -FLT_MAX, FLT_MAX, extInfo); + return -1; + } SET_FLOAT_VAL(payload, value); } } else if (pVariant->nType == TSDB_DATA_TYPE_BOOL || IS_SIGNED_NUMERIC_TYPE(pVariant->nType) || IS_UNSIGNED_NUMERIC_TYPE(pVariant->nType)) { + if (converted) { + *converted = true; + } + + if (pVariant->i64 > FLT_MAX || pVariant->i64 < -FLT_MAX) { + SET_EXT_INFO(converted, pVariant->i64, -FLT_MAX, FLT_MAX, extInfo); + return -1; + } + SET_FLOAT_VAL(payload, pVariant->i64); } else if (IS_FLOAT_TYPE(pVariant->nType)) { + if (converted) { + *converted = true; + } + + if (pVariant->dKey > FLT_MAX || pVariant->dKey < -FLT_MAX) { + SET_EXT_INFO(converted, pVariant->dKey, -FLT_MAX, FLT_MAX, extInfo); + return -1; + } + SET_FLOAT_VAL(payload, pVariant->dKey); } else if (pVariant->nType == TSDB_DATA_TYPE_NULL) { *((uint32_t *)payload) = TSDB_DATA_FLOAT_NULL; @@ -824,6 +893,7 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu return 0; } + /* * In variant, bool/smallint/tinyint/int/bigint share the same attribution of * structure, also ignore the convert the type required @@ -848,7 +918,7 @@ int32_t tVariantTypeSetType(tVariant *pVariant, char type) { case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_TINYINT: case TSDB_DATA_TYPE_SMALLINT: { - convertToInteger(pVariant, &(pVariant->i64), type, true, true); + convertToInteger(pVariant, &(pVariant->i64), type, true, true, NULL); pVariant->nType = TSDB_DATA_TYPE_BIGINT; break; } diff --git a/src/connector/jdbc/pom.xml b/src/connector/jdbc/pom.xml index 907562fe26..fbeeeb56d3 100644 --- a/src/connector/jdbc/pom.xml +++ b/src/connector/jdbc/pom.xml @@ -113,7 +113,6 @@ **/AppMemoryLeakTest.java - **/AuthenticationTest.java **/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java **/DatetimeBefore1970Test.java **/FailOverTest.java 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 f5f16758c1..521a88b128 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 @@ -14,6 +14,8 @@ *****************************************************************************/ package com.taosdata.jdbc; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.sql.*; import java.util.*; import java.util.logging.Logger; @@ -127,6 +129,11 @@ public class TSDBDriver extends AbstractDriver { return null; } + if (!props.containsKey(TSDBDriver.PROPERTY_KEY_USER)) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED); + if (!props.containsKey(TSDBDriver.PROPERTY_KEY_PASSWORD)) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED); + 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)); 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 d626698663..977ae66515 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 @@ -33,6 +33,8 @@ public class TSDBError { TSDBErrorMap.put(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE, "numeric value out of range"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE, "unknown taos type in tdengine"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PRECISION, "unknown timestamp precision"); + TSDBErrorMap.put(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED, "user is required"); + TSDBErrorMap.put(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED, "password is required"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error"); 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 3c44d69be5..2207db6f93 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 @@ -29,6 +29,9 @@ public class TSDBErrorNumbers { public static final int ERROR_UNKNOWN_TIMESTAMP_PRECISION = 0x2316; // unknown timestamp precision public static final int ERROR_RESTFul_Client_Protocol_Exception = 0x2317; public static final int ERROR_RESTFul_Client_IOException = 0x2318; + public static final int ERROR_USER_IS_REQUIRED = 0x2319; // user is required + public static final int ERROR_PASSWORD_IS_REQUIRED = 0x231a; // password is required + public static final int ERROR_UNKNOWN = 0x2350; //unknown error @@ -67,6 +70,8 @@ public class TSDBErrorNumbers { errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE); errorNumbers.add(ERROR_UNKNOWN_TIMESTAMP_PRECISION); errorNumbers.add(ERROR_RESTFul_Client_IOException); + errorNumbers.add(ERROR_USER_IS_REQUIRED); + errorNumbers.add(ERROR_PASSWORD_IS_REQUIRED); errorNumbers.add(ERROR_RESTFul_Client_Protocol_Exception); 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 4fdbb308c5..c634fe2e95 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 @@ -36,7 +36,6 @@ public class TSDBJNIConnector { static { System.loadLibrary("taos"); - System.out.println("java.library.path:" + System.getProperty("java.library.path")); } public boolean isClosed() { 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 9ab67c5502..0a8809e84f 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 @@ -7,6 +7,7 @@ import com.taosdata.jdbc.utils.HttpClientPoolUtil; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.sql.*; import java.util.Properties; import java.util.logging.Logger; @@ -40,8 +41,13 @@ public class RestfulDriver extends AbstractDriver { String loginUrl = "http://" + host + ":" + port + "/rest/login/" + props.getProperty(TSDBDriver.PROPERTY_KEY_USER) + "/" + props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD) + ""; try { - String user = URLEncoder.encode(props.getProperty(TSDBDriver.PROPERTY_KEY_USER), "UTF-8"); - String password = URLEncoder.encode(props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD), "UTF-8"); + if (!props.containsKey(TSDBDriver.PROPERTY_KEY_USER)) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED); + if (!props.containsKey(TSDBDriver.PROPERTY_KEY_PASSWORD)) + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED); + + String user = URLEncoder.encode(props.getProperty(TSDBDriver.PROPERTY_KEY_USER), StandardCharsets.UTF_8.displayName()); + String password = URLEncoder.encode(props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD), StandardCharsets.UTF_8.displayName()); loginUrl = "http://" + props.getProperty(TSDBDriver.PROPERTY_KEY_HOST) + ":" + props.getProperty(TSDBDriver.PROPERTY_KEY_PORT) + "/rest/login/" + user + "/" + password + ""; } catch (UnsupportedEncodingException e) { e.printStackTrace(); 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 f8acd8f061..a88dc411f3 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 @@ -7,6 +7,7 @@ import com.taosdata.jdbc.AbstractStatement; import com.taosdata.jdbc.TSDBDriver; import com.taosdata.jdbc.TSDBError; import com.taosdata.jdbc.TSDBErrorNumbers; +import com.taosdata.jdbc.enums.TimestampFormat; import com.taosdata.jdbc.utils.HttpClientPoolUtil; import com.taosdata.jdbc.utils.SqlSyntaxValidator; @@ -45,9 +46,7 @@ public class RestfulStatement extends AbstractStatement { if (!SqlSyntaxValidator.isValidForExecuteUpdate(sql)) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_UPDATE, "not a valid sql for executeUpdate: " + sql); - final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; - - return executeOneUpdate(url, sql); + return executeOneUpdate(sql); } @Override @@ -62,34 +61,25 @@ public class RestfulStatement extends AbstractStatement { public boolean execute(String sql) throws SQLException { if (isClosed()) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED); - if (!SqlSyntaxValidator.isValidForExecute(sql)) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE, "not a valid sql for execute: " + sql); //如果执行了use操作应该将当前Statement的catalog设置为新的database boolean result = true; - String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; - if (conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).equals("TIMESTAMP")) { - url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt"; - } - if (conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).equals("UTC")) { - url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc"; - } if (SqlSyntaxValidator.isUseSql(sql)) { - HttpClientPoolUtil.execute(url, sql, this.conn.getToken()); + HttpClientPoolUtil.execute(getUrl(), sql, this.conn.getToken()); this.database = sql.trim().replace("use", "").trim(); this.conn.setCatalog(this.database); result = false; } else if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) { executeOneQuery(sql); } else if (SqlSyntaxValidator.isDatabaseUnspecifiedUpdate(sql)) { - executeOneUpdate(url, sql); + executeOneUpdate(sql); result = false; } else { if (SqlSyntaxValidator.isValidForExecuteQuery(sql)) { - executeQuery(sql); + executeOneQuery(sql); } else { - executeUpdate(sql); + executeOneUpdate(sql); result = false; } } @@ -97,19 +87,25 @@ public class RestfulStatement extends AbstractStatement { return result; } + private String getUrl() throws SQLException { + TimestampFormat timestampFormat = TimestampFormat.valueOf(conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).trim().toUpperCase()); + String url; + switch (timestampFormat) { + case TIMESTAMP: + url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt"; + break; + case UTC: + url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc"; + break; + default: + url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; + } + return url; + } + private ResultSet executeOneQuery(String sql) throws SQLException { - if (!SqlSyntaxValidator.isValidForExecuteQuery(sql)) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: " + sql); - // row data - String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; - String timestampFormat = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT); - if ("TIMESTAMP".equalsIgnoreCase(timestampFormat)) - url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt"; - if ("UTC".equalsIgnoreCase(timestampFormat)) - url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc"; - - String result = HttpClientPoolUtil.execute(url, sql, this.conn.getToken()); + String result = HttpClientPoolUtil.execute(getUrl(), sql, this.conn.getToken()); JSONObject resultJson = JSON.parseObject(result); if (resultJson.getString("status").equals("error")) { throw TSDBError.createSQLException(resultJson.getInteger("code"), resultJson.getString("desc")); @@ -119,11 +115,8 @@ public class RestfulStatement extends AbstractStatement { return resultSet; } - private int executeOneUpdate(String url, String sql) throws SQLException { - if (!SqlSyntaxValidator.isValidForExecuteUpdate(sql)) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_UPDATE, "not a valid sql for executeUpdate: " + sql); - - String result = HttpClientPoolUtil.execute(url, sql, this.conn.getToken()); + private int executeOneUpdate(String sql) throws SQLException { + String result = HttpClientPoolUtil.execute(getUrl(), sql, this.conn.getToken()); JSONObject jsonObject = JSON.parseObject(result); if (jsonObject.getString("status").equals("error")) { throw TSDBError.createSQLException(jsonObject.getInteger("code"), jsonObject.getString("desc")); @@ -134,7 +127,7 @@ public class RestfulStatement extends AbstractStatement { } private int getAffectedRows(JSONObject jsonObject) throws SQLException { - // create ... SQLs should return 0 , and Restful result is this: + // create ... SQLs should return 0 , and Restful result like this: // {"status": "succ", "head": ["affected_rows"], "data": [[0]], "rows": 1} JSONArray head = jsonObject.getJSONArray("head"); if (head.size() != 1 || !"affected_rows".equals(head.getString(0))) diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/SqlSyntaxValidator.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/SqlSyntaxValidator.java index 0f99ff4f66..cbd806b35a 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/SqlSyntaxValidator.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/utils/SqlSyntaxValidator.java @@ -16,8 +16,7 @@ package com.taosdata.jdbc.utils; public class SqlSyntaxValidator { - private static final String[] SQL = {"select", "insert", "import", "create", "use", "alter", "drop", "set", "show", "describe", "reset"}; - private static final String[] updateSQL = {"insert", "import", "create", "use", "alter", "drop", "set"}; + private static final String[] updateSQL = {"insert", "import", "create", "use", "alter", "drop", "set", "reset"}; private static final String[] querySQL = {"select", "show", "describe"}; private static final String[] databaseUnspecifiedShow = {"databases", "dnodes", "mnodes", "variables"}; @@ -38,14 +37,6 @@ public class SqlSyntaxValidator { return false; } - public static boolean isValidForExecute(String sql) { - for (String prefix : SQL) { - if (sql.trim().toLowerCase().startsWith(prefix)) - return true; - } - return false; - } - public static boolean isDatabaseUnspecifiedQuery(String sql) { for (String databaseObj : databaseUnspecifiedShow) { if (sql.trim().toLowerCase().matches("show\\s+" + databaseObj + ".*")) @@ -63,9 +54,5 @@ public class SqlSyntaxValidator { return sql.trim().toLowerCase().startsWith("use"); } - public static boolean isSelectSql(String sql) { - return sql.trim().toLowerCase().startsWith("select"); - } - } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SubscribeTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SubscribeTest.java index 24c73fdd5c..95307071e1 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SubscribeTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SubscribeTest.java @@ -69,6 +69,8 @@ public class SubscribeTest { @Before public void createDatabase() throws SQLException { Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata"); 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"); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/AuthenticationTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/AuthenticationTest.java index 6702de9bdb..0ea46dade2 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/AuthenticationTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/AuthenticationTest.java @@ -1,6 +1,9 @@ package com.taosdata.jdbc.cases; +import com.taosdata.jdbc.TSDBErrorNumbers; +import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import java.sql.*; @@ -12,6 +15,47 @@ public class AuthenticationTest { private static final String password = "taos?data"; private Connection conn; + @Test + public void connectWithoutUserByJni() { + try { + DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?"); + } catch (SQLException e) { + Assert.assertEquals(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED, e.getErrorCode()); + Assert.assertEquals("ERROR (2319): user is required", e.getMessage()); + } + } + + @Test + public void connectWithoutUserByRestful() { + try { + DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?"); + } catch (SQLException e) { + Assert.assertEquals(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED, e.getErrorCode()); + Assert.assertEquals("ERROR (2319): user is required", e.getMessage()); + } + } + + @Test + public void connectWithoutPasswordByJni() { + try { + DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root"); + } catch (SQLException e) { + Assert.assertEquals(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED, e.getErrorCode()); + Assert.assertEquals("ERROR (231a): password is required", e.getMessage()); + } + } + + @Test + public void connectWithoutPasswordByRestful() { + try { + DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root"); + } catch (SQLException e) { + Assert.assertEquals(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED, e.getErrorCode()); + Assert.assertEquals("ERROR (231a): password is required", e.getMessage()); + } + } + + @Ignore @Test public void test() { // change password diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BatchInsertTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BatchInsertTest.java index e175d6d114..f2b102cfe7 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BatchInsertTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/BatchInsertTest.java @@ -29,6 +29,8 @@ public class BatchInsertTest { public void before() { try { Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata"); 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"); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ImportTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ImportTest.java index bc11c7f34e..1297a6b4c4 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ImportTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ImportTest.java @@ -21,6 +21,8 @@ public class ImportTest { public static void before() { try { Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata"); 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"); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterJniTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterJniTest.java index 9f8243542f..ac254bebf3 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterJniTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterJniTest.java @@ -270,6 +270,41 @@ public class InsertSpecialCharacterJniTest { } } + @Ignore + @Test + public void testSingleQuotaEscape() throws SQLException { + final long now = System.currentTimeMillis(); + final String sql = "insert into t? using ? tags(?) values(?, ?, ?) t? using " + tbname2 + " tags(?) values(?,?,?) "; + try (PreparedStatement pstmt = conn.prepareStatement(sql)) { + // t1 + pstmt.setInt(1, 1); + pstmt.setString(2, tbname2); + pstmt.setString(3, special_character_str_5); + pstmt.setTimestamp(4, new Timestamp(now)); + pstmt.setBytes(5, special_character_str_5.getBytes()); + // t2 + pstmt.setInt(7, 2); + pstmt.setString(8, special_character_str_5); + pstmt.setTimestamp(9, new Timestamp(now)); + pstmt.setString(11, special_character_str_5); + + int ret = pstmt.executeUpdate(); + Assert.assertEquals(2, ret); + } + + String query = "select * from ?.t? where ? < ? and ts >= ? and f1 is not null"; + try (PreparedStatement pstmt = conn.prepareStatement(query)) { + pstmt.setString(1, dbName); + pstmt.setInt(2, 1); + pstmt.setString(3, "ts"); + pstmt.setTimestamp(4, new Timestamp(System.currentTimeMillis())); + pstmt.setTimestamp(5, new Timestamp(0)); + + ResultSet rs = pstmt.executeQuery(); + Assert.assertNotNull(rs); + } + } + @Test public void testCase10() throws SQLException { final long now = System.currentTimeMillis(); @@ -293,13 +328,12 @@ public class InsertSpecialCharacterJniTest { Assert.assertEquals(2, ret); } //query t1 - String query = "select * from ?.t? where ts < ? and ts >= ? and ? is not null"; + String query = "select * from ?.t? where ts < ? and ts >= ? and f1 is not null"; try (PreparedStatement pstmt = conn.prepareStatement(query)) { pstmt.setString(1, dbName); pstmt.setInt(2, 1); pstmt.setTimestamp(3, new Timestamp(System.currentTimeMillis())); pstmt.setTimestamp(4, new Timestamp(0)); - pstmt.setString(5, "f1"); ResultSet rs = pstmt.executeQuery(); rs.next(); @@ -311,12 +345,11 @@ public class InsertSpecialCharacterJniTest { Assert.assertNull(f2); } // query t2 - query = "select * from t? where ts < ? and ts >= ? and ? is not null"; + query = "select * from t? where ts < ? and ts >= ? and f2 is not null"; try (PreparedStatement pstmt = conn.prepareStatement(query)) { pstmt.setInt(1, 2); pstmt.setTimestamp(2, new Timestamp(System.currentTimeMillis())); pstmt.setTimestamp(3, new Timestamp(0)); - pstmt.setString(4, "f2"); ResultSet rs = pstmt.executeQuery(); rs.next(); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterRestfulTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterRestfulTest.java index 2e981e7f41..eedccec6f1 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterRestfulTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/InsertSpecialCharacterRestfulTest.java @@ -293,13 +293,12 @@ public class InsertSpecialCharacterRestfulTest { Assert.assertEquals(2, ret); } //query t1 - String query = "select * from ?.t? where ts < ? and ts >= ? and ? is not null"; + String query = "select * from ?.t? where ts < ? and ts >= ? and f1 is not null"; try (PreparedStatement pstmt = conn.prepareStatement(query)) { pstmt.setString(1, dbName); pstmt.setInt(2, 1); pstmt.setTimestamp(3, new Timestamp(System.currentTimeMillis())); pstmt.setTimestamp(4, new Timestamp(0)); - pstmt.setString(5, "f1"); ResultSet rs = pstmt.executeQuery(); rs.next(); @@ -311,12 +310,11 @@ public class InsertSpecialCharacterRestfulTest { Assert.assertNull(f2); } // query t2 - query = "select * from t? where ts < ? and ts >= ? and ? is not null"; + query = "select * from t? where ts < ? and ts >= ? and f2 is not null"; try (PreparedStatement pstmt = conn.prepareStatement(query)) { pstmt.setInt(1, 2); pstmt.setTimestamp(2, new Timestamp(System.currentTimeMillis())); pstmt.setTimestamp(3, new Timestamp(0)); - pstmt.setString(4, "f2"); ResultSet rs = pstmt.executeQuery(); rs.next(); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/QueryDataTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/QueryDataTest.java index 3fea221446..b4449491a9 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/QueryDataTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/QueryDataTest.java @@ -22,6 +22,8 @@ public class QueryDataTest { public void createDatabase() { try { Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata"); 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"); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ResetQueryCacheTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ResetQueryCacheTest.java index 4eebbd08e8..48753d62f0 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ResetQueryCacheTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/ResetQueryCacheTest.java @@ -1,51 +1,49 @@ package com.taosdata.jdbc.cases; -import com.taosdata.jdbc.TSDBDriver; -import org.junit.After; -import org.junit.Before; import org.junit.Test; -import java.sql.*; -import java.util.Properties; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; public class ResetQueryCacheTest { - static Connection connection; - static Statement statement; - static String host = "127.0.0.1"; + @Test + public void jni() throws SQLException { + // given + Connection connection = DriverManager.getConnection("jdbc:TAOS://127.0.0.1:0/?user=root&password=taosdata&timezone=UTC-8&charset=UTF-8&locale=en_US.UTF-8"); + Statement statement = connection.createStatement(); - @Before - public void init() { - try { - 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"); - connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties); - statement = connection.createStatement(); - } catch (SQLException e) { - return; - } + // when + boolean execute = statement.execute("reset query cache"); + + // then + assertFalse(execute); + assertEquals(0, statement.getUpdateCount()); + + statement.close(); + connection.close(); } @Test - public void testResetQueryCache() throws SQLException { - String resetSql = "reset query cache"; - statement.execute(resetSql); - } + public void restful() throws SQLException { + // given + Connection connection = DriverManager.getConnection("jdbc:TAOS-RS://127.0.0.1:6041/?user=root&password=taosdata&timezone=UTC-8&charset=UTF-8&locale=en_US.UTF-8"); + Statement statement = connection.createStatement(); - @After - public void close() { - try { - if (statement != null) - statement.close(); - if (connection != null) - connection.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + // when + boolean execute = statement.execute("reset query cache"); + + // then + assertFalse(execute); + assertEquals(0, statement.getUpdateCount()); + + statement.close(); + connection.close(); } } \ No newline at end of file diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/SelectTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/SelectTest.java index 0022ceaf21..b51c0309be 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/SelectTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/SelectTest.java @@ -20,6 +20,8 @@ public class SelectTest { public void createDatabaseAndTable() { try { Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata"); 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"); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/StableTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/StableTest.java index 1600fec13d..8e10743e5e 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/StableTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/StableTest.java @@ -24,6 +24,8 @@ public class StableTest { public static void createDatabase() { try { Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata"); 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"); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/SqlSyntaxValidatorTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/SqlSyntaxValidatorTest.java deleted file mode 100644 index ccb0941da0..0000000000 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/utils/SqlSyntaxValidatorTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.taosdata.jdbc.utils; - -import org.junit.Assert; -import org.junit.Test; - -public class SqlSyntaxValidatorTest { - - @Test - public void isSelectSQL() { - Assert.assertTrue(SqlSyntaxValidator.isSelectSql("select * from test.weather")); - Assert.assertTrue(SqlSyntaxValidator.isSelectSql(" select * from test.weather")); - Assert.assertTrue(SqlSyntaxValidator.isSelectSql(" select * from test.weather ")); - Assert.assertFalse(SqlSyntaxValidator.isSelectSql("insert into test.weather values(now, 1.1, 2)")); - } - - @Test - public void isUseSQL() { - Assert.assertTrue(SqlSyntaxValidator.isUseSql("use database test")); - } - -} \ No newline at end of file diff --git a/src/connector/odbc/examples/go/odbc.go b/src/connector/odbc/examples/go/odbc.go index 4d9c760c4e..4d69d20e9b 100644 --- a/src/connector/odbc/examples/go/odbc.go +++ b/src/connector/odbc/examples/go/odbc.go @@ -1,3 +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 . + */ + package main import ( diff --git a/src/connector/python/README.md b/src/connector/python/README.md index a5dc2b72da..95ef26e1f0 100644 --- a/src/connector/python/README.md +++ b/src/connector/python/README.md @@ -1,6 +1,7 @@ # TDengine Connector for Python -[TDengine] connector for Python enables python programs to access TDengine, using an API which is compliant with the Python DB API 2.0 (PEP-249). It uses TDengine C client library for client server communications. +[TDengine](https://github.com/taosdata/TDengine) connector for Python enables python programs to access TDengine, + using an API which is compliant with the Python DB API 2.0 (PEP-249). It uses TDengine C client library for client server communications. ## Install @@ -11,8 +12,417 @@ pip install ./TDengine/src/connector/python ## Source Code -[TDengine] connector for Python source code is hosted on [GitHub](https://github.com/taosdata/TDengine/tree/develop/src/connector/python). +[TDengine](https://github.com/taosdata/TDengine) connector for Python source code is hosted on [GitHub](https://github.com/taosdata/TDengine/tree/develop/src/connector/python). -## License - AGPL +## Examples + +### Query with PEP-249 API + +```python +import taos + +conn = taos.connect() +cursor = conn.cursor() + +cursor.execute("show databases") +results = cursor.fetchall() +for row in results: + print(row) +cursor.close() +conn.close() +``` + +### Query with objective API + +```python +import taos + +conn = taos.connect() +conn.exec("create database if not exists pytest") + +result = conn.query("show databases") +num_of_fields = result.field_count +for field in result.fields: + print(field) +for row in result: + print(row) +result.close() +conn.exec("drop database pytest") +conn.close() +``` + +### Query with async API + +```python +from taos import * +from ctypes import * +import time + +def fetch_callback(p_param, p_result, num_of_rows): + print("fetched ", num_of_rows, "rows") + p = cast(p_param, POINTER(Counter)) + result = TaosResult(p_result) + + if num_of_rows == 0: + print("fetching completed") + p.contents.done = True + result.close() + return + if num_of_rows < 0: + p.contents.done = True + result.check_error(num_of_rows) + result.close() + return None + + for row in result.rows_iter(num_of_rows): + # print(row) + None + p.contents.count += result.row_count + result.fetch_rows_a(fetch_callback, p_param) + + + +def query_callback(p_param, p_result, code): + # type: (c_void_p, c_void_p, c_int) -> None + if p_result == None: + return + result = TaosResult(p_result) + if code == 0: + result.fetch_rows_a(fetch_callback, p_param) + result.check_error(code) + + +class Counter(Structure): + _fields_ = [("count", c_int), ("done", c_bool)] + + def __str__(self): + return "{ count: %d, done: %s }" % (self.count, self.done) + + +def test_query(conn): + # type: (TaosConnection) -> None + counter = Counter(count=0) + conn.query_a("select * from log.log", query_callback, byref(counter)) + + while not counter.done: + print("wait query callback") + time.sleep(1) + print(counter) + conn.close() + + +if __name__ == "__main__": + test_query(connect()) +``` + +### Statement API - Bind row after row + +```python +from taos import * + +conn = connect() + +dbname = "pytest_taos_stmt" +conn.exec("drop database if exists %s" % dbname) +conn.exec("create database if not exists %s" % dbname) +conn.select_db(dbname) + +conn.exec( + "create table if not exists log(ts timestamp, bo bool, nil tinyint, \ + ti tinyint, si smallint, ii int, bi bigint, tu tinyint unsigned, \ + su smallint unsigned, iu int unsigned, bu bigint unsigned, \ + ff float, dd double, bb binary(100), nn nchar(100), tt timestamp)", +) + +stmt = conn.statement("insert into log values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)") + +params = new_bind_params(16) +params[0].timestamp(1626861392589) +params[1].bool(True) +params[2].null() +params[3].tinyint(2) +params[4].smallint(3) +params[5].int(4) +params[6].bigint(5) +params[7].tinyint_unsigned(6) +params[8].smallint_unsigned(7) +params[9].int_unsigned(8) +params[10].bigint_unsigned(9) +params[11].float(10.1) +params[12].double(10.11) +params[13].binary("hello") +params[14].nchar("stmt") +params[15].timestamp(1626861392589) +stmt.bind_param(params) + +params[0].timestamp(1626861392590) +params[15].null() +stmt.bind_param(params) +stmt.execute() + + +result = stmt.use_result() +assert result.affected_rows == 2 +result.close() + +result = conn.query("select * from log") + +for row in result: + print(row) +result.close() +stmt.close() +conn.close() + +``` + +### Statement API - Bind multi rows + +```python +from taos import * + +conn = connect() + +dbname = "pytest_taos_stmt" +conn.exec("drop database if exists %s" % dbname) +conn.exec("create database if not exists %s" % dbname) +conn.select_db(dbname) + +conn.exec( + "create table if not exists log(ts timestamp, bo bool, nil tinyint, \ + ti tinyint, si smallint, ii int, bi bigint, tu tinyint unsigned, \ + su smallint unsigned, iu int unsigned, bu bigint unsigned, \ + ff float, dd double, bb binary(100), nn nchar(100), tt timestamp)", +) + +stmt = conn.statement("insert into log values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)") + +params = new_multi_binds(16) +params[0].timestamp((1626861392589, 1626861392590, 1626861392591)) +params[1].bool((True, None, False)) +params[2].tinyint([-128, -128, None]) # -128 is tinyint null +params[3].tinyint([0, 127, None]) +params[4].smallint([3, None, 2]) +params[5].int([3, 4, None]) +params[6].bigint([3, 4, None]) +params[7].tinyint_unsigned([3, 4, None]) +params[8].smallint_unsigned([3, 4, None]) +params[9].int_unsigned([3, 4, None]) +params[10].bigint_unsigned([3, 4, None]) +params[11].float([3, None, 1]) +params[12].double([3, None, 1.2]) +params[13].binary(["abc", "dddafadfadfadfadfa", None]) +params[14].nchar(["涛思数据", None, "a long string with 中文字符"]) +params[15].timestamp([None, None, 1626861392591]) +stmt.bind_param_batch(params) +stmt.execute() + + +result = stmt.use_result() +assert result.affected_rows == 3 +result.close() + +result = conn.query("select * from log") +for row in result: + print(row) +result.close() +stmt.close() +conn.close() +``` + +### Statement API - Subscribe + +```python +import taos + +conn = taos.connect() +dbname = "pytest_taos_subscribe_callback" +conn.exec("drop database if exists %s" % dbname) +conn.exec("create database if not exists %s" % dbname) +conn.select_db(dbname) +conn.exec("create table if not exists log(ts timestamp, n int)") +for i in range(10): + conn.exec("insert into log values(now, %d)" % i) + +sub = conn.subscribe(True, "test", "select * from log", 1000) +print("# consume from begin") +for ts, n in sub.consume(): + print(ts, n) + +print("# consume new data") +for i in range(5): + conn.exec("insert into log values(now, %d)(now+1s, %d)" % (i, i)) + result = sub.consume() + for ts, n in result: + print(ts, n) + +print("# consume with a stop condition") +for i in range(10): + conn.exec("insert into log values(now, %d)" % int(random() * 10)) + result = sub.consume() + try: + ts, n = next(result) + print(ts, n) + if n > 5: + result.stop_query() + print("## stopped") + break + except StopIteration: + continue + +sub.close() + +conn.exec("drop database if exists %s" % dbname) +conn.close() +``` + +### Statement API - Subscribe asynchronously with callback + +```python +from taos import * +from ctypes import * + +import time + + +def subscribe_callback(p_sub, p_result, p_param, errno): + # type: (c_void_p, c_void_p, c_void_p, c_int) -> None + print("# fetch in callback") + result = TaosResult(p_result) + result.check_error(errno) + for row in result.rows_iter(): + ts, n = row() + print(ts, n) + + +def test_subscribe_callback(conn): + # type: (TaosConnection) -> None + dbname = "pytest_taos_subscribe_callback" + try: + conn.exec("drop database if exists %s" % dbname) + conn.exec("create database if not exists %s" % dbname) + conn.select_db(dbname) + conn.exec("create table if not exists log(ts timestamp, n int)") + + print("# subscribe with callback") + sub = conn.subscribe(False, "test", "select * from log", 1000, subscribe_callback) + + for i in range(10): + conn.exec("insert into log values(now, %d)" % i) + time.sleep(0.7) + sub.close() + + conn.exec("drop database if exists %s" % dbname) + conn.close() + except Exception as err: + conn.exec("drop database if exists %s" % dbname) + conn.close() + raise err + + +if __name__ == "__main__": + test_subscribe_callback(connect()) + +``` + +### Statement API - Stream + +```python +from taos import * +from ctypes import * + +def stream_callback(p_param, p_result, p_row): + # type: (c_void_p, c_void_p, c_void_p) -> None + + if p_result == None or p_row == None: + return + result = TaosResult(p_result) + row = TaosRow(result, p_row) + try: + ts, count = row() + p = cast(p_param, POINTER(Counter)) + p.contents.count += count + print("[%s] inserted %d in 5s, total count: %d" % (ts.strftime("%Y-%m-%d %H:%M:%S"), count, p.contents.count)) + + except Exception as err: + print(err) + raise err + + +class Counter(ctypes.Structure): + _fields_ = [ + ("count", c_int), + ] + + def __str__(self): + return "%d" % self.count + + +def test_stream(conn): + # type: (TaosConnection) -> None + dbname = "pytest_taos_stream" + try: + conn.exec("drop database if exists %s" % dbname) + conn.exec("create database if not exists %s" % dbname) + conn.select_db(dbname) + conn.exec("create table if not exists log(ts timestamp, n int)") + + result = conn.query("select count(*) from log interval(5s)") + assert result.field_count == 2 + counter = Counter() + counter.count = 0 + stream = conn.stream("select count(*) from log interval(5s)", stream_callback, param=byref(counter)) + + for _ in range(0, 20): + conn.exec("insert into log values(now,0)(now+1s, 1)(now + 2s, 2)") + time.sleep(2) + stream.close() + conn.exec("drop database if exists %s" % dbname) + conn.close() + except Exception as err: + conn.exec("drop database if exists %s" % dbname) + conn.close() + raise err + + +if __name__ == "__main__": + test_stream(connect()) +``` + +### Insert with line protocol + +```python +import taos + +conn = taos.connect() +dbname = "pytest_line" +conn.exec("drop database if exists %s" % dbname) +conn.exec("create database if not exists %s precision 'us'" % dbname) +conn.select_db(dbname) + +lines = [ + 'st,t1=3i64,t2=4f64,t3="t3" c1=3i64,c3=L"pass",c2=false,c4=4f64 1626006833639000000ns', + 'st,t1=4i64,t3="t4",t2=5f64,t4=5f64 c1=3i64,c3=L"pass it again",c2=true,c4=5f64,c5=5f64,c6=7u64 1626006933640000000ns', + 'stf,t1=4i64,t3="t4",t2=5f64,t4=5f64 c1=3i64,c3=L"pass it again_stf",c2=false,c5=5f64,c6=7u64 1626006933641000000ns', +] +conn.insert_lines(lines) +print("inserted") + +lines = [ + 'stf,t1=5i64,t3="t4",t2=5f64,t4=5f64 c1=3i64,c3=L"pass it again_stf",c2=false,c5=5f64,c6=7u64 1626006933641000000ns', +] +conn.insert_lines(lines) + +result = conn.query("show tables") +for row in result: + print(row) +result.close() + + +conn.exec("drop database if exists %s" % dbname) +conn.close() + +``` + +## License - AGPL-3.0 Keep same with [TDengine](https://github.com/taosdata/TDengine). diff --git a/src/connector/python/examples/bind-multi.py b/src/connector/python/examples/bind-multi.py new file mode 100644 index 0000000000..8530253aef --- /dev/null +++ b/src/connector/python/examples/bind-multi.py @@ -0,0 +1,50 @@ +# encoding:UTF-8 +from taos import * + +conn = connect() + +dbname = "pytest_taos_stmt_multi" +conn.execute("drop database if exists %s" % dbname) +conn.execute("create database if not exists %s" % dbname) +conn.select_db(dbname) + +conn.execute( + "create table if not exists log(ts timestamp, bo bool, nil tinyint, \ + ti tinyint, si smallint, ii int, bi bigint, tu tinyint unsigned, \ + su smallint unsigned, iu int unsigned, bu bigint unsigned, \ + ff float, dd double, bb binary(100), nn nchar(100), tt timestamp)", +) + +stmt = conn.statement("insert into log values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)") + +params = new_multi_binds(16) +params[0].timestamp((1626861392589, 1626861392590, 1626861392591)) +params[1].bool((True, None, False)) +params[2].tinyint([-128, -128, None]) # -128 is tinyint null +params[3].tinyint([0, 127, None]) +params[4].smallint([3, None, 2]) +params[5].int([3, 4, None]) +params[6].bigint([3, 4, None]) +params[7].tinyint_unsigned([3, 4, None]) +params[8].smallint_unsigned([3, 4, None]) +params[9].int_unsigned([3, 4, None]) +params[10].bigint_unsigned([3, 4, None]) +params[11].float([3, None, 1]) +params[12].double([3, None, 1.2]) +params[13].binary(["abc", "dddafadfadfadfadfa", None]) +params[14].nchar(["涛思数据", None, "a long string with 中文字符"]) +params[15].timestamp([None, None, 1626861392591]) +stmt.bind_param_batch(params) +stmt.execute() + + +result = stmt.use_result() +assert result.affected_rows == 3 +result.close() + +result = conn.query("select * from log") +for row in result: + print(row) +result.close() +stmt.close() +conn.close() \ No newline at end of file diff --git a/src/connector/python/examples/bind-row.py b/src/connector/python/examples/bind-row.py new file mode 100644 index 0000000000..4ab9a9167a --- /dev/null +++ b/src/connector/python/examples/bind-row.py @@ -0,0 +1,57 @@ +from taos import * + +conn = connect() + +dbname = "pytest_taos_stmt" +conn.execute("drop database if exists %s" % dbname) +conn.execute("create database if not exists %s" % dbname) +conn.select_db(dbname) + +conn.execute( + "create table if not exists log(ts timestamp, bo bool, nil tinyint, \ + ti tinyint, si smallint, ii int, bi bigint, tu tinyint unsigned, \ + su smallint unsigned, iu int unsigned, bu bigint unsigned, \ + ff float, dd double, bb binary(100), nn nchar(100), tt timestamp)", +) + +stmt = conn.statement("insert into log values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)") + +params = new_bind_params(16) +params[0].timestamp(1626861392589) +params[1].bool(True) +params[2].null() +params[3].tinyint(2) +params[4].smallint(3) +params[5].int(4) +params[6].bigint(5) +params[7].tinyint_unsigned(6) +params[8].smallint_unsigned(7) +params[9].int_unsigned(8) +params[10].bigint_unsigned(9) +params[11].float(10.1) +params[12].double(10.11) +params[13].binary("hello") +params[14].nchar("stmt") +params[15].timestamp(1626861392589) +stmt.bind_param(params) + +params[0].timestamp(1626861392590) +params[15].null() +stmt.bind_param(params) +stmt.execute() + + +result = stmt.use_result() +assert result.affected_rows == 2 +# No need to explicitly close, but ok for you +# result.close() + +result = conn.query("select * from log") + +for row in result: + print(row) + +# No need to explicitly close, but ok for you +# result.close() +# stmt.close() +# conn.close() diff --git a/src/connector/python/examples/insert-lines.py b/src/connector/python/examples/insert-lines.py new file mode 100644 index 0000000000..0096b7e8cd --- /dev/null +++ b/src/connector/python/examples/insert-lines.py @@ -0,0 +1,22 @@ +import taos + +conn = taos.connect() +dbname = "pytest_line" +conn.execute("drop database if exists %s" % dbname) +conn.execute("create database if not exists %s precision 'us'" % dbname) +conn.select_db(dbname) + +lines = [ + 'st,t1=3i64,t2=4f64,t3="t3" c1=3i64,c3=L"pass",c2=false,c4=4f64 1626006833639000000ns', +] +conn.insert_lines(lines) +print("inserted") + +conn.insert_lines(lines) + +result = conn.query("show tables") +for row in result: + print(row) + + +conn.execute("drop database if exists %s" % dbname) diff --git a/src/connector/python/examples/pep-249.py b/src/connector/python/examples/pep-249.py new file mode 100644 index 0000000000..971a3c401f --- /dev/null +++ b/src/connector/python/examples/pep-249.py @@ -0,0 +1,9 @@ +import taos + +conn = taos.connect() +cursor = conn.cursor() + +cursor.execute("show databases") +results = cursor.fetchall() +for row in results: + print(row) diff --git a/src/connector/python/examples/query-async.py b/src/connector/python/examples/query-async.py new file mode 100644 index 0000000000..b600b79697 --- /dev/null +++ b/src/connector/python/examples/query-async.py @@ -0,0 +1,62 @@ +from taos import * +from ctypes import * +import time + +def fetch_callback(p_param, p_result, num_of_rows): + print("fetched ", num_of_rows, "rows") + p = cast(p_param, POINTER(Counter)) + result = TaosResult(p_result) + + if num_of_rows == 0: + print("fetching completed") + p.contents.done = True + # should explicitly close the result in fetch completed or cause error + result.close() + return + if num_of_rows < 0: + p.contents.done = True + result.check_error(num_of_rows) + result.close() + return None + + for row in result.rows_iter(num_of_rows): + # print(row) + None + p.contents.count += result.row_count + result.fetch_rows_a(fetch_callback, p_param) + + + +def query_callback(p_param, p_result, code): + # type: (c_void_p, c_void_p, c_int) -> None + if p_result == None: + return + result = TaosResult(p_result) + if code == 0: + result.fetch_rows_a(fetch_callback, p_param) + result.check_error(code) + # explicitly close result while query failed + result.close() + + +class Counter(Structure): + _fields_ = [("count", c_int), ("done", c_bool)] + + def __str__(self): + return "{ count: %d, done: %s }" % (self.count, self.done) + + +def test_query(conn): + # type: (TaosConnection) -> None + counter = Counter(count=0) + conn.query_a("select * from log.log", query_callback, byref(counter)) + + while not counter.done: + print("wait query callback") + time.sleep(1) + print(counter) + # conn.close() + + +if __name__ == "__main__": + test_query(connect()) \ No newline at end of file diff --git a/src/connector/python/examples/query-objectively.py b/src/connector/python/examples/query-objectively.py new file mode 100644 index 0000000000..104347cbf9 --- /dev/null +++ b/src/connector/python/examples/query-objectively.py @@ -0,0 +1,12 @@ +import taos + +conn = taos.connect() +conn.execute("create database if not exists pytest") + +result = conn.query("show databases") +num_of_fields = result.field_count +for field in result.fields: + print(field) +for row in result: + print(row) +conn.execute("drop database pytest") diff --git a/src/connector/python/examples/subscribe-async.py b/src/connector/python/examples/subscribe-async.py new file mode 100644 index 0000000000..3782ce5505 --- /dev/null +++ b/src/connector/python/examples/subscribe-async.py @@ -0,0 +1,43 @@ +from taos import * +from ctypes import * + +import time + + +def subscribe_callback(p_sub, p_result, p_param, errno): + # type: (c_void_p, c_void_p, c_void_p, c_int) -> None + print("# fetch in callback") + result = TaosResult(p_result) + result.check_error(errno) + for row in result.rows_iter(): + ts, n = row() + print(ts, n) + + +def test_subscribe_callback(conn): + # type: (TaosConnection) -> None + dbname = "pytest_taos_subscribe_callback" + try: + conn.execute("drop database if exists %s" % dbname) + conn.execute("create database if not exists %s" % dbname) + conn.select_db(dbname) + conn.execute("create table if not exists log(ts timestamp, n int)") + + print("# subscribe with callback") + sub = conn.subscribe(False, "test", "select * from log", 1000, subscribe_callback) + + for i in range(10): + conn.execute("insert into log values(now, %d)" % i) + time.sleep(0.7) + # sub.close() + + conn.execute("drop database if exists %s" % dbname) + # conn.close() + except Exception as err: + conn.execute("drop database if exists %s" % dbname) + # conn.close() + raise err + + +if __name__ == "__main__": + test_subscribe_callback(connect()) diff --git a/src/connector/python/examples/subscribe-sync.py b/src/connector/python/examples/subscribe-sync.py new file mode 100644 index 0000000000..3a7f65f460 --- /dev/null +++ b/src/connector/python/examples/subscribe-sync.py @@ -0,0 +1,53 @@ +import taos +import random + +conn = taos.connect() +dbname = "pytest_taos_subscribe" +conn.execute("drop database if exists %s" % dbname) +conn.execute("create database if not exists %s" % dbname) +conn.select_db(dbname) +conn.execute("create table if not exists log(ts timestamp, n int)") +for i in range(10): + conn.execute("insert into log values(now, %d)" % i) + +sub = conn.subscribe(False, "test", "select * from log", 1000) +print("# consume from begin") +for ts, n in sub.consume(): + print(ts, n) + +print("# consume new data") +for i in range(5): + conn.execute("insert into log values(now, %d)(now+1s, %d)" % (i, i)) + result = sub.consume() + for ts, n in result: + print(ts, n) + +sub.close(True) +print("# keep progress consume") +sub = conn.subscribe(False, "test", "select * from log", 1000) +result = sub.consume() +rows = result.fetch_all() +# consume from latest subscription needs root privilege(for /var/lib/taos). +assert result.row_count == 0 +print("## consumed ", len(rows), "rows") + +print("# consume with a stop condition") +for i in range(10): + conn.execute("insert into log values(now, %d)" % random.randint(0, 10)) + result = sub.consume() + try: + ts, n = next(result) + print(ts, n) + if n > 5: + result.stop_query() + print("## stopped") + break + except StopIteration: + continue + +sub.close() + +# sub.close() + +conn.execute("drop database if exists %s" % dbname) +# conn.close() diff --git a/src/connector/python/pyproject.toml b/src/connector/python/pyproject.toml new file mode 100644 index 0000000000..a809919956 --- /dev/null +++ b/src/connector/python/pyproject.toml @@ -0,0 +1,27 @@ +[tool.poetry] +name = "taos" +version = "2.1.0" +description = "TDengine connector for python" +authors = ["Taosdata Inc. "] +license = "AGPL-3.0" +readme = "README.md" + +[tool.poetry.dependencies] +python = "^2.7 || ^3.4" +typing = "*" + +[tool.poetry.dev-dependencies] +pytest = [ + { version = "^4.6", python = "^2.7" }, + { version = "^6.2", python = "^3.7" } +] +pdoc = { version = "^7.1.1", python = "^3.7" } +mypy = { version = "^0.910", python = "^3.6" } +black = { version = "^21.7b0", python = "^3.6" } + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" + +[tool.black] +line-length = 119 diff --git a/src/connector/python/setup.py b/src/connector/python/setup.py index 284861ca87..b7e1000173 100644 --- a/src/connector/python/setup.py +++ b/src/connector/python/setup.py @@ -5,7 +5,7 @@ with open("README.md", "r") as fh: setuptools.setup( name="taos", - version="2.0.11", + version="2.1.0", author="Taosdata Inc.", author_email="support@taosdata.com", description="TDengine python client package", diff --git a/src/connector/python/taos/__init__.py b/src/connector/python/taos/__init__.py index 52c6db311e..75138eade3 100644 --- a/src/connector/python/taos/__init__.py +++ b/src/connector/python/taos/__init__.py @@ -1,20 +1,478 @@ +# encoding:UTF-8 +""" +# TDengine Connector for Python -from .connection import TDengineConnection -from .cursor import TDengineCursor +[TDengine](https://github.com/taosdata/TDengine) connector for Python enables python programs to access TDengine, + using an API which is compliant with the Python DB API 2.0 (PEP-249). It uses TDengine C client library for client server communications. -# For some reason, the following is needed for VS Code (through PyLance) to +## Install + +```sh +git clone --depth 1 https://github.com/taosdata/TDengine.git +pip install ./TDengine/src/connector/python +``` + +## Source Code + +[TDengine](https://github.com/taosdata/TDengine) connector for Python source code is hosted on [GitHub](https://github.com/taosdata/TDengine/tree/develop/src/connector/python). + +## Examples + +### Query with PEP-249 API + +```python +import taos + +conn = taos.connect() +cursor = conn.cursor() + +cursor.execute("show databases") +results = cursor.fetchall() +for row in results: + print(row) +cursor.close() +conn.close() +``` + +### Query with objective API + +```python +import taos + +conn = taos.connect() +conn.exec("create database if not exists pytest") + +result = conn.query("show databases") +num_of_fields = result.field_count +for field in result.fields: + print(field) +for row in result: + print(row) +result.close() +conn.exec("drop database pytest") +conn.close() +``` + +### Query with async API + +```python +from taos import * +from ctypes import * +import time + +def fetch_callback(p_param, p_result, num_of_rows): + print("fetched ", num_of_rows, "rows") + p = cast(p_param, POINTER(Counter)) + result = TaosResult(p_result) + + if num_of_rows == 0: + print("fetching completed") + p.contents.done = True + result.close() + return + if num_of_rows < 0: + p.contents.done = True + result.check_error(num_of_rows) + result.close() + return None + + for row in result.rows_iter(num_of_rows): + # print(row) + None + p.contents.count += result.row_count + result.fetch_rows_a(fetch_callback, p_param) + + + +def query_callback(p_param, p_result, code): + # type: (c_void_p, c_void_p, c_int) -> None + if p_result == None: + return + result = TaosResult(p_result) + if code == 0: + result.fetch_rows_a(fetch_callback, p_param) + result.check_error(code) + + +class Counter(Structure): + _fields_ = [("count", c_int), ("done", c_bool)] + + def __str__(self): + return "{ count: %d, done: %s }" % (self.count, self.done) + + +def test_query(conn): + # type: (TaosConnection) -> None + counter = Counter(count=0) + conn.query_a("select * from log.log", query_callback, byref(counter)) + + while not counter.done: + print("wait query callback") + time.sleep(1) + print(counter) + conn.close() + + +if __name__ == "__main__": + test_query(connect()) +``` + +### Statement API - Bind row after row + +```python +from taos import * + +conn = connect() + +dbname = "pytest_taos_stmt" +conn.exec("drop database if exists %s" % dbname) +conn.exec("create database if not exists %s" % dbname) +conn.select_db(dbname) + +conn.exec( + "create table if not exists log(ts timestamp, bo bool, nil tinyint, \\ + ti tinyint, si smallint, ii int, bi bigint, tu tinyint unsigned, \\ + su smallint unsigned, iu int unsigned, bu bigint unsigned, \\ + ff float, dd double, bb binary(100), nn nchar(100), tt timestamp)", +) + +stmt = conn.statement("insert into log values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)") + +params = new_bind_params(16) +params[0].timestamp(1626861392589) +params[1].bool(True) +params[2].null() +params[3].tinyint(2) +params[4].smallint(3) +params[5].int(4) +params[6].bigint(5) +params[7].tinyint_unsigned(6) +params[8].smallint_unsigned(7) +params[9].int_unsigned(8) +params[10].bigint_unsigned(9) +params[11].float(10.1) +params[12].double(10.11) +params[13].binary("hello") +params[14].nchar("stmt") +params[15].timestamp(1626861392589) +stmt.bind_param(params) + +params[0].timestamp(1626861392590) +params[15].null() +stmt.bind_param(params) +stmt.execute() + + +result = stmt.use_result() +assert result.affected_rows == 2 +result.close() + +result = conn.query("select * from log") + +for row in result: + print(row) +result.close() +stmt.close() +conn.close() + +``` + +### Statement API - Bind multi rows + +```python +from taos import * + +conn = connect() + +dbname = "pytest_taos_stmt" +conn.exec("drop database if exists %s" % dbname) +conn.exec("create database if not exists %s" % dbname) +conn.select_db(dbname) + +conn.exec( + "create table if not exists log(ts timestamp, bo bool, nil tinyint, \\ + ti tinyint, si smallint, ii int, bi bigint, tu tinyint unsigned, \\ + su smallint unsigned, iu int unsigned, bu bigint unsigned, \\ + ff float, dd double, bb binary(100), nn nchar(100), tt timestamp)", +) + +stmt = conn.statement("insert into log values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)") + +params = new_multi_binds(16) +params[0].timestamp((1626861392589, 1626861392590, 1626861392591)) +params[1].bool((True, None, False)) +params[2].tinyint([-128, -128, None]) # -128 is tinyint null +params[3].tinyint([0, 127, None]) +params[4].smallint([3, None, 2]) +params[5].int([3, 4, None]) +params[6].bigint([3, 4, None]) +params[7].tinyint_unsigned([3, 4, None]) +params[8].smallint_unsigned([3, 4, None]) +params[9].int_unsigned([3, 4, None]) +params[10].bigint_unsigned([3, 4, None]) +params[11].float([3, None, 1]) +params[12].double([3, None, 1.2]) +params[13].binary(["abc", "dddafadfadfadfadfa", None]) +params[14].nchar(["涛思数据", None, "a long string with 中文字符"]) +params[15].timestamp([None, None, 1626861392591]) +stmt.bind_param_batch(params) +stmt.execute() + + +result = stmt.use_result() +assert result.affected_rows == 3 +result.close() + +result = conn.query("select * from log") +for row in result: + print(row) +result.close() +stmt.close() +conn.close() +``` + +### Statement API - Subscribe + +```python +import taos + +conn = taos.connect() +dbname = "pytest_taos_subscribe_callback" +conn.exec("drop database if exists %s" % dbname) +conn.exec("create database if not exists %s" % dbname) +conn.select_db(dbname) +conn.exec("create table if not exists log(ts timestamp, n int)") +for i in range(10): + conn.exec("insert into log values(now, %d)" % i) + +sub = conn.subscribe(True, "test", "select * from log", 1000) +print("# consume from begin") +for ts, n in sub.consume(): + print(ts, n) + +print("# consume new data") +for i in range(5): + conn.exec("insert into log values(now, %d)(now+1s, %d)" % (i, i)) + result = sub.consume() + for ts, n in result: + print(ts, n) + +print("# consume with a stop condition") +for i in range(10): + conn.exec("insert into log values(now, %d)" % int(random() * 10)) + result = sub.consume() + try: + ts, n = next(result) + print(ts, n) + if n > 5: + result.stop_query() + print("## stopped") + break + except StopIteration: + continue + +sub.close() + +conn.exec("drop database if exists %s" % dbname) +conn.close() +``` + +### Statement API - Subscribe asynchronously with callback + +```python +from taos import * +from ctypes import * + +import time + + +def subscribe_callback(p_sub, p_result, p_param, errno): + # type: (c_void_p, c_void_p, c_void_p, c_int) -> None + print("# fetch in callback") + result = TaosResult(p_result) + result.check_error(errno) + for row in result.rows_iter(): + ts, n = row() + print(ts, n) + + +def test_subscribe_callback(conn): + # type: (TaosConnection) -> None + dbname = "pytest_taos_subscribe_callback" + try: + conn.exec("drop database if exists %s" % dbname) + conn.exec("create database if not exists %s" % dbname) + conn.select_db(dbname) + conn.exec("create table if not exists log(ts timestamp, n int)") + + print("# subscribe with callback") + sub = conn.subscribe(False, "test", "select * from log", 1000, subscribe_callback) + + for i in range(10): + conn.exec("insert into log values(now, %d)" % i) + time.sleep(0.7) + sub.close() + + conn.exec("drop database if exists %s" % dbname) + conn.close() + except Exception as err: + conn.exec("drop database if exists %s" % dbname) + conn.close() + raise err + + +if __name__ == "__main__": + test_subscribe_callback(connect()) + +``` + +### Statement API - Stream + +```python +from taos import * +from ctypes import * + +def stream_callback(p_param, p_result, p_row): + # type: (c_void_p, c_void_p, c_void_p) -> None + + if p_result == None or p_row == None: + return + result = TaosResult(p_result) + row = TaosRow(result, p_row) + try: + ts, count = row() + p = cast(p_param, POINTER(Counter)) + p.contents.count += count + print("[%s] inserted %d in 5s, total count: %d" % (ts.strftime("%Y-%m-%d %H:%M:%S"), count, p.contents.count)) + + except Exception as err: + print(err) + raise err + + +class Counter(ctypes.Structure): + _fields_ = [ + ("count", c_int), + ] + + def __str__(self): + return "%d" % self.count + + +def test_stream(conn): + # type: (TaosConnection) -> None + dbname = "pytest_taos_stream" + try: + conn.exec("drop database if exists %s" % dbname) + conn.exec("create database if not exists %s" % dbname) + conn.select_db(dbname) + conn.exec("create table if not exists log(ts timestamp, n int)") + + result = conn.query("select count(*) from log interval(5s)") + assert result.field_count == 2 + counter = Counter() + counter.count = 0 + stream = conn.stream("select count(*) from log interval(5s)", stream_callback, param=byref(counter)) + + for _ in range(0, 20): + conn.exec("insert into log values(now,0)(now+1s, 1)(now + 2s, 2)") + time.sleep(2) + stream.close() + conn.exec("drop database if exists %s" % dbname) + conn.close() + except Exception as err: + conn.exec("drop database if exists %s" % dbname) + conn.close() + raise err + + +if __name__ == "__main__": + test_stream(connect()) +``` + +### Insert with line protocol + +```python +import taos + +conn = taos.connect() +dbname = "pytest_line" +conn.exec("drop database if exists %s" % dbname) +conn.exec("create database if not exists %s precision 'us'" % dbname) +conn.select_db(dbname) + +lines = [ + 'st,t1=3i64,t2=4f64,t3="t3" c1=3i64,c3=L"passit",c2=false,c4=4f64 1626006833639000000ns', + 'st,t1=4i64,t3="t4",t2=5f64,t4=5f64 c1=3i64,c3=L"passitagin",c2=true,c4=5f64,c5=5f64,c6=7u64 1626006933640000000ns', + 'stf,t1=4i64,t3="t4",t2=5f64,t4=5f64 c1=3i64,c3=L"passitagin_stf",c2=false,c5=5f64,c6=7u64 1626006933641000000ns', +] +conn.insert_lines(lines) +print("inserted") + +lines = [ + 'stf,t1=5i64,t3="t4",t2=5f64,t4=5f64 c1=3i64,c3=L"passitagin_stf",c2=false,c5=5f64,c6=7u64 1626006933641000000ns', +] +conn.insert_lines(lines) + +result = conn.query("show tables") +for row in result: + print(row) +result.close() + + +conn.exec("drop database if exists %s" % dbname) +conn.close() + +``` + +## License - AGPL-3.0 + +Keep same with [TDengine](https://github.com/taosdata/TDengine). +""" +from .connection import TaosConnection + +# For some reason, the following is needed for VS Code (through PyLance) to # recognize that "error" is a valid module of the "taos" package. -from .error import ProgrammingError +from .error import * +from .bind import * +from .field import * +from .cursor import * +from .result import * +from .statement import * +from .subscription import * + +try: + import importlib.metadata + + __version__ = importlib.metadata.version("taos") +except: + None # Globals threadsafety = 0 -paramstyle = 'pyformat' - -__all__ = ['connection', 'cursor'] +paramstyle = "pyformat" +__all__ = [ + # functions + "connect", + "new_bind_param", + "new_bind_params", + "new_multi_binds", + "new_multi_bind", + # objects + "TaosBind", + "TaosConnection", + "TaosCursor", + "TaosResult", + "TaosRows", + "TaosRow", + "TaosStmt", + "PrecisionEnum", +] def connect(*args, **kwargs): - """ Function to return a TDengine connector object + # type: (..., ...) -> TaosConnection + """Function to return a TDengine connector object Current supporting keyword parameters: @dsn: Data source name as string @@ -25,4 +483,4 @@ def connect(*args, **kwargs): @rtype: TDengineConnector """ - return TDengineConnection(*args, **kwargs) + return TaosConnection(*args, **kwargs) diff --git a/src/connector/python/taos/bind.py b/src/connector/python/taos/bind.py new file mode 100644 index 0000000000..ede6381628 --- /dev/null +++ b/src/connector/python/taos/bind.py @@ -0,0 +1,432 @@ +# encoding:UTF-8 +import ctypes +from .constants import FieldType +from .error import * +from .precision import * +from datetime import datetime +from ctypes import * +import sys + +_datetime_epoch = datetime.utcfromtimestamp(0) + +def _is_not_none(obj): + obj != None +class TaosBind(ctypes.Structure): + _fields_ = [ + ("buffer_type", c_int), + ("buffer", c_void_p), + ("buffer_length", c_size_t), + ("length", POINTER(c_size_t)), + ("is_null", POINTER(c_int)), + ("is_unsigned", c_int), + ("error", POINTER(c_int)), + ("u", c_int64), + ("allocated", c_int), + ] + + def null(self): + self.buffer_type = FieldType.C_NULL + self.is_null = pointer(c_int(1)) + + def bool(self, value): + self.buffer_type = FieldType.C_BOOL + self.buffer = cast(pointer(c_bool(value)), c_void_p) + self.buffer_length = sizeof(c_bool) + + def tinyint(self, value): + self.buffer_type = FieldType.C_TINYINT + self.buffer = cast(pointer(c_int8(value)), c_void_p) + self.buffer_length = sizeof(c_int8) + + def smallint(self, value): + self.buffer_type = FieldType.C_SMALLINT + self.buffer = cast(pointer(c_int16(value)), c_void_p) + self.buffer_length = sizeof(c_int16) + + def int(self, value): + self.buffer_type = FieldType.C_INT + self.buffer = cast(pointer(c_int32(value)), c_void_p) + self.buffer_length = sizeof(c_int32) + + def bigint(self, value): + self.buffer_type = FieldType.C_BIGINT + self.buffer = cast(pointer(c_int64(value)), c_void_p) + self.buffer_length = sizeof(c_int64) + + def float(self, value): + self.buffer_type = FieldType.C_FLOAT + self.buffer = cast(pointer(c_float(value)), c_void_p) + self.buffer_length = sizeof(c_float) + + def double(self, value): + self.buffer_type = FieldType.C_DOUBLE + self.buffer = cast(pointer(c_double(value)), c_void_p) + self.buffer_length = sizeof(c_double) + + def binary(self, value): + buffer = None + length = 0 + if isinstance(value, str): + bytes = value.encode("utf-8") + buffer = create_string_buffer(bytes) + length = len(bytes) + else: + buffer = value + length = len(value) + self.buffer_type = FieldType.C_BINARY + self.buffer = cast(buffer, c_void_p) + self.buffer_length = length + self.length = pointer(c_size_t(self.buffer_length)) + + def timestamp(self, value, precision=PrecisionEnum.Milliseconds): + if type(value) is datetime: + if precision == PrecisionEnum.Milliseconds: + ts = int(round((value - _datetime_epoch).total_seconds() * 1000)) + elif precision == PrecisionEnum.Microseconds: + ts = int(round((value - _datetime_epoch).total_seconds() * 10000000)) + else: + raise PrecisionError("datetime do not support nanosecond precision") + elif type(value) is float: + if precision == PrecisionEnum.Milliseconds: + ts = int(round(value * 1000)) + elif precision == PrecisionEnum.Microseconds: + ts = int(round(value * 10000000)) + else: + raise PrecisionError("time float do not support nanosecond precision") + elif isinstance(value, int) and not isinstance(value, bool): + ts = value + elif isinstance(value, str): + value = datetime.fromisoformat(value) + if precision == PrecisionEnum.Milliseconds: + ts = int(round(value * 1000)) + elif precision == PrecisionEnum.Microseconds: + ts = int(round(value * 10000000)) + else: + raise PrecisionError("datetime do not support nanosecond precision") + + self.buffer_type = FieldType.C_TIMESTAMP + self.buffer = cast(pointer(c_int64(ts)), c_void_p) + self.buffer_length = sizeof(c_int64) + + def nchar(self, value): + buffer = None + length = 0 + if isinstance(value, str): + bytes = value.encode("utf-8") + buffer = create_string_buffer(bytes) + length = len(bytes) + else: + buffer = value + length = len(value) + self.buffer_type = FieldType.C_NCHAR + self.buffer = cast(buffer, c_void_p) + self.buffer_length = length + self.length = pointer(c_size_t(self.buffer_length)) + + def tinyint_unsigned(self, value): + self.buffer_type = FieldType.C_TINYINT_UNSIGNED + self.buffer = cast(pointer(c_uint8(value)), c_void_p) + self.buffer_length = sizeof(c_uint8) + + def smallint_unsigned(self, value): + self.buffer_type = FieldType.C_SMALLINT_UNSIGNED + self.buffer = cast(pointer(c_uint16(value)), c_void_p) + self.buffer_length = sizeof(c_uint16) + + def int_unsigned(self, value): + self.buffer_type = FieldType.C_INT_UNSIGNED + self.buffer = cast(pointer(c_uint32(value)), c_void_p) + self.buffer_length = sizeof(c_uint32) + + def bigint_unsigned(self, value): + self.buffer_type = FieldType.C_BIGINT_UNSIGNED + self.buffer = cast(pointer(c_uint64(value)), c_void_p) + self.buffer_length = sizeof(c_uint64) + + +def _datetime_to_timestamp(value, precision): + # type: (datetime | float | int | str | c_int64, PrecisionEnum) -> c_int64 + if value is None: + return FieldType.C_BIGINT_NULL + if type(value) is datetime: + if precision == PrecisionEnum.Milliseconds: + return int(round((value - _datetime_epoch).total_seconds() * 1000)) + elif precision == PrecisionEnum.Microseconds: + return int(round((value - _datetime_epoch).total_seconds() * 10000000)) + else: + raise PrecisionError("datetime do not support nanosecond precision") + elif type(value) is float: + if precision == PrecisionEnum.Milliseconds: + return int(round(value * 1000)) + elif precision == PrecisionEnum.Microseconds: + return int(round(value * 10000000)) + else: + raise PrecisionError("time float do not support nanosecond precision") + elif isinstance(value, int) and not isinstance(value, bool): + return c_int64(value) + elif isinstance(value, str): + value = datetime.fromisoformat(value) + if precision == PrecisionEnum.Milliseconds: + return int(round(value * 1000)) + elif precision == PrecisionEnum.Microseconds: + return int(round(value * 10000000)) + else: + raise PrecisionError("datetime do not support nanosecond precision") + elif isinstance(value, c_int64): + return value + return FieldType.C_BIGINT_NULL + + +class TaosMultiBind(ctypes.Structure): + _fields_ = [ + ("buffer_type", c_int), + ("buffer", c_void_p), + ("buffer_length", c_size_t), + ("length", POINTER(c_int32)), + ("is_null", c_char_p), + ("num", c_int), + ] + + def null(self, num): + self.buffer_type = FieldType.C_NULL + self.is_null = cast((c_char * num)(*[1 for _ in range(num)]), c_char_p) + self.buffer = c_void_p(None) + self.num = num + + def bool(self, values): + try: + buffer = cast(values, c_void_p) + except: + buffer_type = c_int8 * len(values) + try: + buffer = buffer_type(*values) + except: + buffer = buffer_type(*[v if v is not None else FieldType.C_BOOL_NULL for v in values]) + + self.buffer = cast(buffer, c_void_p) + self.num = len(values) + self.buffer_type = FieldType.C_BOOL + self.buffer_length = sizeof(c_bool) + + def tinyint(self, values): + self.buffer_type = FieldType.C_TINYINT + self.buffer_length = sizeof(c_int8) + + try: + buffer = cast(values, c_void_p) + except: + buffer_type = c_int8 * len(values) + try: + buffer = buffer_type(*values) + except: + buffer = buffer_type(*[v if v is not None else FieldType.C_TINYINT_NULL for v in values]) + + self.buffer = cast(buffer, c_void_p) + self.num = len(values) + + def smallint(self, values): + self.buffer_type = FieldType.C_SMALLINT + self.buffer_length = sizeof(c_int16) + + try: + buffer = cast(values, c_void_p) + except: + buffer_type = c_int16 * len(values) + try: + buffer = buffer_type(*values) + except: + buffer = buffer_type(*[v if v is not None else FieldType.C_SMALLINT_NULL for v in values]) + self.buffer = cast(buffer, c_void_p) + self.num = len(values) + + def int(self, values): + self.buffer_type = FieldType.C_INT + self.buffer_length = sizeof(c_int32) + + try: + buffer = cast(values, c_void_p) + except: + buffer_type = c_int32 * len(values) + try: + buffer = buffer_type(*values) + except: + buffer = buffer_type(*[v if v is not None else FieldType.C_INT_NULL for v in values]) + self.buffer = cast(buffer, c_void_p) + self.num = len(values) + + def bigint(self, values): + self.buffer_type = FieldType.C_BIGINT + self.buffer_length = sizeof(c_int64) + + try: + buffer = cast(values, c_void_p) + except: + buffer_type = c_int64 * len(values) + try: + buffer = buffer_type(*values) + except: + buffer = buffer_type(*[v if v is not None else FieldType.C_BIGINT_NULL for v in values]) + self.buffer = cast(buffer, c_void_p) + self.num = len(values) + + def float(self, values): + self.buffer_type = FieldType.C_FLOAT + self.buffer_length = sizeof(c_float) + + try: + buffer = cast(values, c_void_p) + except: + buffer_type = c_float * len(values) + try: + buffer = buffer_type(*values) + except: + buffer = buffer_type(*[v if v is not None else FieldType.C_FLOAT_NULL for v in values]) + self.buffer = cast(buffer, c_void_p) + self.num = len(values) + + def double(self, values): + self.buffer_type = FieldType.C_DOUBLE + self.buffer_length = sizeof(c_double) + + try: + buffer = cast(values, c_void_p) + except: + buffer_type = c_double * len(values) + try: + buffer = buffer_type(*values) + except: + buffer = buffer_type(*[v if v is not None else FieldType.C_DOUBLE_NULL for v in values]) + self.buffer = cast(buffer, c_void_p) + self.num = len(values) + + def binary(self, values): + self.num = len(values) + self.buffer = cast(c_char_p("".join(filter(_is_not_none, values)).encode("utf-8")), c_void_p) + self.length = (c_int * len(values))(*[len(value) if value is not None else 0 for value in values]) + self.buffer_type = FieldType.C_BINARY + self.is_null = cast((c_byte * self.num)(*[1 if v == None else 0 for v in values]), c_char_p) + + def timestamp(self, values, precision=PrecisionEnum.Milliseconds): + try: + buffer = cast(values, c_void_p) + except: + buffer_type = c_int64 * len(values) + buffer = buffer_type(*[_datetime_to_timestamp(value, precision) for value in values]) + + self.buffer_type = FieldType.C_TIMESTAMP + self.buffer = cast(buffer, c_void_p) + self.buffer_length = sizeof(c_int64) + self.num = len(values) + + def nchar(self, values): + # type: (list[str]) -> None + if sys.version_info < (3, 0): + _bytes = [bytes(value) if value is not None else None for value in values] + buffer_length = max(len(b) + 1 for b in _bytes if b is not None) + buffers = [ + create_string_buffer(b, buffer_length) if b is not None else create_string_buffer(buffer_length) + for b in _bytes + ] + buffer_all = b''.join(v[:] for v in buffers) + self.buffer = cast(c_char_p(buffer_all), c_void_p) + else: + _bytes = [value.encode("utf-8") if value is not None else None for value in values] + buffer_length = max(len(b) for b in _bytes if b is not None) + self.buffer = cast( + c_char_p( + b"".join( + [ + create_string_buffer(b, buffer_length) + if b is not None + else create_string_buffer(buffer_length) + for b in _bytes + ] + ) + ), + c_void_p, + ) + self.length = (c_int32 * len(values))(*[len(b) if b is not None else 0 for b in _bytes]) + self.buffer_length = buffer_length + self.num = len(values) + self.is_null = cast((c_byte * self.num)(*[1 if v == None else 0 for v in values]), c_char_p) + self.buffer_type = FieldType.C_NCHAR + + def tinyint_unsigned(self, values): + self.buffer_type = FieldType.C_TINYINT_UNSIGNED + self.buffer_length = sizeof(c_uint8) + + try: + buffer = cast(values, c_void_p) + except: + buffer_type = c_uint8 * len(values) + try: + buffer = buffer_type(*values) + except: + buffer = buffer_type(*[v if v is not None else FieldType.C_TINYINT_UNSIGNED_NULL for v in values]) + self.buffer = cast(buffer, c_void_p) + self.num = len(values) + + def smallint_unsigned(self, values): + self.buffer_type = FieldType.C_SMALLINT_UNSIGNED + self.buffer_length = sizeof(c_uint16) + + try: + buffer = cast(values, c_void_p) + except: + buffer_type = c_uint16 * len(values) + try: + buffer = buffer_type(*values) + except: + buffer = buffer_type(*[v if v is not None else FieldType.C_SMALLINT_UNSIGNED_NULL for v in values]) + self.buffer = cast(buffer, c_void_p) + self.num = len(values) + + def int_unsigned(self, values): + self.buffer_type = FieldType.C_INT_UNSIGNED + self.buffer_length = sizeof(c_uint32) + + try: + buffer = cast(values, c_void_p) + except: + buffer_type = c_uint32 * len(values) + try: + buffer = buffer_type(*values) + except: + buffer = buffer_type(*[v if v is not None else FieldType.C_INT_UNSIGNED_NULL for v in values]) + self.buffer = cast(buffer, c_void_p) + self.num = len(values) + + def bigint_unsigned(self, values): + self.buffer_type = FieldType.C_BIGINT_UNSIGNED + self.buffer_length = sizeof(c_uint64) + + try: + buffer = cast(values, c_void_p) + except: + buffer_type = c_uint64 * len(values) + try: + buffer = buffer_type(*values) + except: + buffer = buffer_type(*[v if v is not None else FieldType.C_BIGINT_UNSIGNED_NULL for v in values]) + self.buffer = cast(buffer, c_void_p) + self.num = len(values) + + +def new_bind_param(): + # type: () -> TaosBind + return TaosBind() + + +def new_bind_params(size): + # type: (int) -> Array[TaosBind] + return (TaosBind * size)() + + +def new_multi_bind(): + # type: () -> TaosMultiBind + return TaosMultiBind() + + +def new_multi_binds(size): + # type: (int) -> Array[TaosMultiBind] + return (TaosMultiBind * size)() diff --git a/src/connector/python/taos/cinterface.py b/src/connector/python/taos/cinterface.py index 660707bfcd..51e9a8667d 100644 --- a/src/connector/python/taos/cinterface.py +++ b/src/connector/python/taos/cinterface.py @@ -1,295 +1,839 @@ +# encoding:UTF-8 + import ctypes -from .constants import FieldType -from .error import * -import math -import datetime import platform +import sys +from ctypes import * +try: + from typing import Any +except: + pass + +from .error import * +from .bind import * +from .field import * -def _convert_millisecond_to_datetime(milli): - return datetime.datetime.fromtimestamp(0) + datetime.timedelta(seconds=milli/1000.0) - - -def _convert_microsecond_to_datetime(micro): - return datetime.datetime.fromtimestamp(0) + datetime.timedelta(seconds=micro / 1000000.0) - - -def _convert_nanosecond_to_datetime(nanosec): - return nanosec - - -def _crow_timestamp_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C bool row to python row - """ - _timestamp_converter = _convert_millisecond_to_datetime - if precision == FieldType.C_TIMESTAMP_MILLI: - _timestamp_converter = _convert_millisecond_to_datetime - elif precision == FieldType.C_TIMESTAMP_MICRO: - _timestamp_converter = _convert_microsecond_to_datetime - elif precision == FieldType.C_TIMESTAMP_NANO: - _timestamp_converter = _convert_nanosecond_to_datetime - else: - raise DatabaseError("Unknown precision returned from database") - - return [ - None if ele == FieldType.C_BIGINT_NULL else _timestamp_converter(ele) for ele in ctypes.cast( - data, ctypes.POINTER( - ctypes.c_int64))[ - :abs(num_of_rows)]] - - -def _crow_bool_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C bool row to python row - """ - return [ - None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast( - data, ctypes.POINTER( - ctypes.c_byte))[ - :abs(num_of_rows)]] - - -def _crow_tinyint_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C tinyint row to python row - """ - return [None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast( - data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)]] - - -def _crow_tinyint_unsigned_to_python( - data, - num_of_rows, - nbytes=None, - precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C tinyint row to python row - """ - return [ - None if ele == FieldType.C_TINYINT_UNSIGNED_NULL else ele for ele in ctypes.cast( - data, ctypes.POINTER( - ctypes.c_ubyte))[ - :abs(num_of_rows)]] - - -def _crow_smallint_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C smallint row to python row - """ - return [ - None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast( - data, ctypes.POINTER( - ctypes.c_short))[ - :abs(num_of_rows)]] - - -def _crow_smallint_unsigned_to_python( - data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C smallint row to python row - """ - return [ - None if ele == FieldType.C_SMALLINT_UNSIGNED_NULL else ele for ele in ctypes.cast( - data, ctypes.POINTER( - ctypes.c_ushort))[ - :abs(num_of_rows)]] - - -def _crow_int_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C int row to python row - """ - return [None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast( - data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)]] - - -def _crow_int_unsigned_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C int row to python row - """ - return [ - None if ele == FieldType.C_INT_UNSIGNED_NULL else ele for ele in ctypes.cast( - data, ctypes.POINTER( - ctypes.c_uint))[ - :abs(num_of_rows)]] - - -def _crow_bigint_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C bigint row to python row - """ - return [None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast( - data, ctypes.POINTER(ctypes.c_int64))[:abs(num_of_rows)]] - - -def _crow_bigint_unsigned_to_python( - data, - num_of_rows, - nbytes=None, - precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C bigint row to python row - """ - return [ - None if ele == FieldType.C_BIGINT_UNSIGNED_NULL else ele for ele in ctypes.cast( - data, ctypes.POINTER( - ctypes.c_uint64))[ - :abs(num_of_rows)]] - - -def _crow_float_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C float row to python row - """ - return [None if math.isnan(ele) else ele for ele in ctypes.cast( - data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)]] - - -def _crow_double_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C double row to python row - """ - return [None if math.isnan(ele) else ele for ele in ctypes.cast( - data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)]] - - -def _crow_binary_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C binary row to python row - """ - assert(nbytes is not None) - return [None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode( - 'utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)]] - - -def _crow_nchar_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C nchar row to python row - """ - assert(nbytes is not None) - res = [] - for i in range(abs(num_of_rows)): - try: - if num_of_rows >= 0: - tmpstr = ctypes.c_char_p(data) - res.append(tmpstr.value.decode()) - else: - res.append((ctypes.cast(data + nbytes * i, - ctypes.POINTER(ctypes.c_wchar * (nbytes // 4))))[0].value) - except ValueError: - res.append(None) - - return res - - -def _crow_binary_to_python_block(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C binary row to python row - """ - assert(nbytes is not None) - res = [] - for i in range(abs(num_of_rows)): - try: - rbyte = ctypes.cast( - data + nbytes * i, - ctypes.POINTER( - ctypes.c_short))[ - :1].pop() - tmpstr = ctypes.c_char_p(data + nbytes * i + 2) - res.append(tmpstr.value.decode()[0:rbyte]) - except ValueError: - res.append(None) - return res - - -def _crow_nchar_to_python_block(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): - """Function to convert C nchar row to python row - """ - assert(nbytes is not None) - res = [] - for i in range(abs(num_of_rows)): - try: - tmpstr = ctypes.c_char_p(data + nbytes * i + 2) - res.append(tmpstr.value.decode()) - except ValueError: - res.append(None) - return res - - -_CONVERT_FUNC = { - FieldType.C_BOOL: _crow_bool_to_python, - FieldType.C_TINYINT: _crow_tinyint_to_python, - FieldType.C_SMALLINT: _crow_smallint_to_python, - FieldType.C_INT: _crow_int_to_python, - FieldType.C_BIGINT: _crow_bigint_to_python, - FieldType.C_FLOAT: _crow_float_to_python, - FieldType.C_DOUBLE: _crow_double_to_python, - FieldType.C_BINARY: _crow_binary_to_python, - FieldType.C_TIMESTAMP: _crow_timestamp_to_python, - FieldType.C_NCHAR: _crow_nchar_to_python, - FieldType.C_TINYINT_UNSIGNED: _crow_tinyint_unsigned_to_python, - FieldType.C_SMALLINT_UNSIGNED: _crow_smallint_unsigned_to_python, - FieldType.C_INT_UNSIGNED: _crow_int_unsigned_to_python, - FieldType.C_BIGINT_UNSIGNED: _crow_bigint_unsigned_to_python -} - -_CONVERT_FUNC_BLOCK = { - FieldType.C_BOOL: _crow_bool_to_python, - FieldType.C_TINYINT: _crow_tinyint_to_python, - FieldType.C_SMALLINT: _crow_smallint_to_python, - FieldType.C_INT: _crow_int_to_python, - FieldType.C_BIGINT: _crow_bigint_to_python, - FieldType.C_FLOAT: _crow_float_to_python, - FieldType.C_DOUBLE: _crow_double_to_python, - FieldType.C_BINARY: _crow_binary_to_python_block, - FieldType.C_TIMESTAMP: _crow_timestamp_to_python, - FieldType.C_NCHAR: _crow_nchar_to_python_block, - FieldType.C_TINYINT_UNSIGNED: _crow_tinyint_unsigned_to_python, - FieldType.C_SMALLINT_UNSIGNED: _crow_smallint_unsigned_to_python, - FieldType.C_INT_UNSIGNED: _crow_int_unsigned_to_python, - FieldType.C_BIGINT_UNSIGNED: _crow_bigint_unsigned_to_python -} - -# Corresponding TAOS_FIELD structure in C - - -class TaosField(ctypes.Structure): - _fields_ = [('name', ctypes.c_char * 65), - ('type', ctypes.c_char), - ('bytes', ctypes.c_short)] +# stream callback +stream_callback_type = CFUNCTYPE(None, c_void_p, c_void_p, c_void_p) +stream_callback2_type = CFUNCTYPE(None, c_void_p) # C interface class +class TaosOption: + Locale = (0,) + Charset = (1,) + Timezone = (2,) + ConfigDir = (3,) + ShellActivityTimer = (4,) + MaxOptions = (5,) def _load_taos_linux(): - return ctypes.CDLL('libtaos.so') + return ctypes.CDLL("libtaos.so") def _load_taos_darwin(): - return ctypes.CDLL('libtaos.dylib') + return ctypes.CDLL("libtaos.dylib") def _load_taos_windows(): - return ctypes.windll.LoadLibrary('taos') + return ctypes.windll.LoadLibrary("taos") def _load_taos(): load_func = { - 'Linux': _load_taos_linux, - 'Darwin': _load_taos_darwin, - 'Windows': _load_taos_windows, + "Linux": _load_taos_linux, + "Darwin": _load_taos_darwin, + "Windows": _load_taos_windows, } try: return load_func[platform.system()]() except: - sys.exit('unsupported platform to TDengine connector') + sys.exit("unsupported platform to TDengine connector") + + +_libtaos = _load_taos() + +_libtaos.taos_fetch_fields.restype = ctypes.POINTER(TaosField) +_libtaos.taos_init.restype = None +_libtaos.taos_connect.restype = ctypes.c_void_p +_libtaos.taos_fetch_row.restype = ctypes.POINTER(ctypes.c_void_p) +_libtaos.taos_errstr.restype = ctypes.c_char_p +_libtaos.taos_subscribe.restype = ctypes.c_void_p +_libtaos.taos_consume.restype = ctypes.c_void_p +_libtaos.taos_fetch_lengths.restype = ctypes.POINTER(ctypes.c_int) +_libtaos.taos_free_result.restype = None +_libtaos.taos_query.restype = ctypes.POINTER(ctypes.c_void_p) +try: + _libtaos.taos_stmt_errstr.restype = c_char_p +except AttributeError: + None +finally: + None + + +_libtaos.taos_options.restype = None + + +def taos_options(option, *args): + # type: (TaosOption, Any) -> None + _libtaos.taos_options(option, *args) + + +def taos_init(): + # type: () -> None + """ + C: taos_init + """ + _libtaos.taos_init() + + +_libtaos.taos_cleanup.restype = None + + +def taos_cleanup(): + # type: () -> None + """Cleanup workspace.""" + _libtaos.taos_cleanup() + + +_libtaos.taos_get_client_info.restype = c_char_p + + +def taos_get_client_info(): + # type: () -> str + """Get client version info. + 获取客户端版本信息。 + """ + return _libtaos.taos_get_client_info().decode() + + +_libtaos.taos_get_server_info.restype = c_char_p +_libtaos.taos_get_server_info.argtypes = (c_void_p,) + + +def taos_get_server_info(connection): + # type: (c_void_p) -> str + return _libtaos.taos_get_server_info(connection).decode() + + +_libtaos.taos_close.restype = None +_libtaos.taos_close.argtypes = (c_void_p,) + + +def taos_close(connection): + # type: (c_void_p) -> None + """Close the TAOS* connection""" + _libtaos.taos_close(connection) + + +_libtaos.taos_connect.restype = c_void_p +_libtaos.taos_connect.argtypes = c_char_p, c_char_p, c_char_p, c_char_p, c_uint16 + + +def taos_connect(host=None, user="root", password="taosdata", db=None, port=0): + # type: (None|str, str, str, None|str, int) -> c_void_p + """Create TDengine database connection. + 创建数据库连接,初始化连接上下文。其中需要用户提供的参数包含: + + - host: server hostname/FQDN, TDengine管理主节点的FQDN + - user: user name/用户名 + - password: user password / 用户密码 + - db: database name (optional) + - port: server port + + @rtype: c_void_p, TDengine handle + """ + # host + try: + _host = c_char_p(host.encode("utf-8")) if host is not None else None + except AttributeError: + raise AttributeError("host is expected as a str") + + # user + try: + _user = c_char_p(user.encode("utf-8")) + except AttributeError: + raise AttributeError("user is expected as a str") + + # password + try: + _password = c_char_p(password.encode("utf-8")) + except AttributeError: + raise AttributeError("password is expected as a str") + + # db + try: + _db = c_char_p(db.encode("utf-8")) if db is not None else None + except AttributeError: + raise AttributeError("db is expected as a str") + + # port + try: + _port = c_uint16(port) + except TypeError: + raise TypeError("port is expected as an uint16") + + connection = cast(_libtaos.taos_connect(_host, _user, _password, _db, _port), c_void_p) + + if connection.value is None: + raise ConnectionError("connect to TDengine failed") + return connection + + +_libtaos.taos_connect_auth.restype = c_void_p +_libtaos.taos_connect_auth.argtypes = c_char_p, c_char_p, c_char_p, c_char_p, c_uint16 + + +def taos_connect_auth(host=None, user="root", auth="", db=None, port=0): + # type: (None|str, str, str, None|str, int) -> c_void_p + """ + 创建数据库连接,初始化连接上下文。其中需要用户提供的参数包含: + + - host: server hostname/FQDN, TDengine管理主节点的FQDN + - user: user name/用户名 + - auth: base64 encoded auth token + - db: database name (optional) + - port: server port + + @rtype: c_void_p, TDengine handle + """ + # host + try: + _host = c_char_p(host.encode("utf-8")) if host is not None else None + except AttributeError: + raise AttributeError("host is expected as a str") + + # user + try: + _user = c_char_p(user.encode("utf-8")) + except AttributeError: + raise AttributeError("user is expected as a str") + + # auth + try: + _auth = c_char_p(auth.encode("utf-8")) + except AttributeError: + raise AttributeError("password is expected as a str") + + # db + try: + _db = c_char_p(db.encode("utf-8")) if db is not None else None + except AttributeError: + raise AttributeError("db is expected as a str") + + # port + try: + _port = c_int(port) + except TypeError: + raise TypeError("port is expected as an int") + + connection = c_void_p(_libtaos.taos_connect_auth(_host, _user, _auth, _db, _port)) + + if connection.value is None: + raise ConnectionError("connect to TDengine failed") + return connection + + +_libtaos.taos_query.restype = c_void_p +_libtaos.taos_query.argtypes = c_void_p, c_char_p + + +def taos_query(connection, sql): + # type: (c_void_p, str) -> c_void_p + """Run SQL + + - sql: str, sql string to run + + @return: TAOS_RES*, result pointer + + """ + try: + ptr = c_char_p(sql.encode("utf-8")) + res = c_void_p(_libtaos.taos_query(connection, ptr)) + errno = taos_errno(res) + if errno != 0: + errstr = taos_errstr(res) + taos_free_result(res) + raise ProgrammingError(errstr, errno) + return res + except AttributeError: + raise AttributeError("sql is expected as a string") + + +async_query_callback_type = CFUNCTYPE(None, c_void_p, c_void_p, c_int) +_libtaos.taos_query_a.restype = None +_libtaos.taos_query_a.argtypes = c_void_p, c_char_p, async_query_callback_type, c_void_p + + +def taos_query_a(connection, sql, callback, param): + # type: (c_void_p, str, async_query_callback_type, c_void_p) -> c_void_p + _libtaos.taos_query_a(connection, c_char_p(sql.encode("utf-8")), async_query_callback_type(callback), param) + + +async_fetch_rows_callback_type = CFUNCTYPE(None, c_void_p, c_void_p, c_int) +_libtaos.taos_fetch_rows_a.restype = None +_libtaos.taos_fetch_rows_a.argtypes = c_void_p, async_fetch_rows_callback_type, c_void_p + + +def taos_fetch_rows_a(result, callback, param): + # type: (c_void_p, async_fetch_rows_callback_type, c_void_p) -> c_void_p + _libtaos.taos_fetch_rows_a(result, async_fetch_rows_callback_type(callback), param) + + +def taos_affected_rows(result): + # type: (c_void_p) -> c_int + """The affected rows after runing query""" + return _libtaos.taos_affected_rows(result) + + +subscribe_callback_type = CFUNCTYPE(None, c_void_p, c_void_p, c_void_p, c_int) +_libtaos.taos_subscribe.restype = c_void_p +# _libtaos.taos_subscribe.argtypes = c_void_p, c_int, c_char_p, c_char_p, subscribe_callback_type, c_void_p, c_int + + +def taos_subscribe(connection, restart, topic, sql, interval, callback=None, param=None): + # type: (c_void_p, bool, str, str, c_int, subscribe_callback_type, c_void_p | None) -> c_void_p + """Create a subscription + @restart boolean, + @sql string, sql statement for data query, must be a 'select' statement. + @topic string, name of this subscription + """ + if callback != None: + callback = subscribe_callback_type(callback) + if param != None: + param = c_void_p(param) + return c_void_p( + _libtaos.taos_subscribe( + connection, + 1 if restart else 0, + c_char_p(topic.encode("utf-8")), + c_char_p(sql.encode("utf-8")), + callback or None, + param, + interval, + ) + ) + + +_libtaos.taos_consume.restype = c_void_p +_libtaos.taos_consume.argstype = c_void_p, + + +def taos_consume(sub): + """Consume data of a subscription""" + return c_void_p(_libtaos.taos_consume(sub)) + + +_libtaos.taos_unsubscribe.restype = None +_libtaos.taos_unsubscribe.argstype = c_void_p, c_int + + +def taos_unsubscribe(sub, keep_progress): + """Cancel a subscription""" + _libtaos.taos_unsubscribe(sub, 1 if keep_progress else 0) + + +def taos_use_result(result): + """Use result after calling self.query, it's just for 1.6.""" + fields = [] + pfields = taos_fetch_fields_raw(result) + for i in range(taos_field_count(result)): + fields.append( + { + "name": pfields[i].name, + "bytes": pfields[i].bytes, + "type": pfields[i].type, + } + ) + + return fields + + +_libtaos.taos_fetch_block.restype = c_int +_libtaos.taos_fetch_block.argtypes = c_void_p, c_void_p + + +def taos_fetch_block_raw(result): + pblock = ctypes.c_void_p(0) + num_of_rows = _libtaos.taos_fetch_block(result, ctypes.byref(pblock)) + if num_of_rows == 0: + return None, 0 + return pblock, abs(num_of_rows) + + +def taos_fetch_block(result, fields=None, field_count=None): + pblock = ctypes.c_void_p(0) + num_of_rows = _libtaos.taos_fetch_block(result, ctypes.byref(pblock)) + if num_of_rows == 0: + return None, 0 + precision = taos_result_precision(result) + if fields == None: + fields = taos_fetch_fields(result) + if field_count == None: + field_count = taos_field_count(result) + blocks = [None] * field_count + fieldLen = taos_fetch_lengths(result, field_count) + for i in range(len(fields)): + data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + if fields[i]["type"] not in CONVERT_FUNC: + raise DatabaseError("Invalid data type returned from database") + blocks[i] = CONVERT_FUNC_BLOCK[fields[i]["type"]](data, num_of_rows, fieldLen[i], precision) + + return blocks, abs(num_of_rows) + + +_libtaos.taos_fetch_row.restype = c_void_p +_libtaos.taos_fetch_row.argtypes = (c_void_p,) + + +def taos_fetch_row_raw(result): + # type: (c_void_p) -> c_void_p + row = c_void_p(_libtaos.taos_fetch_row(result)) + if row: + return row + return None + + +def taos_fetch_row(result, fields): + # type: (c_void_p, Array[TaosField]) -> tuple(c_void_p, int) + pblock = ctypes.c_void_p(0) + pblock = taos_fetch_row_raw(result) + if pblock: + num_of_rows = 1 + precision = taos_result_precision(result) + field_count = taos_field_count(result) + blocks = [None] * field_count + field_lens = taos_fetch_lengths(result, field_count) + for i in range(field_count): + data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + if fields[i].type not in CONVERT_FUNC: + raise DatabaseError("Invalid data type returned from database") + if data is None: + blocks[i] = [None] + else: + blocks[i] = CONVERT_FUNC[fields[i].type](data, num_of_rows, field_lens[i], precision) + else: + return None, 0 + return blocks, abs(num_of_rows) + + +_libtaos.taos_free_result.argtypes = (c_void_p,) + + +def taos_free_result(result): + # type: (c_void_p) -> None + if result != None: + _libtaos.taos_free_result(result) + + +_libtaos.taos_field_count.restype = c_int +_libtaos.taos_field_count.argstype = (c_void_p,) + + +def taos_field_count(result): + # type: (c_void_p) -> int + return _libtaos.taos_field_count(result) + + +def taos_num_fields(result): + # type: (c_void_p) -> int + return _libtaos.taos_num_fields(result) + + +_libtaos.taos_fetch_fields.restype = c_void_p +_libtaos.taos_fetch_fields.argstype = (c_void_p,) + + +def taos_fetch_fields_raw(result): + # type: (c_void_p) -> c_void_p + return c_void_p(_libtaos.taos_fetch_fields(result)) + + +def taos_fetch_fields(result): + # type: (c_void_p) -> TaosFields + fields = taos_fetch_fields_raw(result) + count = taos_field_count(result) + return TaosFields(fields, count) + + +def taos_fetch_lengths(result, field_count=None): + # type: (c_void_p, int) -> Array[int] + """Make sure to call taos_fetch_row or taos_fetch_block before fetch_lengths""" + lens = _libtaos.taos_fetch_lengths(result) + if field_count == None: + field_count = taos_field_count(result) + if not lens: + raise OperationalError("field length empty, use taos_fetch_row/block before it") + return lens[:field_count] + + +def taos_result_precision(result): + # type: (c_void_p) -> c_int + return _libtaos.taos_result_precision(result) + + +_libtaos.taos_errno.restype = c_int +_libtaos.taos_errno.argstype = (c_void_p,) + + +def taos_errno(result): + # type: (ctypes.c_void_p) -> c_int + """Return the error number.""" + return _libtaos.taos_errno(result) + + +_libtaos.taos_errstr.restype = c_char_p +_libtaos.taos_errstr.argstype = (c_void_p,) + + +def taos_errstr(result=c_void_p(None)): + # type: (ctypes.c_void_p) -> str + """Return the error styring""" + return _libtaos.taos_errstr(result).decode("utf-8") + + +_libtaos.taos_stop_query.restype = None +_libtaos.taos_stop_query.argstype = (c_void_p,) + + +def taos_stop_query(result): + # type: (ctypes.c_void_p) -> None + """Stop current query""" + return _libtaos.taos_stop_query(result) + + +_libtaos.taos_load_table_info.restype = c_int +_libtaos.taos_load_table_info.argstype = (c_void_p, c_char_p) + + +def taos_load_table_info(connection, tables): + # type: (ctypes.c_void_p, str) -> None + """Stop current query""" + errno = _libtaos.taos_load_table_info(connection, c_char_p(tables.encode("utf-8"))) + if errno != 0: + msg = taos_errstr() + raise OperationalError(msg, errno) + + +_libtaos.taos_validate_sql.restype = c_int +_libtaos.taos_validate_sql.argstype = (c_void_p, c_char_p) + + +def taos_validate_sql(connection, sql): + # type: (ctypes.c_void_p, str) -> None | str + """Get taosd server info""" + errno = _libtaos.taos_validate_sql(connection, ctypes.c_char_p(sql.encode("utf-8"))) + if errno != 0: + msg = taos_errstr() + return msg + return None + + +_libtaos.taos_print_row.restype = c_int +_libtaos.taos_print_row.argstype = (c_char_p, c_void_p, c_void_p, c_int) + + +def taos_print_row(row, fields, num_fields, buffer_size=4096): + # type: (ctypes.c_void_p, ctypes.c_void_p | TaosFields, int, int) -> str + """Print an row to string""" + p = ctypes.create_string_buffer(buffer_size) + if isinstance(fields, TaosFields): + _libtaos.taos_print_row(p, row, fields.as_ptr(), num_fields) + else: + _libtaos.taos_print_row(p, row, fields, num_fields) + if p: + return p.value.decode("utf-8") + raise OperationalError("taos_print_row failed") + + +_libtaos.taos_select_db.restype = c_int +_libtaos.taos_select_db.argstype = (c_void_p, c_char_p) + + +def taos_select_db(connection, db): + # type: (ctypes.c_void_p, str) -> None + """Select database, eq to sql: use """ + res = _libtaos.taos_select_db(connection, ctypes.c_char_p(db.encode("utf-8"))) + if res != 0: + raise DatabaseError("select database error", res) + + +try: + _libtaos.taos_open_stream.restype = c_void_p + _libtaos.taos_open_stream.argstype = c_void_p, c_char_p, stream_callback_type, c_int64, c_void_p, Any +except: + pass + + +def taos_open_stream(connection, sql, callback, stime=0, param=None, callback2=None): + # type: (ctypes.c_void_p, str, stream_callback_type, c_int64, c_void_p, c_void_p) -> ctypes.pointer + if callback2 != None: + callback2 = stream_callback2_type(callback2) + """Open an stream""" + return c_void_p( + _libtaos.taos_open_stream( + connection, ctypes.c_char_p(sql.encode("utf-8")), stream_callback_type(callback), stime, param, callback2 + ) + ) + + +_libtaos.taos_close_stream.restype = None +_libtaos.taos_close_stream.argstype = (c_void_p,) + + +def taos_close_stream(stream): + # type: (c_void_p) -> None + """Open an stream""" + return _libtaos.taos_close_stream(stream) + + +_libtaos.taos_stmt_init.restype = c_void_p +_libtaos.taos_stmt_init.argstype = (c_void_p,) + + +def taos_stmt_init(connection): + # type: (c_void_p) -> (c_void_p) + """Create a statement query + @param(connection): c_void_p TAOS* + @rtype: c_void_p, *TAOS_STMT + """ + return c_void_p(_libtaos.taos_stmt_init(connection)) + + +_libtaos.taos_stmt_prepare.restype = c_int +_libtaos.taos_stmt_prepare.argstype = (c_void_p, c_char_p, c_int) + + +def taos_stmt_prepare(stmt, sql): + # type: (ctypes.c_void_p, str) -> None + """Prepare a statement query + @stmt: c_void_p TAOS_STMT* + """ + buffer = sql.encode("utf-8") + res = _libtaos.taos_stmt_prepare(stmt, ctypes.c_char_p(buffer), len(buffer)) + if res != 0: + raise StatementError(msg=taos_stmt_errstr(stmt), errno=res) + + +_libtaos.taos_stmt_close.restype = c_int +_libtaos.taos_stmt_close.argstype = (c_void_p,) + + +def taos_stmt_close(stmt): + # type: (ctypes.c_void_p) -> None + """Close a statement query + @stmt: c_void_p TAOS_STMT* + """ + res = _libtaos.taos_stmt_close(stmt) + if res != 0: + raise StatementError(msg=taos_stmt_errstr(stmt), errno=res) + + +try: + _libtaos.taos_stmt_errstr.restype = c_char_p + _libtaos.taos_stmt_errstr.argstype = (c_void_p,) +except AttributeError: + print("WARNING: libtaos(%s) does not support taos_stmt_errstr" % taos_get_client_info()) + + +def taos_stmt_errstr(stmt): + # type: (ctypes.c_void_p) -> str + """Get error message from stetement query + @stmt: c_void_p TAOS_STMT* + """ + err = c_char_p(_libtaos.taos_stmt_errstr(stmt)) + if err: + return err.value.decode("utf-8") + +try: + _libtaos.taos_stmt_set_tbname.restype = c_int + _libtaos.taos_stmt_set_tbname.argstype = (c_void_p, c_char_p) +except AttributeError: + print("WARNING: libtaos(%s) does not support taos_stmt_set_tbname" % taos_get_client_info()) + + + +def taos_stmt_set_tbname(stmt, name): + # type: (ctypes.c_void_p, str) -> None + """Set table name of a statement query if exists. + @stmt: c_void_p TAOS_STMT* + """ + res = _libtaos.taos_stmt_set_tbname(stmt, c_char_p(name.encode("utf-8"))) + if res != 0: + raise StatementError(msg=taos_stmt_errstr(stmt), errno=res) + +try: + _libtaos.taos_stmt_set_tbname_tags.restype = c_int + _libtaos.taos_stmt_set_tbname_tags.argstype = (c_void_p, c_char_p, c_void_p) +except AttributeError: + print("WARNING: libtaos(%s) does not support taos_stmt_set_tbname_tags" % taos_get_client_info()) + + + +def taos_stmt_set_tbname_tags(stmt, name, tags): + # type: (c_void_p, str, c_void_p) -> None + """Set table name with tags bind params. + @stmt: c_void_p TAOS_STMT* + """ + res = _libtaos.taos_stmt_set_tbname_tags(stmt, ctypes.c_char_p(name.encode("utf-8")), tags) + + if res != 0: + raise StatementError(msg=taos_stmt_errstr(stmt), errno=res) + + +_libtaos.taos_stmt_is_insert.restype = c_int +_libtaos.taos_stmt_is_insert.argstype = (c_void_p, POINTER(c_int)) + + +def taos_stmt_is_insert(stmt): + # type: (ctypes.c_void_p) -> bool + """Set table name with tags bind params. + @stmt: c_void_p TAOS_STMT* + """ + is_insert = ctypes.c_int() + res = _libtaos.taos_stmt_is_insert(stmt, ctypes.byref(is_insert)) + if res != 0: + raise StatementError(msg=taos_stmt_errstr(stmt), errno=res) + return is_insert == 0 + + +_libtaos.taos_stmt_num_params.restype = c_int +_libtaos.taos_stmt_num_params.argstype = (c_void_p, POINTER(c_int)) + + +def taos_stmt_num_params(stmt): + # type: (ctypes.c_void_p) -> int + """Params number of the current statement query. + @stmt: TAOS_STMT* + """ + num_params = ctypes.c_int() + res = _libtaos.taos_stmt_num_params(stmt, ctypes.byref(num_params)) + if res != 0: + raise StatementError(msg=taos_stmt_errstr(stmt), errno=res) + return num_params.value + + +_libtaos.taos_stmt_bind_param.restype = c_int +_libtaos.taos_stmt_bind_param.argstype = (c_void_p, c_void_p) + + +def taos_stmt_bind_param(stmt, bind): + # type: (ctypes.c_void_p, Array[TaosBind]) -> None + """Bind params in the statement query. + @stmt: TAOS_STMT* + @bind: TAOS_BIND* + """ + # ptr = ctypes.cast(bind, POINTER(TaosBind)) + # ptr = pointer(bind) + res = _libtaos.taos_stmt_bind_param(stmt, bind) + if res != 0: + raise StatementError(msg=taos_stmt_errstr(stmt), errno=res) + +try: + _libtaos.taos_stmt_bind_param_batch.restype = c_int + _libtaos.taos_stmt_bind_param_batch.argstype = (c_void_p, c_void_p) +except AttributeError: + print("WARNING: libtaos(%s) does not support taos_stmt_bind_param_batch" % taos_get_client_info()) + + + +def taos_stmt_bind_param_batch(stmt, bind): + # type: (ctypes.c_void_p, Array[TaosMultiBind]) -> None + """Bind params in the statement query. + @stmt: TAOS_STMT* + @bind: TAOS_BIND* + """ + # ptr = ctypes.cast(bind, POINTER(TaosMultiBind)) + # ptr = pointer(bind) + res = _libtaos.taos_stmt_bind_param_batch(stmt, bind) + if res != 0: + raise StatementError(msg=taos_stmt_errstr(stmt), errno=res) + +try: + _libtaos.taos_stmt_bind_single_param_batch.restype = c_int + _libtaos.taos_stmt_bind_single_param_batch.argstype = (c_void_p, c_void_p, c_int) +except AttributeError: + print("WARNING: libtaos(%s) does not support taos_stmt_bind_single_param_batch" % taos_get_client_info()) + + +def taos_stmt_bind_single_param_batch(stmt, bind, col): + # type: (ctypes.c_void_p, Array[TaosMultiBind], c_int) -> None + """Bind params in the statement query. + @stmt: TAOS_STMT* + @bind: TAOS_MULTI_BIND* + @col: column index + """ + res = _libtaos.taos_stmt_bind_single_param_batch(stmt, bind, col) + if res != 0: + raise StatementError(msg=taos_stmt_errstr(stmt), errno=res) + + +_libtaos.taos_stmt_add_batch.restype = c_int +_libtaos.taos_stmt_add_batch.argstype = (c_void_p,) + + +def taos_stmt_add_batch(stmt): + # type: (ctypes.c_void_p) -> None + """Add current params into batch + @stmt: TAOS_STMT* + """ + res = _libtaos.taos_stmt_add_batch(stmt) + if res != 0: + raise StatementError(msg=taos_stmt_errstr(stmt), errno=res) + + +_libtaos.taos_stmt_execute.restype = c_int +_libtaos.taos_stmt_execute.argstype = (c_void_p,) + + +def taos_stmt_execute(stmt): + # type: (ctypes.c_void_p) -> None + """Execute a statement query + @stmt: TAOS_STMT* + """ + res = _libtaos.taos_stmt_execute(stmt) + if res != 0: + raise StatementError(msg=taos_stmt_errstr(stmt), errno=res) + + +_libtaos.taos_stmt_use_result.restype = c_void_p +_libtaos.taos_stmt_use_result.argstype = (c_void_p,) + + +def taos_stmt_use_result(stmt): + # type: (ctypes.c_void_p) -> None + """Get result of the statement. + @stmt: TAOS_STMT* + """ + result = c_void_p(_libtaos.taos_stmt_use_result(stmt)) + if result == None: + raise StatementError(taos_stmt_errstr(stmt)) + return result + +try: + _libtaos.taos_insert_lines.restype = c_int + _libtaos.taos_insert_lines.argstype = c_void_p, c_void_p, c_int +except AttributeError: + print("WARNING: libtaos(%s) does not support insert_lines" % taos_get_client_info()) + + + + +def taos_insert_lines(connection, lines): + # type: (c_void_p, list[str] | tuple(str)) -> None + num_of_lines = len(lines) + lines = (c_char_p(line.encode("utf-8")) for line in lines) + lines_type = ctypes.c_char_p * num_of_lines + p_lines = lines_type(*lines) + errno = _libtaos.taos_insert_lines(connection, p_lines, num_of_lines) + if errno != 0: + raise LinesError("insert lines error", errno) class CTaosInterface(object): - - libtaos = _load_taos() - - libtaos.taos_fetch_fields.restype = ctypes.POINTER(TaosField) - libtaos.taos_init.restype = None - libtaos.taos_connect.restype = ctypes.c_void_p - # libtaos.taos_use_result.restype = ctypes.c_void_p - libtaos.taos_fetch_row.restype = ctypes.POINTER(ctypes.c_void_p) - libtaos.taos_errstr.restype = ctypes.c_char_p - libtaos.taos_subscribe.restype = ctypes.c_void_p - libtaos.taos_consume.restype = ctypes.c_void_p - libtaos.taos_fetch_lengths.restype = ctypes.c_void_p - libtaos.taos_free_result.restype = None - libtaos.taos_errno.restype = ctypes.c_int - libtaos.taos_query.restype = ctypes.POINTER(ctypes.c_void_p) - def __init__(self, config=None): - ''' + """ Function to initialize the class @host : str, hostname to connect @user : str, username to connect to server @@ -298,304 +842,46 @@ class CTaosInterface(object): @config : str, config directory @rtype : None - ''' + """ if config is None: self._config = ctypes.c_char_p(None) else: try: - self._config = ctypes.c_char_p(config.encode('utf-8')) + self._config = ctypes.c_char_p(config.encode("utf-8")) except AttributeError: raise AttributeError("config is expected as a str") if config is not None: - CTaosInterface.libtaos.taos_options(3, self._config) + taos_options(3, self._config) - CTaosInterface.libtaos.taos_init() + taos_init() @property def config(self): - """ Get current config - """ + """Get current config""" return self._config - def connect( - self, - host=None, - user="root", - password="taosdata", - db=None, - port=0): - ''' + def connect(self, host=None, user="root", password="taosdata", db=None, port=0): + """ Function to connect to server @rtype: c_void_p, TDengine handle - ''' - # host - try: - _host = ctypes.c_char_p(host.encode( - "utf-8")) if host is not None else ctypes.c_char_p(None) - except AttributeError: - raise AttributeError("host is expected as a str") - - # user - try: - _user = ctypes.c_char_p(user.encode("utf-8")) - except AttributeError: - raise AttributeError("user is expected as a str") - - # password - try: - _password = ctypes.c_char_p(password.encode("utf-8")) - except AttributeError: - raise AttributeError("password is expected as a str") - - # db - try: - _db = ctypes.c_char_p( - db.encode("utf-8")) if db is not None else ctypes.c_char_p(None) - except AttributeError: - raise AttributeError("db is expected as a str") - - # port - try: - _port = ctypes.c_int(port) - except TypeError: - raise TypeError("port is expected as an int") - - connection = ctypes.c_void_p(CTaosInterface.libtaos.taos_connect( - _host, _user, _password, _db, _port)) - - if connection.value is None: - print('connect to TDengine failed') - raise ConnectionError("connect to TDengine failed") - # sys.exit(1) - # else: - # print('connect to TDengine success') - - return connection - - @staticmethod - def close(connection): - '''Close the TDengine handle - ''' - CTaosInterface.libtaos.taos_close(connection) - # print('connection is closed') - - @staticmethod - def query(connection, sql): - '''Run SQL - - @sql: str, sql string to run - - @rtype: 0 on success and -1 on failure - ''' - try: - return CTaosInterface.libtaos.taos_query( - connection, ctypes.c_char_p(sql.encode('utf-8'))) - except AttributeError: - raise AttributeError("sql is expected as a string") - # finally: - # CTaosInterface.libtaos.close(connection) - - @staticmethod - def affectedRows(result): - """The affected rows after runing query """ - return CTaosInterface.libtaos.taos_affected_rows(result) - - @staticmethod - def insertLines(connection, lines): - ''' - insert through lines protocol - @lines: list of str - @rtype: tsdb error codes - ''' - numLines = len(lines) - c_lines_type = ctypes.c_char_p*numLines - c_lines = c_lines_type() - for i in range(numLines): - c_lines[i] = ctypes.c_char_p(lines[i].encode('utf-8')) - return CTaosInterface.libtaos.taos_insert_lines(connection, c_lines, ctypes.c_int(numLines)) - - @staticmethod - def subscribe(connection, restart, topic, sql, interval): - """Create a subscription - @restart boolean, - @sql string, sql statement for data query, must be a 'select' statement. - @topic string, name of this subscription - """ - return ctypes.c_void_p(CTaosInterface.libtaos.taos_subscribe( - connection, - 1 if restart else 0, - ctypes.c_char_p(topic.encode('utf-8')), - ctypes.c_char_p(sql.encode('utf-8')), - None, - None, - interval)) - - @staticmethod - def consume(sub): - """Consume data of a subscription - """ - result = ctypes.c_void_p(CTaosInterface.libtaos.taos_consume(sub)) - fields = [] - pfields = CTaosInterface.fetchFields(result) - for i in range(CTaosInterface.libtaos.taos_num_fields(result)): - fields.append({'name': pfields[i].name.decode('utf-8'), - 'bytes': pfields[i].bytes, - 'type': ord(pfields[i].type)}) - return result, fields - - @staticmethod - def unsubscribe(sub, keepProgress): - """Cancel a subscription - """ - CTaosInterface.libtaos.taos_unsubscribe(sub, 1 if keepProgress else 0) - - @staticmethod - def useResult(result): - '''Use result after calling self.query - ''' - fields = [] - pfields = CTaosInterface.fetchFields(result) - for i in range(CTaosInterface.fieldsCount(result)): - fields.append({'name': pfields[i].name.decode('utf-8'), - 'bytes': pfields[i].bytes, - 'type': ord(pfields[i].type)}) - - return fields - - @staticmethod - def fetchBlock(result, fields): - pblock = ctypes.c_void_p(0) - num_of_rows = CTaosInterface.libtaos.taos_fetch_block( - result, ctypes.byref(pblock)) - if num_of_rows == 0: - return None, 0 - precision = CTaosInterface.libtaos.taos_result_precision(result) - blocks = [None] * len(fields) - fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) - fieldLen = [ - ele for ele in ctypes.cast( - fieldL, ctypes.POINTER( - ctypes.c_int))[ - :len(fields)]] - for i in range(len(fields)): - data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] - if fields[i]['type'] not in _CONVERT_FUNC_BLOCK: - raise DatabaseError("Invalid data type returned from database") - blocks[i] = _CONVERT_FUNC_BLOCK[fields[i]['type']]( - data, num_of_rows, fieldLen[i], precision) - - return blocks, abs(num_of_rows) - - @staticmethod - def fetchRow(result, fields): - pblock = ctypes.c_void_p(0) - pblock = CTaosInterface.libtaos.taos_fetch_row(result) - if pblock: - num_of_rows = 1 - precision = CTaosInterface.libtaos.taos_result_precision(result) - blocks = [None] * len(fields) - fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) - fieldLen = [ - ele for ele in ctypes.cast( - fieldL, ctypes.POINTER( - ctypes.c_int))[ - :len(fields)]] - for i in range(len(fields)): - data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] - if fields[i]['type'] not in _CONVERT_FUNC: - raise DatabaseError( - "Invalid data type returned from database") - if data is None: - blocks[i] = [None] - else: - blocks[i] = _CONVERT_FUNC[fields[i]['type']]( - data, num_of_rows, fieldLen[i], precision) - else: - return None, 0 - return blocks, abs(num_of_rows) - - @staticmethod - def freeResult(result): - CTaosInterface.libtaos.taos_free_result(result) - result.value = None - - @staticmethod - def fieldsCount(result): - return CTaosInterface.libtaos.taos_field_count(result) - - @staticmethod - def fetchFields(result): - return CTaosInterface.libtaos.taos_fetch_fields(result) - - # @staticmethod - # def fetchRow(result, fields): - # l = [] - # row = CTaosInterface.libtaos.taos_fetch_row(result) - # if not row: - # return None - - # for i in range(len(fields)): - # l.append(CTaosInterface.getDataValue( - # row[i], fields[i]['type'], fields[i]['bytes'])) - - # return tuple(l) - - # @staticmethod - # def getDataValue(data, dtype, byte): - # ''' - # ''' - # if not data: - # return None - - # if (dtype == CTaosInterface.TSDB_DATA_TYPE_BOOL): - # return ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[0] - # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_TINYINT): - # return ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[0] - # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_SMALLINT): - # return ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[0] - # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_INT): - # return ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[0] - # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_BIGINT): - # return ctypes.cast(data, ctypes.POINTER(ctypes.c_int64))[0] - # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_FLOAT): - # return ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[0] - # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_DOUBLE): - # return ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[0] - # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_BINARY): - # return (ctypes.cast(data, ctypes.POINTER(ctypes.c_char))[0:byte]).rstrip('\x00') - # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_TIMESTAMP): - # return ctypes.cast(data, ctypes.POINTER(ctypes.c_int64))[0] - # elif (dtype == CTaosInterface.TSDB_DATA_TYPE_NCHAR): - # return (ctypes.cast(data, ctypes.c_char_p).value).rstrip('\x00') - - @staticmethod - def errno(result): - """Return the error number. - """ - return CTaosInterface.libtaos.taos_errno(result) - - @staticmethod - def errStr(result): - """Return the error styring - """ - return CTaosInterface.libtaos.taos_errstr(result).decode('utf-8') + return taos_connect(host, user, password, db, port) -if __name__ == '__main__': +if __name__ == "__main__": cinter = CTaosInterface() conn = cinter.connect() - result = cinter.query(conn, 'show databases') + result = cinter.query(conn, "show databases") - print('Query Affected rows: {}'.format(cinter.affectedRows(result))) + print("Query Affected rows: {}".format(cinter.affected_rows(result))) - fields = CTaosInterface.useResult(result) + fields = taos_fetch_fields_raw(result) - data, num_of_rows = CTaosInterface.fetchBlock(result, fields) + data, num_of_rows = taos_fetch_block(result, fields) print(data) - cinter.freeResult(result) + cinter.free_result(result) cinter.close(conn) diff --git a/src/connector/python/taos/connection.py b/src/connector/python/taos/connection.py index 88d06cd718..7857c8c706 100644 --- a/src/connector/python/taos/connection.py +++ b/src/connector/python/taos/connection.py @@ -1,11 +1,15 @@ -from .cursor import TDengineCursor -from .subscription import TDengineSubscription -from .cinterface import CTaosInterface +# encoding:UTF-8 +from types import FunctionType +from .cinterface import * +from .cursor import TaosCursor +from .subscription import TaosSubscription +from .statement import TaosStmt +from .stream import TaosStream +from .result import * -class TDengineConnection(object): - """ TDengine connection object - """ +class TaosConnection(object): + """TDengine connection object""" def __init__(self, *args, **kwargs): self._conn = None @@ -21,63 +25,130 @@ class TDengineConnection(object): def config(self, **kwargs): # host - if 'host' in kwargs: - self._host = kwargs['host'] + if "host" in kwargs: + self._host = kwargs["host"] # user - if 'user' in kwargs: - self._user = kwargs['user'] + if "user" in kwargs: + self._user = kwargs["user"] # password - if 'password' in kwargs: - self._password = kwargs['password'] + if "password" in kwargs: + self._password = kwargs["password"] # database - if 'database' in kwargs: - self._database = kwargs['database'] + if "database" in kwargs: + self._database = kwargs["database"] # port - if 'port' in kwargs: - self._port = kwargs['port'] + if "port" in kwargs: + self._port = kwargs["port"] # config - if 'config' in kwargs: - self._config = kwargs['config'] + if "config" in kwargs: + self._config = kwargs["config"] self._chandle = CTaosInterface(self._config) - self._conn = self._chandle.connect( - self._host, - self._user, - self._password, - self._database, - self._port) + self._conn = self._chandle.connect(self._host, self._user, self._password, self._database, self._port) def close(self): - """Close current connection. - """ - return CTaosInterface.close(self._conn) + """Close current connection.""" + if self._conn: + taos_close(self._conn) + self._conn = None - def subscribe(self, restart, topic, sql, interval): - """Create a subscription. - """ + @property + def client_info(self): + # type: () -> str + return taos_get_client_info() + + @property + def server_info(self): + # type: () -> str + return taos_get_server_info(self._conn) + + def select_db(self, database): + # type: (str) -> None + taos_select_db(self._conn, database) + + def execute(self, sql): + # type: (str) -> None + """Simplely execute sql ignoring the results""" + res = taos_query(self._conn, sql) + taos_free_result(res) + + def query(self, sql): + # type: (str) -> TaosResult + result = taos_query(self._conn, sql) + return TaosResult(result, True, self) + + def query_a(self, sql, callback, param): + # type: (str, async_query_callback_type, c_void_p) -> None + """Asynchronously query a sql with callback function""" + taos_query_a(self._conn, sql, callback, param) + + def subscribe(self, restart, topic, sql, interval, callback=None, param=None): + # type: (bool, str, str, int, subscribe_callback_type, c_void_p) -> TaosSubscription + """Create a subscription.""" if self._conn is None: return None - sub = CTaosInterface.subscribe( - self._conn, restart, topic, sql, interval) - return TDengineSubscription(sub) + sub = taos_subscribe(self._conn, restart, topic, sql, interval, callback, param) + return TaosSubscription(sub, callback != None) - def insertLines(self, lines): - """ - insert lines through line protocol - """ + def statement(self, sql=None): + # type: (str | None) -> TaosStmt if self._conn is None: return None - return CTaosInterface.insertLines(self._conn, lines) - + stmt = taos_stmt_init(self._conn) + if sql != None: + taos_stmt_prepare(stmt, sql) + + return TaosStmt(stmt) + + def load_table_info(self, tables): + # type: (str) -> None + taos_load_table_info(self._conn, tables) + + def stream(self, sql, callback, stime=0, param=None, callback2=None): + # type: (str, Callable[[Any, TaosResult, TaosRows], None], int, Any, c_void_p) -> TaosStream + # cb = cast(callback, stream_callback_type) + # ref = byref(cb) + + stream = taos_open_stream(self._conn, sql, callback, stime, param, callback2) + return TaosStream(stream) + + def insert_lines(self, lines): + # type: (list[str]) -> None + """Line protocol and schemaless support + + ## Example + + ```python + import taos + conn = taos.connect() + conn.exec("drop database if exists test") + conn.select_db("test") + lines = [ + 'ste,t2=5,t3=L"ste" c1=true,c2=4,c3="string" 1626056811855516532', + ] + conn.insert_lines(lines) + ``` + + ## Exception + + ```python + try: + conn.insert_lines(lines) + except SchemalessError as err: + print(err) + ``` + """ + return taos_insert_lines(self._conn, lines) + def cursor(self): - """Return a new Cursor object using the connection. - """ - return TDengineCursor(self) + # type: () -> TaosCursor + """Return a new Cursor object using the connection.""" + return TaosCursor(self) def commit(self): """Commit any pending transaction to the database. @@ -87,17 +158,18 @@ class TDengineConnection(object): pass def rollback(self): - """Void functionality - """ + """Void functionality""" pass def clear_result_set(self): - """Clear unused result set on this connection. - """ + """Clear unused result set on this connection.""" pass + def __del__(self): + self.close() + if __name__ == "__main__": - conn = TDengineConnection(host='192.168.1.107') + conn = TaosConnection() conn.close() print("Hello world") diff --git a/src/connector/python/taos/constants.py b/src/connector/python/taos/constants.py index 85689b02db..b500df627c 100644 --- a/src/connector/python/taos/constants.py +++ b/src/connector/python/taos/constants.py @@ -1,12 +1,11 @@ +# encoding:UTF-8 + """Constants in TDengine python """ -from .dbapi import * - - class FieldType(object): - """TDengine Field Types - """ + """TDengine Field Types""" + # type_code C_NULL = 0 C_BOOL = 1 @@ -34,9 +33,9 @@ class FieldType(object): C_INT_UNSIGNED_NULL = 4294967295 C_BIGINT_NULL = -9223372036854775808 C_BIGINT_UNSIGNED_NULL = 18446744073709551615 - C_FLOAT_NULL = float('nan') - C_DOUBLE_NULL = float('nan') - C_BINARY_NULL = bytearray([int('0xff', 16)]) + C_FLOAT_NULL = float("nan") + C_DOUBLE_NULL = float("nan") + C_BINARY_NULL = bytearray([int("0xff", 16)]) # Timestamp precision definition C_TIMESTAMP_MILLI = 0 C_TIMESTAMP_MICRO = 1 diff --git a/src/connector/python/taos/cursor.py b/src/connector/python/taos/cursor.py index d443ec95d0..5d21ff95af 100644 --- a/src/connector/python/taos/cursor.py +++ b/src/connector/python/taos/cursor.py @@ -1,18 +1,18 @@ -from .cinterface import CTaosInterface +# encoding:UTF-8 +from .cinterface import * from .error import * from .constants import FieldType - -# querySeqNum = 0 +from .result import * -class TDengineCursor(object): +class TaosCursor(object): """Database cursor which is used to manage the context of a fetch operation. Attributes: .description: Read-only attribute consists of 7-item sequences: - > name (mondatory) - > type_code (mondatory) + > name (mandatory) + > type_code (mandatory) > display_size > internal_size > precision @@ -55,8 +55,7 @@ class TDengineCursor(object): raise OperationalError("Invalid use of fetch iterator") if self._block_rows <= self._block_iter: - block, self._block_rows = CTaosInterface.fetchRow( - self._result, self._fields) + block, self._block_rows = taos_fetch_row(self._result, self._fields) if self._block_rows == 0: raise StopIteration self._block = list(map(tuple, zip(*block))) @@ -69,20 +68,17 @@ class TDengineCursor(object): @property def description(self): - """Return the description of the object. - """ + """Return the description of the object.""" return self._description @property def rowcount(self): - """Return the rowcount of the object - """ + """Return the rowcount of the object""" return self._rowcount @property def affected_rows(self): - """Return the rowcount of insertion - """ + """Return the rowcount of insertion""" return self._affected_rows def callproc(self, procname, *args): @@ -96,8 +92,7 @@ class TDengineCursor(object): self._logfile = logfile def close(self): - """Close the cursor. - """ + """Close the cursor.""" if self._connection is None: return False @@ -107,8 +102,7 @@ class TDengineCursor(object): return True def execute(self, operation, params=None): - """Prepare and execute a database operation (query or command). - """ + """Prepare and execute a database operation (query or command).""" if not operation: return None @@ -124,104 +118,91 @@ class TDengineCursor(object): # global querySeqNum # querySeqNum += 1 - # localSeqNum = querySeqNum # avoid raice condition + # localSeqNum = querySeqNum # avoid race condition # print(" >> Exec Query ({}): {}".format(localSeqNum, str(stmt))) - self._result = CTaosInterface.query(self._connection._conn, stmt) + self._result = taos_query(self._connection._conn, stmt) # print(" << Query ({}) Exec Done".format(localSeqNum)) - if (self._logfile): + if self._logfile: with open(self._logfile, "a") as logfile: logfile.write("%s;\n" % operation) - errno = CTaosInterface.libtaos.taos_errno(self._result) - if errno == 0: - if CTaosInterface.fieldsCount(self._result) == 0: - self._affected_rows += CTaosInterface.affectedRows( - self._result) - return CTaosInterface.affectedRows(self._result) - else: - self._fields = CTaosInterface.useResult( - self._result) - return self._handle_result() + if taos_field_count(self._result) == 0: + affected_rows = taos_affected_rows(self._result) + self._affected_rows += affected_rows + return affected_rows else: - raise ProgrammingError( - CTaosInterface.errStr( - self._result), errno) + self._fields = taos_fetch_fields(self._result) + return self._handle_result() def executemany(self, operation, seq_of_parameters): - """Prepare a database operation (query or command) and then execute it against all parameter sequences or mappings found in the sequence seq_of_parameters. - """ + """Prepare a database operation (query or command) and then execute it against all parameter sequences or mappings found in the sequence seq_of_parameters.""" pass def fetchone(self): - """Fetch the next row of a query result set, returning a single sequence, or None when no more data is available. - """ + """Fetch the next row of a query result set, returning a single sequence, or None when no more data is available.""" pass def fetchmany(self): pass def istype(self, col, dataType): - if (dataType.upper() == "BOOL"): - if (self._description[col][1] == FieldType.C_BOOL): + if dataType.upper() == "BOOL": + if self._description[col][1] == FieldType.C_BOOL: return True - if (dataType.upper() == "TINYINT"): - if (self._description[col][1] == FieldType.C_TINYINT): + if dataType.upper() == "TINYINT": + if self._description[col][1] == FieldType.C_TINYINT: return True - if (dataType.upper() == "TINYINT UNSIGNED"): - if (self._description[col][1] == FieldType.C_TINYINT_UNSIGNED): + if dataType.upper() == "TINYINT UNSIGNED": + if self._description[col][1] == FieldType.C_TINYINT_UNSIGNED: return True - if (dataType.upper() == "SMALLINT"): - if (self._description[col][1] == FieldType.C_SMALLINT): + if dataType.upper() == "SMALLINT": + if self._description[col][1] == FieldType.C_SMALLINT: return True - if (dataType.upper() == "SMALLINT UNSIGNED"): - if (self._description[col][1] == FieldType.C_SMALLINT_UNSIGNED): + if dataType.upper() == "SMALLINT UNSIGNED": + if self._description[col][1] == FieldType.C_SMALLINT_UNSIGNED: return True - if (dataType.upper() == "INT"): - if (self._description[col][1] == FieldType.C_INT): + if dataType.upper() == "INT": + if self._description[col][1] == FieldType.C_INT: return True - if (dataType.upper() == "INT UNSIGNED"): - if (self._description[col][1] == FieldType.C_INT_UNSIGNED): + if dataType.upper() == "INT UNSIGNED": + if self._description[col][1] == FieldType.C_INT_UNSIGNED: return True - if (dataType.upper() == "BIGINT"): - if (self._description[col][1] == FieldType.C_BIGINT): + if dataType.upper() == "BIGINT": + if self._description[col][1] == FieldType.C_BIGINT: return True - if (dataType.upper() == "BIGINT UNSIGNED"): - if (self._description[col][1] == FieldType.C_BIGINT_UNSIGNED): + if dataType.upper() == "BIGINT UNSIGNED": + if self._description[col][1] == FieldType.C_BIGINT_UNSIGNED: return True - if (dataType.upper() == "FLOAT"): - if (self._description[col][1] == FieldType.C_FLOAT): + if dataType.upper() == "FLOAT": + if self._description[col][1] == FieldType.C_FLOAT: return True - if (dataType.upper() == "DOUBLE"): - if (self._description[col][1] == FieldType.C_DOUBLE): + if dataType.upper() == "DOUBLE": + if self._description[col][1] == FieldType.C_DOUBLE: return True - if (dataType.upper() == "BINARY"): - if (self._description[col][1] == FieldType.C_BINARY): + if dataType.upper() == "BINARY": + if self._description[col][1] == FieldType.C_BINARY: return True - if (dataType.upper() == "TIMESTAMP"): - if (self._description[col][1] == FieldType.C_TIMESTAMP): + if dataType.upper() == "TIMESTAMP": + if self._description[col][1] == FieldType.C_TIMESTAMP: return True - if (dataType.upper() == "NCHAR"): - if (self._description[col][1] == FieldType.C_NCHAR): + if dataType.upper() == "NCHAR": + if self._description[col][1] == FieldType.C_NCHAR: return True return False def fetchall_row(self): - """Fetch all (remaining) rows of a query result, returning them as a sequence of sequences (e.g. a list of tuples). Note that the cursor's arraysize attribute can affect the performance of this operation. - """ + """Fetch all (remaining) rows of a query result, returning them as a sequence of sequences (e.g. a list of tuples). Note that the cursor's arraysize attribute can affect the performance of this operation.""" if self._result is None or self._fields is None: raise OperationalError("Invalid use of fetchall") buffer = [[] for i in range(len(self._fields))] self._rowcount = 0 while True: - block, num_of_fields = CTaosInterface.fetchRow( - self._result, self._fields) - errno = CTaosInterface.libtaos.taos_errno(self._result) + block, num_of_fields = taos_fetch_row(self._result, self._fields) + errno = taos_errno(self._result) if errno != 0: - raise ProgrammingError( - CTaosInterface.errStr( - self._result), errno) + raise ProgrammingError(taos_errstr(self._result), errno) if num_of_fields == 0: break self._rowcount += num_of_fields @@ -230,19 +211,16 @@ class TDengineCursor(object): return list(map(tuple, zip(*buffer))) def fetchall(self): - if self._result is None or self._fields is None: + if self._result is None: raise OperationalError("Invalid use of fetchall") - - buffer = [[] for i in range(len(self._fields))] + fields = self._fields if self._fields is not None else taos_fetch_fields(self._result) + buffer = [[] for i in range(len(fields))] self._rowcount = 0 while True: - block, num_of_fields = CTaosInterface.fetchBlock( - self._result, self._fields) - errno = CTaosInterface.libtaos.taos_errno(self._result) + block, num_of_fields = taos_fetch_block(self._result, self._fields) + errno = taos_errno(self._result) if errno != 0: - raise ProgrammingError( - CTaosInterface.errStr( - self._result), errno) + raise ProgrammingError(taos_errstr(self._result), errno) if num_of_fields == 0: break self._rowcount += num_of_fields @@ -250,9 +228,12 @@ class TDengineCursor(object): buffer[i].extend(block[i]) return list(map(tuple, zip(*buffer))) + def stop_query(self): + if self._result != None: + taos_stop_query(self._result) + def nextset(self): - """ - """ + """ """ pass def setinputsize(self, sizes): @@ -262,12 +243,11 @@ class TDengineCursor(object): pass def _reset_result(self): - """Reset the result to unused version. - """ + """Reset the result to unused version.""" self._description = [] self._rowcount = -1 if self._result is not None: - CTaosInterface.freeResult(self._result) + taos_free_result(self._result) self._result = None self._fields = None self._block = None @@ -276,11 +256,12 @@ class TDengineCursor(object): self._affected_rows = 0 def _handle_result(self): - """Handle the return result from query. - """ + """Handle the return result from query.""" self._description = [] for ele in self._fields: - self._description.append( - (ele['name'], ele['type'], None, None, None, None, False)) + self._description.append((ele["name"], ele["type"], None, None, None, None, False)) return self._result + + def __del__(self): + self.close() diff --git a/src/connector/python/taos/dbapi.py b/src/connector/python/taos/dbapi.py deleted file mode 100644 index 594681ada9..0000000000 --- a/src/connector/python/taos/dbapi.py +++ /dev/null @@ -1,44 +0,0 @@ -"""Type Objects and Constructors. -""" - -import time -import datetime - - -class DBAPITypeObject(object): - def __init__(self, *values): - self.values = values - - def __com__(self, other): - if other in self.values: - return 0 - if other < self.values: - return 1 - else: - return -1 - - -Date = datetime.date -Time = datetime.time -Timestamp = datetime.datetime - - -def DataFromTicks(ticks): - return Date(*time.localtime(ticks)[:3]) - - -def TimeFromTicks(ticks): - return Time(*time.localtime(ticks)[3:6]) - - -def TimestampFromTicks(ticks): - return Timestamp(*time.localtime(ticks)[:6]) - - -Binary = bytes - -# STRING = DBAPITypeObject(*constants.FieldType.get_string_types()) -# BINARY = DBAPITypeObject(*constants.FieldType.get_binary_types()) -# NUMBER = BAPITypeObject(*constants.FieldType.get_number_types()) -# DATETIME = DBAPITypeObject(*constants.FieldType.get_timestamp_types()) -# ROWID = DBAPITypeObject() diff --git a/src/connector/python/taos/error.py b/src/connector/python/taos/error.py index c584badce8..a30adbb162 100644 --- a/src/connector/python/taos/error.py +++ b/src/connector/python/taos/error.py @@ -1,66 +1,86 @@ +# encoding:UTF-8 """Python exceptions """ class Error(Exception): - def __init__(self, msg=None, errno=None): + def __init__(self, msg=None, errno=0xffff): self.msg = msg - self._full_msg = self.msg self.errno = errno + self._full_msg = "[0x%04x]: %s" % (self.errno & 0xffff, self.msg) def __str__(self): return self._full_msg class Warning(Exception): - """Exception raised for important warnings like data truncations while inserting. - """ + """Exception raised for important warnings like data truncations while inserting.""" + pass class InterfaceError(Error): - """Exception raised for errors that are related to the database interface rather than the database itself. - """ + """Exception raised for errors that are related to the database interface rather than the database itself.""" + pass class DatabaseError(Error): - """Exception raised for errors that are related to the database. - """ + """Exception raised for errors that are related to the database.""" + pass +class ConnectionError(Error): + """Exceptin raised for connection failed""" + pass class DataError(DatabaseError): - """Exception raised for errors that are due to problems with the processed data like division by zero, numeric value out of range. - """ + """Exception raised for errors that are due to problems with the processed data like division by zero, numeric value out of range.""" + pass class OperationalError(DatabaseError): - """Exception raised for errors that are related to the database's operation and not necessarily under the control of the programmer - """ + """Exception raised for errors that are related to the database's operation and not necessarily under the control of the programmer""" + pass class IntegrityError(DatabaseError): - """Exception raised when the relational integrity of the database is affected. - """ + """Exception raised when the relational integrity of the database is affected.""" + pass class InternalError(DatabaseError): - """Exception raised when the database encounters an internal error. - """ + """Exception raised when the database encounters an internal error.""" + pass class ProgrammingError(DatabaseError): - """Exception raised for programming errors. - """ + """Exception raised for programming errors.""" + pass class NotSupportedError(DatabaseError): - """Exception raised in case a method or database API was used which is not supported by the database,. - """ + """Exception raised in case a method or database API was used which is not supported by the database,.""" + pass + + +class StatementError(DatabaseError): + """Exception raised in STMT API.""" + + pass + +class ResultError(DatabaseError): + """Result related APIs.""" + + pass + +class LinesError(DatabaseError): + """taos_insert_lines errors.""" + + pass \ No newline at end of file diff --git a/src/connector/python/taos/field.py b/src/connector/python/taos/field.py new file mode 100644 index 0000000000..445cd8afdb --- /dev/null +++ b/src/connector/python/taos/field.py @@ -0,0 +1,302 @@ +# encoding:UTF-8 +import ctypes +import math +import datetime +from ctypes import * + +from .constants import FieldType +from .error import * + +_datetime_epoch = datetime.datetime.fromtimestamp(0) + +def _convert_millisecond_to_datetime(milli): + return _datetime_epoch + datetime.timedelta(seconds=milli / 1000.0) + + +def _convert_microsecond_to_datetime(micro): + return _datetime_epoch + datetime.timedelta(seconds=micro / 1000000.0) + + +def _convert_nanosecond_to_datetime(nanosec): + return nanosec + + +def _crow_timestamp_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C bool row to python row""" + _timestamp_converter = _convert_millisecond_to_datetime + if precision == FieldType.C_TIMESTAMP_MILLI: + _timestamp_converter = _convert_millisecond_to_datetime + elif precision == FieldType.C_TIMESTAMP_MICRO: + _timestamp_converter = _convert_microsecond_to_datetime + elif precision == FieldType.C_TIMESTAMP_NANO: + _timestamp_converter = _convert_nanosecond_to_datetime + else: + raise DatabaseError("Unknown precision returned from database") + + return [ + None if ele == FieldType.C_BIGINT_NULL else _timestamp_converter(ele) + for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int64))[: abs(num_of_rows)] + ] + + +def _crow_bool_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C bool row to python row""" + return [ + None if ele == FieldType.C_BOOL_NULL else bool(ele) + for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[: abs(num_of_rows)] + ] + + +def _crow_tinyint_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C tinyint row to python row""" + return [ + None if ele == FieldType.C_TINYINT_NULL else ele + for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[: abs(num_of_rows)] + ] + + +def _crow_tinyint_unsigned_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C tinyint row to python row""" + return [ + None if ele == FieldType.C_TINYINT_UNSIGNED_NULL else ele + for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_ubyte))[: abs(num_of_rows)] + ] + + +def _crow_smallint_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C smallint row to python row""" + return [ + None if ele == FieldType.C_SMALLINT_NULL else ele + for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[: abs(num_of_rows)] + ] + + +def _crow_smallint_unsigned_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C smallint row to python row""" + return [ + None if ele == FieldType.C_SMALLINT_UNSIGNED_NULL else ele + for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_ushort))[: abs(num_of_rows)] + ] + + +def _crow_int_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C int row to python row""" + return [ + None if ele == FieldType.C_INT_NULL else ele + for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[: abs(num_of_rows)] + ] + + +def _crow_int_unsigned_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C int row to python row""" + return [ + None if ele == FieldType.C_INT_UNSIGNED_NULL else ele + for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_uint))[: abs(num_of_rows)] + ] + + +def _crow_bigint_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C bigint row to python row""" + return [ + None if ele == FieldType.C_BIGINT_NULL else ele + for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int64))[: abs(num_of_rows)] + ] + + +def _crow_bigint_unsigned_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C bigint row to python row""" + return [ + None if ele == FieldType.C_BIGINT_UNSIGNED_NULL else ele + for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_uint64))[: abs(num_of_rows)] + ] + + +def _crow_float_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C float row to python row""" + return [ + None if math.isnan(ele) else ele + for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[: abs(num_of_rows)] + ] + + +def _crow_double_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C double row to python row""" + return [ + None if math.isnan(ele) else ele + for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[: abs(num_of_rows)] + ] + + +def _crow_binary_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C binary row to python row""" + assert nbytes is not None + return [ + None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode("utf-8") + for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[: abs(num_of_rows)] + ] + + +def _crow_nchar_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C nchar row to python row""" + assert nbytes is not None + res = [] + for i in range(abs(num_of_rows)): + try: + if num_of_rows >= 0: + tmpstr = ctypes.c_char_p(data) + res.append(tmpstr.value.decode()) + else: + res.append( + ( + ctypes.cast( + data + nbytes * i, + ctypes.POINTER(ctypes.c_wchar * (nbytes // 4)), + ) + )[0].value + ) + except ValueError: + res.append(None) + + return res + + +def _crow_binary_to_python_block(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C binary row to python row""" + assert nbytes is not None + res = [] + for i in range(abs(num_of_rows)): + try: + rbyte = ctypes.cast(data + nbytes * i, ctypes.POINTER(ctypes.c_short))[:1].pop() + tmpstr = ctypes.c_char_p(data + nbytes * i + 2) + res.append(tmpstr.value.decode()[0:rbyte]) + except ValueError: + res.append(None) + return res + + +def _crow_nchar_to_python_block(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN): + """Function to convert C nchar row to python row""" + assert nbytes is not None + res = [] + for i in range(abs(num_of_rows)): + try: + tmpstr = ctypes.c_char_p(data + nbytes * i + 2) + res.append(tmpstr.value.decode()) + except ValueError: + res.append(None) + return res + + +CONVERT_FUNC = { + FieldType.C_BOOL: _crow_bool_to_python, + FieldType.C_TINYINT: _crow_tinyint_to_python, + FieldType.C_SMALLINT: _crow_smallint_to_python, + FieldType.C_INT: _crow_int_to_python, + FieldType.C_BIGINT: _crow_bigint_to_python, + FieldType.C_FLOAT: _crow_float_to_python, + FieldType.C_DOUBLE: _crow_double_to_python, + FieldType.C_BINARY: _crow_binary_to_python, + FieldType.C_TIMESTAMP: _crow_timestamp_to_python, + FieldType.C_NCHAR: _crow_nchar_to_python, + FieldType.C_TINYINT_UNSIGNED: _crow_tinyint_unsigned_to_python, + FieldType.C_SMALLINT_UNSIGNED: _crow_smallint_unsigned_to_python, + FieldType.C_INT_UNSIGNED: _crow_int_unsigned_to_python, + FieldType.C_BIGINT_UNSIGNED: _crow_bigint_unsigned_to_python, +} + +CONVERT_FUNC_BLOCK = { + FieldType.C_BOOL: _crow_bool_to_python, + FieldType.C_TINYINT: _crow_tinyint_to_python, + FieldType.C_SMALLINT: _crow_smallint_to_python, + FieldType.C_INT: _crow_int_to_python, + FieldType.C_BIGINT: _crow_bigint_to_python, + FieldType.C_FLOAT: _crow_float_to_python, + FieldType.C_DOUBLE: _crow_double_to_python, + FieldType.C_BINARY: _crow_binary_to_python_block, + FieldType.C_TIMESTAMP: _crow_timestamp_to_python, + FieldType.C_NCHAR: _crow_nchar_to_python_block, + FieldType.C_TINYINT_UNSIGNED: _crow_tinyint_unsigned_to_python, + FieldType.C_SMALLINT_UNSIGNED: _crow_smallint_unsigned_to_python, + FieldType.C_INT_UNSIGNED: _crow_int_unsigned_to_python, + FieldType.C_BIGINT_UNSIGNED: _crow_bigint_unsigned_to_python, +} + +# Corresponding TAOS_FIELD structure in C + + +class TaosField(ctypes.Structure): + _fields_ = [ + ("_name", ctypes.c_char * 65), + ("_type", ctypes.c_uint8), + ("_bytes", ctypes.c_uint16), + ] + + @property + def name(self): + return self._name.decode("utf-8") + + @property + def length(self): + """alias to self.bytes""" + return self._bytes + + @property + def bytes(self): + return self._bytes + + @property + def type(self): + return self._type + + def __dict__(self): + return {"name": self.name, "type": self.type, "bytes": self.length} + + def __str__(self): + return "{name: %s, type: %d, bytes: %d}" % (self.name, self.type, self.length) + + def __getitem__(self, item): + return getattr(self, item) + + +class TaosFields(object): + def __init__(self, fields, count): + if isinstance(fields, c_void_p): + self._fields = cast(fields, POINTER(TaosField)) + if isinstance(fields, POINTER(TaosField)): + self._fields = fields + self._count = count + self._iter = 0 + + def as_ptr(self): + return self._fields + + @property + def count(self): + return self._count + + @property + def fields(self): + return self._fields + + def __next__(self): + return self._next_field() + + def next(self): + return self._next_field() + + def _next_field(self): + if self._iter < self.count: + field = self._fields[self._iter] + self._iter += 1 + return field + else: + raise StopIteration + + def __getitem__(self, item): + return self._fields[item] + + def __iter__(self): + return self + + def __len__(self): + return self.count diff --git a/src/connector/python/taos/precision.py b/src/connector/python/taos/precision.py new file mode 100644 index 0000000000..d67da592cc --- /dev/null +++ b/src/connector/python/taos/precision.py @@ -0,0 +1,12 @@ +class PrecisionEnum(object): + """Precision enums""" + + Milliseconds = 0 + Microseconds = 1 + Nanoseconds = 2 + + +class PrecisionError(Exception): + """Python datetime does not support nanoseconds error""" + + pass diff --git a/src/connector/python/taos/result.py b/src/connector/python/taos/result.py new file mode 100644 index 0000000000..8115173361 --- /dev/null +++ b/src/connector/python/taos/result.py @@ -0,0 +1,245 @@ +from .cinterface import * + +# from .connection import TaosConnection +from .error import * + + +class TaosResult(object): + """TDengine result interface""" + + def __init__(self, result, close_after=False, conn=None): + # type: (c_void_p, bool, TaosConnection) -> TaosResult + # to make the __del__ order right + self._conn = conn + self._close_after = close_after + self._result = result + self._fields = None + self._field_count = None + self._precision = None + + self._block = None + self._block_length = None + self._row_count = 0 + + def __iter__(self): + return self + + def __next__(self): + return self._next_row() + + def next(self): + # fetch next row + return self._next_row() + + def _next_row(self): + if self._result is None or self.fields is None: + raise OperationalError("Invalid use of fetch iterator") + + if self._block == None or self._block_iter >= self._block_length: + self._block, self._block_length = self.fetch_block() + self._block_iter = 0 + # self._row_count += self._block_length + + raw = self._block[self._block_iter] + self._block_iter += 1 + return raw + + @property + def fields(self): + """fields definitions of the current result""" + if self._result is None: + raise ResultError("no result object setted") + if self._fields == None: + self._fields = taos_fetch_fields(self._result) + + return self._fields + + @property + def field_count(self): + """Field count of the current result, eq to taos_field_count(result)""" + return self.fields.count + + @property + def row_count(self): + """Return the rowcount of the object""" + return self._row_count + + @property + def precision(self): + if self._precision == None: + self._precision = taos_result_precision(self._result) + return self._precision + + @property + def affected_rows(self): + return taos_affected_rows(self._result) + + # @property + def field_lengths(self): + return taos_fetch_lengths(self._result, self.field_count) + + def rows_iter(self, num_of_rows=None): + return TaosRows(self, num_of_rows) + + def blocks_iter(self): + return TaosBlocks(self) + + def fetch_block(self): + if self._result is None: + raise OperationalError("Invalid use of fetch iterator") + + block, length = taos_fetch_block_raw(self._result) + if length == 0: + raise StopIteration + precision = self.precision + field_count = self.field_count + fields = self.fields + blocks = [None] * field_count + lengths = self.field_lengths() + for i in range(field_count): + data = ctypes.cast(block, ctypes.POINTER(ctypes.c_void_p))[i] + if fields[i].type not in CONVERT_FUNC_BLOCK: + raise DatabaseError("Invalid data type returned from database") + blocks[i] = CONVERT_FUNC_BLOCK[fields[i].type](data, length, lengths[i], precision) + + return list(map(tuple, zip(*blocks))), length + + def fetch_all(self): + if self._result is None: + raise OperationalError("Invalid use of fetchall") + + if self._fields == None: + self._fields = taos_fetch_fields(self._result) + buffer = [[] for i in range(len(self._fields))] + self._row_count = 0 + while True: + block, num_of_fields = taos_fetch_block(self._result, self._fields) + errno = taos_errno(self._result) + if errno != 0: + raise ProgrammingError(taos_errstr(self._result), errno) + if num_of_fields == 0: + break + self._row_count += num_of_fields + for i in range(len(self._fields)): + buffer[i].extend(block[i]) + return list(map(tuple, zip(*buffer))) + + def fetch_rows_a(self, callback, param): + taos_fetch_rows_a(self._result, callback, param) + + def stop_query(self): + return taos_stop_query(self._result) + + def errno(self): + """**DO NOT** use this directly unless you know what you are doing""" + return taos_errno(self._result) + + def errstr(self): + return taos_errstr(self._result) + + def check_error(self, errno=None, close=True): + if errno == None: + errno = self.errno() + if errno != 0: + msg = self.errstr() + self.close() + raise OperationalError(msg, errno) + + def close(self): + """free result object.""" + if self._result != None and self._close_after: + taos_free_result(self._result) + self._result = None + self._fields = None + self._field_count = None + self._field_lengths = None + + def __del__(self): + self.close() + + +class TaosRows: + """TDengine result rows iterator""" + + def __init__(self, result, num_of_rows=None): + self._result = result + self._num_of_rows = num_of_rows + + def __iter__(self): + return self + + def __next__(self): + return self._next_row() + + def next(self): + return self._next_row() + + def _next_row(self): + if self._result is None: + raise OperationalError("Invalid use of fetch iterator") + if self._num_of_rows != None and self._num_of_rows <= self._result._row_count: + raise StopIteration + + row = taos_fetch_row_raw(self._result._result) + if not row: + raise StopIteration + self._result._row_count += 1 + return TaosRow(self._result, row) + + @property + def row_count(self): + """Return the rowcount of the object""" + return self._result._row_count + + +class TaosRow: + def __init__(self, result, row): + self._result = result + self._row = row + + def __str__(self): + return taos_print_row(self._row, self._result.fields, self._result.field_count) + + def __call__(self): + return self.as_tuple() + + def _astuple(self): + return self.as_tuple() + + def __iter__(self): + return self.as_tuple() + + def as_ptr(self): + return self._row + + def as_tuple(self): + precision = self._result.precision + field_count = self._result.field_count + blocks = [None] * field_count + fields = self._result.fields + field_lens = self._result.field_lengths() + for i in range(field_count): + data = ctypes.cast(self._row, ctypes.POINTER(ctypes.c_void_p))[i] + if fields[i].type not in CONVERT_FUNC: + raise DatabaseError("Invalid data type returned from database") + if data is None: + blocks[i] = None + else: + blocks[i] = CONVERT_FUNC[fields[i].type](data, 1, field_lens[i], precision)[0] + return tuple(blocks) + + +class TaosBlocks: + """TDengine result blocks iterator""" + + def __init__(self, result): + self._result = result + + def __iter__(self): + return self + + def __next__(self): + return self._result.fetch_block() + + def next(self): + return self._result.fetch_block() diff --git a/src/connector/python/taos/statement.py b/src/connector/python/taos/statement.py new file mode 100644 index 0000000000..155e98173b --- /dev/null +++ b/src/connector/python/taos/statement.py @@ -0,0 +1,85 @@ +from taos.cinterface import * +from taos.error import * +from taos.result import * + + +class TaosStmt(object): + """TDengine STMT interface""" + + def __init__(self, stmt, conn = None): + self._conn = conn + self._stmt = stmt + + def set_tbname(self, name): + """Set table name if needed. + + Note that the set_tbname* method should only used in insert statement + """ + if self._stmt is None: + raise StatementError("Invalid use of set_tbname") + taos_stmt_set_tbname(self._stmt, name) + + def prepare(self, sql): + # type: (str) -> None + taos_stmt_prepare(self._stmt, sql) + + def set_tbname_tags(self, name, tags): + # type: (str, Array[TaosBind]) -> None + """Set table name with tags, tags is array of BindParams""" + if self._stmt is None: + raise StatementError("Invalid use of set_tbname") + taos_stmt_set_tbname_tags(self._stmt, name, tags) + + def bind_param(self, params, add_batch=True): + # type: (Array[TaosBind], bool) -> None + if self._stmt is None: + raise StatementError("Invalid use of stmt") + taos_stmt_bind_param(self._stmt, params) + if add_batch: + taos_stmt_add_batch(self._stmt) + + def bind_param_batch(self, binds, add_batch=True): + # type: (Array[TaosMultiBind], bool) -> None + if self._stmt is None: + raise StatementError("Invalid use of stmt") + taos_stmt_bind_param_batch(self._stmt, binds) + if add_batch: + taos_stmt_add_batch(self._stmt) + + def add_batch(self): + if self._stmt is None: + raise StatementError("Invalid use of stmt") + taos_stmt_add_batch(self._stmt) + + def execute(self): + if self._stmt is None: + raise StatementError("Invalid use of execute") + taos_stmt_execute(self._stmt) + + def use_result(self): + result = taos_stmt_use_result(self._stmt) + return TaosResult(result) + + def close(self): + """Close stmt.""" + if self._stmt is None: + return + taos_stmt_close(self._stmt) + self._stmt = None + + def __del__(self): + self.close() + + +if __name__ == "__main__": + from taos.connection import TaosConnection + + conn = TaosConnection() + + stmt = conn.statement("select * from log.log limit 10") + stmt.execute() + result = stmt.use_result() + for row in result: + print(row) + stmt.close() + conn.close() diff --git a/src/connector/python/taos/stream.py b/src/connector/python/taos/stream.py new file mode 100644 index 0000000000..fe3c8c85e3 --- /dev/null +++ b/src/connector/python/taos/stream.py @@ -0,0 +1,22 @@ +from taos.cinterface import * +from taos.error import * +from taos.result import * + + +class TaosStream(object): + """TDengine Stream interface""" + + def __init__(self, stream): + self._raw = stream + + def as_ptr(self): + return self._raw + + def close(self): + """Close stmt.""" + if self._raw is not None: + taos_close_stream(self._raw) + self._raw = None + + def __del__(self): + self.close() diff --git a/src/connector/python/taos/subscription.py b/src/connector/python/taos/subscription.py index 270d9de092..3c6958b6f8 100644 --- a/src/connector/python/taos/subscription.py +++ b/src/connector/python/taos/subscription.py @@ -1,49 +1,41 @@ -from .cinterface import CTaosInterface +from taos.result import TaosResult +from .cinterface import * from .error import * -class TDengineSubscription(object): - """TDengine subscription object - """ +class TaosSubscription(object): + """TDengine subscription object""" - def __init__(self, sub): + def __init__(self, sub, with_callback = False): self._sub = sub + self._with_callback = with_callback def consume(self): - """Consume rows of a subscription - """ + """Consume rows of a subscription""" if self._sub is None: raise OperationalError("Invalid use of consume") - - result, fields = CTaosInterface.consume(self._sub) - buffer = [[] for i in range(len(fields))] - while True: - block, num_of_fields = CTaosInterface.fetchBlock(result, fields) - if num_of_fields == 0: - break - for i in range(len(fields)): - buffer[i].extend(block[i]) - - self.fields = fields - return list(map(tuple, zip(*buffer))) + if self._with_callback: + raise OperationalError("DONOT use consume method in an subscription with callback") + result = taos_consume(self._sub) + return TaosResult(result) def close(self, keepProgress=True): - """Close the Subscription. - """ + """Close the Subscription.""" if self._sub is None: return False - CTaosInterface.unsubscribe(self._sub, keepProgress) + taos_unsubscribe(self._sub, keepProgress) + self._sub = None return True + + def __del__(self): + self.close() -if __name__ == '__main__': - from .connection import TDengineConnection - conn = TDengineConnection( - host="127.0.0.1", - user="root", - password="taosdata", - database="test") +if __name__ == "__main__": + from .connection import TaosConnection + + conn = TaosConnection(host="127.0.0.1", user="root", password="taosdata", database="test") # Generate a cursor object to run SQL commands sub = conn.subscribe(True, "test", "select * from meters;", 1000) diff --git a/src/connector/python/taos/timestamp.py b/src/connector/python/taos/timestamp.py new file mode 100644 index 0000000000..ab5679fdf1 --- /dev/null +++ b/src/connector/python/taos/timestamp.py @@ -0,0 +1,17 @@ + +class TimestampType(object): + """Choose which type that parsing TDengine timestamp data to + + - DATETIME: use python datetime.datetime, note that it does not support nanosecond precision, + and python taos will use raw c_int64 as a fallback for nanosecond results. + - NUMPY: use numpy.datetime64 type. + - RAW: use raw c_int64. + - TAOS: use taos' TaosTimestamp. + """ + DATETIME = 0, + NUMPY = 1, + RAW = 2, + TAOS = 3, + +class TaosTimestamp: + pass diff --git a/src/connector/python/tests/test_ctaos.py b/src/connector/python/tests/test_ctaos.py new file mode 100644 index 0000000000..7b9566931f --- /dev/null +++ b/src/connector/python/tests/test_ctaos.py @@ -0,0 +1,162 @@ +from taos.cinterface import * +from taos.precision import * +from taos.bind import * + +import time +import datetime +import pytest + +@pytest.fixture +def conn(): + return CTaosInterface().connect() + + +def test_simple(conn, caplog): + dbname = "pytest_ctaos_simple" + try: + res = taos_query(conn, "create database if not exists %s" % dbname) + taos_free_result(res) + + taos_select_db(conn, dbname) + + res = taos_query( + conn, + "create table if not exists log(ts timestamp, level tinyint, content binary(100), ipaddr binary(134))", + ) + taos_free_result(res) + + res = taos_query(conn, "insert into log values(now, 1, 'hello', 'test')") + taos_free_result(res) + + res = taos_query(conn, "select level,content,ipaddr from log limit 1") + + fields = taos_fetch_fields_raw(res) + field_count = taos_field_count(res) + + fields = taos_fetch_fields(res) + for field in fields: + print(field) + + # field_lengths = taos_fetch_lengths(res, field_count) + # if not field_lengths: + # raise "fetch lengths error" + + row = taos_fetch_row_raw(res) + rowstr = taos_print_row(row, fields, field_count) + assert rowstr == "1 hello test" + + row, num = taos_fetch_row(res, fields) + print(row) + taos_free_result(res) + taos_query(conn, "drop database if exists " + dbname) + taos_close(conn) + except Exception as err: + taos_query(conn, "drop database if exists " + dbname) + raise err + + +def test_stmt(conn, caplog): + dbname = "pytest_ctaos_stmt" + try: + res = taos_query(conn, "drop database if exists %s" % dbname) + taos_free_result(res) + res = taos_query(conn, "create database if not exists %s" % dbname) + taos_free_result(res) + + taos_select_db(conn, dbname) + + res = taos_query( + conn, + "create table if not exists log(ts timestamp, nil tinyint, ti tinyint, si smallint, ii int,\ + bi bigint, tu tinyint unsigned, su smallint unsigned, iu int unsigned, bu bigint unsigned, \ + ff float, dd double, bb binary(100), nn nchar(100))", + ) + taos_free_result(res) + + stmt = taos_stmt_init(conn) + + taos_stmt_prepare(stmt, "insert into log values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)") + + params = new_bind_params(14) + params[0].timestamp(1626861392589, PrecisionEnum.Milliseconds) + params[1].null() + params[2].tinyint(2) + params[3].smallint(3) + params[4].int(4) + params[5].bigint(5) + params[6].tinyint_unsigned(6) + params[7].smallint_unsigned(7) + params[8].int_unsigned(8) + params[9].bigint_unsigned(9) + params[10].float(10.1) + params[11].double(10.11) + params[12].binary("hello") + params[13].nchar("stmt") + taos_stmt_bind_param(stmt, params) + taos_stmt_add_batch(stmt) + taos_stmt_execute(stmt) + + res = taos_query(conn, "select * from log limit 1") + + fields = taos_fetch_fields(res) + filed_count = taos_field_count(res) + + row = taos_fetch_row_raw(res) + rowstr = taos_print_row(row, fields, filed_count, 100) + + taos_free_result(res) + taos_query(conn, "drop database if exists " + dbname) + taos_close(conn) + + assert rowstr == "1626861392589 NULL 2 3 4 5 6 7 8 9 10.100000 10.110000 hello stmt" + except Exception as err: + taos_query(conn, "drop database if exists " + dbname) + raise err + +def stream_callback(param, result, row): + # type: (c_void_p, c_void_p, c_void_p) -> None + try: + if result == None or row == None: + return + result = c_void_p(result) + row = c_void_p(row) + fields = taos_fetch_fields_raw(result) + num_fields = taos_field_count(result) + s = taos_print_row(row, fields, num_fields) + print(s) + taos_stop_query(result) + except Exception as err: + print(err) + +def test_stream(conn, caplog): + dbname = "pytest_ctaos_stream" + try: + res = taos_query(conn, "create database if not exists %s" % dbname) + taos_free_result(res) + + taos_select_db(conn, dbname) + + res = taos_query( + conn, + "create table if not exists log(ts timestamp, n int)", + ) + taos_free_result(res) + + res = taos_query(conn, "select count(*) from log interval(5s)") + cc = taos_num_fields(res) + assert cc == 2 + + stream = taos_open_stream(conn, "select count(*) from log interval(5s)", stream_callback, 0, None, None) + print("waiting for data") + time.sleep(1) + + for i in range(0, 2): + res = taos_query(conn, "insert into log values(now,0)(now+1s, 1)(now + 2s, 2)") + taos_free_result(res) + time.sleep(2) + taos_close_stream(stream) + taos_query(conn, "drop database if exists " + dbname) + taos_close(conn) + except Exception as err: + taos_query(conn, "drop database if exists " + dbname) + raise err diff --git a/src/connector/python/tests/test_info.py b/src/connector/python/tests/test_info.py new file mode 100644 index 0000000000..bddfec7ef9 --- /dev/null +++ b/src/connector/python/tests/test_info.py @@ -0,0 +1,23 @@ +from taos.cinterface import * + +from taos import * + +import pytest + +@pytest.fixture +def conn(): + return connect() + +def test_client_info(): + print(taos_get_client_info()) + None + +def test_server_info(conn): + # type: (TaosConnection) -> None + print(conn.client_info) + print(conn.server_info) + None + +if __name__ == "__main__": + test_client_info() + test_server_info(connect()) diff --git a/src/connector/python/tests/test_lines.py b/src/connector/python/tests/test_lines.py new file mode 100644 index 0000000000..bd9d2cdb39 --- /dev/null +++ b/src/connector/python/tests/test_lines.py @@ -0,0 +1,57 @@ +from taos.error import OperationalError +from taos import connect, new_bind_params, PrecisionEnum +from taos import * + +from ctypes import * +import taos +import pytest + + +@pytest.fixture +def conn(): + # type: () -> taos.TaosConnection + return connect() + + +def test_insert_lines(conn): + # type: (TaosConnection) -> None + + dbname = "pytest_taos_insert_lines" + try: + conn.execute("drop database if exists %s" % dbname) + conn.execute("create database if not exists %s precision 'us'" % dbname) + conn.select_db(dbname) + + lines = [ + 'st,t1=3i64,t2=4f64,t3="t3" c1=3i64,c3=L"passit",c2=false,c4=4f64 1626006833639000000ns', + 'st,t1=4i64,t3="t4",t2=5f64,t4=5f64 c1=3i64,c3=L"passitagin",c2=true,c4=5f64,c5=5f64,c6=7u64 1626006933640000000ns', + 'stf,t1=4i64,t3="t4",t2=5f64,t4=5f64 c1=3i64,c3=L"passitagin_stf",c2=false,c5=5f64,c6=7u64 1626006933641000000ns', + ] + conn.insert_lines(lines) + print("inserted") + + lines = [ + 'stf,t1=5i64,t3="t4",t2=5f64,t4=5f64 c1=3i64,c3=L"passitagin_stf",c2=false,c5=5f64,c6=7u64 1626006933641000000ns', + ] + conn.insert_lines(lines) + print("inserted") + result = conn.query("select * from st") + print(*result.fields) + all = result.rows_iter() + for row in all: + print(row) + result.close() + print(result.row_count) + + conn.execute("drop database if exists %s" % dbname) + conn.close() + + except Exception as err: + conn.execute("drop database if exists %s" % dbname) + conn.close() + print(err) + raise err + + +if __name__ == "__main__": + test_insert_lines(connect()) diff --git a/src/connector/python/tests/test_query.py b/src/connector/python/tests/test_query.py new file mode 100644 index 0000000000..f4e139b1f1 --- /dev/null +++ b/src/connector/python/tests/test_query.py @@ -0,0 +1,43 @@ +from datetime import datetime +import taos +import pytest + +@pytest.fixture +def conn(): + return taos.connect() + +def test_query(conn): + """This test will use fetch_block for rows fetching, significantly faster than rows_iter""" + result = conn.query("select * from log.log limit 10000") + fields = result.fields + for field in fields: + print("field: %s" % field) + start = datetime.now() + for row in result: + # print(row) + None + end = datetime.now() + elapsed = end - start + print("elapsed time: ", elapsed) + result.close() + conn.close() + +def test_query_row_iter(conn): + """This test will use fetch_row for each row fetching, this is the only way in async callback""" + result = conn.query("select * from log.log limit 10000") + fields = result.fields + for field in fields: + print("field: %s" % field) + start = datetime.now() + for row in result.rows_iter(): + # print(row) + None + end = datetime.now() + elapsed = end - start + print("elapsed time: ", elapsed) + result.close() + conn.close() + +if __name__ == "__main__": + test_query(taos.connect(database = "log")) + test_query_row_iter(taos.connect(database = "log")) diff --git a/src/connector/python/tests/test_query_a.py b/src/connector/python/tests/test_query_a.py new file mode 100644 index 0000000000..2b4be5695a --- /dev/null +++ b/src/connector/python/tests/test_query_a.py @@ -0,0 +1,66 @@ +from taos import * +from ctypes import * +import taos +import pytest +import time + + +@pytest.fixture +def conn(): + return taos.connect() + +def fetch_callback(p_param, p_result, num_of_rows): + print("fetched ", num_of_rows, "rows") + p = cast(p_param, POINTER(Counter)) + result = TaosResult(p_result) + + if num_of_rows == 0: + print("fetching completed") + p.contents.done = True + result.close() + return + if num_of_rows < 0: + p.contents.done = True + result.check_error(num_of_rows) + result.close() + return None + + for row in result.rows_iter(num_of_rows): + # print(row) + None + p.contents.count += result.row_count + result.fetch_rows_a(fetch_callback, p_param) + + + +def query_callback(p_param, p_result, code): + # type: (c_void_p, c_void_p, c_int) -> None + if p_result == None: + return + result = TaosResult(p_result) + if code == 0: + result.fetch_rows_a(fetch_callback, p_param) + result.check_error(code) + + +class Counter(Structure): + _fields_ = [("count", c_int), ("done", c_bool)] + + def __str__(self): + return "{ count: %d, done: %s }" % (self.count, self.done) + + +def test_query(conn): + # type: (TaosConnection) -> None + counter = Counter(count=0) + conn.query_a("select * from log.log", query_callback, byref(counter)) + + while not counter.done: + print("wait query callback") + time.sleep(1) + print(counter) + conn.close() + + +if __name__ == "__main__": + test_query(taos.connect()) diff --git a/src/connector/python/tests/test_stmt.py b/src/connector/python/tests/test_stmt.py new file mode 100644 index 0000000000..938ba10eb3 --- /dev/null +++ b/src/connector/python/tests/test_stmt.py @@ -0,0 +1,149 @@ +from taos import * + +from ctypes import * +from datetime import datetime +import taos +import pytest + +@pytest.fixture +def conn(): + # type: () -> taos.TaosConnection + return connect() + +def test_stmt_insert(conn): + # type: (TaosConnection) -> None + + dbname = "pytest_taos_stmt" + try: + conn.execute("drop database if exists %s" % dbname) + conn.execute("create database if not exists %s" % dbname) + conn.select_db(dbname) + + conn.execute( + "create table if not exists log(ts timestamp, bo bool, nil tinyint, ti tinyint, si smallint, ii int,\ + bi bigint, tu tinyint unsigned, su smallint unsigned, iu int unsigned, bu bigint unsigned, \ + ff float, dd double, bb binary(100), nn nchar(100), tt timestamp)", + ) + conn.load_table_info("log") + + + stmt = conn.statement("insert into log values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)") + params = new_bind_params(16) + params[0].timestamp(1626861392589, PrecisionEnum.Milliseconds) + params[1].bool(True) + params[2].null() + params[3].tinyint(2) + params[4].smallint(3) + params[5].int(4) + params[6].bigint(5) + params[7].tinyint_unsigned(6) + params[8].smallint_unsigned(7) + params[9].int_unsigned(8) + params[10].bigint_unsigned(9) + params[11].float(10.1) + params[12].double(10.11) + params[13].binary("hello") + params[14].nchar("stmt") + params[15].timestamp(1626861392589, PrecisionEnum.Milliseconds) + + stmt.bind_param(params) + stmt.execute() + + result = stmt.use_result() + assert result.affected_rows == 1 + result.close() + stmt.close() + + stmt = conn.statement("select * from log") + stmt.execute() + result = stmt.use_result() + row = result.next() + print(row) + assert row[2] == None + for i in range(3, 11): + assert row[i] == i - 1 + #float == may not work as expected + # assert row[10] == c_float(10.1) + assert row[12] == 10.11 + assert row[13] == "hello" + assert row[14] == "stmt" + + conn.execute("drop database if exists %s" % dbname) + conn.close() + + except Exception as err: + conn.execute("drop database if exists %s" % dbname) + conn.close() + raise err + +def test_stmt_insert_multi(conn): + # type: (TaosConnection) -> None + + dbname = "pytest_taos_stmt_multi" + try: + conn.execute("drop database if exists %s" % dbname) + conn.execute("create database if not exists %s" % dbname) + conn.select_db(dbname) + + conn.execute( + "create table if not exists log(ts timestamp, bo bool, nil tinyint, ti tinyint, si smallint, ii int,\ + bi bigint, tu tinyint unsigned, su smallint unsigned, iu int unsigned, bu bigint unsigned, \ + ff float, dd double, bb binary(100), nn nchar(100), tt timestamp)", + ) + conn.load_table_info("log") + + start = datetime.now() + stmt = conn.statement("insert into log values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") + + params = new_multi_binds(16) + params[0].timestamp((1626861392589, 1626861392590, 1626861392591)) + params[1].bool((True, None, False)) + params[2].tinyint([-128, -128, None]) # -128 is tinyint null + params[3].tinyint([0, 127, None]) + params[4].smallint([3, None, 2]) + params[5].int([3, 4, None]) + params[6].bigint([3, 4, None]) + params[7].tinyint_unsigned([3, 4, None]) + params[8].smallint_unsigned([3, 4, None]) + params[9].int_unsigned([3, 4, None]) + params[10].bigint_unsigned([3, 4, None]) + params[11].float([3, None, 1]) + params[12].double([3, None, 1.2]) + params[13].binary(["abc", "dddafadfadfadfadfa", None]) + params[14].nchar(["涛思数据", None, "a long string with 中文字符"]) + params[15].timestamp([None, None, 1626861392591]) + stmt.bind_param_batch(params) + + stmt.execute() + end = datetime.now() + print("elapsed time: ", end - start) + result = stmt.use_result() + assert result.affected_rows == 3 + result.close() + stmt.close() + + stmt = conn.statement("select * from log") + stmt.execute() + result = stmt.use_result() + for row in result: + print(row) + result.close() + + stmt.close() + + # start = datetime.now() + # conn.query("insert into log values(1626861392660, true, NULL, 0, 3,3,3,3,3,3,3,3.0,3.0, 'abc','涛思数据',NULL)(1626861392661, true, NULL, 0, 3,3,3,3,3,3,3,3.0,3.0, 'abc','涛思数据',NULL)(1626861392662, true, NULL, 0, 3,3,3,3,3,3,3,3.0,3.0, 'abc','涛思数据',NULL)") + + # end = datetime.now() + # print("elapsed time: ", end - start) + + conn.execute("drop database if exists %s" % dbname) + conn.close() + + except Exception as err: + conn.execute("drop database if exists %s" % dbname) + conn.close() + raise err +if __name__ == "__main__": + test_stmt_insert(connect()) + test_stmt_insert_multi(connect()) \ No newline at end of file diff --git a/src/connector/python/tests/test_stream.py b/src/connector/python/tests/test_stream.py new file mode 100644 index 0000000000..de6e20928b --- /dev/null +++ b/src/connector/python/tests/test_stream.py @@ -0,0 +1,70 @@ +from taos.cinterface import * +from taos.precision import * +from taos.bind import * +from taos import * +from ctypes import * +import time +import pytest + + +@pytest.fixture +def conn(): + return connect() + + +def stream_callback(p_param, p_result, p_row): + # type: (c_void_p, c_void_p, c_void_p) -> None + + if p_result == None or p_row == None: + return + result = TaosResult(p_result) + row = TaosRow(result, p_row) + try: + ts, count = row() + p = cast(p_param, POINTER(Counter)) + p.contents.count += count + print("[%s] inserted %d in 5s, total count: %d" % (ts.strftime("%Y-%m-%d %H:%M:%S"), count, p.contents.count)) + + except Exception as err: + print(err) + raise err + + +class Counter(ctypes.Structure): + _fields_ = [ + ("count", c_int), + ] + + def __str__(self): + return "%d" % self.count + + +def test_stream(conn): + # type: (TaosConnection) -> None + dbname = "pytest_taos_stream" + try: + conn.execute("drop database if exists %s" % dbname) + conn.execute("create database if not exists %s" % dbname) + conn.select_db(dbname) + conn.execute("create table if not exists log(ts timestamp, n int)") + + result = conn.query("select count(*) from log interval(5s)") + assert result.field_count == 2 + counter = Counter() + counter.count = 0 + stream = conn.stream("select count(*) from log interval(5s)", stream_callback, param=byref(counter)) + + for _ in range(0, 20): + conn.execute("insert into log values(now,0)(now+1s, 1)(now + 2s, 2)") + time.sleep(2) + stream.close() + conn.execute("drop database if exists %s" % dbname) + conn.close() + except Exception as err: + conn.execute("drop database if exists %s" % dbname) + conn.close() + raise err + + +if __name__ == "__main__": + test_stream(connect()) diff --git a/src/connector/python/tests/test_subscribe.py b/src/connector/python/tests/test_subscribe.py new file mode 100644 index 0000000000..99fe5b2636 --- /dev/null +++ b/src/connector/python/tests/test_subscribe.py @@ -0,0 +1,100 @@ +from taos.subscription import TaosSubscription +from taos import * +from ctypes import * +import taos +import pytest +import time +from random import random + + +@pytest.fixture +def conn(): + return taos.connect() + + +def test_subscribe(conn): + # type: (TaosConnection) -> None + + dbname = "pytest_taos_subscribe_callback" + try: + conn.execute("drop database if exists %s" % dbname) + conn.execute("create database if not exists %s" % dbname) + conn.select_db(dbname) + conn.execute("create table if not exists log(ts timestamp, n int)") + for i in range(10): + conn.execute("insert into log values(now, %d)" % i) + + sub = conn.subscribe(True, "test", "select * from log", 1000) + print("# consume from begin") + for ts, n in sub.consume(): + print(ts, n) + + print("# consume new data") + for i in range(5): + conn.execute("insert into log values(now, %d)(now+1s, %d)" % (i, i)) + result = sub.consume() + for ts, n in result: + print(ts, n) + + print("# consume with a stop condition") + for i in range(10): + conn.execute("insert into log values(now, %d)" % int(random() * 10)) + result = sub.consume() + try: + ts, n = next(result) + print(ts, n) + if n > 5: + result.stop_query() + print("## stopped") + break + except StopIteration: + continue + + sub.close() + + conn.execute("drop database if exists %s" % dbname) + conn.close() + except Exception as err: + conn.execute("drop database if exists %s" % dbname) + conn.close() + raise err + + +def subscribe_callback(p_sub, p_result, p_param, errno): + # type: (c_void_p, c_void_p, c_void_p, c_int) -> None + print("callback") + result = TaosResult(p_result) + result.check_error(errno) + for row in result.rows_iter(): + ts, n = row() + print(ts, n) + + +def test_subscribe_callback(conn): + # type: (TaosConnection) -> None + dbname = "pytest_taos_subscribe_callback" + try: + conn.execute("drop database if exists %s" % dbname) + conn.execute("create database if not exists %s" % dbname) + conn.select_db(dbname) + conn.execute("create table if not exists log(ts timestamp, n int)") + + print("# subscribe with callback") + sub = conn.subscribe(False, "test", "select * from log", 1000, subscribe_callback) + + for i in range(10): + conn.execute("insert into log values(now, %d)" % i) + time.sleep(0.7) + sub.close() + + conn.execute("drop database if exists %s" % dbname) + conn.close() + except Exception as err: + conn.execute("drop database if exists %s" % dbname) + conn.close() + raise err + + +if __name__ == "__main__": + test_subscribe(taos.connect()) + test_subscribe_callback(taos.connect()) diff --git a/src/inc/taosdef.h b/src/inc/taosdef.h index 5b96f0ebd9..fceeaea0ae 100644 --- a/src/inc/taosdef.h +++ b/src/inc/taosdef.h @@ -34,6 +34,7 @@ extern "C" { #define TSWINDOW_INITIALIZER ((STimeWindow) {INT64_MIN, INT64_MAX}) #define TSWINDOW_DESC_INITIALIZER ((STimeWindow) {INT64_MAX, INT64_MIN}) +#define IS_TSWINDOW_SPECIFIED(win) (((win).skey != INT64_MIN) || ((win).ekey != INT64_MAX)) #define TSKEY_INITIAL_VAL INT64_MIN diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index 2214078f55..368658377c 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -272,7 +272,8 @@ int32_t* taosGetErrno(); #define TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW TAOS_DEF_ERROR_CODE(0, 0x070A) //"Too many time window in query") #define TSDB_CODE_QRY_NOT_ENOUGH_BUFFER TAOS_DEF_ERROR_CODE(0, 0x070B) //"Query buffer limit has reached") #define TSDB_CODE_QRY_INCONSISTAN TAOS_DEF_ERROR_CODE(0, 0x070C) //"File inconsistency in replica") -#define TSDB_CODE_QRY_SYS_ERROR TAOS_DEF_ERROR_CODE(0, 0x070D) //"System error") +#define TSDB_CODE_QRY_INVALID_TIME_CONDITION TAOS_DEF_ERROR_CODE(0, 0x070D) //"invalid time condition") +#define TSDB_CODE_QRY_SYS_ERROR TAOS_DEF_ERROR_CODE(0, 0x070E) //"System error") // grant diff --git a/src/inc/taosmsg.h b/src/inc/taosmsg.h index 2af4e4857a..d3e028bdab 100644 --- a/src/inc/taosmsg.h +++ b/src/inc/taosmsg.h @@ -489,7 +489,8 @@ typedef struct { int16_t numOfCols; // the number of columns will be load from vnode SInterval interval; SSessionWindow sw; // session window - uint32_t tagCondLen; // tag length in current query + uint16_t tagCondLen; // tag length in current query + uint16_t colCondLen; // column length in current query uint32_t tbnameCondLen; // table name filter condition string length int16_t numOfGroupCols; // num of group by columns int16_t orderByIdx; diff --git a/src/inc/ttokendef.h b/src/inc/ttokendef.h index e89fed6282..a97de15e93 100644 --- a/src/inc/ttokendef.h +++ b/src/inc/ttokendef.h @@ -75,131 +75,131 @@ #define TK_SCORES 57 #define TK_GRANTS 58 #define TK_VNODES 59 -#define TK_IPTOKEN 60 -#define TK_DOT 61 -#define TK_CREATE 62 -#define TK_TABLE 63 -#define TK_STABLE 64 -#define TK_DATABASE 65 -#define TK_TABLES 66 -#define TK_STABLES 67 -#define TK_VGROUPS 68 -#define TK_DROP 69 -#define TK_TOPIC 70 -#define TK_FUNCTION 71 -#define TK_DNODE 72 -#define TK_USER 73 -#define TK_ACCOUNT 74 -#define TK_USE 75 -#define TK_DESCRIBE 76 -#define TK_ALTER 77 -#define TK_PASS 78 -#define TK_PRIVILEGE 79 -#define TK_LOCAL 80 -#define TK_COMPACT 81 -#define TK_LP 82 -#define TK_RP 83 -#define TK_IF 84 -#define TK_EXISTS 85 -#define TK_AS 86 -#define TK_OUTPUTTYPE 87 -#define TK_AGGREGATE 88 -#define TK_BUFSIZE 89 -#define TK_PPS 90 -#define TK_TSERIES 91 -#define TK_DBS 92 -#define TK_STORAGE 93 -#define TK_QTIME 94 -#define TK_CONNS 95 -#define TK_STATE 96 -#define TK_COMMA 97 -#define TK_KEEP 98 -#define TK_CACHE 99 -#define TK_REPLICA 100 -#define TK_QUORUM 101 -#define TK_DAYS 102 -#define TK_MINROWS 103 -#define TK_MAXROWS 104 -#define TK_BLOCKS 105 -#define TK_CTIME 106 -#define TK_WAL 107 -#define TK_FSYNC 108 -#define TK_COMP 109 -#define TK_PRECISION 110 -#define TK_UPDATE 111 -#define TK_CACHELAST 112 -#define TK_PARTITIONS 113 -#define TK_UNSIGNED 114 -#define TK_TAGS 115 -#define TK_USING 116 -#define TK_NULL 117 -#define TK_NOW 118 -#define TK_SELECT 119 -#define TK_UNION 120 -#define TK_ALL 121 -#define TK_DISTINCT 122 -#define TK_FROM 123 -#define TK_VARIABLE 124 -#define TK_INTERVAL 125 -#define TK_SESSION 126 -#define TK_STATE_WINDOW 127 -#define TK_FILL 128 -#define TK_SLIDING 129 -#define TK_ORDER 130 -#define TK_BY 131 -#define TK_ASC 132 -#define TK_DESC 133 -#define TK_GROUP 134 -#define TK_HAVING 135 -#define TK_LIMIT 136 -#define TK_OFFSET 137 -#define TK_SLIMIT 138 -#define TK_SOFFSET 139 -#define TK_WHERE 140 -#define TK_RESET 141 -#define TK_QUERY 142 -#define TK_SYNCDB 143 -#define TK_ADD 144 -#define TK_COLUMN 145 -#define TK_MODIFY 146 -#define TK_TAG 147 -#define TK_CHANGE 148 -#define TK_SET 149 -#define TK_KILL 150 -#define TK_CONNECTION 151 -#define TK_STREAM 152 -#define TK_COLON 153 -#define TK_ABORT 154 -#define TK_AFTER 155 -#define TK_ATTACH 156 -#define TK_BEFORE 157 -#define TK_BEGIN 158 -#define TK_CASCADE 159 -#define TK_CLUSTER 160 -#define TK_CONFLICT 161 -#define TK_COPY 162 -#define TK_DEFERRED 163 -#define TK_DELIMITERS 164 -#define TK_DETACH 165 -#define TK_EACH 166 -#define TK_END 167 -#define TK_EXPLAIN 168 -#define TK_FAIL 169 -#define TK_FOR 170 -#define TK_IGNORE 171 -#define TK_IMMEDIATE 172 -#define TK_INITIALLY 173 -#define TK_INSTEAD 174 -#define TK_MATCH 175 -#define TK_KEY 176 -#define TK_OF 177 -#define TK_RAISE 178 -#define TK_REPLACE 179 -#define TK_RESTRICT 180 -#define TK_ROW 181 -#define TK_STATEMENT 182 -#define TK_TRIGGER 183 -#define TK_VIEW 184 +#define TK_DOT 60 +#define TK_CREATE 61 +#define TK_TABLE 62 +#define TK_STABLE 63 +#define TK_DATABASE 64 +#define TK_TABLES 65 +#define TK_STABLES 66 +#define TK_VGROUPS 67 +#define TK_DROP 68 +#define TK_TOPIC 69 +#define TK_FUNCTION 70 +#define TK_DNODE 71 +#define TK_USER 72 +#define TK_ACCOUNT 73 +#define TK_USE 74 +#define TK_DESCRIBE 75 +#define TK_ALTER 76 +#define TK_PASS 77 +#define TK_PRIVILEGE 78 +#define TK_LOCAL 79 +#define TK_COMPACT 80 +#define TK_LP 81 +#define TK_RP 82 +#define TK_IF 83 +#define TK_EXISTS 84 +#define TK_AS 85 +#define TK_OUTPUTTYPE 86 +#define TK_AGGREGATE 87 +#define TK_BUFSIZE 88 +#define TK_PPS 89 +#define TK_TSERIES 90 +#define TK_DBS 91 +#define TK_STORAGE 92 +#define TK_QTIME 93 +#define TK_CONNS 94 +#define TK_STATE 95 +#define TK_COMMA 96 +#define TK_KEEP 97 +#define TK_CACHE 98 +#define TK_REPLICA 99 +#define TK_QUORUM 100 +#define TK_DAYS 101 +#define TK_MINROWS 102 +#define TK_MAXROWS 103 +#define TK_BLOCKS 104 +#define TK_CTIME 105 +#define TK_WAL 106 +#define TK_FSYNC 107 +#define TK_COMP 108 +#define TK_PRECISION 109 +#define TK_UPDATE 110 +#define TK_CACHELAST 111 +#define TK_PARTITIONS 112 +#define TK_UNSIGNED 113 +#define TK_TAGS 114 +#define TK_USING 115 +#define TK_NULL 116 +#define TK_NOW 117 +#define TK_SELECT 118 +#define TK_UNION 119 +#define TK_ALL 120 +#define TK_DISTINCT 121 +#define TK_FROM 122 +#define TK_VARIABLE 123 +#define TK_INTERVAL 124 +#define TK_SESSION 125 +#define TK_STATE_WINDOW 126 +#define TK_FILL 127 +#define TK_SLIDING 128 +#define TK_ORDER 129 +#define TK_BY 130 +#define TK_ASC 131 +#define TK_DESC 132 +#define TK_GROUP 133 +#define TK_HAVING 134 +#define TK_LIMIT 135 +#define TK_OFFSET 136 +#define TK_SLIMIT 137 +#define TK_SOFFSET 138 +#define TK_WHERE 139 +#define TK_RESET 140 +#define TK_QUERY 141 +#define TK_SYNCDB 142 +#define TK_ADD 143 +#define TK_COLUMN 144 +#define TK_MODIFY 145 +#define TK_TAG 146 +#define TK_CHANGE 147 +#define TK_SET 148 +#define TK_KILL 149 +#define TK_CONNECTION 150 +#define TK_STREAM 151 +#define TK_COLON 152 +#define TK_ABORT 153 +#define TK_AFTER 154 +#define TK_ATTACH 155 +#define TK_BEFORE 156 +#define TK_BEGIN 157 +#define TK_CASCADE 158 +#define TK_CLUSTER 159 +#define TK_CONFLICT 160 +#define TK_COPY 161 +#define TK_DEFERRED 162 +#define TK_DELIMITERS 163 +#define TK_DETACH 164 +#define TK_EACH 165 +#define TK_END 166 +#define TK_EXPLAIN 167 +#define TK_FAIL 168 +#define TK_FOR 169 +#define TK_IGNORE 170 +#define TK_IMMEDIATE 171 +#define TK_INITIALLY 172 +#define TK_INSTEAD 173 +#define TK_MATCH 174 +#define TK_KEY 175 +#define TK_OF 176 +#define TK_RAISE 177 +#define TK_REPLACE 178 +#define TK_RESTRICT 179 +#define TK_ROW 180 +#define TK_STATEMENT 181 +#define TK_TRIGGER 182 +#define TK_VIEW 183 +#define TK_IPTOKEN 184 #define TK_SEMI 185 #define TK_NONE 186 #define TK_PREV 187 diff --git a/src/inc/ttype.h b/src/inc/ttype.h index 44e666106a..3f1606e957 100644 --- a/src/inc/ttype.h +++ b/src/inc/ttype.h @@ -47,7 +47,8 @@ typedef struct { // this data type is internally used only in 'in' query to hold the values -#define TSDB_DATA_TYPE_ARRAY (1000) +#define TSDB_DATA_TYPE_POINTER_ARRAY (1000) +#define TSDB_DATA_TYPE_VALUE_ARRAY (1001) #define GET_TYPED_DATA(_v, _finalType, _type, _data) \ do { \ @@ -181,6 +182,8 @@ typedef struct tDataTypeDescriptor { int16_t nameLen; int32_t bytes; char * name; + int64_t minValue; + int64_t maxValue; int (*compFunc)(const char *const input, int inputSize, const int nelements, char *const output, int outputSize, char algorithm, char *const buffer, int bufferSize); int (*decompFunc)(const char *const input, int compressedSize, const int nelements, char *const output, @@ -200,6 +203,9 @@ const void *getNullValue(int32_t type); void assignVal(char *val, const char *src, int32_t len, int32_t type); void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size, void* buf); +void operateVal(void *dst, void *s1, void *s2, int32_t optr, int32_t type); +void* getDataMin(int32_t type); +void* getDataMax(int32_t type); int32_t tStrToInteger(const char* z, int16_t type, int32_t n, int64_t* value, bool issigned); diff --git a/src/kit/shell/src/shellEngine.c b/src/kit/shell/src/shellEngine.c index 58f4b7ff02..cdce61e578 100644 --- a/src/kit/shell/src/shellEngine.c +++ b/src/kit/shell/src/shellEngine.c @@ -98,7 +98,6 @@ TAOS *shellInit(SShellArguments *_args) { } if (con == NULL) { - printf("taos connect failed, reason: %s.\n\n", tstrerror(terrno)); fflush(stdout); return con; } diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index d98d5bdf0b..3838344a8b 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -76,7 +76,7 @@ extern char configDir[]; #define COND_BUF_LEN (BUFFER_SIZE - 30) #define COL_BUFFER_LEN ((TSDB_COL_NAME_LEN + 15) * TSDB_MAX_COLUMNS) #define MAX_USERNAME_SIZE 64 -#define MAX_PASSWORD_SIZE 64 +#define MAX_PASSWORD_SIZE 16 #define MAX_HOSTNAME_SIZE 253 // https://man7.org/linux/man-pages/man7/hostname.7.html #define MAX_TB_NAME_SIZE 64 #define MAX_DATA_SIZE (16*TSDB_MAX_COLUMNS)+20 // max record len: 16*MAX_COLUMNS, timestamp string and ,('') need extra space @@ -215,7 +215,7 @@ typedef struct SArguments_S { uint16_t port; uint16_t iface; char * user; - char * password; + char password[MAX_PASSWORD_SIZE]; char * database; int replica; char * tb_prefix; @@ -710,24 +710,24 @@ static void printHelp() { printf("%s%s%s%s\n", indent, "-u", indent, "The TDengine user name to use when connecting to the server. Default is 'root'."); #ifdef _TD_POWER_ - printf("%s%s%s%s\n", indent, "-P", indent, + printf("%s%s%s%s\n", indent, "-p", indent, "The password to use when connecting to the server. Default is 'powerdb'."); printf("%s%s%s%s\n", indent, "-c", indent, "Configuration directory. Default is '/etc/power/'."); #elif (_TD_TQ_ == true) - printf("%s%s%s%s\n", indent, "-P", indent, + printf("%s%s%s%s\n", indent, "-p", indent, "The password to use when connecting to the server. Default is 'tqueue'."); printf("%s%s%s%s\n", indent, "-c", indent, "Configuration directory. Default is '/etc/tq/'."); #else - printf("%s%s%s%s\n", indent, "-P", indent, + printf("%s%s%s%s\n", indent, "-p", indent, "The password to use when connecting to the server. Default is 'taosdata'."); printf("%s%s%s%s\n", indent, "-c", indent, "Configuration directory. Default is '/etc/taos/'."); #endif printf("%s%s%s%s\n", indent, "-h", indent, "The host to connect to TDengine. Default is localhost."); - printf("%s%s%s%s\n", indent, "-p", indent, + printf("%s%s%s%s\n", indent, "-P", indent, "The TCP/IP port number to use for the connection. Default is 0."); printf("%s%s%s%s\n", indent, "-I", indent, #if STMT_IFACE_ENABLED == 1 @@ -827,11 +827,11 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { exit(EXIT_FAILURE); } arguments->host = argv[++i]; - } else if (strcmp(argv[i], "-p") == 0) { + } else if (strcmp(argv[i], "-P") == 0) { if ((argc == i+1) || (!isStringNumber(argv[i+1]))) { printHelp(); - errorPrint("%s", "\n\t-p need a number following!\n"); + errorPrint("%s", "\n\t-P need a number following!\n"); exit(EXIT_FAILURE); } arguments->port = atoi(argv[++i]); @@ -861,13 +861,13 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { exit(EXIT_FAILURE); } arguments->user = argv[++i]; - } else if (strcmp(argv[i], "-P") == 0) { - if (argc == i+1) { - printHelp(); - errorPrint("%s", "\n\t-P need a valid string following!\n"); - exit(EXIT_FAILURE); + } else if (strncmp(argv[i], "-p", 2) == 0) { + if (strlen(argv[i]) == 2) { + printf("Enter password:"); + scanf("%s", arguments->password); + } else { + tstrncpy(arguments->password, (char *)(argv[i] + 2), MAX_PASSWORD_SIZE); } - arguments->password = argv[++i]; } else if (strcmp(argv[i], "-o") == 0) { if (argc == i+1) { printHelp(); @@ -1065,7 +1065,7 @@ static 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) { + } else if (strcmp(argv[i], "-PP") == 0) { arguments->performance_print = true; } else if (strcmp(argv[i], "-O") == 0) { if ((argc == i+1) || @@ -2318,15 +2318,15 @@ static void printfDbInfoForQueryToFile( } static void printfQuerySystemInfo(TAOS * taos) { - char filename[BUFFER_SIZE+1] = {0}; - char buffer[BUFFER_SIZE+1] = {0}; + char filename[MAX_FILE_NAME_LEN] = {0}; + char buffer[1024] = {0}; TAOS_RES* res; time_t t; struct tm* lt; time(&t); lt = localtime(&t); - snprintf(filename, BUFFER_SIZE, "querySystemInfo-%d-%d-%d %d:%d:%d", + snprintf(filename, MAX_FILE_NAME_LEN, "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); @@ -2358,12 +2358,12 @@ static void printfQuerySystemInfo(TAOS * taos) { printfDbInfoForQueryToFile(filename, dbInfos[i], i); // show db.vgroups - snprintf(buffer, BUFFER_SIZE, "show %s.vgroups;", dbInfos[i]->name); + snprintf(buffer, 1024, "show %s.vgroups;", dbInfos[i]->name); res = taos_query(taos, buffer); xDumpResultToFile(filename, res); // show db.stables - snprintf(buffer, BUFFER_SIZE, "show %s.stables;", dbInfos[i]->name); + snprintf(buffer, 1024, "show %s.stables;", dbInfos[i]->name); res = taos_query(taos, buffer); xDumpResultToFile(filename, res); free(dbInfos[i]); @@ -2712,7 +2712,7 @@ static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos, char* dbName, char* sTblName, char** childTblNameOfSuperTbl, int64_t* childTblCountOfSuperTbl, int64_t limit, uint64_t offset) { - char command[BUFFER_SIZE] = "\0"; + char command[1024] = "\0"; char limitBuf[100] = "\0"; TAOS_RES * res; @@ -2726,7 +2726,7 @@ static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos, } //get all child table name use cmd: select tbname from superTblName; - snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s", + snprintf(command, 1024, "select tbname from %s.%s %s", dbName, sTblName, limitBuf); res = taos_query(taos, command); @@ -2804,13 +2804,13 @@ static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName, static int getSuperTableFromServer(TAOS * taos, char* dbName, SSuperTable* superTbls) { - char command[BUFFER_SIZE] = "\0"; + char command[1024] = "\0"; TAOS_RES * res; TAOS_ROW row = NULL; int count = 0; //get schema use cmd: describe superTblName; - snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName); + snprintf(command, 1024, "describe %s.%s", dbName, superTbls->sTblName); res = taos_query(taos, command); int32_t code = taos_errno(res); if (code != 0) { @@ -2890,7 +2890,8 @@ static int createSuperTable( TAOS * taos, char* dbName, SSuperTable* superTbl) { - char command[BUFFER_SIZE] = "\0"; + char *command = calloc(1, BUFFER_SIZE); + assert(command); char cols[COL_BUFFER_LEN] = "\0"; int colIndex; @@ -2901,6 +2902,7 @@ static int createSuperTable( if (superTbl->columnCount == 0) { errorPrint("%s() LN%d, super table column count is %d\n", __func__, __LINE__, superTbl->columnCount); + free(command); return -1; } @@ -2963,6 +2965,7 @@ static int createSuperTable( taos_close(taos); errorPrint("%s() LN%d, config error data type : %s\n", __func__, __LINE__, dataType); + free(command); exit(-1); } } @@ -2975,6 +2978,7 @@ static int createSuperTable( errorPrint("%s() LN%d, Failed when calloc, size:%d", __func__, __LINE__, len+1); taos_close(taos); + free(command); exit(-1); } @@ -2985,6 +2989,7 @@ static int createSuperTable( if (superTbl->tagCount == 0) { errorPrint("%s() LN%d, super table tag count is %d\n", __func__, __LINE__, superTbl->tagCount); + free(command); return -1; } @@ -3050,6 +3055,7 @@ static int createSuperTable( taos_close(taos); errorPrint("%s() LN%d, config error tag type : %s\n", __func__, __LINE__, dataType); + free(command); exit(-1); } } @@ -3065,13 +3071,16 @@ static int createSuperTable( if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) { errorPrint( "create supertable %s failed!\n\n", superTbl->sTblName); + free(command); return -1; } + debugPrint("create supertable %s success!\n\n", superTbl->sTblName); + free(command); return 0; } -static int createDatabasesAndStables() { +int createDatabasesAndStables(char *command) { TAOS * taos = NULL; int ret = 0; taos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, NULL, g_Dbs.port); @@ -3079,8 +3088,7 @@ static int createDatabasesAndStables() { errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); return -1; } - char command[BUFFER_SIZE] = "\0"; - + for (int i = 0; i < g_Dbs.dbCount; i++) { if (g_Dbs.db[i].drop) { sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName); @@ -5981,7 +5989,7 @@ static int32_t prepareStbStmtBind( int64_t startTime, int32_t recSeq, bool isColumn) { - char *bindBuffer = calloc(1, g_args.len_of_binary); + char *bindBuffer = calloc(1, DOUBLE_BUFF_LEN); // g_args.len_of_binary); if (bindBuffer == NULL) { errorPrint("%s() LN%d, Failed to allocate %d bind buffer\n", __func__, __LINE__, g_args.len_of_binary); @@ -6316,8 +6324,8 @@ static void printStatPerThread(threadInfo *pThreadInfo) pThreadInfo->threadID, pThreadInfo->totalInsertRows, pThreadInfo->totalAffectedRows, - (pThreadInfo->totalDelay/1000.0)? - (double)(pThreadInfo->totalAffectedRows/(pThreadInfo->totalDelay/1000.0)): + (pThreadInfo->totalDelay)? + (double)(pThreadInfo->totalAffectedRows/((double)pThreadInfo->totalDelay/1000000.0)): FLT_MAX); } @@ -6537,7 +6545,7 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { verbosePrint("[%d] %s() LN%d, buffer=%s\n", pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->buffer); - startTs = taosGetTimestampMs(); + startTs = taosGetTimestampUs(); if (recOfBatch == 0) { errorPrint("[%d] %s() LN%d Failed to insert records of batch %d\n", @@ -6553,10 +6561,10 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { } int64_t affectedRows = execInsert(pThreadInfo, recOfBatch); - endTs = taosGetTimestampMs(); + endTs = taosGetTimestampUs(); uint64_t delay = endTs - startTs; - performancePrint("%s() LN%d, insert execution time is %"PRIu64"ms\n", - __func__, __LINE__, delay); + performancePrint("%s() LN%d, insert execution time is %10.2f ms\n", + __func__, __LINE__, delay / 1000.0); verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n", pThreadInfo->threadID, __func__, __LINE__, affectedRows); @@ -6713,14 +6721,14 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { start_time += generated * timeStampStep; pThreadInfo->totalInsertRows += generated; - startTs = taosGetTimestampMs(); + startTs = taosGetTimestampUs(); int32_t affectedRows = execInsert(pThreadInfo, generated); - endTs = taosGetTimestampMs(); + endTs = taosGetTimestampUs(); uint64_t delay = endTs - startTs; - performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n", - __func__, __LINE__, delay); + performancePrint("%s() LN%d, insert execution time is %10.f ms\n", + __func__, __LINE__, delay/1000.0); verbosePrint("[%d] %s() LN%d affectedRows=%d\n", pThreadInfo->threadID, __func__, __LINE__, affectedRows); @@ -7111,7 +7119,8 @@ static void startMultiThreadInsertData(int threads, char* db_name, exit(-1); } - char buffer[BUFFER_SIZE]; + char *buffer = calloc(1, BUFFER_SIZE); + assert(buffer); char *pstr = buffer; if ((superTblInfo) @@ -7140,8 +7149,11 @@ static void startMultiThreadInsertData(int threads, char* db_name, ret, taos_stmt_errstr(pThreadInfo->stmt)); free(pids); free(infos); + free(buffer); exit(-1); } + + free(buffer); } #endif } else { @@ -7254,11 +7266,15 @@ static void startMultiThreadInsertData(int threads, char* db_name, } } - fprintf(stderr, "insert delay, avg: %10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n", - avgDelay, maxDelay, minDelay); + fprintf(stderr, "insert delay, avg: %10.2fms, max: %10.2fms, min: %10.2fms\n\n", + (double)avgDelay/1000.0, + (double)maxDelay/1000.0, + (double)minDelay/1000.0); if (g_fpOfInsertResult) { - fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n", - avgDelay, maxDelay, minDelay); + fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %10.2fms, min: %10.2fms\n\n", + (double)avgDelay/1000.0, + (double)maxDelay/1000.0, + (double)minDelay/1000.0); } //taos_close(taos); @@ -7272,12 +7288,15 @@ static void *readTable(void *sarg) { threadInfo *pThreadInfo = (threadInfo *)sarg; TAOS *taos = pThreadInfo->taos; setThreadName("readTable"); - char command[BUFFER_SIZE] = "\0"; + char *command = calloc(1, BUFFER_SIZE); + assert(command); + uint64_t sTime = pThreadInfo->start_time; char *tb_prefix = pThreadInfo->tb_prefix; FILE *fp = fopen(pThreadInfo->filePath, "a"); if (NULL == fp) { errorPrint( "fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno)); + free(command); return NULL; } @@ -7316,6 +7335,7 @@ static void *readTable(void *sarg) { taos_free_result(pSql); taos_close(taos); fclose(fp); + free(command); return NULL; } @@ -7336,6 +7356,7 @@ static void *readTable(void *sarg) { } fprintf(fp, "\n"); fclose(fp); + free(command); #endif return NULL; } @@ -7345,10 +7366,13 @@ static void *readMetric(void *sarg) { threadInfo *pThreadInfo = (threadInfo *)sarg; TAOS *taos = pThreadInfo->taos; setThreadName("readMetric"); - char command[BUFFER_SIZE] = "\0"; + char *command = calloc(1, BUFFER_SIZE); + assert(command); + FILE *fp = fopen(pThreadInfo->filePath, "a"); if (NULL == fp) { printf("fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno)); + free(command); return NULL; } @@ -7393,6 +7417,7 @@ static void *readMetric(void *sarg) { taos_free_result(pSql); taos_close(taos); fclose(fp); + free(command); return NULL; } int count = 0; @@ -7410,6 +7435,7 @@ static void *readMetric(void *sarg) { fprintf(fp, "\n"); } fclose(fp); + free(command); #endif return NULL; } @@ -7446,11 +7472,16 @@ static int insertTestProcess() { init_rand_data(); // create database and super tables - if(createDatabasesAndStables() != 0) { + char *cmdBuffer = calloc(1, BUFFER_SIZE); + assert(cmdBuffer); + + if(createDatabasesAndStables(cmdBuffer) != 0) { if (g_fpOfInsertResult) fclose(g_fpOfInsertResult); + free(cmdBuffer); return -1; } + free(cmdBuffer); // pretreatement if (prepareSampleData() != 0) { @@ -7619,7 +7650,9 @@ static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) { } static void *superTableQuery(void *sarg) { - char sqlstr[BUFFER_SIZE]; + char *sqlstr = calloc(1, BUFFER_SIZE); + assert(sqlstr); + threadInfo *pThreadInfo = (threadInfo *)sarg; setThreadName("superTableQuery"); @@ -7634,6 +7667,7 @@ static void *superTableQuery(void *sarg) { if (taos == NULL) { errorPrint("[%d] Failed to connect to TDengine, reason:%s\n", pThreadInfo->threadID, taos_errstr(NULL)); + free(sqlstr); return NULL; } else { pThreadInfo->taos = taos; @@ -7658,7 +7692,7 @@ static void *superTableQuery(void *sarg) { st = taosGetTimestampMs(); for (int i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) { for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) { - memset(sqlstr,0,sizeof(sqlstr)); + memset(sqlstr, 0, BUFFER_SIZE); replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i); if (g_queryInfo.superQueryInfo.result[j][0] != '\0') { sprintf(pThreadInfo->filePath, "%s-%d", @@ -7689,6 +7723,7 @@ static void *superTableQuery(void *sarg) { (double)(et - st)/1000.0); } + free(sqlstr); return NULL; } @@ -7922,7 +7957,9 @@ static TAOS_SUB* subscribeImpl( static void *superSubscribe(void *sarg) { threadInfo *pThreadInfo = (threadInfo *)sarg; - char subSqlstr[BUFFER_SIZE]; + char *subSqlStr = calloc(1, BUFFER_SIZE); + assert(subSqlStr); + TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT] = {0}; uint64_t tsubSeq; @@ -7931,6 +7968,7 @@ static void *superSubscribe(void *sarg) { if (pThreadInfo->ntables > MAX_QUERY_SQL_COUNT) { errorPrint("The table number(%"PRId64") of the thread is more than max query sql count: %d\n", pThreadInfo->ntables, MAX_QUERY_SQL_COUNT); + free(subSqlStr); exit(-1); } @@ -7943,6 +7981,7 @@ static void *superSubscribe(void *sarg) { if (pThreadInfo->taos == NULL) { errorPrint("[%d] Failed to connect to TDengine, reason:%s\n", pThreadInfo->threadID, taos_errstr(NULL)); + free(subSqlStr); return NULL; } } @@ -7953,6 +7992,7 @@ static void *superSubscribe(void *sarg) { taos_close(pThreadInfo->taos); errorPrint( "use database %s failed!\n\n", g_queryInfo.dbName); + free(subSqlStr); return NULL; } @@ -7967,25 +8007,26 @@ static void *superSubscribe(void *sarg) { pThreadInfo->end_table_to, i); sprintf(topic, "taosdemo-subscribe-%"PRIu64"-%"PRIu64"", i, pThreadInfo->querySeq); - memset(subSqlstr, 0, sizeof(subSqlstr)); + memset(subSqlStr, 0, BUFFER_SIZE); replaceChildTblName( g_queryInfo.superQueryInfo.sql[pThreadInfo->querySeq], - subSqlstr, i); + subSqlStr, i); if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) { sprintf(pThreadInfo->filePath, "%s-%d", g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq], pThreadInfo->threadID); } - verbosePrint("%s() LN%d, [%d] subSqlstr: %s\n", - __func__, __LINE__, pThreadInfo->threadID, subSqlstr); + verbosePrint("%s() LN%d, [%d] subSqlStr: %s\n", + __func__, __LINE__, pThreadInfo->threadID, subSqlStr); tsub[tsubSeq] = subscribeImpl( STABLE_CLASS, - pThreadInfo, subSqlstr, topic, + pThreadInfo, subSqlStr, topic, g_queryInfo.superQueryInfo.subscribeRestart, g_queryInfo.superQueryInfo.subscribeInterval); if (NULL == tsub[tsubSeq]) { taos_close(pThreadInfo->taos); + free(subSqlStr); return NULL; } } @@ -8042,12 +8083,13 @@ static void *superSubscribe(void *sarg) { consumed[tsubSeq]= 0; tsub[tsubSeq] = subscribeImpl( STABLE_CLASS, - pThreadInfo, subSqlstr, topic, + pThreadInfo, subSqlStr, topic, g_queryInfo.superQueryInfo.subscribeRestart, g_queryInfo.superQueryInfo.subscribeInterval ); if (NULL == tsub[tsubSeq]) { taos_close(pThreadInfo->taos); + free(subSqlStr); return NULL; } } @@ -8067,6 +8109,7 @@ static void *superSubscribe(void *sarg) { } taos_close(pThreadInfo->taos); + free(subSqlStr); return NULL; } @@ -8369,9 +8412,7 @@ static void setParaFromArg() { tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE); } - if (g_args.password) { - tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE); - } + tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE); if (g_args.port) { g_Dbs.port = g_args.port; diff --git a/src/kit/taosdump/taosdump.c b/src/kit/taosdump/taosdump.c index e3f3880f0c..bea6e65106 100644 --- a/src/kit/taosdump/taosdump.c +++ b/src/kit/taosdump/taosdump.c @@ -231,8 +231,8 @@ static struct argp_option options[] = { {"schemaonly", 's', 0, 0, "Only dump schema.", 2}, {"without-property", 'N', 0, 0, "Dump schema without properties.", 2}, {"avro", 'V', 0, 0, "Dump apache avro format data file. By default, dump sql command sequence.", 2}, - {"start-time", 'S', "START_TIME", 0, "Start time to dump. Either epoch or ISO8601/RFC3339 format is acceptable. ISO8601 format example: 2017-10-01T18:00:00.000+0800 or 2017-10-0100:00:00.000+0800 or '2017-10-01 00:00:00.000+0800'", 4}, - {"end-time", 'E', "END_TIME", 0, "End time to dump. Either epoch or ISO8601/RFC3339 format is acceptable. ISO8601 format example: 2017-10-01T18:00:00.000+0800 or 2017-10-0100:00:00.000+0800 or '2017-10-01 00:00:00.000+0800'", 5}, + {"start-time", 'S', "START_TIME", 0, "Start time to dump. Either epoch or ISO8601/RFC3339 format is acceptable. ISO8601 format example: 2017-10-01T00:00:00.000+0800 or 2017-10-0100:00:00:000+0800 or '2017-10-01 00:00:00.000+0800'", 4}, + {"end-time", 'E', "END_TIME", 0, "End time to dump. Either epoch or ISO8601/RFC3339 format is acceptable. ISO8601 format example: 2017-10-01T00:00:00.000+0800 or 2017-10-0100:00:00.000+0800 or '2017-10-01 00:00:00.000+0800'", 5}, #if TSDB_SUPPORT_NANOSECOND == 1 {"precision", 'C', "PRECISION", 0, "Specify precision for converting human-readable time to epoch. Valid value is one of ms, us, and ns. Default is ms.", 6}, #else diff --git a/src/mnode/inc/mnodeDef.h b/src/mnode/inc/mnodeDef.h index e974251d2e..5521267841 100644 --- a/src/mnode/inc/mnodeDef.h +++ b/src/mnode/inc/mnodeDef.h @@ -80,6 +80,7 @@ typedef struct SMnodeObj { int8_t updateEnd[4]; int32_t refCount; int8_t role; + int64_t roleTime; int8_t reserved2[3]; } SMnodeObj; diff --git a/src/mnode/src/mnodeDnode.c b/src/mnode/src/mnodeDnode.c index 02cf1c782c..73be7ea045 100644 --- a/src/mnode/src/mnodeDnode.c +++ b/src/mnode/src/mnodeDnode.c @@ -1181,7 +1181,7 @@ static int32_t mnodeGetVnodeMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pC pShow->bytes[cols] = 4; pSchema[cols].type = TSDB_DATA_TYPE_INT; - strcpy(pSchema[cols].name, "vnode"); + strcpy(pSchema[cols].name, "vgId"); pSchema[cols].bytes = htons(pShow->bytes[cols]); cols++; @@ -1243,8 +1243,10 @@ static int32_t mnodeRetrieveVnodes(SShowObj *pShow, char *data, int32_t rows, vo cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - strcpy(pWrite, syncRole[pVgid->role]); + STR_TO_VARSTR(pWrite, syncRole[pVgid->role]); cols++; + + numOfRows++; } } diff --git a/src/mnode/src/mnodeMnode.c b/src/mnode/src/mnodeMnode.c index bccad22157..13dd06bcac 100644 --- a/src/mnode/src/mnodeMnode.c +++ b/src/mnode/src/mnodeMnode.c @@ -122,6 +122,7 @@ static int32_t mnodeMnodeActionRestored() { void *pIter = mnodeGetNextMnode(NULL, &pMnode); if (pMnode != NULL) { pMnode->role = TAOS_SYNC_ROLE_MASTER; + pMnode->roleTime = taosGetTimestampMs(); mnodeDecMnodeRef(pMnode); } mnodeCancelGetNextMnode(pIter); @@ -496,7 +497,13 @@ static int32_t mnodeGetMnodeMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pC strcpy(pSchema[cols].name, "role"); pSchema[cols].bytes = htons(pShow->bytes[cols]); cols++; - + + pShow->bytes[cols] = 8; + pSchema[cols].type = TSDB_DATA_TYPE_TIMESTAMP; + strcpy(pSchema[cols].name, "role_time"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + pShow->bytes[cols] = 8; pSchema[cols].type = TSDB_DATA_TYPE_TIMESTAMP; strcpy(pSchema[cols].name, "create_time"); @@ -552,6 +559,10 @@ static int32_t mnodeRetrieveMnodes(SShowObj *pShow, char *data, int32_t rows, vo STR_WITH_MAXSIZE_TO_VARSTR(pWrite, roles, pShow->bytes[cols]); cols++; + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int64_t *)pWrite = pMnode->roleTime; + cols++; + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; *(int64_t *)pWrite = pMnode->createdTime; cols++; diff --git a/src/mnode/src/mnodeSdb.c b/src/mnode/src/mnodeSdb.c index 7644f4d733..1e3057f270 100644 --- a/src/mnode/src/mnodeSdb.c +++ b/src/mnode/src/mnodeSdb.c @@ -227,6 +227,7 @@ void sdbUpdateMnodeRoles() { SMnodeObj *pMnode = mnodeGetMnode(roles.nodeId[i]); if (pMnode != NULL) { if (pMnode->role != roles.role[i]) { + pMnode->roleTime = taosGetTimestampMs(); bnNotify(); } diff --git a/src/os/src/detail/osTime.c b/src/os/src/detail/osTime.c index a95d919a83..5b2a01edc3 100644 --- a/src/os/src/detail/osTime.c +++ b/src/os/src/detail/osTime.c @@ -72,36 +72,55 @@ int64_t user_mktime64(const unsigned int year0, const unsigned int mon0, // ==== mktime() kernel code =================// static int64_t m_deltaUtc = 0; -void deltaToUtcInitOnce() { +void deltaToUtcInitOnce() { struct tm tm = {0}; - + (void)strptime("1970-01-01 00:00:00", (const char *)("%Y-%m-%d %H:%M:%S"), &tm); m_deltaUtc = (int64_t)mktime(&tm); - //printf("====delta:%lld\n\n", seconds); + //printf("====delta:%lld\n\n", seconds); return; } static int64_t parseFraction(char* str, char** end, int32_t timePrec); -static int32_t parseTimeWithTz(char* timestr, int64_t* time, int32_t timePrec); +static int32_t parseTimeWithTz(char* timestr, int64_t* time, int32_t timePrec, char delim); static int32_t parseLocaltime(char* timestr, int64_t* time, int32_t timePrec); static int32_t parseLocaltimeWithDst(char* timestr, int64_t* time, int32_t timePrec); +static char* forwardToTimeStringEnd(char* str); +static bool checkTzPresent(char *str, int32_t len); static int32_t (*parseLocaltimeFp[]) (char* timestr, int64_t* time, int32_t timePrec) = { parseLocaltime, parseLocaltimeWithDst -}; +}; int32_t taosGetTimestampSec() { return (int32_t)time(NULL); } int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t day_light) { /* parse datatime string in with tz */ if (strnchr(timestr, 'T', len, false) != NULL) { - return parseTimeWithTz(timestr, time, timePrec); + return parseTimeWithTz(timestr, time, timePrec, 'T'); + } else if (checkTzPresent(timestr, len)) { + return parseTimeWithTz(timestr, time, timePrec, 0); } else { return (*parseLocaltimeFp[day_light])(timestr, time, timePrec); } } +bool checkTzPresent(char *str, int32_t len) { + char *seg = forwardToTimeStringEnd(str); + int32_t seg_len = len - (int32_t)(seg - str); + + char *c = &seg[seg_len - 1]; + for (int i = 0; i < seg_len; ++i) { + if (*c == 'Z' || *c == 'z' || *c == '+' || *c == '-') { + return true; + } + c--; + } + return false; + +} + char* forwardToTimeStringEnd(char* str) { int32_t i = 0; int32_t numOfSep = 0; @@ -187,6 +206,13 @@ int32_t parseTimezone(char* str, int64_t* tzOffset) { i += 2; } + //return error if there're illegal charaters after min(2 Digits) + char *minStr = &str[i]; + if (minStr[1] != '\0' && minStr[2] != '\0') { + return -1; + } + + int64_t minute = strnatoi(&str[i], 2); if (minute > 59) { return -1; @@ -213,14 +239,23 @@ int32_t parseTimezone(char* str, int64_t* tzOffset) { * 2013-04-12T15:52:01+0800 * 2013-04-12T15:52:01.123+0800 */ -int32_t parseTimeWithTz(char* timestr, int64_t* time, int32_t timePrec) { +int32_t parseTimeWithTz(char* timestr, int64_t* time, int32_t timePrec, char delim) { int64_t factor = (timePrec == TSDB_TIME_PRECISION_MILLI) ? 1000 : (timePrec == TSDB_TIME_PRECISION_MICRO ? 1000000 : 1000000000); int64_t tzOffset = 0; struct tm tm = {0}; - char* str = strptime(timestr, "%Y-%m-%dT%H:%M:%S", &tm); + + char* str; + if (delim == 'T') { + str = strptime(timestr, "%Y-%m-%dT%H:%M:%S", &tm); + } else if (delim == 0) { + str = strptime(timestr, "%Y-%m-%d %H:%M:%S", &tm); + } else { + str = NULL; + } + if (str == NULL) { return -1; } @@ -236,7 +271,7 @@ int32_t parseTimeWithTz(char* timestr, int64_t* time, int32_t timePrec) { int64_t fraction = 0; str = forwardToTimeStringEnd(timestr); - if (str[0] == 'Z' || str[0] == 'z') { + if ((str[0] == 'Z' || str[0] == 'z') && str[1] == '\0') { /* utc time, no millisecond, return directly*/ *time = seconds * factor; } else if (str[0] == '.') { @@ -250,6 +285,8 @@ int32_t parseTimeWithTz(char* timestr, int64_t* time, int32_t timePrec) { char seg = str[0]; if (seg != 'Z' && seg != 'z' && seg != '+' && seg != '-') { return -1; + } else if ((seg == 'Z' || seg == 'z') && str[1] != '\0') { + return -1; } else if (seg == '+' || seg == '-') { // parse the timezone if (parseTimezone(str, &tzOffset) == -1) { diff --git a/src/query/inc/qExecutor.h b/src/query/inc/qExecutor.h index c9675c3844..a65ef524ae 100644 --- a/src/query/inc/qExecutor.h +++ b/src/query/inc/qExecutor.h @@ -252,8 +252,10 @@ typedef struct SQueryAttr { int32_t numOfFilterCols; int64_t* fillVal; SOrderedPrjQueryInfo prjInfo; // limit value for each vgroup, only available in global order projection query. - SSingleColumnFilterInfo* pFilterInfo; + SSingleColumnFilterInfo* pFilterInfo; + SFilterInfo *pFilters; + void* tsdb; SMemRef memRef; STableGroupInfo tableGroupInfo; // table list SArray @@ -383,6 +385,7 @@ typedef struct SQInfo { typedef struct SQueryParam { char *sql; char *tagCond; + char *colCond; char *tbnameCond; char *prevResult; SArray *pTableIdList; @@ -391,6 +394,8 @@ typedef struct SQueryParam { SExprInfo *pExprs; SExprInfo *pSecExprs; + SFilterInfo *pFilters; + SColIndex *pGroupColIndex; SColumnInfo *pTagColumnInfo; SGroupbyExpr *pGroupbyExpr; @@ -581,6 +586,7 @@ SSDataBlock* doSLimit(void* param, bool* newgroup); int32_t doCreateFilterInfo(SColumnInfo* pCols, int32_t numOfCols, int32_t numOfFilterCols, SSingleColumnFilterInfo** pFilterInfo, uint64_t qId); void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, SSDataBlock* pBlock); +void doSetFilterColInfo(SFilterInfo *pFilters, SSDataBlock* pBlock); bool doFilterDataBlock(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, int32_t numOfRows, int8_t* p); void doCompactSDataBlock(SSDataBlock* pBlock, int32_t numOfRows, int8_t* p); @@ -602,9 +608,11 @@ int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExp int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg *pQueryMsg, int32_t numOfOutput, SExprInfo **pExprInfo, SSqlExpr **pExpr, SExprInfo *prevExpr, SUdfInfo *pUdfInfo); +int32_t createQueryFilter(char *data, uint16_t len, SFilterInfo** pFilters); + SGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code); SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SGroupbyExpr *pGroupbyExpr, SExprInfo *pExprs, - SExprInfo *pSecExprs, STableGroupInfo *pTableGroupInfo, SColumnInfo* pTagCols, int32_t vgId, char* sql, uint64_t qId, SUdfInfo* pUdfInfo); + SExprInfo *pSecExprs, STableGroupInfo *pTableGroupInfo, SColumnInfo* pTagCols, SFilterInfo* pFilters, int32_t vgId, char* sql, uint64_t qId, SUdfInfo* pUdfInfo); int32_t initQInfo(STsBufInfo* pTsBufInfo, void* tsdb, void* sourceOptr, SQInfo* pQInfo, SQueryParam* param, char* start, int32_t prevResultLen, void* merger); diff --git a/src/query/inc/qFilter.h b/src/query/inc/qFilter.h new file mode 100644 index 0000000000..7a7b3157ea --- /dev/null +++ b/src/query/inc/qFilter.h @@ -0,0 +1,324 @@ +/* + * 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 TDENGINE_QFILTER_H +#define TDENGINE_QFILTER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "texpr.h" +#include "hash.h" +#include "tname.h" + +#define FILTER_DEFAULT_GROUP_SIZE 4 +#define FILTER_DEFAULT_UNIT_SIZE 4 +#define FILTER_DEFAULT_FIELD_SIZE 4 +#define FILTER_DEFAULT_VALUE_SIZE 4 +#define FILTER_DEFAULT_GROUP_UNIT_SIZE 2 + +#define FILTER_DUMMY_EMPTY_OPTR 127 +#define FILTER_DUMMY_RANGE_OPTR 126 + +#define MAX_NUM_STR_SIZE 40 + +enum { + FLD_TYPE_COLUMN = 1, + FLD_TYPE_VALUE = 2, + FLD_TYPE_MAX = 3, + FLD_DESC_NO_FREE = 4, + FLD_DATA_NO_FREE = 8, + FLD_DATA_IS_HASH = 16, +}; + +enum { + MR_ST_START = 1, + MR_ST_FIN = 2, + MR_ST_ALL = 4, + MR_ST_EMPTY = 8, +}; + +enum { + RANGE_FLG_EXCLUDE = 1, + RANGE_FLG_INCLUDE = 2, + RANGE_FLG_NULL = 4, +}; + +enum { + FI_OPTION_NO_REWRITE = 1, + FI_OPTION_TIMESTAMP = 2, + FI_OPTION_NEED_UNIQE = 4, +}; + +enum { + FI_STATUS_ALL = 1, + FI_STATUS_EMPTY = 2, + FI_STATUS_REWRITE = 4, + FI_STATUS_CLONED = 8, +}; + +enum { + RANGE_TYPE_UNIT = 1, + RANGE_TYPE_VAR_HASH = 2, + RANGE_TYPE_MR_CTX = 3, +}; + +typedef struct OptrStr { + uint16_t optr; + char *str; +} OptrStr; + +typedef struct SFilterRange { + int64_t s; + int64_t e; + char sflag; + char eflag; +} SFilterRange; + +typedef struct SFilterColRange { + uint16_t idx; //column field idx + bool isNull; + bool notNull; + bool isRange; + SFilterRange ra; +} SFilterColRange; + +typedef bool (*rangeCompFunc) (const void *, const void *, const void *, const void *, __compar_fn_t); +typedef int32_t(*filter_desc_compare_func)(const void *, const void *); +typedef bool(*filter_exec_func)(void *, int32_t, int8_t*); + +typedef struct SFilterRangeCompare { + int64_t s; + int64_t e; + rangeCompFunc func; +} SFilterRangeCompare; + +typedef struct SFilterRangeNode { + struct SFilterRangeNode* prev; + struct SFilterRangeNode* next; + union { + SFilterRange ra; + SFilterRangeCompare rc; + }; +} SFilterRangeNode; + +typedef struct SFilterRangeCtx { + int32_t type; + int32_t options; + int8_t status; + bool isnull; + bool notnull; + bool isrange; + int16_t colId; + __compar_fn_t pCompareFunc; + SFilterRangeNode *rf; //freed + SFilterRangeNode *rs; +} SFilterRangeCtx ; + +typedef struct SFilterVarCtx { + int32_t type; + int32_t options; + int8_t status; + bool isnull; + bool notnull; + bool isrange; + SHashObj *wild; + SHashObj *value; +} SFilterVarCtx; + +typedef struct SFilterField { + uint16_t flag; + void* desc; + void* data; +} SFilterField; + +typedef struct SFilterFields { + uint16_t size; + uint16_t num; + SFilterField *fields; +} SFilterFields; + +typedef struct SFilterFieldId { + uint16_t type; + uint16_t idx; +} SFilterFieldId; + +typedef struct SFilterGroup { + uint16_t unitSize; + uint16_t unitNum; + uint16_t *unitIdxs; + uint8_t *unitFlags; // !unit result +} SFilterGroup; + +typedef struct SFilterColInfo { + uint8_t type; + int32_t dataType; + void *info; +} SFilterColInfo; + +typedef struct SFilterGroupCtx { + uint16_t colNum; + uint16_t *colIdx; + SFilterColInfo *colInfo; +} SFilterGroupCtx; + +typedef struct SFilterColCtx { + uint16_t colIdx; + void* ctx; +} SFilterColCtx; + +typedef struct SFilterCompare { + uint8_t type; + uint8_t optr; + uint8_t optr2; +} SFilterCompare; + +typedef struct SFilterUnit { + SFilterCompare compare; + SFilterFieldId left; + SFilterFieldId right; + SFilterFieldId right2; +} SFilterUnit; + +typedef struct SFilterComUnit { + void *colData; + void *valData; + void *valData2; + uint16_t dataSize; + uint8_t dataType; + uint8_t optr; + int8_t func; + int8_t rfunc; +} SFilterComUnit; + +typedef struct SFilterPCtx { + SHashObj *valHash; + SHashObj *unitHash; +} SFilterPCtx; + +typedef struct SFilterInfo { + uint32_t options; + uint32_t status; + uint16_t unitSize; + uint16_t unitNum; + uint16_t groupNum; + uint16_t colRangeNum; + SFilterFields fields[FLD_TYPE_MAX]; + SFilterGroup *groups; + uint16_t *cgroups; + SFilterUnit *units; + SFilterComUnit *cunits; + uint8_t *unitRes; // result + uint8_t *unitFlags; // got result + SFilterRangeCtx **colRange; + filter_exec_func func; + + SFilterPCtx pctx; +} SFilterInfo; + +#define COL_FIELD_SIZE (sizeof(SFilterField) + 2 * sizeof(int64_t)) + +#define FILTER_NO_MERGE_DATA_TYPE(t) ((t) == TSDB_DATA_TYPE_BINARY || (t) == TSDB_DATA_TYPE_NCHAR) +#define FILTER_NO_MERGE_OPTR(o) ((o) == TSDB_RELATION_ISNULL || (o) == TSDB_RELATION_NOTNULL || (o) == FILTER_DUMMY_EMPTY_OPTR) + +#define MR_EMPTY_RES(ctx) (ctx->rs == NULL) + +#define SET_AND_OPTR(ctx, o) do {if (o == TSDB_RELATION_ISNULL) { (ctx)->isnull = true; } else if (o == TSDB_RELATION_NOTNULL) { if (!(ctx)->isrange) { (ctx)->notnull = true; } } else if (o != FILTER_DUMMY_EMPTY_OPTR) { (ctx)->isrange = true; (ctx)->notnull = false; } } while (0) +#define SET_OR_OPTR(ctx,o) do {if (o == TSDB_RELATION_ISNULL) { (ctx)->isnull = true; } else if (o == TSDB_RELATION_NOTNULL) { (ctx)->notnull = true; (ctx)->isrange = false; } else if (o != FILTER_DUMMY_EMPTY_OPTR) { if (!(ctx)->notnull) { (ctx)->isrange = true; } } } while (0) +#define CHK_OR_OPTR(ctx) ((ctx)->isnull == true && (ctx)->notnull == true) +#define CHK_AND_OPTR(ctx) ((ctx)->isnull == true && (((ctx)->notnull == true) || ((ctx)->isrange == true))) + + +#define FILTER_GET_FLAG(st, f) (st & f) +#define FILTER_SET_FLAG(st, f) st |= (f) +#define FILTER_CLR_FLAG(st, f) st &= (~f) + +#define SIMPLE_COPY_VALUES(dst, src) *((int64_t *)dst) = *((int64_t *)src) +#define FILTER_PACKAGE_UNIT_HASH_KEY(v, optr, idx1, idx2) do { char *_t = (char *)v; _t[0] = optr; *(uint16_t *)(_t + 1) = idx1; *(uint16_t *)(_t + 3) = idx2; } while (0) +#define FILTER_GREATER(cr,sflag,eflag) ((cr > 0) || ((cr == 0) && (FILTER_GET_FLAG(sflag,RANGE_FLG_EXCLUDE) || FILTER_GET_FLAG(eflag,RANGE_FLG_EXCLUDE)))) +#define FILTER_COPY_RA(dst, src) do { (dst)->sflag = (src)->sflag; (dst)->eflag = (src)->eflag; (dst)->s = (src)->s; (dst)->e = (src)->e; } while (0) + +#define RESET_RANGE(ctx, r) do { (r)->next = (ctx)->rf; (ctx)->rf = r; } while (0) +#define FREE_RANGE(ctx, r) do { if ((r)->prev) { (r)->prev->next = (r)->next; } else { (ctx)->rs = (r)->next;} if ((r)->next) { (r)->next->prev = (r)->prev; } RESET_RANGE(ctx, r); } while (0) +#define FREE_FROM_RANGE(ctx, r) do { SFilterRangeNode *_r = r; if ((_r)->prev) { (_r)->prev->next = NULL; } else { (ctx)->rs = NULL;} while (_r) {SFilterRangeNode *n = (_r)->next; RESET_RANGE(ctx, _r); _r = n; } } while (0) +#define INSERT_RANGE(ctx, r, ra) do { SFilterRangeNode *n = filterNewRange(ctx, ra); n->prev = (r)->prev; if ((r)->prev) { (r)->prev->next = n; } else { (ctx)->rs = n; } (r)->prev = n; n->next = r; } while (0) +#define APPEND_RANGE(ctx, r, ra) do { SFilterRangeNode *n = filterNewRange(ctx, ra); n->prev = (r); if (r) { (r)->next = n; } else { (ctx)->rs = n; } } while (0) + +#define ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { return _code; } } while (0) +#define ERR_LRET(c,...) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { qError(__VA_ARGS__); return _code; } } while (0) +#define ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { goto _return; } } while (0) + +#define CHK_RETV(c) do { if (c) { return; } } while (0) +#define CHK_RET(c, r) do { if (c) { return r; } } while (0) +#define CHK_JMP(c) do { if (c) { goto _return; } } while (0) +#define CHK_LRETV(c,...) do { if (c) { qError(__VA_ARGS__); return; } } while (0) +#define CHK_LRET(c, r,...) do { if (c) { qError(__VA_ARGS__); return r; } } while (0) + +#define FILTER_GET_FIELD(i, id) (&((i)->fields[(id).type].fields[(id).idx])) +#define FILTER_GET_COL_FIELD(i, idx) (&((i)->fields[FLD_TYPE_COLUMN].fields[idx])) +#define FILTER_GET_COL_FIELD_TYPE(fi) (((SSchema *)((fi)->desc))->type) +#define FILTER_GET_COL_FIELD_SIZE(fi) (((SSchema *)((fi)->desc))->bytes) +#define FILTER_GET_COL_FIELD_DESC(fi) ((SSchema *)((fi)->desc)) +#define FILTER_GET_COL_FIELD_DATA(fi, ri) ((char *)(fi)->data + ((SSchema *)((fi)->desc))->bytes * (ri)) +#define FILTER_GET_VAL_FIELD_TYPE(fi) (((tVariant *)((fi)->desc))->nType) +#define FILTER_GET_VAL_FIELD_DATA(fi) ((char *)(fi)->data) +#define FILTER_GET_TYPE(fl) ((fl) & FLD_TYPE_MAX) + +#define FILTER_GROUP_UNIT(i, g, uid) ((i)->units + (g)->unitIdxs[uid]) +#define FILTER_UNIT_LEFT_FIELD(i, u) FILTER_GET_FIELD(i, (u)->left) +#define FILTER_UNIT_RIGHT_FIELD(i, u) FILTER_GET_FIELD(i, (u)->right) +#define FILTER_UNIT_DATA_TYPE(u) ((u)->compare.type) +#define FILTER_UNIT_COL_DESC(i, u) FILTER_GET_COL_FIELD_DESC(FILTER_UNIT_LEFT_FIELD(i, u)) +#define FILTER_UNIT_COL_DATA(i, u, ri) FILTER_GET_COL_FIELD_DATA(FILTER_UNIT_LEFT_FIELD(i, u), ri) +#define FILTER_UNIT_COL_SIZE(i, u) FILTER_GET_COL_FIELD_SIZE(FILTER_UNIT_LEFT_FIELD(i, u)) +#define FILTER_UNIT_VAL_DATA(i, u) FILTER_GET_VAL_FIELD_DATA(FILTER_UNIT_RIGHT_FIELD(i, u)) +#define FILTER_UNIT_COL_IDX(u) ((u)->left.idx) +#define FILTER_UNIT_OPTR(u) ((u)->compare.optr) +#define FILTER_UNIT_COMP_FUNC(u) ((u)->compare.func) + +#define FILTER_UNIT_CLR_F(i) memset((i)->unitFlags, 0, (i)->unitNum * sizeof(*info->unitFlags)) +#define FILTER_UNIT_SET_F(i, idx) (i)->unitFlags[idx] = 1 +#define FILTER_UNIT_GET_F(i, idx) ((i)->unitFlags[idx]) +#define FILTER_UNIT_GET_R(i, idx) ((i)->unitRes[idx]) +#define FILTER_UNIT_SET_R(i, idx, v) (i)->unitRes[idx] = (v) + +#define FILTER_PUSH_UNIT(colInfo, u) do { (colInfo).type = RANGE_TYPE_UNIT; (colInfo).dataType = FILTER_UNIT_DATA_TYPE(u);taosArrayPush((SArray *)((colInfo).info), &u);} while (0) +#define FILTER_PUSH_VAR_HASH(colInfo, ha) do { (colInfo).type = RANGE_TYPE_VAR_HASH; (colInfo).info = ha;} while (0) +#define FILTER_PUSH_CTX(colInfo, ctx) do { (colInfo).type = RANGE_TYPE_MR_CTX; (colInfo).info = ctx;} while (0) + +#define FILTER_COPY_IDX(dst, src, n) do { *(dst) = malloc(sizeof(uint16_t) * n); memcpy(*(dst), src, sizeof(uint16_t) * n);} while (0) + +#define FILTER_ADD_CTX_TO_GRES(gres, idx, ctx) do { if ((gres)->colCtxs == NULL) { (gres)->colCtxs = taosArrayInit(gres->colNum, sizeof(SFilterColCtx)); } SFilterColCtx cCtx = {idx, ctx}; taosArrayPush((gres)->colCtxs, &cCtx); } while (0) + + +#define FILTER_ALL_RES(i) FILTER_GET_FLAG((i)->status, FI_STATUS_ALL) +#define FILTER_EMPTY_RES(i) FILTER_GET_FLAG((i)->status, FI_STATUS_EMPTY) + + +extern int32_t filterInitFromTree(tExprNode* tree, SFilterInfo **pinfo, uint32_t options); +extern bool filterExecute(SFilterInfo *info, int32_t numOfRows, int8_t* p); +extern int32_t filterSetColFieldData(SFilterInfo *info, int16_t colId, void *data); +extern int32_t filterGetTimeRange(SFilterInfo *info, STimeWindow *win); +extern int32_t filterConverNcharColumns(SFilterInfo* pFilterInfo, int32_t rows, bool *gotNchar); +extern int32_t filterFreeNcharColumns(SFilterInfo* pFilterInfo); +extern void filterFreeInfo(SFilterInfo *info); +extern bool filterRangeExecute(SFilterInfo *info, SDataStatis *pDataStatis, int32_t numOfCols, int32_t numOfRows); + +#ifdef __cplusplus +} +#endif + +#endif // TDENGINE_QFILTER_H diff --git a/src/query/inc/qTableMeta.h b/src/query/inc/qTableMeta.h index 0dae74ac82..d6b04b0330 100644 --- a/src/query/inc/qTableMeta.h +++ b/src/query/inc/qTableMeta.h @@ -3,6 +3,7 @@ #include "tsdb.h" //todo tsdb should not be here #include "qSqlparser.h" +#include "qFilter.h" typedef struct SFieldInfo { int16_t numOfOutput; // number of column in result @@ -16,6 +17,14 @@ typedef struct SCond { char * cond; } SCond; +typedef struct STblCond { + uint64_t uid; + int16_t idx; //table index + int32_t len; // length of tag query condition data + char * cond; +} STblCond; + + typedef struct SJoinNode { uint64_t uid; int16_t tagColId; @@ -89,6 +98,11 @@ typedef struct STableMetaInfo { struct SQInfo; // global merge operator struct SQueryAttr; // query object +typedef struct STableFilter { + uint64_t uid; + SFilterInfo info; +} STableFilter; + typedef struct SQueryInfo { int16_t command; // the command may be different for each subclause, so keep it seperately. uint32_t type; // query/insert type @@ -106,8 +120,11 @@ typedef struct SQueryInfo { SLimitVal slimit; STagCond tagCond; + SArray * colCond; + SOrderVal order; int16_t numOfTables; + int16_t curTableIdx; STableMetaInfo **pTableMetaInfo; struct STSBuf *tsBuf; diff --git a/src/query/inc/sql.y b/src/query/inc/sql.y index 96f1e680f1..8b43e55693 100644 --- a/src/query/inc/sql.y +++ b/src/query/inc/sql.y @@ -80,7 +80,7 @@ cmd ::= SHOW SCORES. { setShowOptions(pInfo, TSDB_MGMT_TABLE_SCORES, 0, 0); cmd ::= SHOW GRANTS. { setShowOptions(pInfo, TSDB_MGMT_TABLE_GRANTS, 0, 0); } cmd ::= SHOW VNODES. { setShowOptions(pInfo, TSDB_MGMT_TABLE_VNODES, 0, 0); } -cmd ::= SHOW VNODES IPTOKEN(X). { setShowOptions(pInfo, TSDB_MGMT_TABLE_VNODES, &X, 0); } +cmd ::= SHOW VNODES ids(X). { setShowOptions(pInfo, TSDB_MGMT_TABLE_VNODES, &X, 0); } %type dbPrefix {SStrToken} diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 9c8219c559..4d697b06a5 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -2541,77 +2541,14 @@ static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, i #define IS_PREFILTER_TYPE(_t) ((_t) != TSDB_DATA_TYPE_BINARY && (_t) != TSDB_DATA_TYPE_NCHAR) -static bool doFilterByBlockStatistics(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis, SQLFunctionCtx *pCtx, int32_t numOfRows) { +static FORCE_INLINE bool doFilterByBlockStatistics(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis, SQLFunctionCtx *pCtx, int32_t numOfRows) { SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr; - if (pDataStatis == NULL || pQueryAttr->numOfFilterCols == 0) { + if (pDataStatis == NULL || pQueryAttr->pFilters == NULL) { return true; } - bool ret = true; - for (int32_t k = 0; k < pQueryAttr->numOfFilterCols; ++k) { - SSingleColumnFilterInfo *pFilterInfo = &pQueryAttr->pFilterInfo[k]; - int32_t index = -1; - for(int32_t i = 0; i < pQueryAttr->numOfCols; ++i) { - if (pDataStatis[i].colId == pFilterInfo->info.colId) { - index = i; - break; - } - } - - // no statistics data, load the true data block - if (index == -1) { - return true; - } - - // not support pre-filter operation on binary/nchar data type - if (!IS_PREFILTER_TYPE(pFilterInfo->info.type)) { - return true; - } - - // all data in current column are NULL, no need to check its boundary value - if (pDataStatis[index].numOfNull == numOfRows) { - - // if isNULL query exists, load the null data column - for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) { - SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j]; - if (pFilterElem->fp == isNullOperator) { - return true; - } - } - - continue; - } - - SDataStatis* pDataBlockst = &pDataStatis[index]; - - if (pFilterInfo->info.type == TSDB_DATA_TYPE_FLOAT) { - float minval = (float)(*(double *)(&pDataBlockst->min)); - float maxval = (float)(*(double *)(&pDataBlockst->max)); - - for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) { - if (pFilterInfo->pFilters[i].filterInfo.lowerRelOptr == TSDB_RELATION_IN) { - continue; - } - ret &= pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval, TSDB_DATA_TYPE_FLOAT); - if (ret == false) { - return false; - } - } - } else { - for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) { - if (pFilterInfo->pFilters[i].filterInfo.lowerRelOptr == TSDB_RELATION_IN) { - continue; - } - ret &= pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pDataBlockst->min, (char *)&pDataBlockst->max, pFilterInfo->info.type); - if (ret == false) { - return false; - } - } - } - } - - return ret; + return filterRangeExecute(pQueryAttr->pFilters, pDataStatis, pQueryAttr->numOfCols, numOfRows); } static bool overlapWithTimeWindow(SQueryAttr* pQueryAttr, SDataBlockInfo* pBlockInfo) { @@ -2830,6 +2767,49 @@ void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInf tfree(p); } +void filterColRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSDataBlock* pBlock, bool ascQuery) { + int32_t numOfRows = pBlock->info.rows; + + int8_t *p = calloc(numOfRows, sizeof(int8_t)); + bool all = true; + + if (pRuntimeEnv->pTsBuf != NULL) { + SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0); + + TSKEY* k = (TSKEY*) pColInfoData->pData; + for (int32_t i = 0; i < numOfRows; ++i) { + int32_t offset = ascQuery? i:(numOfRows - i - 1); + int32_t ret = doTSJoinFilter(pRuntimeEnv, k[offset], ascQuery); + if (ret == TS_JOIN_TAG_NOT_EQUALS) { + break; + } else if (ret == TS_JOIN_TS_NOT_EQUALS) { + all = false; + continue; + } else { + assert(ret == TS_JOIN_TS_EQUAL); + p[offset] = true; + } + + if (!tsBufNextPos(pRuntimeEnv->pTsBuf)) { + break; + } + } + + // save the cursor status + pRuntimeEnv->current->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf); + } else { + all = filterExecute(pRuntimeEnv->pQueryAttr->pFilters, numOfRows, p); + } + + if (!all) { + doCompactSDataBlock(pBlock, numOfRows, p); + } + + tfree(p); +} + + + static SColumnInfo* doGetTagColumnInfoById(SColumnInfo* pTagColList, int32_t numOfTags, int16_t colId); static void doSetTagValueInParam(void* pTable, int32_t tagColId, tVariant *tag, int16_t type, int16_t bytes); @@ -2871,6 +2851,15 @@ void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFi } } + +void doSetFilterColInfo(SFilterInfo * pFilters, SSDataBlock* pBlock) { + for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) { + SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, j); + + filterSetColFieldData(pFilters, pColInfo->info.colId, pColInfo->pData); + } +} + int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock, uint32_t* status) { *status = BLK_DATA_NO_NEEDED; @@ -2910,7 +2899,7 @@ int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTa // Calculate all time windows that are overlapping or contain current data block. // If current data block is contained by all possible time window, do not load current data block. - if (pQueryAttr->numOfFilterCols > 0 || pQueryAttr->groupbyColumn || pQueryAttr->sw.gap > 0 || + if (pQueryAttr->pFilters || pQueryAttr->groupbyColumn || pQueryAttr->sw.gap > 0 || (QUERY_IS_INTERVAL_QUERY(pQueryAttr) && overlapWithTimeWindow(pQueryAttr, &pBlock->info))) { (*status) = BLK_DATA_ALL_NEEDED; } @@ -3012,9 +3001,12 @@ int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTa return terrno; } - doSetFilterColumnInfo(pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols, pBlock); - if (pQueryAttr->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL) { - filterRowsInDataBlock(pRuntimeEnv, pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols, pBlock, ascQuery); + if (pQueryAttr->pFilters != NULL) { + doSetFilterColInfo(pQueryAttr->pFilters, pBlock); + } + + if (pQueryAttr->pFilters != NULL || pRuntimeEnv->pTsBuf != NULL) { + filterColRowsInDataBlock(pRuntimeEnv, pBlock, ascQuery); } } @@ -7001,7 +6993,8 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols); pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput); pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols); - pQueryMsg->tagCondLen = htonl(pQueryMsg->tagCondLen); + pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen); + pQueryMsg->colCondLen = htons(pQueryMsg->colCondLen); pQueryMsg->tsBuf.tsOffset = htonl(pQueryMsg->tsBuf.tsOffset); pQueryMsg->tsBuf.tsLen = htonl(pQueryMsg->tsBuf.tsLen); pQueryMsg->tsBuf.tsNumOfBlocks = htonl(pQueryMsg->tsBuf.tsNumOfBlocks); @@ -7032,7 +7025,7 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { pColInfo->colId = htons(pColInfo->colId); pColInfo->type = htons(pColInfo->type); pColInfo->bytes = htons(pColInfo->bytes); - pColInfo->flist.numOfFilters = htons(pColInfo->flist.numOfFilters); + pColInfo->flist.numOfFilters = 0; if (!isValidDataType(pColInfo->type)) { qDebug("qmsg:%p, invalid data type in source column, index:%d, type:%d", pQueryMsg, col, pColInfo->type); @@ -7040,6 +7033,7 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { goto _cleanup; } +/* int32_t numOfFilters = pColInfo->flist.numOfFilters; if (numOfFilters > 0) { pColInfo->flist.filterInfo = calloc(numOfFilters, sizeof(SColumnFilterInfo)); @@ -7053,8 +7047,21 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { if (code != TSDB_CODE_SUCCESS) { goto _cleanup; } +*/ } + if (pQueryMsg->colCondLen > 0) { + param->colCond = calloc(1, pQueryMsg->colCondLen); + if (param->colCond == NULL) { + code = TSDB_CODE_QRY_OUT_OF_MEMORY; + goto _cleanup; + } + + memcpy(param->colCond, pMsg, pQueryMsg->colCondLen); + pMsg += pQueryMsg->colCondLen; + } + + param->tableScanOperator = pQueryMsg->tableScanOperator; param->pExpr = calloc(pQueryMsg->numOfOutput, POINTER_BYTES); if (param->pExpr == NULL) { @@ -7628,6 +7635,28 @@ int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExp return TSDB_CODE_SUCCESS; } +int32_t createQueryFilter(char *data, uint16_t len, SFilterInfo** pFilters) { + tExprNode* expr = NULL; + + TRY(TSDB_MAX_TAG_CONDITIONS) { + expr = exprTreeFromBinary(data, len); + } CATCH( code ) { + CLEANUP_EXECUTE(); + return code; + } END_TRY + + if (expr == NULL) { + qError("failed to create expr tree"); + return TSDB_CODE_QRY_APP_ERROR; + } + + int32_t ret = filterInitFromTree(expr, pFilters, 0); + tExprTreeDestroy(expr, NULL); + + return ret; +} + + // todo refactor int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo, SSqlExpr** pExpr, SExprInfo* prevExpr, SUdfInfo *pUdfInfo) { @@ -7777,7 +7806,7 @@ void* doDestroyFilterInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFil int32_t createFilterInfo(SQueryAttr* pQueryAttr, uint64_t qId) { for (int32_t i = 0; i < pQueryAttr->numOfCols; ++i) { - if (pQueryAttr->tableCols[i].flist.numOfFilters > 0) { + if (pQueryAttr->tableCols[i].flist.numOfFilters > 0 && pQueryAttr->tableCols[i].flist.filterInfo != NULL) { pQueryAttr->numOfFilterCols++; } } @@ -7860,7 +7889,7 @@ FORCE_INLINE bool checkQIdEqual(void *qHandle, uint64_t qId) { } SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SGroupbyExpr* pGroupbyExpr, SExprInfo* pExprs, - SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, int32_t vgId, + SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, SFilterInfo* pFilters, int32_t vgId, char* sql, uint64_t qId, SUdfInfo* pUdfInfo) { int16_t numOfCols = pQueryMsg->numOfCols; int16_t numOfOutput = pQueryMsg->numOfOutput; @@ -7912,7 +7941,8 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SGroupbyExpr* pGroupbyExpr, S pQueryAttr->needReverseScan = pQueryMsg->needReverseScan; pQueryAttr->stateWindow = pQueryMsg->stateWindow; pQueryAttr->vgId = vgId; - + pQueryAttr->pFilters = pFilters; + pQueryAttr->tableCols = calloc(numOfCols, sizeof(SSingleColumnFilterInfo)); if (pQueryAttr->tableCols == NULL) { goto _cleanup; @@ -7945,10 +7975,6 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SGroupbyExpr* pGroupbyExpr, S } doUpdateExprColumnIndex(pQueryAttr); - int32_t ret = createFilterInfo(pQueryAttr, pQInfo->qId); - if (ret != TSDB_CODE_SUCCESS) { - goto _cleanup; - } if (pSecExprs != NULL) { int32_t resultRowSize = 0; @@ -8063,6 +8089,8 @@ _cleanup_qinfo: tfree(pExprs); + filterFreeInfo(pFilters); + _cleanup: freeQInfo(pQInfo); return NULL; @@ -8418,6 +8446,8 @@ void freeQueryAttr(SQueryAttr* pQueryAttr) { taosArrayDestroy(pQueryAttr->pGroupbyExpr->columnInfo); tfree(pQueryAttr->pGroupbyExpr); } + + filterFreeInfo(pQueryAttr->pFilters); } } diff --git a/src/query/src/qFilter.c b/src/query/src/qFilter.c new file mode 100644 index 0000000000..1171bb0896 --- /dev/null +++ b/src/query/src/qFilter.c @@ -0,0 +1,3076 @@ +/* + * 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 "os.h" +#include "queryLog.h" +#include "qFilter.h" +#include "tcompare.h" +#include "hash.h" +#include "tscUtil.h" + +OptrStr gOptrStr[] = { + {TSDB_RELATION_INVALID, "invalid"}, + {TSDB_RELATION_LESS, "<"}, + {TSDB_RELATION_GREATER, ">"}, + {TSDB_RELATION_EQUAL, "="}, + {TSDB_RELATION_LESS_EQUAL, "<="}, + {TSDB_RELATION_GREATER_EQUAL, ">="}, + {TSDB_RELATION_NOT_EQUAL, "!="}, + {TSDB_RELATION_LIKE, "like"}, + {TSDB_RELATION_ISNULL, "is null"}, + {TSDB_RELATION_NOTNULL, "not null"}, + {TSDB_RELATION_IN, "in"}, + {TSDB_RELATION_AND, "and"}, + {TSDB_RELATION_OR, "or"}, + {TSDB_RELATION_NOT, "not"} +}; + +static FORCE_INLINE int32_t filterFieldColDescCompare(const void *desc1, const void *desc2) { + const SSchema *sch1 = desc1; + const SSchema *sch2 = desc2; + + return sch1->colId != sch2->colId; +} + +static FORCE_INLINE int32_t filterFieldValDescCompare(const void *desc1, const void *desc2) { + const tVariant *val1 = desc1; + const tVariant *val2 = desc2; + + return tVariantCompare(val1, val2); +} + + +filter_desc_compare_func gDescCompare [FLD_TYPE_MAX] = { + NULL, + filterFieldColDescCompare, + filterFieldValDescCompare +}; + +bool filterRangeCompGi (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(maxv, minr) >= 0; +} +bool filterRangeCompGe (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(maxv, minr) > 0; +} +bool filterRangeCompLi (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(minv, maxr) <= 0; +} +bool filterRangeCompLe (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(minv, maxr) < 0; +} +bool filterRangeCompii (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(maxv, minr) >= 0 && cfunc(minv, maxr) <= 0; +} +bool filterRangeCompee (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(maxv, minr) > 0 && cfunc(minv, maxr) < 0; +} +bool filterRangeCompei (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(maxv, minr) > 0 && cfunc(minv, maxr) <= 0; +} +bool filterRangeCompie (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(maxv, minr) >= 0 && cfunc(minv, maxr) < 0; +} + +rangeCompFunc filterGetRangeCompFunc(char sflag, char eflag) { + if (FILTER_GET_FLAG(sflag, RANGE_FLG_NULL)) { + if (FILTER_GET_FLAG(eflag, RANGE_FLG_EXCLUDE)) { + return filterRangeCompLe; + } + + return filterRangeCompLi; + } + + if (FILTER_GET_FLAG(eflag, RANGE_FLG_NULL)) { + if (FILTER_GET_FLAG(sflag, RANGE_FLG_EXCLUDE)) { + return filterRangeCompGe; + } + + return filterRangeCompGi; + } + + if (FILTER_GET_FLAG(sflag, RANGE_FLG_EXCLUDE)) { + if (FILTER_GET_FLAG(eflag, RANGE_FLG_EXCLUDE)) { + return filterRangeCompee; + } + + return filterRangeCompei; + } + + if (FILTER_GET_FLAG(eflag, RANGE_FLG_EXCLUDE)) { + return filterRangeCompie; + } + + return filterRangeCompii; +} + +rangeCompFunc gRangeCompare[] = {filterRangeCompee, filterRangeCompei, filterRangeCompie, filterRangeCompii, filterRangeCompGe, + filterRangeCompGi, filterRangeCompLe, filterRangeCompLi}; + + +int8_t filterGetRangeCompFuncFromOptrs(uint8_t optr, uint8_t optr2) { + if (optr2) { + assert(optr2 == TSDB_RELATION_LESS || optr2 == TSDB_RELATION_LESS_EQUAL); + + if (optr == TSDB_RELATION_GREATER) { + if (optr2 == TSDB_RELATION_LESS) { + return 0; + } + + return 1; + } + + if (optr2 == TSDB_RELATION_LESS) { + return 2; + } + + return 3; + } else { + switch (optr) { + case TSDB_RELATION_GREATER: + return 4; + case TSDB_RELATION_GREATER_EQUAL: + return 5; + case TSDB_RELATION_LESS: + return 6; + case TSDB_RELATION_LESS_EQUAL: + return 7; + default: + break; + } + } + + return -1; +} + +__compar_fn_t gDataCompare[] = {compareInt32Val, compareInt8Val, compareInt16Val, compareInt64Val, compareFloatVal, + compareDoubleVal, compareLenPrefixedStr, compareStrPatternComp, compareFindItemInSet, compareWStrPatternComp, + compareLenPrefixedWStr, compareUint8Val, compareUint16Val, compareUint32Val, compareUint64Val, + setCompareBytes1, setCompareBytes2, setCompareBytes4, setCompareBytes8 +}; + +int8_t filterGetCompFuncIdx(int32_t type, int32_t optr) { + int8_t comparFn = 0; + + if (optr == TSDB_RELATION_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR)) { + switch (type) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_UTINYINT: + return 15; + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_USMALLINT: + return 16; + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_FLOAT: + return 17; + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_DOUBLE: + case TSDB_DATA_TYPE_TIMESTAMP: + return 18; + default: + assert(0); + } + } + + switch (type) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: comparFn = 1; break; + case TSDB_DATA_TYPE_SMALLINT: comparFn = 2; break; + case TSDB_DATA_TYPE_INT: comparFn = 0; break; + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_TIMESTAMP: comparFn = 3; break; + case TSDB_DATA_TYPE_FLOAT: comparFn = 4; break; + case TSDB_DATA_TYPE_DOUBLE: comparFn = 5; break; + case TSDB_DATA_TYPE_BINARY: { + if (optr == TSDB_RELATION_LIKE) { /* wildcard query using like operator */ + comparFn = 7; + } else if (optr == TSDB_RELATION_IN) { + comparFn = 8; + } else { /* normal relational comparFn */ + comparFn = 6; + } + + break; + } + + case TSDB_DATA_TYPE_NCHAR: { + if (optr == TSDB_RELATION_LIKE) { + comparFn = 9; + } else if (optr == TSDB_RELATION_IN) { + comparFn = 8; + } else { + comparFn = 10; + } + break; + } + + case TSDB_DATA_TYPE_UTINYINT: comparFn = 11; break; + case TSDB_DATA_TYPE_USMALLINT: comparFn = 12;break; + case TSDB_DATA_TYPE_UINT: comparFn = 13;break; + case TSDB_DATA_TYPE_UBIGINT: comparFn = 14;break; + + default: + comparFn = 0; + break; + } + + return comparFn; +} + + +static FORCE_INLINE int32_t filterCompareGroupCtx(const void *pLeft, const void *pRight) { + SFilterGroupCtx *left = *((SFilterGroupCtx**)pLeft), *right = *((SFilterGroupCtx**)pRight); + if (left->colNum > right->colNum) return 1; + if (left->colNum < right->colNum) return -1; + return 0; +} + +int32_t filterInitUnitsFields(SFilterInfo *info) { + info->unitSize = FILTER_DEFAULT_UNIT_SIZE; + info->units = calloc(info->unitSize, sizeof(SFilterUnit)); + + info->fields[FLD_TYPE_COLUMN].num = 0; + info->fields[FLD_TYPE_COLUMN].size = FILTER_DEFAULT_FIELD_SIZE; + info->fields[FLD_TYPE_COLUMN].fields = calloc(info->fields[FLD_TYPE_COLUMN].size, COL_FIELD_SIZE); + info->fields[FLD_TYPE_VALUE].num = 0; + info->fields[FLD_TYPE_VALUE].size = FILTER_DEFAULT_FIELD_SIZE; + info->fields[FLD_TYPE_VALUE].fields = calloc(info->fields[FLD_TYPE_VALUE].size, sizeof(SFilterField)); + + return TSDB_CODE_SUCCESS; +} + +static FORCE_INLINE SFilterRangeNode* filterNewRange(SFilterRangeCtx *ctx, SFilterRange* ra) { + SFilterRangeNode *r = NULL; + + if (ctx->rf) { + r = ctx->rf; + ctx->rf = ctx->rf->next; + r->prev = NULL; + r->next = NULL; + } else { + r = calloc(1, sizeof(SFilterRangeNode)); + } + + FILTER_COPY_RA(&r->ra, ra); + + return r; +} + +void* filterInitRangeCtx(int32_t type, int32_t options) { + if (type > TSDB_DATA_TYPE_UBIGINT || type < TSDB_DATA_TYPE_BOOL || type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { + qError("not supported range type:%d", type); + return NULL; + } + + SFilterRangeCtx *ctx = calloc(1, sizeof(SFilterRangeCtx)); + + ctx->type = type; + ctx->options = options; + ctx->pCompareFunc = getComparFunc(type, 0); + + return ctx; +} + + +int32_t filterResetRangeCtx(SFilterRangeCtx *ctx) { + ctx->status = 0; + + if (ctx->rf == NULL) { + ctx->rf = ctx->rs; + ctx->rs = NULL; + return TSDB_CODE_SUCCESS; + } + + ctx->isnull = false; + ctx->notnull = false; + ctx->isrange = false; + + SFilterRangeNode *r = ctx->rf; + + while (r && r->next) { + r = r->next; + } + + r->next = ctx->rs; + ctx->rs = NULL; + return TSDB_CODE_SUCCESS; +} + +int32_t filterReuseRangeCtx(SFilterRangeCtx *ctx, int32_t type, int32_t options) { + filterResetRangeCtx(ctx); + + ctx->type = type; + ctx->options = options; + ctx->pCompareFunc = getComparFunc(type, 0); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterConvertRange(SFilterRangeCtx *cur, SFilterRange *ra, bool *notNull) { + if (!FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) { + int32_t sr = cur->pCompareFunc(&ra->s, getDataMin(cur->type)); + if (sr == 0) { + FILTER_SET_FLAG(ra->sflag, RANGE_FLG_NULL); + } + } + + if (!FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL)) { + int32_t er = cur->pCompareFunc(&ra->e, getDataMax(cur->type)); + if (er == 0) { + FILTER_SET_FLAG(ra->eflag, RANGE_FLG_NULL); + } + } + + + if (FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL) && FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL)) { + *notNull = true; + } else { + *notNull = false; + } + + return TSDB_CODE_SUCCESS; +} + +int32_t filterAddRangeOptr(void* h, uint8_t raOptr, int32_t optr, bool *empty, bool *all) { + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + + if (optr == TSDB_RELATION_AND) { + SET_AND_OPTR(ctx, raOptr); + if (CHK_AND_OPTR(ctx) || (raOptr == FILTER_DUMMY_EMPTY_OPTR)) { + FILTER_SET_FLAG(ctx->status, MR_ST_EMPTY); + *empty = true; + } + } else { + SET_OR_OPTR(ctx, raOptr); + if (CHK_OR_OPTR(ctx)) { + FILTER_SET_FLAG(ctx->status, MR_ST_ALL); + *all = true; + } + } + + return TSDB_CODE_SUCCESS; +} + + + +int32_t filterAddRangeImpl(void* h, SFilterRange* ra, int32_t optr) { + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + + if (ctx->rs == NULL) { + if ((FILTER_GET_FLAG(ctx->status, MR_ST_START) == 0) + || (FILTER_GET_FLAG(ctx->status, MR_ST_ALL) && (optr == TSDB_RELATION_AND)) + || ((!FILTER_GET_FLAG(ctx->status, MR_ST_ALL)) && (optr == TSDB_RELATION_OR))) { + APPEND_RANGE(ctx, ctx->rs, ra); + FILTER_SET_FLAG(ctx->status, MR_ST_START); + } + + return TSDB_CODE_SUCCESS; + } + + SFilterRangeNode *r = ctx->rs; + SFilterRangeNode *rn = NULL; + int32_t cr = 0; + + if (optr == TSDB_RELATION_AND) { + while (r != NULL) { + cr = ctx->pCompareFunc(&r->ra.s, &ra->e); + if (FILTER_GREATER(cr, r->ra.sflag, ra->eflag)) { + FREE_FROM_RANGE(ctx, r); + break; + } + + cr = ctx->pCompareFunc(&ra->s, &r->ra.e); + if (FILTER_GREATER(cr, ra->sflag, r->ra.eflag)) { + rn = r->next; + FREE_RANGE(ctx, r); + r = rn; + continue; + } + + cr = ctx->pCompareFunc(&ra->s, &r->ra.s); + if (FILTER_GREATER(cr, ra->sflag, r->ra.sflag)) { + SIMPLE_COPY_VALUES((char *)&r->ra.s, &ra->s); + cr == 0 ? (r->ra.sflag |= ra->sflag) : (r->ra.sflag = ra->sflag); + } + + cr = ctx->pCompareFunc(&r->ra.e, &ra->e); + if (FILTER_GREATER(cr, r->ra.eflag, ra->eflag)) { + SIMPLE_COPY_VALUES((char *)&r->ra.e, &ra->e); + cr == 0 ? (r->ra.eflag |= ra->eflag) : (r->ra.eflag = ra->eflag); + break; + } + + r = r->next; + } + + return TSDB_CODE_SUCCESS; + } + + + //TSDB_RELATION_OR + + bool smerged = false; + bool emerged = false; + + while (r != NULL) { + cr = ctx->pCompareFunc(&r->ra.s, &ra->e); + if (FILTER_GREATER(cr, r->ra.sflag, ra->eflag)) { + if (emerged == false) { + INSERT_RANGE(ctx, r, ra); + } + + break; + } + + if (smerged == false) { + cr = ctx->pCompareFunc(&ra->s, &r->ra.e); + if (FILTER_GREATER(cr, ra->sflag, r->ra.eflag)) { + if (r->next) { + r= r->next; + continue; + } + + APPEND_RANGE(ctx, r, ra); + break; + } + + cr = ctx->pCompareFunc(&r->ra.s, &ra->s); + if (FILTER_GREATER(cr, r->ra.sflag, ra->sflag)) { + SIMPLE_COPY_VALUES((char *)&r->ra.s, &ra->s); + cr == 0 ? (r->ra.sflag &= ra->sflag) : (r->ra.sflag = ra->sflag); + } + + smerged = true; + } + + if (emerged == false) { + cr = ctx->pCompareFunc(&ra->e, &r->ra.e); + if (FILTER_GREATER(cr, ra->eflag, r->ra.eflag)) { + SIMPLE_COPY_VALUES((char *)&r->ra.e, &ra->e); + if (cr == 0) { + r->ra.eflag &= ra->eflag; + break; + } + + r->ra.eflag = ra->eflag; + emerged = true; + r = r->next; + continue; + } + + break; + } + + cr = ctx->pCompareFunc(&ra->e, &r->ra.e); + if (FILTER_GREATER(cr, ra->eflag, r->ra.eflag)) { + rn = r->next; + FREE_RANGE(ctx, r); + r = rn; + + continue; + } else { + SIMPLE_COPY_VALUES(&r->prev->ra.e, (char *)&r->ra.e); + cr == 0 ? (r->prev->ra.eflag &= r->ra.eflag) : (r->prev->ra.eflag = r->ra.eflag); + FREE_RANGE(ctx, r); + + break; + } + } + + if (ctx->rs && ctx->rs->next == NULL) { + bool notnull; + filterConvertRange(ctx, &ctx->rs->ra, ¬null); + if (notnull) { + bool all = false; + FREE_FROM_RANGE(ctx, ctx->rs); + filterAddRangeOptr(h, TSDB_RELATION_NOTNULL, optr, NULL, &all); + if (all) { + FILTER_SET_FLAG(ctx->status, MR_ST_ALL); + } + } + } + + return TSDB_CODE_SUCCESS; +} + +int32_t filterAddRange(void* h, SFilterRange* ra, int32_t optr) { + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + + if (FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) { + SIMPLE_COPY_VALUES(&ra->s, getDataMin(ctx->type)); + //FILTER_CLR_FLAG(ra->sflag, RA_NULL); + } + + if (FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL)) { + SIMPLE_COPY_VALUES(&ra->e, getDataMax(ctx->type)); + //FILTER_CLR_FLAG(ra->eflag, RA_NULL); + } + + return filterAddRangeImpl(h, ra, optr); +} + + +int32_t filterAddRangeCtx(void *dst, void *src, int32_t optr) { + SFilterRangeCtx *dctx = (SFilterRangeCtx *)dst; + SFilterRangeCtx *sctx = (SFilterRangeCtx *)src; + + assert(optr == TSDB_RELATION_OR); + + if (sctx->rs == NULL) { + return TSDB_CODE_SUCCESS; + } + + SFilterRangeNode *r = sctx->rs; + + while (r) { + filterAddRange(dctx, &r->ra, optr); + r = r->next; + } + + return TSDB_CODE_SUCCESS; +} + +int32_t filterCopyRangeCtx(void *dst, void *src) { + SFilterRangeCtx *dctx = (SFilterRangeCtx *)dst; + SFilterRangeCtx *sctx = (SFilterRangeCtx *)src; + + dctx->status = sctx->status; + + dctx->isnull = sctx->isnull; + dctx->notnull = sctx->notnull; + dctx->isrange = sctx->isrange; + + SFilterRangeNode *r = sctx->rs; + SFilterRangeNode *dr = dctx->rs; + + while (r) { + APPEND_RANGE(dctx, dr, &r->ra); + if (dr == NULL) { + dr = dctx->rs; + } else { + dr = dr->next; + } + r = r->next; + } + + return TSDB_CODE_SUCCESS; +} + + + +int32_t filterFinishRange(void* h) { + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + + if (FILTER_GET_FLAG(ctx->status, MR_ST_FIN)) { + return TSDB_CODE_SUCCESS; + } + + if (FILTER_GET_FLAG(ctx->options, FI_OPTION_TIMESTAMP)) { + SFilterRangeNode *r = ctx->rs; + SFilterRangeNode *rn = NULL; + + while (r && r->next) { + int64_t tmp = 1; + operateVal(&tmp, &r->ra.e, &tmp, TSDB_BINARY_OP_ADD, ctx->type); + if (ctx->pCompareFunc(&tmp, &r->next->ra.s) == 0) { + rn = r->next; + SIMPLE_COPY_VALUES((char *)&r->next->ra.s, (char *)&r->ra.s); + FREE_RANGE(ctx, r); + r = rn; + + continue; + } + + r = r->next; + } + } + + FILTER_SET_FLAG(ctx->status, MR_ST_FIN); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterGetRangeNum(void* h, int32_t* num) { + filterFinishRange(h); + + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + + *num = 0; + + SFilterRangeNode *r = ctx->rs; + + while (r) { + ++(*num); + r = r->next; + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterGetRangeRes(void* h, SFilterRange *ra) { + filterFinishRange(h); + + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + uint32_t num = 0; + SFilterRangeNode* r = ctx->rs; + + while (r) { + FILTER_COPY_RA(ra, &r->ra); + + ++num; + r = r->next; + ++ra; + } + + if (num == 0) { + qError("no range result"); + return TSDB_CODE_QRY_APP_ERROR; + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterSourceRangeFromCtx(SFilterRangeCtx *ctx, void *sctx, int32_t optr, bool *empty, bool *all) { + SFilterRangeCtx *src = (SFilterRangeCtx *)sctx; + + if (src->isnull){ + filterAddRangeOptr(ctx, TSDB_RELATION_ISNULL, optr, empty, all); + if (FILTER_GET_FLAG(ctx->status, MR_ST_ALL)) { + *all = true; + } + } + + if (src->notnull) { + filterAddRangeOptr(ctx, TSDB_RELATION_NOTNULL, optr, empty, all); + if (FILTER_GET_FLAG(ctx->status, MR_ST_ALL)) { + *all = true; + } + } + + if (src->isrange) { + filterAddRangeOptr(ctx, 0, optr, empty, all); + + if (!(optr == TSDB_RELATION_OR && ctx->notnull)) { + filterAddRangeCtx(ctx, src, optr); + } + + if (FILTER_GET_FLAG(ctx->status, MR_ST_ALL)) { + *all = true; + } + } + + return TSDB_CODE_SUCCESS; +} + + + +int32_t filterFreeRangeCtx(void* h) { + if (h == NULL) { + return TSDB_CODE_SUCCESS; + } + + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + SFilterRangeNode *r = ctx->rs; + SFilterRangeNode *rn = NULL; + + while (r) { + rn = r->next; + free(r); + r = rn; + } + + r = ctx->rf; + while (r) { + rn = r->next; + free(r); + r = rn; + } + + free(ctx); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterDetachCnfGroup(SFilterGroup *gp1, SFilterGroup *gp2, SArray* group) { + SFilterGroup gp = {0}; + + gp.unitNum = gp1->unitNum + gp2->unitNum; + gp.unitIdxs = calloc(gp.unitNum, sizeof(*gp.unitIdxs)); + memcpy(gp.unitIdxs, gp1->unitIdxs, gp1->unitNum * sizeof(*gp.unitIdxs)); + memcpy(gp.unitIdxs + gp1->unitNum, gp2->unitIdxs, gp2->unitNum * sizeof(*gp.unitIdxs)); + + gp.unitFlags = NULL; + + taosArrayPush(group, &gp); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterDetachCnfGroups(SArray* group, SArray* left, SArray* right) { + int32_t leftSize = (int32_t)taosArrayGetSize(left); + int32_t rightSize = (int32_t)taosArrayGetSize(right); + + CHK_LRET(taosArrayGetSize(left) <= 0, TSDB_CODE_QRY_APP_ERROR, "empty group"); + CHK_LRET(taosArrayGetSize(right) <= 0, TSDB_CODE_QRY_APP_ERROR, "empty group"); + + for (int32_t l = 0; l < leftSize; ++l) { + SFilterGroup *gp1 = taosArrayGet(left, l); + + for (int32_t r = 0; r < rightSize; ++r) { + SFilterGroup *gp2 = taosArrayGet(right, r); + + filterDetachCnfGroup(gp1, gp2, group); + } + } + + + return TSDB_CODE_SUCCESS; +} + +int32_t filterGetFiledByDesc(SFilterFields* fields, int32_t type, void *v) { + for (uint16_t i = 0; i < fields->num; ++i) { + if (0 == gDescCompare[type](fields->fields[i].desc, v)) { + return i; + } + } + + return -1; +} + + +int32_t filterGetFiledByData(SFilterInfo *info, int32_t type, void *v, int32_t dataLen) { + if (type == FLD_TYPE_VALUE) { + if (info->pctx.valHash == false) { + qError("value hash is empty"); + return -1; + } + + void *hv = taosHashGet(info->pctx.valHash, v, dataLen); + if (hv) { + return *(int32_t *)hv; + } + } + + return -1; +} + + +int32_t filterAddField(SFilterInfo *info, void *desc, void **data, int32_t type, SFilterFieldId *fid, int32_t dataLen, bool freeIfExists) { + int32_t idx = -1; + uint16_t *num; + + num = &info->fields[type].num; + + if (*num > 0) { + if (type == FLD_TYPE_COLUMN) { + idx = filterGetFiledByDesc(&info->fields[type], type, desc); + } else if (data && (*data) && dataLen > 0 && FILTER_GET_FLAG(info->options, FI_OPTION_NEED_UNIQE)) { + idx = filterGetFiledByData(info, type, *data, dataLen); + } + } + + if (idx < 0) { + idx = *num; + if (idx >= info->fields[type].size) { + info->fields[type].size += FILTER_DEFAULT_FIELD_SIZE; + info->fields[type].fields = realloc(info->fields[type].fields, info->fields[type].size * sizeof(SFilterField)); + } + + info->fields[type].fields[idx].flag = type; + info->fields[type].fields[idx].desc = desc; + info->fields[type].fields[idx].data = data ? *data : NULL; + + if (type == FLD_TYPE_COLUMN) { + FILTER_SET_FLAG(info->fields[type].fields[idx].flag, FLD_DATA_NO_FREE); + } + + ++(*num); + + if (data && (*data) && dataLen > 0 && FILTER_GET_FLAG(info->options, FI_OPTION_NEED_UNIQE)) { + if (info->pctx.valHash == NULL) { + info->pctx.valHash = taosHashInit(FILTER_DEFAULT_GROUP_SIZE * FILTER_DEFAULT_VALUE_SIZE, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, false); + } + + taosHashPut(info->pctx.valHash, *data, dataLen, &idx, sizeof(idx)); + } + } else { + if (freeIfExists) { + tfree(desc); + } + + if (data && freeIfExists) { + tfree(*data); + } + } + + fid->type = type; + fid->idx = idx; + + return TSDB_CODE_SUCCESS; +} + +static FORCE_INLINE int32_t filterAddColFieldFromField(SFilterInfo *info, SFilterField *field, SFilterFieldId *fid) { + filterAddField(info, field->desc, &field->data, FILTER_GET_TYPE(field->flag), fid, 0, false); + + FILTER_SET_FLAG(field->flag, FLD_DESC_NO_FREE); + FILTER_SET_FLAG(field->flag, FLD_DATA_NO_FREE); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterAddFieldFromNode(SFilterInfo *info, tExprNode *node, SFilterFieldId *fid) { + CHK_LRET(node == NULL, TSDB_CODE_QRY_APP_ERROR, "empty node"); + CHK_RET(node->nodeType != TSQL_NODE_COL && node->nodeType != TSQL_NODE_VALUE, TSDB_CODE_QRY_APP_ERROR); + + int32_t type; + void *v; + + if (node->nodeType == TSQL_NODE_COL) { + type = FLD_TYPE_COLUMN; + v = node->pSchema; + node->pSchema = NULL; + } else { + type = FLD_TYPE_VALUE; + v = node->pVal; + node->pVal = NULL; + } + + filterAddField(info, v, NULL, type, fid, 0, true); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterAddUnit(SFilterInfo *info, uint8_t optr, SFilterFieldId *left, SFilterFieldId *right, uint16_t *uidx) { + if (FILTER_GET_FLAG(info->options, FI_OPTION_NEED_UNIQE)) { + if (info->pctx.unitHash == NULL) { + info->pctx.unitHash = taosHashInit(FILTER_DEFAULT_GROUP_SIZE * FILTER_DEFAULT_UNIT_SIZE, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, false); + } else { + int64_t v = 0; + FILTER_PACKAGE_UNIT_HASH_KEY(&v, optr, left->idx, right ? right->idx : -1); + void *hu = taosHashGet(info->pctx.unitHash, &v, sizeof(v)); + if (hu) { + *uidx = *(uint16_t *)hu; + return TSDB_CODE_SUCCESS; + } + } + } + + if (info->unitNum >= info->unitSize) { + uint16_t psize = info->unitSize; + info->unitSize += FILTER_DEFAULT_UNIT_SIZE; + info->units = realloc(info->units, info->unitSize * sizeof(SFilterUnit)); + memset(info->units + psize, 0, sizeof(*info->units) * FILTER_DEFAULT_UNIT_SIZE); + } + + SFilterUnit *u = &info->units[info->unitNum]; + + u->compare.optr = optr; + u->left = *left; + if (right) { + u->right = *right; + } + + if (u->right.type == FLD_TYPE_VALUE) { + SFilterField *val = FILTER_UNIT_RIGHT_FIELD(info, u); + assert(FILTER_GET_FLAG(val->flag, FLD_TYPE_VALUE)); + } else { + assert(optr == TSDB_RELATION_ISNULL || optr == TSDB_RELATION_NOTNULL || optr == FILTER_DUMMY_EMPTY_OPTR); + } + + SFilterField *col = FILTER_UNIT_LEFT_FIELD(info, u); + assert(FILTER_GET_FLAG(col->flag, FLD_TYPE_COLUMN)); + + info->units[info->unitNum].compare.type = FILTER_GET_COL_FIELD_TYPE(col); + + *uidx = info->unitNum; + + if (FILTER_GET_FLAG(info->options, FI_OPTION_NEED_UNIQE)) { + int64_t v = 0; + FILTER_PACKAGE_UNIT_HASH_KEY(&v, optr, left->idx, right ? right->idx : -1); + taosHashPut(info->pctx.unitHash, &v, sizeof(v), uidx, sizeof(*uidx)); + } + + ++info->unitNum; + + return TSDB_CODE_SUCCESS; +} + + + +int32_t filterAddUnitToGroup(SFilterGroup *group, uint16_t unitIdx) { + if (group->unitNum >= group->unitSize) { + group->unitSize += FILTER_DEFAULT_UNIT_SIZE; + group->unitIdxs = realloc(group->unitIdxs, group->unitSize * sizeof(*group->unitIdxs)); + } + + group->unitIdxs[group->unitNum++] = unitIdx; + + return TSDB_CODE_SUCCESS; +} + +int32_t filterConvertSetFromBinary(void **q, const char *buf, int32_t len, uint32_t tType) { + SBufferReader br = tbufInitReader(buf, len, false); + uint32_t sType = tbufReadUint32(&br); + SHashObj *pObj = taosHashInit(256, taosGetDefaultHashFunction(tType), true, false); + int32_t code = 0; + + taosHashSetEqualFp(pObj, taosGetDefaultEqualFunction(tType)); + + int dummy = -1; + tVariant tmpVar = {0}; + size_t t = 0; + int32_t sz = tbufReadInt32(&br); + void *pvar = NULL; + int64_t val = 0; + int32_t bufLen = 0; + if (IS_NUMERIC_TYPE(sType)) { + bufLen = 60; // The maximum length of string that a number is converted to. + } else { + bufLen = 128; + } + + char *tmp = calloc(1, bufLen * TSDB_NCHAR_SIZE); + + for (int32_t i = 0; i < sz; i++) { + switch (sType) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_TINYINT: { + *(uint8_t *)&val = (uint8_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_SMALLINT: { + *(uint16_t *)&val = (uint16_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_INT: { + *(uint32_t *)&val = (uint32_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_BIGINT: { + *(uint64_t *)&val = (uint64_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_DOUBLE: { + *(double *)&val = tbufReadDouble(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_FLOAT: { + *(float *)&val = (float)tbufReadDouble(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_BINARY: { + pvar = (char *)tbufReadBinary(&br, &t); + break; + } + case TSDB_DATA_TYPE_NCHAR: { + pvar = (char *)tbufReadBinary(&br, &t); + break; + } + default: + taosHashCleanup(pObj); + *q = NULL; + assert(0); + } + + tVariantCreateFromBinary(&tmpVar, (char *)pvar, t, sType); + + if (bufLen < t) { + tmp = realloc(tmp, t * TSDB_NCHAR_SIZE); + bufLen = (int32_t)t; + } + + bool converted = false; + char extInfo = 0; + + switch (tType) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_TINYINT: { + if (tVariantDumpEx(&tmpVar, (char *)&val, tType, false, &converted, &extInfo)) { + if (converted) { + tVariantDestroy(&tmpVar); + memset(&tmpVar, 0, sizeof(tmpVar)); + continue; + } + + goto _return; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_SMALLINT: { + if (tVariantDumpEx(&tmpVar, (char *)&val, tType, false, &converted, &extInfo)) { + if (converted) { + tVariantDestroy(&tmpVar); + memset(&tmpVar, 0, sizeof(tmpVar)); + continue; + } + + goto _return; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_INT: { + if (tVariantDumpEx(&tmpVar, (char *)&val, tType, false, &converted, &extInfo)) { + if (converted) { + tVariantDestroy(&tmpVar); + memset(&tmpVar, 0, sizeof(tmpVar)); + continue; + } + + goto _return; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_BIGINT: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto _return; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_DOUBLE: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto _return; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_FLOAT: { + if (tVariantDumpEx(&tmpVar, (char *)&val, tType, false, &converted, &extInfo)) { + if (converted) { + tVariantDestroy(&tmpVar); + memset(&tmpVar, 0, sizeof(tmpVar)); + continue; + } + + goto _return; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_BINARY: { + if (tVariantDump(&tmpVar, tmp, tType, true)) { + goto _return; + } + t = varDataLen(tmp); + pvar = varDataVal(tmp); + break; + } + case TSDB_DATA_TYPE_NCHAR: { + if (tVariantDump(&tmpVar, tmp, tType, true)) { + goto _return; + } + t = varDataLen(tmp); + pvar = varDataVal(tmp); + break; + } + default: + goto _return; + } + + taosHashPut(pObj, (char *)pvar, t, &dummy, sizeof(dummy)); + tVariantDestroy(&tmpVar); + memset(&tmpVar, 0, sizeof(tmpVar)); + } + + *q = (void *)pObj; + pObj = NULL; + +_return: + tVariantDestroy(&tmpVar); + taosHashCleanup(pObj); + tfree(tmp); + + return code; +} + + + +int32_t filterAddGroupUnitFromNode(SFilterInfo *info, tExprNode* tree, SArray *group) { + SFilterFieldId left = {0}, right = {0}; + + filterAddFieldFromNode(info, tree->_node.pLeft, &left); + + tVariant* var = tree->_node.pRight->pVal; + int32_t type = FILTER_GET_COL_FIELD_TYPE(FILTER_GET_FIELD(info, left)); + int32_t len = 0; + uint16_t uidx = 0; + + if (tree->_node.optr == TSDB_RELATION_IN && (!IS_VAR_DATA_TYPE(type))) { + void *data = NULL; + filterConvertSetFromBinary((void **)&data, var->pz, var->nLen, type); + CHK_LRET(data == NULL, TSDB_CODE_QRY_APP_ERROR, "failed to convert in param"); + + if (taosHashGetSize((SHashObj *)data) <= 0) { + filterAddUnit(info, FILTER_DUMMY_EMPTY_OPTR, &left, NULL, &uidx); + + SFilterGroup fgroup = {0}; + filterAddUnitToGroup(&fgroup, uidx); + + taosArrayPush(group, &fgroup); + taosHashCleanup(data); + + return TSDB_CODE_SUCCESS; + } + + void *p = taosHashIterate((SHashObj *)data, NULL); + while(p) { + void *key = taosHashGetDataKey((SHashObj *)data, p); + void *fdata = NULL; + + if (IS_VAR_DATA_TYPE(type)) { + len = (int32_t)taosHashGetDataKeyLen((SHashObj *)data, p); + fdata = malloc(len + VARSTR_HEADER_SIZE); + varDataLen(fdata) = len; + memcpy(varDataVal(fdata), key, len); + len += VARSTR_HEADER_SIZE; + } else { + fdata = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(fdata, key); + len = tDataTypes[type].bytes; + } + + filterAddField(info, NULL, &fdata, FLD_TYPE_VALUE, &right, len, true); + + filterAddUnit(info, TSDB_RELATION_EQUAL, &left, &right, &uidx); + + SFilterGroup fgroup = {0}; + filterAddUnitToGroup(&fgroup, uidx); + + taosArrayPush(group, &fgroup); + + p = taosHashIterate((SHashObj *)data, p); + } + + taosHashCleanup(data); + } else { + filterAddFieldFromNode(info, tree->_node.pRight, &right); + + filterAddUnit(info, tree->_node.optr, &left, &right, &uidx); + + SFilterGroup fgroup = {0}; + filterAddUnitToGroup(&fgroup, uidx); + + taosArrayPush(group, &fgroup); + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterAddUnitFromUnit(SFilterInfo *dst, SFilterInfo *src, SFilterUnit* u, uint16_t *uidx) { + SFilterFieldId left, right, *pright = &right; + int32_t type = FILTER_UNIT_DATA_TYPE(u); + uint16_t flag = FLD_DESC_NO_FREE; + + filterAddField(dst, FILTER_UNIT_COL_DESC(src, u), NULL, FLD_TYPE_COLUMN, &left, 0, false); + SFilterField *t = FILTER_UNIT_LEFT_FIELD(src, u); + FILTER_SET_FLAG(t->flag, flag); + + if (u->right.type == FLD_TYPE_VALUE) { + void *data = FILTER_UNIT_VAL_DATA(src, u); + if (IS_VAR_DATA_TYPE(type)) { + if (FILTER_UNIT_OPTR(u) == TSDB_RELATION_IN) { + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, 0, false); + + t = FILTER_GET_FIELD(dst, right); + + FILTER_SET_FLAG(t->flag, FLD_DATA_IS_HASH); + } else { + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, varDataTLen(data), false); + } + } else { + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, false); + } + + flag = FLD_DATA_NO_FREE; + t = FILTER_UNIT_RIGHT_FIELD(src, u); + FILTER_SET_FLAG(t->flag, flag); + } else { + pright = NULL; + } + + return filterAddUnit(dst, FILTER_UNIT_OPTR(u), &left, pright, uidx); +} + +int32_t filterAddUnitRight(SFilterInfo *info, uint8_t optr, SFilterFieldId *right, uint16_t uidx) { + SFilterUnit *u = &info->units[uidx]; + + u->compare.optr2 = optr; + u->right2 = *right; + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterAddGroupUnitFromCtx(SFilterInfo *dst, SFilterInfo *src, SFilterRangeCtx *ctx, uint16_t cidx, SFilterGroup *g, int32_t optr, SArray *res) { + SFilterFieldId left, right, right2; + uint16_t uidx = 0; + + SFilterField *col = FILTER_GET_COL_FIELD(src, cidx); + + filterAddColFieldFromField(dst, col, &left); + + int32_t type = FILTER_GET_COL_FIELD_TYPE(FILTER_GET_FIELD(dst, left)); + + if (optr == TSDB_RELATION_AND) { + if (ctx->isnull) { + assert(ctx->notnull == false && ctx->isrange == false); + filterAddUnit(dst, TSDB_RELATION_ISNULL, &left, NULL, &uidx); + filterAddUnitToGroup(g, uidx); + return TSDB_CODE_SUCCESS; + } + + if (ctx->notnull) { + assert(ctx->isnull == false && ctx->isrange == false); + filterAddUnit(dst, TSDB_RELATION_NOTNULL, &left, NULL, &uidx); + filterAddUnitToGroup(g, uidx); + return TSDB_CODE_SUCCESS; + } + + if (!ctx->isrange) { + assert(ctx->isnull || ctx->notnull); + return TSDB_CODE_SUCCESS; + } + + assert(ctx->rs && ctx->rs->next == NULL); + + SFilterRange *ra = &ctx->rs->ra; + + assert(!((FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) && (FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL)))); + + if ((!FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) && (!FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL))) { + __compar_fn_t func = getComparFunc(type, 0); + if (func(&ra->s, &ra->e) == 0) { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &ra->s); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + filterAddUnit(dst, TSDB_RELATION_EQUAL, &left, &right, &uidx); + filterAddUnitToGroup(g, uidx); + return TSDB_CODE_SUCCESS; + } else { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &ra->s); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + void *data2 = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data2, &ra->e); + filterAddField(dst, NULL, &data2, FLD_TYPE_VALUE, &right2, tDataTypes[type].bytes, true); + + filterAddUnit(dst, FILTER_GET_FLAG(ra->sflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_GREATER : TSDB_RELATION_GREATER_EQUAL, &left, &right, &uidx); + filterAddUnitRight(dst, FILTER_GET_FLAG(ra->eflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_LESS : TSDB_RELATION_LESS_EQUAL, &right2, uidx); + filterAddUnitToGroup(g, uidx); + return TSDB_CODE_SUCCESS; + } + } + + if (!FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &ra->s); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + filterAddUnit(dst, FILTER_GET_FLAG(ra->sflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_GREATER : TSDB_RELATION_GREATER_EQUAL, &left, &right, &uidx); + filterAddUnitToGroup(g, uidx); + } + + if (!FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL)) { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &ra->e); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + filterAddUnit(dst, FILTER_GET_FLAG(ra->eflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_LESS : TSDB_RELATION_LESS_EQUAL, &left, &right, &uidx); + filterAddUnitToGroup(g, uidx); + } + + return TSDB_CODE_SUCCESS; + } + + // OR PROCESS + + SFilterGroup ng = {0}; + g = &ng; + + assert(ctx->isnull || ctx->notnull || ctx->isrange); + + if (ctx->isnull) { + filterAddUnit(dst, TSDB_RELATION_ISNULL, &left, NULL, &uidx); + filterAddUnitToGroup(g, uidx); + taosArrayPush(res, g); + } + + if (ctx->notnull) { + assert(!ctx->isrange); + memset(g, 0, sizeof(*g)); + + filterAddUnit(dst, TSDB_RELATION_NOTNULL, &left, NULL, &uidx); + filterAddUnitToGroup(g, uidx); + taosArrayPush(res, g); + } + + if (!ctx->isrange) { + assert(ctx->isnull || ctx->notnull); + g->unitNum = 0; + return TSDB_CODE_SUCCESS; + } + + SFilterRangeNode *r = ctx->rs; + + while (r) { + memset(g, 0, sizeof(*g)); + + if ((!FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_NULL)) &&(!FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_NULL))) { + __compar_fn_t func = getComparFunc(type, 0); + if (func(&r->ra.s, &r->ra.e) == 0) { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &r->ra.s); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + filterAddUnit(dst, TSDB_RELATION_EQUAL, &left, &right, &uidx); + filterAddUnitToGroup(g, uidx); + } else { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &r->ra.s); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + void *data2 = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data2, &r->ra.e); + filterAddField(dst, NULL, &data2, FLD_TYPE_VALUE, &right2, tDataTypes[type].bytes, true); + + filterAddUnit(dst, FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_GREATER : TSDB_RELATION_GREATER_EQUAL, &left, &right, &uidx); + filterAddUnitRight(dst, FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_LESS : TSDB_RELATION_LESS_EQUAL, &right2, uidx); + filterAddUnitToGroup(g, uidx); + } + + taosArrayPush(res, g); + + r = r->next; + + continue; + } + + if (!FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_NULL)) { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &r->ra.s); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + filterAddUnit(dst, FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_GREATER : TSDB_RELATION_GREATER_EQUAL, &left, &right, &uidx); + filterAddUnitToGroup(g, uidx); + } + + if (!FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_NULL)) { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &r->ra.e); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + filterAddUnit(dst, FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_LESS : TSDB_RELATION_LESS_EQUAL, &left, &right, &uidx); + filterAddUnitToGroup(g, uidx); + } + + assert (g->unitNum > 0); + + taosArrayPush(res, g); + + r = r->next; + } + + g->unitNum = 0; + + return TSDB_CODE_SUCCESS; +} + + +static void filterFreeGroup(void *pItem) { + if (pItem == NULL) { + return; + } + + SFilterGroup* p = (SFilterGroup*) pItem; + tfree(p->unitIdxs); + tfree(p->unitFlags); +} + + +int32_t filterTreeToGroup(tExprNode* tree, SFilterInfo *info, SArray* group) { + int32_t code = TSDB_CODE_SUCCESS; + SArray* leftGroup = NULL; + SArray* rightGroup = NULL; + + if (tree->nodeType != TSQL_NODE_EXPR) { + qError("invalid nodeType:%d", tree->nodeType); + return TSDB_CODE_QRY_APP_ERROR; + } + + if (tree->_node.optr == TSDB_RELATION_AND) { + leftGroup = taosArrayInit(4, sizeof(SFilterGroup)); + rightGroup = taosArrayInit(4, sizeof(SFilterGroup)); + ERR_JRET(filterTreeToGroup(tree->_node.pLeft, info, leftGroup)); + ERR_JRET(filterTreeToGroup(tree->_node.pRight, info, rightGroup)); + + ERR_JRET(filterDetachCnfGroups(group, leftGroup, rightGroup)); + + taosArrayDestroyEx(leftGroup, filterFreeGroup); + taosArrayDestroyEx(rightGroup, filterFreeGroup); + + return TSDB_CODE_SUCCESS; + } + + if (tree->_node.optr == TSDB_RELATION_OR) { + ERR_RET(filterTreeToGroup(tree->_node.pLeft, info, group)); + ERR_RET(filterTreeToGroup(tree->_node.pRight, info, group)); + + return TSDB_CODE_SUCCESS; + } + + code = filterAddGroupUnitFromNode(info, tree, group); + + +_return: + + taosArrayDestroyEx(leftGroup, filterFreeGroup); + taosArrayDestroyEx(rightGroup, filterFreeGroup); + + return code; +} + +#if 0 +int32_t filterInitUnitFunc(SFilterInfo *info) { + for (uint16_t i = 0; i < info->unitNum; ++i) { + SFilterUnit* unit = &info->units[i]; + + info->cunits[i].func = getComparFunc(FILTER_UNIT_DATA_TYPE(unit), unit->compare.optr); + } + + return TSDB_CODE_SUCCESS; +} +#endif + + +void filterDumpInfoToString(SFilterInfo *info, const char *msg, int32_t options) { + if (qDebugFlag & DEBUG_DEBUG) { + CHK_LRETV(info == NULL, "%s - FilterInfo: EMPTY", msg); + + if (options == 0) { + qDebug("%s - FilterInfo:", msg); + qDebug("COLUMN Field Num:%u", info->fields[FLD_TYPE_COLUMN].num); + for (uint16_t i = 0; i < info->fields[FLD_TYPE_COLUMN].num; ++i) { + SFilterField *field = &info->fields[FLD_TYPE_COLUMN].fields[i]; + SSchema *sch = field->desc; + qDebug("COL%d => [%d][%s]", i, sch->colId, sch->name); + } + + qDebug("VALUE Field Num:%u", info->fields[FLD_TYPE_VALUE].num); + for (uint16_t i = 0; i < info->fields[FLD_TYPE_VALUE].num; ++i) { + SFilterField *field = &info->fields[FLD_TYPE_VALUE].fields[i]; + if (field->desc) { + tVariant *var = field->desc; + if (var->nType == TSDB_DATA_TYPE_VALUE_ARRAY) { + qDebug("VAL%d => [type:TS][val:[%" PRIi64"] - [%" PRId64 "]]", i, *(int64_t *)field->data, *(((int64_t *)field->data) + 1)); + } else { + qDebug("VAL%d => [type:%d][val:%" PRIx64"]", i, var->nType, var->i64); //TODO + } + } else if (field->data) { + qDebug("VAL%d => [type:NIL][val:NIL]", i); //TODO + } + } + + qDebug("UNIT Num:%u", info->unitNum); + for (uint16_t i = 0; i < info->unitNum; ++i) { + SFilterUnit *unit = &info->units[i]; + int32_t type = FILTER_UNIT_DATA_TYPE(unit); + int32_t len = 0; + int32_t tlen = 0; + char str[256] = {0}; + + SFilterField *left = FILTER_UNIT_LEFT_FIELD(info, unit); + SSchema *sch = left->desc; + len = sprintf(str, "UNIT[%d] => [%d][%s] %s [", i, sch->colId, sch->name, gOptrStr[unit->compare.optr].str); + + if (unit->right.type == FLD_TYPE_VALUE && FILTER_UNIT_OPTR(unit) != TSDB_RELATION_IN) { + SFilterField *right = FILTER_UNIT_RIGHT_FIELD(info, unit); + char *data = right->data; + if (IS_VAR_DATA_TYPE(type)) { + tlen = varDataLen(data); + data += VARSTR_HEADER_SIZE; + } + converToStr(str + len, type, data, tlen > 32 ? 32 : tlen, &tlen); + } else { + strcat(str, "NULL"); + } + strcat(str, "]"); + + qDebug("%s", str); //TODO + } + + qDebug("GROUP Num:%u", info->groupNum); + for (uint16_t i = 0; i < info->groupNum; ++i) { + SFilterGroup *group = &info->groups[i]; + qDebug("Group%d : unit num[%u]", i, group->unitNum); + + for (uint16_t u = 0; u < group->unitNum; ++u) { + qDebug("unit id:%u", group->unitIdxs[u]); + } + } + + return; + } + + qDebug("%s - RANGE info:", msg); + + qDebug("RANGE Num:%u", info->colRangeNum); + for (uint16_t i = 0; i < info->colRangeNum; ++i) { + SFilterRangeCtx *ctx = info->colRange[i]; + qDebug("Column ID[%d] RANGE: isnull[%d],notnull[%d],range[%d]", ctx->colId, ctx->isnull, ctx->notnull, ctx->isrange); + if (ctx->isrange) { + SFilterRangeNode *r = ctx->rs; + while (r) { + char str[256] = {0}; + int32_t tlen = 0; + if (FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_NULL)) { + strcat(str,"(NULL)"); + } else { + FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_EXCLUDE) ? strcat(str,"(") : strcat(str,"["); + converToStr(str + strlen(str), ctx->type, &r->ra.s, tlen > 32 ? 32 : tlen, &tlen); + FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_EXCLUDE) ? strcat(str,")") : strcat(str,"]"); + } + strcat(str, " - "); + if (FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_NULL)) { + strcat(str, "(NULL)"); + } else { + FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_EXCLUDE) ? strcat(str,"(") : strcat(str,"["); + converToStr(str + strlen(str), ctx->type, &r->ra.e, tlen > 32 ? 32 : tlen, &tlen); + FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_EXCLUDE) ? strcat(str,")") : strcat(str,"]"); + } + qDebug("range: %s", str); + + r = r->next; + } + } + } + } +} + +void filterFreeColInfo(void *data) { + SFilterColInfo* info = (SFilterColInfo *)data; + + if (info->info == NULL) { + return; + } + + if (info->type == RANGE_TYPE_VAR_HASH) { + //TODO + } else if (info->type == RANGE_TYPE_MR_CTX) { + filterFreeRangeCtx(info->info); + } else if (info->type == RANGE_TYPE_UNIT) { + taosArrayDestroy((SArray *)info->info); + } + + //NO NEED TO FREE UNIT + + info->type = 0; + info->info = NULL; +} + +void filterFreeColCtx(void *data) { + SFilterColCtx* ctx = (SFilterColCtx *)data; + + if (ctx->ctx) { + filterFreeRangeCtx(ctx->ctx); + } +} + + +void filterFreeGroupCtx(SFilterGroupCtx* gRes) { + if (gRes == NULL) { + return; + } + + tfree(gRes->colIdx); + + int16_t i = 0, j = 0; + + while (i < gRes->colNum) { + if (gRes->colInfo[j].info) { + filterFreeColInfo(&gRes->colInfo[j]); + ++i; + } + + ++j; + } + + tfree(gRes->colInfo); + tfree(gRes); +} + +void filterFreeField(SFilterField* field, int32_t type) { + if (field == NULL) { + return; + } + + if (!FILTER_GET_FLAG(field->flag, FLD_DESC_NO_FREE)) { + if (type == FLD_TYPE_VALUE) { + tVariantDestroy(field->desc); + } + + tfree(field->desc); + } + + if (!FILTER_GET_FLAG(field->flag, FLD_DATA_NO_FREE)) { + if (FILTER_GET_FLAG(field->flag, FLD_DATA_IS_HASH)) { + taosHashCleanup(field->data); + } else { + tfree(field->data); + } + } +} + +void filterFreePCtx(SFilterPCtx *pctx) { + taosHashCleanup(pctx->valHash); + taosHashCleanup(pctx->unitHash); +} + +void filterFreeInfo(SFilterInfo *info) { + CHK_RETV(info == NULL); + + tfree(info->cunits); + + for (int32_t i = 0; i < FLD_TYPE_MAX; ++i) { + for (uint16_t f = 0; f < info->fields[i].num; ++f) { + filterFreeField(&info->fields[i].fields[f], i); + } + + tfree(info->fields[i].fields); + } + + for (int32_t i = 0; i < info->groupNum; ++i) { + filterFreeGroup(&info->groups[i]); + } + + tfree(info->groups); + + tfree(info->units); + + tfree(info->unitRes); + + tfree(info->unitFlags); + + for (uint16_t i = 0; i < info->colRangeNum; ++i) { + filterFreeRangeCtx(info->colRange[i]); + } + + tfree(info->colRange); + + filterFreePCtx(&info->pctx); + + if (!FILTER_GET_FLAG(info->status, FI_STATUS_CLONED)) { + tfree(info); + } +} + +int32_t filterHandleValueExtInfo(SFilterUnit* unit, char extInfo) { + assert(extInfo > 0 || extInfo < 0); + + uint8_t optr = FILTER_UNIT_OPTR(unit); + switch (optr) { + case TSDB_RELATION_GREATER: + case TSDB_RELATION_GREATER_EQUAL: + unit->compare.optr = (extInfo > 0) ? FILTER_DUMMY_EMPTY_OPTR : TSDB_RELATION_NOTNULL; + break; + case TSDB_RELATION_LESS: + case TSDB_RELATION_LESS_EQUAL: + unit->compare.optr = (extInfo > 0) ? TSDB_RELATION_NOTNULL : FILTER_DUMMY_EMPTY_OPTR; + break; + case TSDB_RELATION_EQUAL: + unit->compare.optr = FILTER_DUMMY_EMPTY_OPTR; + break; + default: + assert(0); + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterInitValFieldData(SFilterInfo *info) { + for (uint16_t i = 0; i < info->unitNum; ++i) { + SFilterUnit* unit = &info->units[i]; + if (unit->right.type != FLD_TYPE_VALUE) { + assert(unit->compare.optr == TSDB_RELATION_ISNULL || unit->compare.optr == TSDB_RELATION_NOTNULL || unit->compare.optr == FILTER_DUMMY_EMPTY_OPTR); + continue; + } + + SFilterField* right = FILTER_UNIT_RIGHT_FIELD(info, unit); + + assert(FILTER_GET_FLAG(right->flag, FLD_TYPE_VALUE)); + + uint32_t type = FILTER_UNIT_DATA_TYPE(unit); + SFilterField* fi = right; + + tVariant* var = fi->desc; + + if (var == NULL) { + assert(fi->data != NULL); + continue; + } + + if (unit->compare.optr == TSDB_RELATION_IN) { + filterConvertSetFromBinary((void **)&fi->data, var->pz, var->nLen, type); + CHK_LRET(fi->data == NULL, TSDB_CODE_QRY_APP_ERROR, "failed to convert in param"); + + FILTER_SET_FLAG(fi->flag, FLD_DATA_IS_HASH); + + continue; + } + + if (type == TSDB_DATA_TYPE_BINARY) { + size_t len = (var->nType == TSDB_DATA_TYPE_BINARY || var->nType == TSDB_DATA_TYPE_NCHAR) ? var->nLen : MAX_NUM_STR_SIZE; + fi->data = calloc(1, len + 1 + VARSTR_HEADER_SIZE); + } else if (type == TSDB_DATA_TYPE_NCHAR) { + size_t len = (var->nType == TSDB_DATA_TYPE_BINARY || var->nType == TSDB_DATA_TYPE_NCHAR) ? var->nLen : MAX_NUM_STR_SIZE; + fi->data = calloc(1, (len + 1) * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE); + } else { + if (var->nType == TSDB_DATA_TYPE_VALUE_ARRAY) { //TIME RANGE + fi->data = calloc(var->nLen, tDataTypes[type].bytes); + for (int32_t a = 0; a < var->nLen; ++a) { + int64_t *v = taosArrayGet(var->arr, a); + assignVal((char *)fi->data + a * tDataTypes[type].bytes, (char *)v, 0, type); + } + + continue; + } else { + fi->data = calloc(1, sizeof(int64_t)); + } + } + + bool converted = false; + char extInfo = 0; + if (tVariantDumpEx(var, (char*)fi->data, type, true, &converted, &extInfo)) { + if (converted) { + filterHandleValueExtInfo(unit, extInfo); + + continue; + } + qError("dump value to type[%d] failed", type); + return TSDB_CODE_TSC_INVALID_OPERATION; + } + } + + return TSDB_CODE_SUCCESS; +} + + +bool filterDoCompare(__compar_fn_t func, uint8_t optr, void *left, void *right) { + int32_t ret = func(left, right); + + switch (optr) { + case TSDB_RELATION_EQUAL: { + return ret == 0; + } + case TSDB_RELATION_NOT_EQUAL: { + return ret != 0; + } + case TSDB_RELATION_GREATER_EQUAL: { + return ret >= 0; + } + case TSDB_RELATION_GREATER: { + return ret > 0; + } + case TSDB_RELATION_LESS_EQUAL: { + return ret <= 0; + } + case TSDB_RELATION_LESS: { + return ret < 0; + } + case TSDB_RELATION_LIKE: { + return ret == 0; + } + case TSDB_RELATION_IN: { + return ret == 1; + } + + default: + assert(false); + } + + return true; +} + + +int32_t filterAddUnitRange(SFilterInfo *info, SFilterUnit* u, SFilterRangeCtx *ctx, int32_t optr) { + int32_t type = FILTER_UNIT_DATA_TYPE(u); + uint8_t uoptr = FILTER_UNIT_OPTR(u); + void *val = FILTER_UNIT_VAL_DATA(info, u); + SFilterRange ra = {0}; + int64_t tmp = 0; + + switch (uoptr) { + case TSDB_RELATION_GREATER: + SIMPLE_COPY_VALUES(&ra.s, val); + FILTER_SET_FLAG(ra.sflag, RANGE_FLG_EXCLUDE); + FILTER_SET_FLAG(ra.eflag, RANGE_FLG_NULL); + break; + case TSDB_RELATION_GREATER_EQUAL: + SIMPLE_COPY_VALUES(&ra.s, val); + FILTER_SET_FLAG(ra.eflag, RANGE_FLG_NULL); + break; + case TSDB_RELATION_LESS: + SIMPLE_COPY_VALUES(&ra.e, val); + FILTER_SET_FLAG(ra.eflag, RANGE_FLG_EXCLUDE); + FILTER_SET_FLAG(ra.sflag, RANGE_FLG_NULL); + break; + case TSDB_RELATION_LESS_EQUAL: + SIMPLE_COPY_VALUES(&ra.e, val); + FILTER_SET_FLAG(ra.sflag, RANGE_FLG_NULL); + break; + case TSDB_RELATION_NOT_EQUAL: + assert(type == TSDB_DATA_TYPE_BOOL); + if (GET_INT8_VAL(val)) { + SIMPLE_COPY_VALUES(&ra.s, &tmp); + SIMPLE_COPY_VALUES(&ra.e, &tmp); + } else { + *(bool *)&tmp = true; + SIMPLE_COPY_VALUES(&ra.s, &tmp); + SIMPLE_COPY_VALUES(&ra.e, &tmp); + } + break; + case TSDB_RELATION_EQUAL: + SIMPLE_COPY_VALUES(&ra.s, val); + SIMPLE_COPY_VALUES(&ra.e, val); + break; + default: + assert(0); + } + + filterAddRange(ctx, &ra, optr); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterCompareRangeCtx(SFilterRangeCtx *ctx1, SFilterRangeCtx *ctx2, bool *equal) { + CHK_JMP(ctx1->status != ctx2->status); + CHK_JMP(ctx1->isnull != ctx2->isnull); + CHK_JMP(ctx1->notnull != ctx2->notnull); + CHK_JMP(ctx1->isrange != ctx2->isrange); + + SFilterRangeNode *r1 = ctx1->rs; + SFilterRangeNode *r2 = ctx2->rs; + + while (r1 && r2) { + CHK_JMP(r1->ra.sflag != r2->ra.sflag); + CHK_JMP(r1->ra.eflag != r2->ra.eflag); + CHK_JMP(r1->ra.s != r2->ra.s); + CHK_JMP(r1->ra.e != r2->ra.e); + + r1 = r1->next; + r2 = r2->next; + } + + CHK_JMP(r1 != r2); + + *equal = true; + + return TSDB_CODE_SUCCESS; + +_return: + *equal = false; + return TSDB_CODE_SUCCESS; +} + + +int32_t filterMergeUnits(SFilterInfo *info, SFilterGroupCtx* gRes, uint16_t colIdx, bool *empty) { + SArray* colArray = (SArray *)gRes->colInfo[colIdx].info; + int32_t size = (int32_t)taosArrayGetSize(colArray); + int32_t type = gRes->colInfo[colIdx].dataType; + SFilterRangeCtx* ctx = filterInitRangeCtx(type, 0); + + for (uint32_t i = 0; i < size; ++i) { + SFilterUnit* u = taosArrayGetP(colArray, i); + uint8_t optr = FILTER_UNIT_OPTR(u); + + filterAddRangeOptr(ctx, optr, TSDB_RELATION_AND, empty, NULL); + CHK_JMP(*empty); + + if (!FILTER_NO_MERGE_OPTR(optr)) { + filterAddUnitRange(info, u, ctx, TSDB_RELATION_AND); + CHK_JMP(MR_EMPTY_RES(ctx)); + } + } + + taosArrayDestroy(colArray); + + FILTER_PUSH_CTX(gRes->colInfo[colIdx], ctx); + + return TSDB_CODE_SUCCESS; + +_return: + + *empty = true; + + filterFreeRangeCtx(ctx); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterMergeGroupUnits(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t* gResNum) { + bool empty = false; + uint16_t *colIdx = malloc(info->fields[FLD_TYPE_COLUMN].num * sizeof(uint16_t)); + uint16_t colIdxi = 0; + uint16_t gResIdx = 0; + + for (uint16_t i = 0; i < info->groupNum; ++i) { + SFilterGroup* g = info->groups + i; + + gRes[gResIdx] = calloc(1, sizeof(SFilterGroupCtx)); + gRes[gResIdx]->colInfo = calloc(info->fields[FLD_TYPE_COLUMN].num, sizeof(SFilterColInfo)); + colIdxi = 0; + empty = false; + + for (uint16_t j = 0; j < g->unitNum; ++j) { + SFilterUnit* u = FILTER_GROUP_UNIT(info, g, j); + uint16_t cidx = FILTER_UNIT_COL_IDX(u); + + if (gRes[gResIdx]->colInfo[cidx].info == NULL) { + gRes[gResIdx]->colInfo[cidx].info = (SArray *)taosArrayInit(4, POINTER_BYTES); + colIdx[colIdxi++] = cidx; + ++gRes[gResIdx]->colNum; + } else { + if (!FILTER_NO_MERGE_DATA_TYPE(FILTER_UNIT_DATA_TYPE(u))) { + FILTER_SET_FLAG(info->status, FI_STATUS_REWRITE); + } + } + + FILTER_PUSH_UNIT(gRes[gResIdx]->colInfo[cidx], u); + } + + if (colIdxi > 1) { + qsort(colIdx, colIdxi, sizeof(uint16_t), getComparFunc(TSDB_DATA_TYPE_USMALLINT, 0)); + } + + for (uint16_t l = 0; l < colIdxi; ++l) { + int32_t type = gRes[gResIdx]->colInfo[colIdx[l]].dataType; + + if (FILTER_NO_MERGE_DATA_TYPE(type)) { + continue; + } + + filterMergeUnits(info, gRes[gResIdx], colIdx[l], &empty); + + if (empty) { + break; + } + } + + if (empty) { + FILTER_SET_FLAG(info->status, FI_STATUS_REWRITE); + filterFreeGroupCtx(gRes[gResIdx]); + gRes[gResIdx] = NULL; + + continue; + } + + gRes[gResIdx]->colNum = colIdxi; + FILTER_COPY_IDX(&gRes[gResIdx]->colIdx, colIdx, colIdxi); + ++gResIdx; + } + + tfree(colIdx); + + *gResNum = gResIdx; + + if (gResIdx == 0) { + FILTER_SET_FLAG(info->status, FI_STATUS_EMPTY); + } + + return TSDB_CODE_SUCCESS; +} + +void filterCheckColConflict(SFilterGroupCtx* gRes1, SFilterGroupCtx* gRes2, bool *conflict) { + uint16_t idx1 = 0, idx2 = 0, m = 0, n = 0; + bool equal = false; + + for (; m < gRes1->colNum; ++m) { + idx1 = gRes1->colIdx[m]; + + equal = false; + + for (; n < gRes2->colNum; ++n) { + idx2 = gRes2->colIdx[n]; + if (idx1 < idx2) { + *conflict = true; + return; + } + + if (idx1 > idx2) { + continue; + } + + if (FILTER_NO_MERGE_DATA_TYPE(gRes1->colInfo[idx1].dataType)) { + *conflict = true; + return; + } + + ++n; + equal = true; + break; + } + + if (!equal) { + *conflict = true; + return; + } + } + + *conflict = false; + return; +} + + +int32_t filterMergeTwoGroupsImpl(SFilterInfo *info, SFilterRangeCtx **ctx, int32_t optr, uint16_t cidx, SFilterGroupCtx* gRes1, SFilterGroupCtx* gRes2, bool *empty, bool *all) { + SFilterField *fi = FILTER_GET_COL_FIELD(info, cidx); + int32_t type = FILTER_GET_COL_FIELD_TYPE(fi); + + if ((*ctx) == NULL) { + *ctx = filterInitRangeCtx(type, 0); + } else { + filterReuseRangeCtx(*ctx, type, 0); + } + + assert(gRes2->colInfo[cidx].type == RANGE_TYPE_MR_CTX); + assert(gRes1->colInfo[cidx].type == RANGE_TYPE_MR_CTX); + + filterCopyRangeCtx(*ctx, gRes2->colInfo[cidx].info); + filterSourceRangeFromCtx(*ctx, gRes1->colInfo[cidx].info, optr, empty, all); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterMergeTwoGroups(SFilterInfo *info, SFilterGroupCtx** gRes1, SFilterGroupCtx** gRes2, bool *all) { + bool conflict = false; + + filterCheckColConflict(*gRes1, *gRes2, &conflict); + if (conflict) { + return TSDB_CODE_SUCCESS; + } + + FILTER_SET_FLAG(info->status, FI_STATUS_REWRITE); + + uint16_t idx1 = 0, idx2 = 0, m = 0, n = 0; + bool numEqual = (*gRes1)->colNum == (*gRes2)->colNum; + bool equal = false; + uint16_t equal1 = 0, equal2 = 0, merNum = 0; + SFilterRangeCtx *ctx = NULL; + SFilterColCtx colCtx = {0}; + SArray* colCtxs = taosArrayInit((*gRes2)->colNum, sizeof(SFilterColCtx)); + + for (; m < (*gRes1)->colNum; ++m) { + idx1 = (*gRes1)->colIdx[m]; + + for (; n < (*gRes2)->colNum; ++n) { + idx2 = (*gRes2)->colIdx[n]; + + if (idx1 > idx2) { + continue; + } + + assert(idx1 == idx2); + + ++merNum; + + filterMergeTwoGroupsImpl(info, &ctx, TSDB_RELATION_OR, idx1, *gRes1, *gRes2, NULL, all); + + CHK_JMP(*all); + + if (numEqual) { + if ((*gRes1)->colNum == 1) { + ++equal1; + colCtx.colIdx = idx1; + colCtx.ctx = ctx; + taosArrayPush(colCtxs, &colCtx); + break; + } else { + filterCompareRangeCtx(ctx, (*gRes1)->colInfo[idx1].info, &equal); + if (equal) { + ++equal1; + } + + filterCompareRangeCtx(ctx, (*gRes2)->colInfo[idx2].info, &equal); + if (equal) { + ++equal2; + } + + CHK_JMP(equal1 != merNum && equal2 != merNum); + colCtx.colIdx = idx1; + colCtx.ctx = ctx; + ctx = NULL; + taosArrayPush(colCtxs, &colCtx); + } + } else { + filterCompareRangeCtx(ctx, (*gRes1)->colInfo[idx1].info, &equal); + if (equal) { + ++equal1; + } + + CHK_JMP(equal1 != merNum); + colCtx.colIdx = idx1; + colCtx.ctx = ctx; + ctx = NULL; + taosArrayPush(colCtxs, &colCtx); + } + + ++n; + break; + } + } + + assert(merNum > 0); + + SFilterColInfo *colInfo = NULL; + assert (merNum == equal1 || merNum == equal2); + + filterFreeGroupCtx(*gRes2); + *gRes2 = NULL; + + assert(colCtxs && taosArrayGetSize(colCtxs) > 0); + + int32_t ctxSize = (int32_t)taosArrayGetSize(colCtxs); + SFilterColCtx *pctx = NULL; + + for (int32_t i = 0; i < ctxSize; ++i) { + pctx = taosArrayGet(colCtxs, i); + colInfo = &(*gRes1)->colInfo[pctx->colIdx]; + + filterFreeColInfo(colInfo); + FILTER_PUSH_CTX((*gRes1)->colInfo[pctx->colIdx], pctx->ctx); + } + + taosArrayDestroy(colCtxs); + + return TSDB_CODE_SUCCESS; + +_return: + + if (colCtxs) { + if (taosArrayGetSize(colCtxs) > 0) { + taosArrayDestroyEx(colCtxs, filterFreeColCtx); + } else { + taosArrayDestroy(colCtxs); + } + } + + filterFreeRangeCtx(ctx); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterMergeGroups(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t *gResNum) { + if (*gResNum <= 1) { + return TSDB_CODE_SUCCESS; + } + + qsort(gRes, *gResNum, POINTER_BYTES, filterCompareGroupCtx); + + int32_t pEnd = 0, cStart = 0, cEnd = 0; + uint16_t pColNum = 0, cColNum = 0; + int32_t movedNum = 0; + bool all = false; + + cColNum = gRes[0]->colNum; + + for (int32_t i = 1; i <= *gResNum; ++i) { + if (i < (*gResNum) && gRes[i]->colNum == cColNum) { + continue; + } + + cEnd = i - 1; + + movedNum = 0; + if (pColNum > 0) { + for (int32_t m = 0; m <= pEnd; ++m) { + for (int32_t n = cStart; n <= cEnd; ++n) { + assert(m < n); + filterMergeTwoGroups(info, &gRes[m], &gRes[n], &all); + + CHK_JMP(all); + + if (gRes[n] == NULL) { + if (n < ((*gResNum) - 1)) { + memmove(&gRes[n], &gRes[n+1], (*gResNum-n-1) * POINTER_BYTES); + } + + --cEnd; + --(*gResNum); + ++movedNum; + --n; + } + } + } + } + + for (int32_t m = cStart; m < cEnd; ++m) { + for (int32_t n = m + 1; n <= cEnd; ++n) { + assert(m < n); + filterMergeTwoGroups(info, &gRes[m], &gRes[n], &all); + + CHK_JMP(all); + + if (gRes[n] == NULL) { + if (n < ((*gResNum) - 1)) { + memmove(&gRes[n], &gRes[n+1], (*gResNum-n-1) * POINTER_BYTES); + } + + --cEnd; + --(*gResNum); + ++movedNum; + --n; + } + } + } + + pColNum = cColNum; + pEnd = cEnd; + + i -= movedNum; + + if (i >= (*gResNum)) { + break; + } + + cStart = i; + cEnd = i; + cColNum = gRes[i]->colNum; + } + + return TSDB_CODE_SUCCESS; + +_return: + + FILTER_SET_FLAG(info->status, FI_STATUS_ALL); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterConvertGroupFromArray(SFilterInfo *info, SArray* group) { + size_t groupSize = taosArrayGetSize(group); + + info->groupNum = (uint16_t)groupSize; + + if (info->groupNum > 0) { + info->groups = calloc(info->groupNum, sizeof(*info->groups)); + } + + for (size_t i = 0; i < groupSize; ++i) { + SFilterGroup *pg = taosArrayGet(group, i); + pg->unitFlags = calloc(pg->unitNum, sizeof(*pg->unitFlags)); + info->groups[i] = *pg; + } + + return TSDB_CODE_SUCCESS; +} + +int32_t filterRewrite(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t gResNum) { + if (!FILTER_GET_FLAG(info->status, FI_STATUS_REWRITE)) { + qDebug("no need rewrite"); + return TSDB_CODE_SUCCESS; + } + + SFilterInfo oinfo = *info; + + FILTER_SET_FLAG(oinfo.status, FI_STATUS_CLONED); + + SArray* group = taosArrayInit(FILTER_DEFAULT_GROUP_SIZE, sizeof(SFilterGroup)); + SFilterGroupCtx *res = NULL; + SFilterColInfo *colInfo = NULL; + int32_t optr = 0; + uint16_t uidx = 0; + + memset(info, 0, sizeof(*info)); + + info->colRangeNum = oinfo.colRangeNum; + info->colRange = oinfo.colRange; + oinfo.colRangeNum = 0; + oinfo.colRange = NULL; + + FILTER_SET_FLAG(info->options, FI_OPTION_NEED_UNIQE); + + filterInitUnitsFields(info); + + for (int32_t i = 0; i < gResNum; ++i) { + res = gRes[i]; + + optr = (res->colNum > 1) ? TSDB_RELATION_AND : TSDB_RELATION_OR; + + SFilterGroup ng = {0}; + + for (uint16_t m = 0; m < res->colNum; ++m) { + colInfo = &res->colInfo[res->colIdx[m]]; + if (FILTER_NO_MERGE_DATA_TYPE(colInfo->dataType)) { + assert(colInfo->type == RANGE_TYPE_UNIT); + int32_t usize = (int32_t)taosArrayGetSize((SArray *)colInfo->info); + + for (int32_t n = 0; n < usize; ++n) { + SFilterUnit* u = taosArrayGetP((SArray *)colInfo->info, n); + + filterAddUnitFromUnit(info, &oinfo, u, &uidx); + filterAddUnitToGroup(&ng, uidx); + } + + continue; + } + + assert(colInfo->type == RANGE_TYPE_MR_CTX); + + filterAddGroupUnitFromCtx(info, &oinfo, colInfo->info, res->colIdx[m], &ng, optr, group); + } + + if (ng.unitNum > 0) { + taosArrayPush(group, &ng); + } + } + + filterConvertGroupFromArray(info, group); + + taosArrayDestroy(group); + + filterFreeInfo(&oinfo); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterGenerateColRange(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t gResNum) { + uint16_t *idxs = NULL; + uint16_t colNum = 0; + SFilterGroupCtx *res = NULL; + uint16_t *idxNum = calloc(info->fields[FLD_TYPE_COLUMN].num, sizeof(*idxNum)); + + for (int32_t i = 0; i < gResNum; ++i) { + for (uint16_t m = 0; m < gRes[i]->colNum; ++m) { + SFilterColInfo *colInfo = &gRes[i]->colInfo[gRes[i]->colIdx[m]]; + if (FILTER_NO_MERGE_DATA_TYPE(colInfo->dataType)) { + continue; + } + + ++idxNum[gRes[i]->colIdx[m]]; + } + } + + for (uint16_t i = 0; i < info->fields[FLD_TYPE_COLUMN].num; ++i) { + if (idxNum[i] < gResNum) { + continue; + } + + assert(idxNum[i] == gResNum); + + if (idxs == NULL) { + idxs = calloc(info->fields[FLD_TYPE_COLUMN].num, sizeof(*idxs)); + } + + idxs[colNum++] = i; + } + + CHK_JMP(colNum <= 0); + + info->colRangeNum = colNum; + info->colRange = calloc(colNum, POINTER_BYTES); + + for (int32_t i = 0; i < gResNum; ++i) { + res = gRes[i]; + uint16_t n = 0; + + for (uint16_t m = 0; m < info->colRangeNum; ++m) { + for (; n < res->colNum; ++n) { + if (res->colIdx[n] < idxs[m]) { + continue; + } + + assert(res->colIdx[n] == idxs[m]); + + SFilterColInfo * colInfo = &res->colInfo[res->colIdx[n]]; + if (info->colRange[m] == NULL) { + info->colRange[m] = filterInitRangeCtx(colInfo->dataType, 0); + SFilterField* fi = FILTER_GET_COL_FIELD(info, res->colIdx[n]); + info->colRange[m]->colId = ((SSchema*)fi->desc)->colId; + } + + assert(colInfo->type == RANGE_TYPE_MR_CTX); + + bool all = false; + filterSourceRangeFromCtx(info->colRange[m], colInfo->info, TSDB_RELATION_OR, NULL, &all); + if (all) { + filterFreeRangeCtx(info->colRange[m]); + info->colRange[m] = NULL; + + if (m < (info->colRangeNum - 1)) { + memmove(&info->colRange[m], &info->colRange[m + 1], (info->colRangeNum - m - 1) * POINTER_BYTES); + memmove(&idxs[m], &idxs[m + 1], (info->colRangeNum - m - 1) * sizeof(*idxs)); + } + + --info->colRangeNum; + --m; + + CHK_JMP(info->colRangeNum <= 0); + } + + ++n; + break; + } + } + } + +_return: + tfree(idxNum); + tfree(idxs); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterPostProcessRange(SFilterInfo *info) { + for (uint16_t i = 0; i < info->colRangeNum; ++i) { + SFilterRangeCtx* ctx = info->colRange[i]; + SFilterRangeNode *r = ctx->rs; + while (r) { + r->rc.func = filterGetRangeCompFunc(r->ra.sflag, r->ra.eflag); + r = r->next; + } + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterGenerateComInfo(SFilterInfo *info) { + uint16_t n = 0; + + info->cunits = malloc(info->unitNum * sizeof(*info->cunits)); + + for (uint16_t i = 0; i < info->unitNum; ++i) { + SFilterUnit *unit = &info->units[i]; + + info->cunits[i].func = filterGetCompFuncIdx(FILTER_UNIT_DATA_TYPE(unit), unit->compare.optr); + info->cunits[i].rfunc = filterGetRangeCompFuncFromOptrs(unit->compare.optr, unit->compare.optr2); + info->cunits[i].optr = FILTER_UNIT_OPTR(unit); + info->cunits[i].colData = NULL; + + if (unit->right.type == FLD_TYPE_VALUE) { + info->cunits[i].valData = FILTER_UNIT_VAL_DATA(info, unit); + } else { + info->cunits[i].valData = NULL; + } + if (unit->right2.type == FLD_TYPE_VALUE) { + info->cunits[i].valData2 = FILTER_GET_VAL_FIELD_DATA(FILTER_GET_FIELD(info, unit->right2)); + } else { + info->cunits[i].valData2 = info->cunits[i].valData; + } + + info->cunits[i].dataSize = FILTER_UNIT_COL_SIZE(info, unit); + info->cunits[i].dataType = FILTER_UNIT_DATA_TYPE(unit); + } + + uint16_t cgroupNum = info->groupNum + 1; + + for (uint16_t i = 0; i < info->groupNum; ++i) { + cgroupNum += info->groups[i].unitNum; + } + + info->cgroups = malloc(cgroupNum * sizeof(*info->cgroups)); + + for (uint16_t i = 0; i < info->groupNum; ++i) { + info->cgroups[n++] = info->groups[i].unitNum; + + for (uint16_t m = 0; m < info->groups[i].unitNum; ++m) { + info->cgroups[n++] = info->groups[i].unitIdxs[m]; + } + } + + info->cgroups[n] = 0; + + return TSDB_CODE_SUCCESS; +} + +int32_t filterUpdateComUnits(SFilterInfo *info) { + for (uint16_t i = 0; i < info->unitNum; ++i) { + SFilterUnit *unit = &info->units[i]; + + info->cunits[i].colData = FILTER_UNIT_COL_DATA(info, unit, 0); + } + + return TSDB_CODE_SUCCESS; +} + + +static FORCE_INLINE bool filterExecuteImplAll(void *info, int32_t numOfRows, int8_t* p) { + return true; +} +static FORCE_INLINE bool filterExecuteImplEmpty(void *info, int32_t numOfRows, int8_t* p) { + return false; +} +static FORCE_INLINE bool filterExecuteImplIsNull(void *pinfo, int32_t numOfRows, int8_t* p) { + SFilterInfo *info = (SFilterInfo *)pinfo; + bool all = true; + + for (int32_t i = 0; i < numOfRows; ++i) { + uint16_t uidx = info->groups[0].unitIdxs[0]; + void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i; + p[i] = isNull(colData, info->cunits[uidx].dataType); + if (p[i] == 0) { + all = false; + } + } + + return all; +} +static FORCE_INLINE bool filterExecuteImplNotNull(void *pinfo, int32_t numOfRows, int8_t* p) { + SFilterInfo *info = (SFilterInfo *)pinfo; + bool all = true; + + for (int32_t i = 0; i < numOfRows; ++i) { + uint16_t uidx = info->groups[0].unitIdxs[0]; + void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i; + p[i] = !isNull(colData, info->cunits[uidx].dataType); + if (p[i] == 0) { + all = false; + } + } + + return all; +} + +bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t* p) { + SFilterInfo *info = (SFilterInfo *)pinfo; + bool all = true; + uint16_t dataSize = info->cunits[0].dataSize; + char *colData = (char *)info->cunits[0].colData; + rangeCompFunc rfunc = gRangeCompare[info->cunits[0].rfunc]; + void *valData = info->cunits[0].valData; + void *valData2 = info->cunits[0].valData2; + __compar_fn_t func = gDataCompare[info->cunits[0].func]; + + for (int32_t i = 0; i < numOfRows; ++i) { + if (isNull(colData, info->cunits[0].dataType)) { + all = false; + colData += dataSize; + continue; + } + + p[i] = (*rfunc)(colData, colData, valData, valData2, func); + + if (p[i] == 0) { + all = false; + } + + colData += dataSize; + } + + return all; +} + +bool filterExecuteImplMisc(void *pinfo, int32_t numOfRows, int8_t* p) { + SFilterInfo *info = (SFilterInfo *)pinfo; + bool all = true; + + for (int32_t i = 0; i < numOfRows; ++i) { + uint16_t uidx = info->groups[0].unitIdxs[0]; + void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i; + if (isNull(colData, info->cunits[uidx].dataType)) { + all = false; + continue; + } + + p[i] = filterDoCompare(gDataCompare[info->cunits[uidx].func], info->cunits[uidx].optr, colData, info->cunits[uidx].valData); + + if (p[i] == 0) { + all = false; + } + } + + return all; +} + + +bool filterExecuteImpl(void *pinfo, int32_t numOfRows, int8_t* p) { + SFilterInfo *info = (SFilterInfo *)pinfo; + bool all = true; + + for (int32_t i = 0; i < numOfRows; ++i) { + //FILTER_UNIT_CLR_F(info); + + for (uint32_t g = 0; g < info->groupNum; ++g) { + SFilterGroup *group = &info->groups[g]; + for (uint32_t u = 0; u < group->unitNum; ++u) { + uint16_t uidx = group->unitIdxs[u]; + SFilterComUnit *cunit = &info->cunits[uidx]; + void *colData = (char *)cunit->colData + cunit->dataSize * i; + + //if (FILTER_UNIT_GET_F(info, uidx)) { + // p[i] = FILTER_UNIT_GET_R(info, uidx); + //} else { + uint8_t optr = cunit->optr; + + if (isNull(colData, cunit->dataType)) { + p[i] = optr == TSDB_RELATION_ISNULL ? true : false; + } else { + if (optr == TSDB_RELATION_NOTNULL) { + p[i] = 1; + } else if (optr == TSDB_RELATION_ISNULL) { + p[i] = 0; + } else if (cunit->rfunc >= 0) { + p[i] = (*gRangeCompare[cunit->rfunc])(colData, colData, cunit->valData, cunit->valData2, gDataCompare[cunit->func]); + } else { + p[i] = filterDoCompare(gDataCompare[cunit->func], cunit->optr, colData, cunit->valData); + } + + //FILTER_UNIT_SET_R(info, uidx, p[i]); + //FILTER_UNIT_SET_F(info, uidx); + } + + if (p[i] == 0) { + break; + } + } + + if (p[i]) { + break; + } + } + + if (p[i] == 0) { + all = false; + } + } + + return all; +} + +FORCE_INLINE bool filterExecute(SFilterInfo *info, int32_t numOfRows, int8_t* p) { + return (*info->func)(info, numOfRows, p); +} + +int32_t filterSetExecFunc(SFilterInfo *info) { + if (FILTER_ALL_RES(info)) { + info->func = filterExecuteImplAll; + return TSDB_CODE_SUCCESS; + } + + if (FILTER_EMPTY_RES(info)) { + info->func = filterExecuteImplEmpty; + return TSDB_CODE_SUCCESS; + } + + if (info->unitNum > 1) { + info->func = filterExecuteImpl; + return TSDB_CODE_SUCCESS; + } + + if (info->units[0].compare.optr == TSDB_RELATION_ISNULL) { + info->func = filterExecuteImplIsNull; + return TSDB_CODE_SUCCESS; + } + + if (info->units[0].compare.optr == TSDB_RELATION_NOTNULL) { + info->func = filterExecuteImplNotNull; + return TSDB_CODE_SUCCESS; + } + + if (info->cunits[0].rfunc >= 0) { + info->func = filterExecuteImplRange; + return TSDB_CODE_SUCCESS; + } + + info->func = filterExecuteImplMisc; + return TSDB_CODE_SUCCESS; +} + + + +int32_t filterPreprocess(SFilterInfo *info) { + SFilterGroupCtx** gRes = calloc(info->groupNum, sizeof(SFilterGroupCtx *)); + int32_t gResNum = 0; + + filterMergeGroupUnits(info, gRes, &gResNum); + + filterMergeGroups(info, gRes, &gResNum); + + if (FILTER_GET_FLAG(info->status, FI_STATUS_ALL)) { + qInfo("Final - FilterInfo: [ALL]"); + goto _return; + } + + + if (FILTER_GET_FLAG(info->status, FI_STATUS_EMPTY)) { + qInfo("Final - FilterInfo: [EMPTY]"); + goto _return; + } + + filterGenerateColRange(info, gRes, gResNum); + + filterDumpInfoToString(info, "Final", 1); + + filterPostProcessRange(info); + + filterRewrite(info, gRes, gResNum); + + filterGenerateComInfo(info); + +_return: + + filterSetExecFunc(info); + + for (int32_t i = 0; i < gResNum; ++i) { + filterFreeGroupCtx(gRes[i]); + } + + tfree(gRes); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterSetColFieldData(SFilterInfo *info, int16_t colId, void *data) { + CHK_LRET(info == NULL, TSDB_CODE_QRY_APP_ERROR, "info NULL"); + CHK_LRET(info->fields[FLD_TYPE_COLUMN].num <= 0, TSDB_CODE_QRY_APP_ERROR, "no column fileds"); + + if (FILTER_ALL_RES(info) || FILTER_EMPTY_RES(info)) { + return TSDB_CODE_SUCCESS; + } + + for (uint16_t i = 0; i < info->fields[FLD_TYPE_COLUMN].num; ++i) { + SFilterField* fi = &info->fields[FLD_TYPE_COLUMN].fields[i]; + SSchema* sch = fi->desc; + if (sch->colId == colId) { + fi->data = data; + + break; + } + } + + filterUpdateComUnits(info); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterInitFromTree(tExprNode* tree, SFilterInfo **pinfo, uint32_t options) { + int32_t code = TSDB_CODE_SUCCESS; + SFilterInfo *info = NULL; + + CHK_LRET(tree == NULL || pinfo == NULL, TSDB_CODE_QRY_APP_ERROR, "invalid param"); + + if (*pinfo == NULL) { + *pinfo = calloc(1, sizeof(SFilterInfo)); + } + + info = *pinfo; + + info->options = options; + + SArray* group = taosArrayInit(FILTER_DEFAULT_GROUP_SIZE, sizeof(SFilterGroup)); + + filterInitUnitsFields(info); + + code = filterTreeToGroup(tree, info, group); + + ERR_JRET(code); + + filterConvertGroupFromArray(info, group); + + ERR_JRET(filterInitValFieldData(info)); + + if (!FILTER_GET_FLAG(info->options, FI_OPTION_NO_REWRITE)) { + filterDumpInfoToString(info, "Before preprocess", 0); + + ERR_JRET(filterPreprocess(info)); + + CHK_JMP(FILTER_GET_FLAG(info->status, FI_STATUS_ALL)); + + if (FILTER_GET_FLAG(info->status, FI_STATUS_EMPTY)) { + taosArrayDestroy(group); + return code; + } + + //ERR_JRET(filterInitUnitFunc(info)); + } + + info->unitRes = malloc(info->unitNum * sizeof(*info->unitRes)); + info->unitFlags = malloc(info->unitNum * sizeof(*info->unitFlags)); + + filterDumpInfoToString(info, "Final", 0); + + taosArrayDestroy(group); + + return code; + +_return: + qInfo("No filter, code:%d", code); + + taosArrayDestroy(group); + + filterFreeInfo(*pinfo); + + *pinfo = NULL; + + return code; +} + + + + +bool filterRangeExecute(SFilterInfo *info, SDataStatis *pDataStatis, int32_t numOfCols, int32_t numOfRows) { + if (FILTER_EMPTY_RES(info)) { + return false; + } + + if (FILTER_ALL_RES(info)) { + return true; + } + + bool ret = true; + void *minVal, *maxVal; + + for (int32_t k = 0; k < info->colRangeNum; ++k) { + int32_t index = -1; + SFilterRangeCtx *ctx = info->colRange[k]; + for(int32_t i = 0; i < numOfCols; ++i) { + if (pDataStatis[i].colId == ctx->colId) { + index = i; + break; + } + } + + // no statistics data, load the true data block + if (index == -1) { + return true; + } + + // not support pre-filter operation on binary/nchar data type + if (FILTER_NO_MERGE_DATA_TYPE(ctx->type)) { + return true; + } + + if ((pDataStatis[index].numOfNull <= 0) && (ctx->isnull && !ctx->notnull && !ctx->isrange)) { + return false; + } + + // all data in current column are NULL, no need to check its boundary value + if (pDataStatis[index].numOfNull == numOfRows) { + + // if isNULL query exists, load the null data column + if ((ctx->notnull || ctx->isrange) && (!ctx->isnull)) { + return false; + } + + continue; + } + + SDataStatis* pDataBlockst = &pDataStatis[index]; + + SFilterRangeNode *r = ctx->rs; + + if (ctx->type == TSDB_DATA_TYPE_FLOAT) { + float minv = (float)(*(double *)(&pDataBlockst->min)); + float maxv = (float)(*(double *)(&pDataBlockst->max)); + + minVal = &minv; + maxVal = &maxv; + } else { + minVal = &pDataBlockst->min; + maxVal = &pDataBlockst->max; + } + + while (r) { + ret = r->rc.func(minVal, maxVal, &r->rc.s, &r->rc.e, ctx->pCompareFunc); + if (ret) { + break; + } + r = r->next; + } + + CHK_RET(!ret, ret); + } + + return ret; +} + + + +int32_t filterGetTimeRange(SFilterInfo *info, STimeWindow *win) { + SFilterRange ra = {0}; + SFilterRangeCtx *prev = filterInitRangeCtx(TSDB_DATA_TYPE_TIMESTAMP, FI_OPTION_TIMESTAMP); + SFilterRangeCtx *tmpc = filterInitRangeCtx(TSDB_DATA_TYPE_TIMESTAMP, FI_OPTION_TIMESTAMP); + SFilterRangeCtx *cur = NULL; + int32_t num = 0; + int32_t optr = 0; + int32_t code = 0; + bool empty = false, all = false; + + for (int32_t i = 0; i < info->groupNum; ++i) { + SFilterGroup *group = &info->groups[i]; + if (group->unitNum > 1) { + cur = tmpc; + optr = TSDB_RELATION_AND; + } else { + cur = prev; + optr = TSDB_RELATION_OR; + } + + for (int32_t u = 0; u < group->unitNum; ++u) { + uint16_t uidx = group->unitIdxs[u]; + SFilterUnit *unit = &info->units[uidx]; + + uint8_t raOptr = FILTER_UNIT_OPTR(unit); + + filterAddRangeOptr(cur, raOptr, TSDB_RELATION_AND, &empty, NULL); + CHK_JMP(empty); + + if (FILTER_NO_MERGE_OPTR(raOptr)) { + continue; + } + + SFilterField *right = FILTER_UNIT_RIGHT_FIELD(info, unit); + void *s = FILTER_GET_VAL_FIELD_DATA(right); + void *e = FILTER_GET_VAL_FIELD_DATA(right) + tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes; + + SIMPLE_COPY_VALUES(&ra.s, s); + SIMPLE_COPY_VALUES(&ra.e, e); + + filterAddRange(cur, &ra, optr); + } + + if (cur->notnull) { + prev->notnull = true; + break; + } + + if (group->unitNum > 1) { + filterSourceRangeFromCtx(prev, cur, TSDB_RELATION_OR, &empty, &all); + filterResetRangeCtx(cur); + if (all) { + break; + } + } + } + + if (prev->notnull) { + *win = TSWINDOW_INITIALIZER; + } else { + filterGetRangeNum(prev, &num); + if (num > 1) { + qError("only one time range accepted, num:%d", num); + ERR_JRET(TSDB_CODE_QRY_INVALID_TIME_CONDITION); + } + + CHK_JMP(num < 1); + + SFilterRange tra; + filterGetRangeRes(prev, &tra); + win->skey = tra.s; + win->ekey = tra.e; + } + + filterFreeRangeCtx(prev); + filterFreeRangeCtx(tmpc); + + qDebug("qFilter time range:[%"PRId64 "]-[%"PRId64 "]", win->skey, win->ekey); + return TSDB_CODE_SUCCESS; + +_return: + + *win = TSWINDOW_DESC_INITIALIZER; + + filterFreeRangeCtx(prev); + filterFreeRangeCtx(tmpc); + + qDebug("qFilter time range:[%"PRId64 "]-[%"PRId64 "]", win->skey, win->ekey); + + return code; +} + + +int32_t filterConverNcharColumns(SFilterInfo* info, int32_t rows, bool *gotNchar) { + for (uint16_t i = 0; i < info->fields[FLD_TYPE_COLUMN].num; ++i) { + SFilterField* fi = &info->fields[FLD_TYPE_COLUMN].fields[i]; + int32_t type = FILTER_GET_COL_FIELD_TYPE(fi); + if (type == TSDB_DATA_TYPE_NCHAR) { + SFilterField nfi = {0}; + nfi.desc = fi->desc; + int32_t bytes = FILTER_GET_COL_FIELD_SIZE(fi); + nfi.data = malloc(rows * bytes); + int32_t bufSize = bytes - VARSTR_HEADER_SIZE; + for (int32_t j = 0; j < rows; ++j) { + char *src = FILTER_GET_COL_FIELD_DATA(fi, j); + char *dst = FILTER_GET_COL_FIELD_DATA(&nfi, j); + int32_t len = 0; + taosMbsToUcs4(varDataVal(src), varDataLen(src), varDataVal(dst), bufSize, &len); + varDataLen(dst) = len; + } + + fi->data = nfi.data; + + *gotNchar = true; + } + } + + if (*gotNchar) { + filterUpdateComUnits(info); + } + + return TSDB_CODE_SUCCESS; +} + +int32_t filterFreeNcharColumns(SFilterInfo* info) { + for (uint16_t i = 0; i < info->fields[FLD_TYPE_COLUMN].num; ++i) { + SFilterField* fi = &info->fields[FLD_TYPE_COLUMN].fields[i]; + int32_t type = FILTER_GET_COL_FIELD_TYPE(fi); + if (type == TSDB_DATA_TYPE_NCHAR) { + tfree(fi->data); + } + } + + return TSDB_CODE_SUCCESS; +} + + + + + diff --git a/src/query/src/qSqlParser.c b/src/query/src/qSqlParser.c index a512c7bf1a..011892fe93 100644 --- a/src/query/src/qSqlParser.c +++ b/src/query/src/qSqlParser.c @@ -423,6 +423,9 @@ tSqlExpr *tSqlExprClone(tSqlExpr *pSrc) { pExpr->pRight = tSqlExprClone(pSrc->pRight); } + memset(&pExpr->value, 0, sizeof(pExpr->value)); + tVariantAssign(&pExpr->value, &pSrc->value); + //we don't clone paramList now because clone is only used for between/and assert(pSrc->Expr.paramList == NULL); return pExpr; @@ -478,9 +481,7 @@ static void doDestroySqlExprNode(tSqlExpr *pExpr) { return; } - if (pExpr->tokenId == TK_STRING) { - tVariantDestroy(&pExpr->value); - } + tVariantDestroy(&pExpr->value); tSqlExprListDestroy(pExpr->Expr.paramList); free(pExpr); @@ -954,6 +955,8 @@ void SqlInfoDestroy(SSqlInfo *pInfo) { taosArrayDestroy(pInfo->pAlterInfo->pAddColumns); tfree(pInfo->pAlterInfo->tagData.data); tfree(pInfo->pAlterInfo); + } else if (pInfo->type == TSDB_SQL_COMPACT_VNODE) { + tSqlExprListDestroy(pInfo->list); } else { if (pInfo->pMiscInfo != NULL) { taosArrayDestroy(pInfo->pMiscInfo->a); diff --git a/src/query/src/queryMain.c b/src/query/src/queryMain.c index 878698752f..1a9c057ef0 100644 --- a/src/query/src/queryMain.c +++ b/src/query/src/queryMain.c @@ -103,6 +103,12 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, qi } } + if (param.colCond != NULL) { + if ((code = createQueryFilter(param.colCond, pQueryMsg->colCondLen, ¶m.pFilters)) != TSDB_CODE_SUCCESS) { + goto _over; + } + } + param.pGroupbyExpr = createGroupbyExprFromMsg(pQueryMsg, param.pGroupColIndex, &code); if ((param.pGroupbyExpr == NULL && pQueryMsg->numOfGroupCols != 0) || code != TSDB_CODE_SUCCESS) { goto _over; @@ -162,13 +168,19 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, qi assert(pQueryMsg->stableQuery == isSTableQuery); (*pQInfo) = createQInfoImpl(pQueryMsg, param.pGroupbyExpr, param.pExprs, param.pSecExprs, &tableGroupInfo, - param.pTagColumnInfo, vgId, param.sql, qId, param.pUdfInfo); + param.pTagColumnInfo, param.pFilters, vgId, param.sql, qId, param.pUdfInfo); param.sql = NULL; param.pExprs = NULL; param.pSecExprs = NULL; param.pGroupbyExpr = NULL; param.pTagColumnInfo = NULL; + param.pFilters = NULL; + + if ((*pQInfo) == NULL) { + code = TSDB_CODE_QRY_OUT_OF_MEMORY; + goto _over; + } param.pUdfInfo = NULL; code = initQInfo(&pQueryMsg->tsBuf, tsdb, NULL, *pQInfo, ¶m, (char*)pQueryMsg, pQueryMsg->prevResultLen, NULL); @@ -178,6 +190,8 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, qi taosArrayDestroy(param.pGroupbyExpr->columnInfo); } + tfree(param.colCond); + destroyUdfInfo(param.pUdfInfo); taosArrayDestroy(param.pTableIdList); @@ -190,6 +204,8 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, qi freeColumnFilterInfo(column->flist.filterInfo, column->flist.numOfFilters); } + filterFreeInfo(param.pFilters); + //pQInfo already freed in initQInfo, but *pQInfo may not pointer to null; if (code != TSDB_CODE_SUCCESS) { *pQInfo = NULL; diff --git a/src/query/src/sql.c b/src/query/src/sql.c index dc5123b7fb..09be4c0cf0 100644 --- a/src/query/src/sql.c +++ b/src/query/src/sql.c @@ -23,7 +23,9 @@ ** input grammar file: */ #include +#include /************ Begin %include sections from the grammar ************************/ +#line 23 "sql.y" #include #include @@ -36,6 +38,7 @@ #include "ttokendef.h" #include "tutil.h" #include "tvariant.h" +#line 42 "sql.c" /**************** End of %include directives **********************************/ /* These constants specify the various numeric values for terminal symbols ** in a format understandable to "makeheaders". This section is blank unless @@ -76,8 +79,10 @@ ** zero the stack is dynamically sized using realloc() ** ParseARG_SDECL A static variable declaration for the %extra_argument ** ParseARG_PDECL A parameter declaration for the %extra_argument +** ParseARG_PARAM Code to pass %extra_argument as a subroutine parameter ** ParseARG_STORE Code to store %extra_argument into yypParser ** ParseARG_FETCH Code to extract %extra_argument from yypParser +** ParseCTX_* As ParseARG_ except for %extra_context ** YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. ** YYNSTATE the combined number of states. @@ -97,39 +102,46 @@ #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int -#define YYNOCODE 277 +#define YYNOCODE 275 #define YYACTIONTYPE unsigned short int #define ParseTOKENTYPE SStrToken typedef union { int yyinit; ParseTOKENTYPE yy0; - TAOS_FIELD yy31; - int yy52; - SLimitVal yy126; - SWindowStateVal yy144; - SCreateTableSql* yy158; - SCreateDbInfo yy214; - SSessionWindowVal yy259; - tSqlExpr* yy370; - SRelationInfo* yy412; - SCreatedTableInfo yy432; - SSqlNode* yy464; - int64_t yy501; - tVariant yy506; - SIntervalVal yy520; - SArray* yy525; - SCreateAcctInfo yy547; + SSessionWindowVal yy39; + SCreateDbInfo yy42; + int yy43; + tSqlExpr* yy46; + SCreatedTableInfo yy96; + SArray* yy131; + TAOS_FIELD yy163; + SSqlNode* yy256; + SCreateTableSql* yy272; + SLimitVal yy284; + SCreateAcctInfo yy341; + int64_t yy459; + tVariant yy516; + SIntervalVal yy530; + SWindowStateVal yy538; + SRelationInfo* yy544; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 #endif #define ParseARG_SDECL SSqlInfo* pInfo; #define ParseARG_PDECL ,SSqlInfo* pInfo -#define ParseARG_FETCH SSqlInfo* pInfo = yypParser->pInfo -#define ParseARG_STORE yypParser->pInfo = pInfo +#define ParseARG_PARAM ,pInfo +#define ParseARG_FETCH SSqlInfo* pInfo=yypParser->pInfo; +#define ParseARG_STORE yypParser->pInfo=pInfo; +#define ParseCTX_SDECL +#define ParseCTX_PDECL +#define ParseCTX_PARAM +#define ParseCTX_FETCH +#define ParseCTX_STORE #define YYFALLBACK 1 #define YYNSTATE 362 #define YYNRULE 289 +#define YYNRULE_WITH_ACTION 289 #define YYNTOKEN 195 #define YY_MAX_SHIFT 361 #define YY_MIN_SHIFTREDUCE 567 @@ -140,6 +152,7 @@ typedef union { #define YY_MIN_REDUCE 859 #define YY_MAX_REDUCE 1147 /************* End control #defines *******************************************/ +#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) /* Define the yytestcase() macro to be a no-op if is not already defined ** otherwise. @@ -204,249 +217,249 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (753) +#define YY_ACTTAB_COUNT (754) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 206, 618, 245, 618, 618, 97, 244, 228, 359, 619, - /* 10 */ 1123, 619, 619, 56, 57, 152, 60, 61, 654, 1027, - /* 20 */ 248, 50, 1036, 59, 317, 64, 62, 65, 63, 984, - /* 30 */ 249, 982, 983, 55, 54, 231, 985, 53, 52, 51, - /* 40 */ 986, 1002, 987, 988, 53, 52, 51, 568, 569, 570, + /* 0 */ 207, 618, 246, 618, 618, 245, 360, 229, 160, 619, + /* 10 */ 1123, 619, 619, 56, 57, 1036, 60, 61, 857, 361, + /* 20 */ 249, 50, 618, 59, 318, 64, 62, 65, 63, 984, + /* 30 */ 619, 982, 983, 55, 54, 160, 985, 53, 52, 51, + /* 40 */ 986, 153, 987, 988, 356, 945, 654, 568, 569, 570, /* 50 */ 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, - /* 60 */ 581, 360, 206, 257, 229, 159, 206, 56, 57, 37, - /* 70 */ 60, 61, 1124, 174, 248, 50, 1124, 59, 317, 64, - /* 80 */ 62, 65, 63, 277, 276, 29, 79, 55, 54, 1033, - /* 90 */ 206, 53, 52, 51, 56, 57, 315, 60, 61, 234, - /* 100 */ 1124, 248, 50, 1014, 59, 317, 64, 62, 65, 63, - /* 110 */ 358, 357, 144, 230, 55, 54, 85, 1011, 53, 52, - /* 120 */ 51, 56, 58, 240, 60, 61, 347, 1014, 248, 50, - /* 130 */ 94, 59, 317, 64, 62, 65, 63, 794, 1073, 242, - /* 140 */ 289, 55, 54, 1014, 618, 53, 52, 51, 57, 23, - /* 150 */ 60, 61, 619, 44, 248, 50, 1000, 59, 317, 64, - /* 160 */ 62, 65, 63, 997, 998, 34, 1001, 55, 54, 857, - /* 170 */ 361, 53, 52, 51, 43, 313, 354, 353, 312, 311, - /* 180 */ 310, 352, 309, 308, 307, 351, 306, 350, 349, 976, - /* 190 */ 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, - /* 200 */ 974, 975, 977, 978, 60, 61, 24, 1008, 248, 50, - /* 210 */ 257, 59, 317, 64, 62, 65, 63, 1027, 122, 1027, - /* 220 */ 175, 55, 54, 37, 209, 53, 52, 51, 247, 809, - /* 230 */ 347, 215, 798, 232, 801, 270, 804, 135, 134, 214, - /* 240 */ 315, 247, 809, 322, 85, 798, 14, 801, 37, 804, - /* 250 */ 93, 159, 726, 241, 203, 723, 800, 724, 803, 725, - /* 260 */ 226, 227, 257, 16, 318, 15, 37, 238, 5, 40, - /* 270 */ 178, 1011, 1012, 226, 227, 177, 103, 108, 99, 107, - /* 280 */ 96, 44, 204, 253, 254, 210, 64, 62, 65, 63, - /* 290 */ 355, 945, 159, 302, 55, 54, 1010, 251, 53, 52, - /* 300 */ 51, 1013, 78, 269, 256, 77, 120, 114, 125, 66, - /* 310 */ 239, 702, 222, 124, 1011, 130, 133, 123, 37, 197, - /* 320 */ 195, 193, 66, 127, 1072, 37, 192, 139, 138, 137, - /* 330 */ 136, 799, 159, 802, 37, 43, 999, 354, 353, 337, - /* 340 */ 336, 37, 352, 262, 810, 805, 351, 37, 350, 349, - /* 350 */ 37, 806, 266, 265, 742, 55, 54, 810, 805, 53, - /* 360 */ 52, 51, 326, 291, 806, 90, 1011, 727, 728, 327, - /* 370 */ 37, 37, 252, 1011, 250, 807, 325, 324, 328, 258, - /* 380 */ 82, 255, 1011, 332, 331, 329, 150, 148, 147, 1011, - /* 390 */ 907, 333, 83, 917, 334, 1011, 908, 188, 1011, 271, - /* 400 */ 188, 739, 92, 188, 70, 91, 1, 176, 3, 189, - /* 410 */ 775, 776, 758, 38, 335, 339, 80, 273, 1011, 1011, - /* 420 */ 766, 767, 73, 712, 294, 33, 154, 9, 714, 273, - /* 430 */ 296, 713, 796, 830, 67, 26, 246, 38, 38, 746, - /* 440 */ 811, 319, 67, 76, 95, 67, 71, 25, 1120, 617, - /* 450 */ 808, 132, 131, 113, 25, 112, 1119, 6, 297, 18, - /* 460 */ 1118, 17, 74, 25, 731, 729, 732, 730, 797, 20, - /* 470 */ 1083, 19, 119, 224, 118, 701, 22, 225, 21, 207, - /* 480 */ 208, 211, 205, 212, 213, 217, 218, 219, 216, 202, - /* 490 */ 1143, 1082, 1135, 236, 267, 1079, 1078, 237, 338, 151, - /* 500 */ 1035, 1046, 47, 1065, 1043, 149, 1064, 1025, 1028, 1044, - /* 510 */ 274, 1048, 153, 170, 158, 1009, 278, 285, 171, 1007, - /* 520 */ 172, 233, 166, 280, 161, 757, 160, 173, 162, 922, - /* 530 */ 163, 299, 300, 301, 304, 305, 282, 292, 45, 290, - /* 540 */ 75, 200, 288, 813, 272, 41, 72, 49, 316, 164, - /* 550 */ 916, 323, 1142, 110, 1141, 1138, 286, 179, 330, 1134, - /* 560 */ 284, 116, 1133, 1130, 180, 281, 942, 42, 39, 46, - /* 570 */ 201, 904, 279, 126, 303, 902, 128, 129, 900, 899, - /* 580 */ 259, 191, 897, 896, 895, 894, 893, 892, 891, 194, - /* 590 */ 196, 888, 886, 884, 882, 198, 879, 199, 48, 81, - /* 600 */ 86, 348, 283, 1066, 121, 340, 341, 342, 343, 344, - /* 610 */ 223, 345, 346, 356, 855, 243, 298, 260, 261, 854, - /* 620 */ 263, 220, 221, 264, 853, 836, 104, 921, 920, 105, - /* 630 */ 835, 268, 273, 10, 293, 734, 275, 84, 30, 898, - /* 640 */ 890, 183, 182, 943, 187, 181, 184, 185, 2, 140, - /* 650 */ 186, 141, 142, 889, 4, 143, 980, 881, 87, 944, - /* 660 */ 759, 165, 167, 168, 169, 880, 155, 157, 768, 156, - /* 670 */ 235, 762, 88, 89, 990, 764, 287, 31, 11, 32, - /* 680 */ 12, 13, 27, 295, 28, 96, 98, 101, 35, 100, - /* 690 */ 632, 36, 102, 667, 665, 664, 663, 661, 660, 659, - /* 700 */ 656, 314, 622, 106, 7, 320, 812, 321, 8, 109, - /* 710 */ 814, 111, 68, 69, 115, 704, 703, 38, 117, 700, - /* 720 */ 648, 646, 638, 644, 640, 642, 636, 634, 670, 669, - /* 730 */ 668, 666, 662, 658, 657, 190, 620, 585, 583, 859, + /* 60 */ 581, 151, 207, 230, 907, 207, 56, 57, 1027, 60, + /* 70 */ 61, 189, 1124, 249, 50, 1124, 59, 318, 64, 62, + /* 80 */ 65, 63, 1072, 1033, 271, 79, 55, 54, 3, 190, + /* 90 */ 53, 52, 51, 56, 57, 250, 60, 61, 702, 1027, + /* 100 */ 249, 50, 29, 59, 318, 64, 62, 65, 63, 91, + /* 110 */ 278, 277, 37, 55, 54, 232, 94, 53, 52, 51, + /* 120 */ 235, 120, 114, 125, 1014, 241, 338, 337, 124, 1014, + /* 130 */ 130, 133, 123, 56, 58, 794, 60, 61, 127, 85, + /* 140 */ 249, 50, 92, 59, 318, 64, 62, 65, 63, 997, + /* 150 */ 998, 34, 1001, 55, 54, 207, 80, 53, 52, 51, + /* 160 */ 57, 1010, 60, 61, 316, 1124, 249, 50, 263, 59, + /* 170 */ 318, 64, 62, 65, 63, 37, 44, 267, 266, 55, + /* 180 */ 54, 348, 243, 53, 52, 51, 1014, 160, 43, 314, + /* 190 */ 355, 354, 313, 312, 311, 353, 310, 309, 308, 352, + /* 200 */ 307, 351, 350, 976, 964, 965, 966, 967, 968, 969, + /* 210 */ 970, 971, 972, 973, 974, 975, 977, 978, 60, 61, + /* 220 */ 231, 160, 249, 50, 1011, 59, 318, 64, 62, 65, + /* 230 */ 63, 1008, 1027, 24, 258, 55, 54, 1000, 97, 53, + /* 240 */ 52, 51, 252, 248, 809, 175, 1013, 798, 233, 801, + /* 250 */ 210, 804, 248, 809, 1143, 917, 798, 216, 801, 292, + /* 260 */ 804, 90, 189, 135, 134, 215, 258, 55, 54, 323, + /* 270 */ 85, 53, 52, 51, 1002, 227, 228, 176, 242, 319, + /* 280 */ 5, 40, 179, 258, 227, 228, 23, 178, 103, 108, + /* 290 */ 99, 107, 204, 726, 1012, 1073, 723, 290, 724, 908, + /* 300 */ 725, 64, 62, 65, 63, 303, 189, 44, 257, 55, + /* 310 */ 54, 37, 37, 53, 52, 51, 800, 253, 803, 251, + /* 320 */ 316, 326, 325, 66, 254, 255, 198, 196, 194, 270, + /* 330 */ 37, 77, 66, 193, 139, 138, 137, 136, 223, 742, + /* 340 */ 799, 43, 802, 355, 354, 37, 37, 37, 353, 53, + /* 350 */ 52, 51, 352, 37, 351, 350, 239, 240, 810, 805, + /* 360 */ 1011, 1011, 272, 78, 37, 806, 122, 810, 805, 37, + /* 370 */ 37, 359, 358, 144, 806, 327, 38, 14, 348, 1011, + /* 380 */ 82, 93, 70, 259, 739, 256, 320, 333, 332, 83, + /* 390 */ 328, 329, 330, 73, 1011, 1011, 1011, 999, 334, 150, + /* 400 */ 148, 147, 1011, 1, 177, 775, 776, 727, 728, 335, + /* 410 */ 9, 96, 796, 1011, 336, 340, 758, 274, 1011, 1011, + /* 420 */ 1083, 766, 767, 746, 71, 712, 274, 295, 714, 297, + /* 430 */ 155, 713, 33, 74, 807, 67, 26, 830, 811, 38, + /* 440 */ 247, 38, 67, 95, 76, 67, 617, 16, 797, 15, + /* 450 */ 205, 25, 25, 113, 18, 112, 17, 731, 808, 732, + /* 460 */ 25, 6, 729, 211, 730, 298, 20, 119, 19, 118, + /* 470 */ 22, 1120, 21, 132, 131, 1119, 701, 1118, 225, 226, + /* 480 */ 208, 209, 1135, 212, 206, 213, 214, 813, 218, 219, + /* 490 */ 220, 217, 203, 1082, 237, 1079, 1078, 238, 339, 47, + /* 500 */ 1028, 268, 152, 1065, 1064, 1035, 149, 275, 1009, 279, + /* 510 */ 1046, 1043, 1044, 1048, 154, 159, 286, 171, 172, 273, + /* 520 */ 234, 1007, 173, 162, 174, 922, 300, 301, 302, 305, + /* 530 */ 306, 757, 1025, 45, 281, 201, 161, 283, 41, 317, + /* 540 */ 75, 916, 293, 72, 49, 324, 164, 1142, 291, 110, + /* 550 */ 1141, 1138, 163, 289, 180, 331, 1134, 116, 1133, 1130, + /* 560 */ 287, 285, 181, 942, 42, 39, 46, 202, 282, 904, + /* 570 */ 126, 902, 128, 129, 900, 899, 260, 280, 192, 897, + /* 580 */ 896, 895, 894, 893, 892, 891, 195, 197, 888, 886, + /* 590 */ 884, 882, 199, 48, 879, 200, 875, 304, 349, 81, + /* 600 */ 86, 284, 1066, 121, 341, 342, 343, 344, 345, 346, + /* 610 */ 347, 357, 855, 262, 261, 854, 224, 244, 299, 264, + /* 620 */ 265, 853, 836, 221, 222, 835, 269, 294, 104, 921, + /* 630 */ 920, 274, 105, 10, 276, 87, 84, 898, 734, 140, + /* 640 */ 30, 156, 141, 184, 890, 183, 943, 182, 185, 187, + /* 650 */ 186, 142, 188, 2, 889, 759, 143, 881, 980, 165, + /* 660 */ 880, 166, 167, 944, 168, 169, 170, 4, 990, 768, + /* 670 */ 157, 158, 762, 88, 236, 764, 89, 288, 31, 11, + /* 680 */ 32, 12, 13, 27, 296, 28, 96, 101, 98, 35, + /* 690 */ 100, 632, 36, 667, 102, 665, 664, 663, 661, 660, + /* 700 */ 659, 656, 622, 315, 106, 7, 321, 812, 322, 8, + /* 710 */ 814, 109, 111, 68, 69, 38, 704, 703, 115, 700, + /* 720 */ 117, 648, 646, 638, 644, 640, 642, 636, 634, 670, + /* 730 */ 669, 668, 666, 662, 658, 657, 191, 620, 585, 859, /* 740 */ 858, 858, 858, 858, 858, 858, 858, 858, 858, 858, - /* 750 */ 858, 145, 146, + /* 750 */ 858, 858, 145, 146, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 265, 1, 205, 1, 1, 206, 205, 198, 199, 9, - /* 10 */ 275, 9, 9, 13, 14, 199, 16, 17, 5, 246, - /* 20 */ 20, 21, 199, 23, 24, 25, 26, 27, 28, 222, - /* 30 */ 205, 224, 225, 33, 34, 262, 229, 37, 38, 39, - /* 40 */ 233, 242, 235, 236, 37, 38, 39, 45, 46, 47, + /* 0 */ 264, 1, 204, 1, 1, 204, 197, 198, 197, 9, + /* 10 */ 274, 9, 9, 13, 14, 197, 16, 17, 195, 196, + /* 20 */ 20, 21, 1, 23, 24, 25, 26, 27, 28, 221, + /* 30 */ 9, 223, 224, 33, 34, 197, 228, 37, 38, 39, + /* 40 */ 232, 197, 234, 235, 219, 220, 5, 45, 46, 47, /* 50 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 60 */ 58, 59, 265, 199, 62, 199, 265, 13, 14, 199, - /* 70 */ 16, 17, 275, 209, 20, 21, 275, 23, 24, 25, - /* 80 */ 26, 27, 28, 267, 268, 82, 86, 33, 34, 266, - /* 90 */ 265, 37, 38, 39, 13, 14, 84, 16, 17, 244, - /* 100 */ 275, 20, 21, 248, 23, 24, 25, 26, 27, 28, - /* 110 */ 66, 67, 68, 243, 33, 34, 82, 247, 37, 38, - /* 120 */ 39, 13, 14, 244, 16, 17, 90, 248, 20, 21, - /* 130 */ 206, 23, 24, 25, 26, 27, 28, 83, 272, 244, - /* 140 */ 274, 33, 34, 248, 1, 37, 38, 39, 14, 265, - /* 150 */ 16, 17, 9, 119, 20, 21, 0, 23, 24, 25, - /* 160 */ 26, 27, 28, 239, 240, 241, 242, 33, 34, 196, - /* 170 */ 197, 37, 38, 39, 98, 99, 100, 101, 102, 103, - /* 180 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 222, - /* 190 */ 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, - /* 200 */ 233, 234, 235, 236, 16, 17, 44, 199, 20, 21, - /* 210 */ 199, 23, 24, 25, 26, 27, 28, 246, 78, 246, - /* 220 */ 209, 33, 34, 199, 62, 37, 38, 39, 1, 2, - /* 230 */ 90, 69, 5, 262, 7, 262, 9, 75, 76, 77, - /* 240 */ 84, 1, 2, 81, 82, 5, 82, 7, 199, 9, - /* 250 */ 86, 199, 2, 245, 265, 5, 5, 7, 7, 9, - /* 260 */ 33, 34, 199, 145, 37, 147, 199, 243, 63, 64, - /* 270 */ 65, 247, 209, 33, 34, 70, 71, 72, 73, 74, - /* 280 */ 116, 119, 265, 33, 34, 265, 25, 26, 27, 28, - /* 290 */ 220, 221, 199, 88, 33, 34, 247, 69, 37, 38, - /* 300 */ 39, 248, 206, 141, 69, 143, 63, 64, 65, 82, - /* 310 */ 243, 5, 150, 70, 247, 72, 73, 74, 199, 63, - /* 320 */ 64, 65, 82, 80, 272, 199, 70, 71, 72, 73, - /* 330 */ 74, 5, 199, 7, 199, 98, 240, 100, 101, 33, - /* 340 */ 34, 199, 105, 142, 117, 118, 109, 199, 111, 112, - /* 350 */ 199, 124, 151, 152, 37, 33, 34, 117, 118, 37, - /* 360 */ 38, 39, 243, 270, 124, 272, 247, 117, 118, 243, - /* 370 */ 199, 199, 144, 247, 146, 124, 148, 149, 243, 144, - /* 380 */ 83, 146, 247, 148, 149, 243, 63, 64, 65, 247, - /* 390 */ 204, 243, 83, 204, 243, 247, 204, 211, 247, 83, - /* 400 */ 211, 97, 249, 211, 97, 272, 207, 208, 202, 203, - /* 410 */ 132, 133, 83, 97, 243, 243, 263, 120, 247, 247, - /* 420 */ 83, 83, 97, 83, 83, 82, 97, 123, 83, 120, - /* 430 */ 83, 83, 1, 83, 97, 97, 61, 97, 97, 122, - /* 440 */ 83, 15, 97, 82, 97, 97, 139, 97, 265, 83, - /* 450 */ 124, 78, 79, 145, 97, 147, 265, 82, 115, 145, - /* 460 */ 265, 147, 137, 97, 5, 5, 7, 7, 37, 145, - /* 470 */ 238, 147, 145, 265, 147, 114, 145, 265, 147, 265, - /* 480 */ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, - /* 490 */ 248, 238, 248, 238, 199, 238, 238, 238, 238, 199, - /* 500 */ 199, 199, 264, 273, 199, 61, 273, 261, 246, 199, - /* 510 */ 246, 199, 199, 250, 199, 246, 269, 199, 199, 199, - /* 520 */ 199, 269, 254, 269, 259, 124, 260, 199, 258, 199, - /* 530 */ 257, 199, 199, 199, 199, 199, 269, 130, 199, 134, - /* 540 */ 136, 199, 128, 117, 200, 199, 138, 135, 199, 256, - /* 550 */ 199, 199, 199, 199, 199, 199, 127, 199, 199, 199, - /* 560 */ 126, 199, 199, 199, 199, 129, 199, 199, 199, 199, - /* 570 */ 199, 199, 125, 199, 89, 199, 199, 199, 199, 199, - /* 580 */ 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, - /* 590 */ 199, 199, 199, 199, 199, 199, 199, 199, 140, 200, - /* 600 */ 200, 113, 200, 200, 96, 95, 51, 92, 94, 55, - /* 610 */ 200, 93, 91, 84, 5, 200, 200, 153, 5, 5, - /* 620 */ 153, 200, 200, 5, 5, 100, 206, 210, 210, 206, - /* 630 */ 99, 142, 120, 82, 115, 83, 97, 121, 82, 200, - /* 640 */ 200, 213, 217, 219, 212, 218, 216, 214, 207, 201, - /* 650 */ 215, 201, 201, 200, 202, 201, 237, 200, 97, 221, - /* 660 */ 83, 255, 253, 252, 251, 200, 82, 97, 83, 82, - /* 670 */ 1, 83, 82, 82, 237, 83, 82, 97, 131, 97, - /* 680 */ 131, 82, 82, 115, 82, 116, 78, 71, 87, 86, - /* 690 */ 5, 87, 86, 9, 5, 5, 5, 5, 5, 5, - /* 700 */ 5, 15, 85, 78, 82, 24, 83, 59, 82, 147, - /* 710 */ 117, 147, 16, 16, 147, 5, 5, 97, 147, 83, - /* 720 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - /* 730 */ 5, 5, 5, 5, 5, 97, 85, 61, 60, 0, - /* 740 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 750 */ 276, 21, 21, 276, 276, 276, 276, 276, 276, 276, - /* 760 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 770 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 780 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 790 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 800 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 810 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 820 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 830 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 840 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 850 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 860 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 870 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 880 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 890 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 900 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 910 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 920 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 930 */ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, - /* 940 */ 276, 276, 276, 276, 276, 276, 276, 276, + /* 60 */ 58, 59, 264, 61, 203, 264, 13, 14, 245, 16, + /* 70 */ 17, 210, 274, 20, 21, 274, 23, 24, 25, 26, + /* 80 */ 27, 28, 271, 265, 261, 85, 33, 34, 201, 202, + /* 90 */ 37, 38, 39, 13, 14, 204, 16, 17, 5, 245, + /* 100 */ 20, 21, 81, 23, 24, 25, 26, 27, 28, 271, + /* 110 */ 266, 267, 197, 33, 34, 261, 205, 37, 38, 39, + /* 120 */ 243, 62, 63, 64, 247, 243, 33, 34, 69, 247, + /* 130 */ 71, 72, 73, 13, 14, 82, 16, 17, 79, 81, + /* 140 */ 20, 21, 248, 23, 24, 25, 26, 27, 28, 238, + /* 150 */ 239, 240, 241, 33, 34, 264, 262, 37, 38, 39, + /* 160 */ 14, 246, 16, 17, 83, 274, 20, 21, 141, 23, + /* 170 */ 24, 25, 26, 27, 28, 197, 118, 150, 151, 33, + /* 180 */ 34, 89, 243, 37, 38, 39, 247, 197, 97, 98, + /* 190 */ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + /* 200 */ 109, 110, 111, 221, 222, 223, 224, 225, 226, 227, + /* 210 */ 228, 229, 230, 231, 232, 233, 234, 235, 16, 17, + /* 220 */ 242, 197, 20, 21, 246, 23, 24, 25, 26, 27, + /* 230 */ 28, 197, 245, 44, 197, 33, 34, 0, 205, 37, + /* 240 */ 38, 39, 68, 1, 2, 208, 247, 5, 261, 7, + /* 250 */ 61, 9, 1, 2, 247, 203, 5, 68, 7, 269, + /* 260 */ 9, 271, 210, 74, 75, 76, 197, 33, 34, 80, + /* 270 */ 81, 37, 38, 39, 241, 33, 34, 208, 244, 37, + /* 280 */ 62, 63, 64, 197, 33, 34, 264, 69, 70, 71, + /* 290 */ 72, 73, 264, 2, 208, 271, 5, 273, 7, 203, + /* 300 */ 9, 25, 26, 27, 28, 87, 210, 118, 68, 33, + /* 310 */ 34, 197, 197, 37, 38, 39, 5, 143, 7, 145, + /* 320 */ 83, 147, 148, 81, 33, 34, 62, 63, 64, 140, + /* 330 */ 197, 142, 81, 69, 70, 71, 72, 73, 149, 37, + /* 340 */ 5, 97, 7, 99, 100, 197, 197, 197, 104, 37, + /* 350 */ 38, 39, 108, 197, 110, 111, 242, 242, 116, 117, + /* 360 */ 246, 246, 82, 205, 197, 123, 77, 116, 117, 197, + /* 370 */ 197, 65, 66, 67, 123, 242, 96, 81, 89, 246, + /* 380 */ 82, 85, 96, 143, 96, 145, 15, 147, 148, 82, + /* 390 */ 242, 242, 242, 96, 246, 246, 246, 239, 242, 62, + /* 400 */ 63, 64, 246, 206, 207, 131, 132, 116, 117, 242, + /* 410 */ 122, 115, 1, 246, 242, 242, 82, 119, 246, 246, + /* 420 */ 237, 82, 82, 121, 138, 82, 119, 82, 82, 82, + /* 430 */ 96, 82, 81, 136, 123, 96, 96, 82, 82, 96, + /* 440 */ 60, 96, 96, 96, 81, 96, 82, 144, 37, 146, + /* 450 */ 264, 96, 96, 144, 144, 146, 146, 5, 123, 7, + /* 460 */ 96, 81, 5, 264, 7, 114, 144, 144, 146, 146, + /* 470 */ 144, 264, 146, 77, 78, 264, 113, 264, 264, 264, + /* 480 */ 264, 264, 247, 264, 264, 264, 264, 116, 264, 264, + /* 490 */ 264, 264, 264, 237, 237, 237, 237, 237, 237, 263, + /* 500 */ 245, 197, 197, 272, 272, 197, 60, 245, 245, 268, + /* 510 */ 197, 197, 197, 197, 197, 197, 197, 249, 197, 199, + /* 520 */ 268, 197, 197, 258, 197, 197, 197, 197, 197, 197, + /* 530 */ 197, 123, 260, 197, 268, 197, 259, 268, 197, 197, + /* 540 */ 135, 197, 129, 137, 134, 197, 256, 197, 133, 197, + /* 550 */ 197, 197, 257, 127, 197, 197, 197, 197, 197, 197, + /* 560 */ 126, 125, 197, 197, 197, 197, 197, 197, 128, 197, + /* 570 */ 197, 197, 197, 197, 197, 197, 197, 124, 197, 197, + /* 580 */ 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, + /* 590 */ 197, 197, 197, 139, 197, 197, 197, 88, 112, 199, + /* 600 */ 199, 199, 199, 95, 94, 51, 91, 93, 55, 92, + /* 610 */ 90, 83, 5, 5, 152, 5, 199, 199, 199, 152, + /* 620 */ 5, 5, 99, 199, 199, 98, 141, 114, 205, 209, + /* 630 */ 209, 119, 205, 81, 96, 96, 120, 199, 82, 200, + /* 640 */ 81, 81, 200, 212, 199, 216, 218, 217, 215, 214, + /* 650 */ 213, 200, 211, 206, 199, 82, 200, 199, 236, 255, + /* 660 */ 199, 254, 253, 220, 252, 251, 250, 201, 236, 82, + /* 670 */ 81, 96, 82, 81, 1, 82, 81, 81, 96, 130, + /* 680 */ 96, 130, 81, 81, 114, 81, 115, 70, 77, 86, + /* 690 */ 85, 5, 86, 9, 85, 5, 5, 5, 5, 5, + /* 700 */ 5, 5, 84, 15, 77, 81, 24, 82, 59, 81, + /* 710 */ 116, 146, 146, 16, 16, 96, 5, 5, 146, 82, + /* 720 */ 146, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 730 */ 5, 5, 5, 5, 5, 5, 96, 84, 60, 0, + /* 740 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 750 */ 275, 275, 21, 21, 275, 275, 275, 275, 275, 275, + /* 760 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 770 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 780 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 790 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 800 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 810 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 820 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 830 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 840 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 850 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 860 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 870 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 880 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 890 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 900 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 910 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 920 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 930 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, + /* 940 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, }; #define YY_SHIFT_COUNT (361) #define YY_SHIFT_MIN (0) #define YY_SHIFT_MAX (739) static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 162, 76, 76, 237, 237, 12, 227, 240, 240, 3, - /* 10 */ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - /* 20 */ 143, 143, 143, 0, 2, 240, 250, 250, 250, 34, - /* 30 */ 34, 143, 143, 143, 156, 143, 143, 143, 143, 140, - /* 40 */ 12, 36, 36, 13, 753, 753, 753, 240, 240, 240, - /* 50 */ 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, - /* 60 */ 240, 240, 240, 240, 240, 240, 240, 250, 250, 250, - /* 70 */ 306, 306, 306, 306, 306, 306, 306, 143, 143, 143, - /* 80 */ 317, 143, 143, 143, 34, 34, 143, 143, 143, 143, - /* 90 */ 278, 278, 304, 34, 143, 143, 143, 143, 143, 143, - /* 100 */ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - /* 110 */ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - /* 120 */ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - /* 130 */ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - /* 140 */ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - /* 150 */ 143, 444, 444, 444, 401, 401, 401, 401, 444, 444, - /* 160 */ 404, 408, 407, 412, 405, 414, 429, 434, 436, 447, - /* 170 */ 458, 444, 444, 444, 485, 485, 488, 12, 12, 444, - /* 180 */ 444, 508, 510, 555, 515, 514, 554, 518, 521, 488, - /* 190 */ 13, 444, 529, 529, 444, 529, 444, 529, 444, 444, - /* 200 */ 753, 753, 54, 81, 81, 108, 81, 134, 188, 205, - /* 210 */ 261, 261, 261, 261, 243, 256, 322, 322, 322, 322, - /* 220 */ 228, 235, 201, 164, 7, 7, 251, 326, 44, 323, - /* 230 */ 316, 297, 309, 329, 337, 338, 307, 325, 340, 341, - /* 240 */ 345, 347, 348, 343, 350, 357, 431, 375, 426, 366, - /* 250 */ 118, 308, 314, 459, 460, 324, 327, 361, 331, 373, - /* 260 */ 609, 464, 613, 614, 467, 618, 619, 525, 531, 489, - /* 270 */ 512, 519, 551, 516, 552, 556, 539, 561, 577, 584, - /* 280 */ 585, 587, 588, 570, 590, 592, 591, 669, 594, 580, - /* 290 */ 547, 582, 549, 599, 519, 600, 568, 602, 569, 608, - /* 300 */ 601, 603, 616, 685, 604, 606, 684, 689, 690, 691, - /* 310 */ 692, 693, 694, 695, 617, 686, 625, 622, 623, 593, - /* 320 */ 626, 681, 648, 696, 562, 564, 620, 620, 620, 620, - /* 330 */ 697, 567, 571, 620, 620, 620, 710, 711, 636, 620, - /* 340 */ 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, - /* 350 */ 725, 726, 727, 728, 729, 638, 651, 730, 731, 676, + /* 0 */ 189, 91, 91, 244, 244, 81, 242, 251, 251, 21, + /* 10 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + /* 20 */ 3, 3, 3, 0, 2, 251, 291, 291, 291, 58, + /* 30 */ 58, 3, 3, 3, 237, 3, 3, 3, 3, 289, + /* 40 */ 81, 92, 92, 41, 754, 754, 754, 251, 251, 251, + /* 50 */ 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, + /* 60 */ 251, 251, 251, 251, 251, 251, 251, 291, 291, 291, + /* 70 */ 93, 93, 93, 93, 93, 93, 93, 3, 3, 3, + /* 80 */ 302, 3, 3, 3, 58, 58, 3, 3, 3, 3, + /* 90 */ 274, 274, 288, 58, 3, 3, 3, 3, 3, 3, + /* 100 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + /* 110 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + /* 120 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + /* 130 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + /* 140 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + /* 150 */ 3, 3, 446, 446, 446, 408, 408, 408, 408, 446, + /* 160 */ 446, 405, 406, 413, 410, 415, 426, 434, 436, 440, + /* 170 */ 453, 454, 446, 446, 446, 509, 509, 486, 81, 81, + /* 180 */ 446, 446, 508, 510, 554, 515, 514, 553, 517, 520, + /* 190 */ 486, 41, 446, 528, 528, 446, 528, 446, 528, 446, + /* 200 */ 446, 754, 754, 53, 80, 80, 120, 80, 146, 202, + /* 210 */ 218, 276, 276, 276, 276, 59, 264, 234, 234, 234, + /* 220 */ 234, 174, 240, 27, 296, 312, 312, 311, 335, 306, + /* 230 */ 337, 280, 298, 307, 334, 339, 340, 286, 297, 343, + /* 240 */ 345, 346, 347, 349, 351, 355, 356, 411, 380, 371, + /* 250 */ 364, 303, 309, 310, 452, 457, 322, 323, 363, 326, + /* 260 */ 396, 607, 462, 608, 610, 467, 615, 616, 523, 527, + /* 270 */ 485, 512, 513, 552, 516, 556, 559, 538, 539, 573, + /* 280 */ 560, 587, 589, 590, 575, 592, 593, 595, 673, 596, + /* 290 */ 582, 549, 584, 551, 601, 513, 602, 570, 604, 571, + /* 300 */ 611, 603, 605, 617, 686, 606, 609, 684, 690, 691, + /* 310 */ 692, 693, 694, 695, 696, 618, 688, 627, 624, 625, + /* 320 */ 594, 628, 682, 649, 697, 565, 566, 619, 619, 619, + /* 330 */ 619, 698, 572, 574, 619, 619, 619, 711, 712, 637, + /* 340 */ 619, 716, 717, 718, 719, 720, 721, 722, 723, 724, + /* 350 */ 725, 726, 727, 728, 729, 730, 640, 653, 731, 732, /* 360 */ 678, 739, }; -#define YY_REDUCE_COUNT (201) -#define YY_REDUCE_MIN (-265) -#define YY_REDUCE_MAX (465) +#define YY_REDUCE_COUNT (202) +#define YY_REDUCE_MIN (-264) +#define YY_REDUCE_MAX (466) static const short yy_reduce_ofst[] = { - /* 0 */ -27, -33, -33, -193, -193, -76, -203, -199, -175, -184, - /* 10 */ -130, -134, 93, 24, 67, 119, 126, 135, 142, 148, - /* 20 */ 151, 171, 172, -177, -191, -265, -145, -121, -105, -227, - /* 30 */ -29, 52, 133, 8, -201, -136, 11, 63, 49, 186, - /* 40 */ 96, 189, 192, 70, 153, 199, 206, -116, -11, 17, - /* 50 */ 20, 183, 191, 195, 208, 212, 214, 215, 216, 217, - /* 60 */ 218, 219, 220, 221, 222, 223, 224, 53, 242, 244, - /* 70 */ 232, 253, 255, 257, 258, 259, 260, 295, 300, 301, - /* 80 */ 238, 302, 305, 310, 262, 264, 312, 313, 315, 318, - /* 90 */ 230, 233, 263, 269, 319, 320, 321, 328, 330, 332, - /* 100 */ 333, 334, 335, 336, 339, 342, 346, 349, 351, 352, - /* 110 */ 353, 354, 355, 356, 358, 359, 360, 362, 363, 364, - /* 120 */ 365, 367, 368, 369, 370, 371, 372, 374, 376, 377, - /* 130 */ 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, - /* 140 */ 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - /* 150 */ 398, 344, 399, 400, 247, 252, 254, 267, 402, 403, - /* 160 */ 246, 266, 265, 270, 273, 293, 406, 268, 409, 411, - /* 170 */ 413, 410, 415, 416, 417, 418, 419, 420, 423, 421, - /* 180 */ 422, 424, 427, 425, 428, 430, 433, 435, 432, 437, - /* 190 */ 438, 439, 448, 450, 440, 451, 453, 454, 457, 465, - /* 200 */ 441, 452, + /* 0 */ -177, -18, -18, -192, -192, -89, -202, -199, -109, -156, + /* 10 */ -22, 24, -10, 114, 115, 133, 148, 149, 150, 156, + /* 20 */ 167, 172, 173, -182, -191, -264, -123, -118, -61, -146, + /* 30 */ -13, -189, -162, 34, 33, 37, 69, 86, -85, -139, + /* 40 */ 158, 52, 96, -175, -106, 197, -113, 22, 28, 186, + /* 50 */ 199, 207, 211, 213, 214, 215, 216, 217, 219, 220, + /* 60 */ 221, 222, 224, 225, 226, 227, 228, -1, 7, 235, + /* 70 */ 183, 256, 257, 258, 259, 260, 261, 304, 305, 308, + /* 80 */ 236, 313, 314, 315, 255, 262, 316, 317, 318, 319, + /* 90 */ 231, 232, 268, 263, 321, 324, 325, 327, 328, 329, + /* 100 */ 330, 331, 332, 333, 336, 338, 341, 342, 344, 348, + /* 110 */ 350, 352, 353, 354, 357, 358, 359, 360, 361, 362, + /* 120 */ 365, 366, 367, 368, 369, 370, 372, 373, 374, 375, + /* 130 */ 376, 377, 378, 379, 381, 382, 383, 384, 385, 386, + /* 140 */ 387, 388, 389, 390, 391, 392, 393, 394, 395, 397, + /* 150 */ 398, 399, 320, 400, 401, 241, 252, 266, 269, 402, + /* 160 */ 403, 272, 277, 265, 295, 290, 404, 407, 409, 412, + /* 170 */ 414, 416, 417, 418, 419, 420, 421, 422, 423, 427, + /* 180 */ 424, 425, 428, 430, 429, 431, 433, 437, 435, 441, + /* 190 */ 432, 443, 438, 439, 442, 445, 451, 455, 456, 458, + /* 200 */ 461, 447, 466, }; static const YYACTIONTYPE yy_default[] = { /* 0 */ 856, 979, 918, 989, 905, 915, 1126, 1126, 1126, 856, @@ -464,28 +477,28 @@ static const YYACTIONTYPE yy_default[] = { /* 120 */ 856, 856, 856, 856, 856, 856, 903, 856, 901, 856, /* 130 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, /* 140 */ 856, 856, 856, 856, 887, 856, 856, 856, 856, 856, - /* 150 */ 856, 878, 878, 878, 856, 856, 856, 856, 878, 878, - /* 160 */ 1076, 1080, 1062, 1074, 1070, 1057, 1055, 1053, 1061, 1052, - /* 170 */ 1084, 878, 878, 878, 923, 923, 919, 915, 915, 878, - /* 180 */ 878, 941, 939, 937, 929, 935, 931, 933, 927, 906, - /* 190 */ 856, 878, 913, 913, 878, 913, 878, 913, 878, 878, - /* 200 */ 963, 981, 856, 1085, 1075, 856, 1125, 1115, 1114, 856, - /* 210 */ 1121, 1113, 1112, 1111, 856, 856, 1107, 1110, 1109, 1108, - /* 220 */ 856, 856, 856, 856, 1117, 1116, 856, 856, 856, 856, - /* 230 */ 856, 856, 856, 856, 856, 856, 1081, 1077, 856, 856, - /* 240 */ 856, 856, 856, 856, 856, 856, 856, 1087, 856, 856, - /* 250 */ 856, 856, 856, 856, 856, 856, 856, 991, 856, 856, + /* 150 */ 856, 874, 878, 878, 878, 856, 856, 856, 856, 878, + /* 160 */ 878, 1076, 1080, 1062, 1074, 1070, 1057, 1055, 1053, 1061, + /* 170 */ 1052, 1084, 878, 878, 878, 923, 923, 919, 915, 915, + /* 180 */ 878, 878, 941, 939, 937, 929, 935, 931, 933, 927, + /* 190 */ 906, 856, 878, 913, 913, 878, 913, 878, 913, 878, + /* 200 */ 878, 963, 981, 856, 1085, 1075, 856, 1125, 1115, 1114, + /* 210 */ 856, 1121, 1113, 1112, 1111, 856, 856, 1107, 1110, 1109, + /* 220 */ 1108, 856, 856, 856, 856, 1117, 1116, 856, 856, 856, + /* 230 */ 856, 856, 856, 856, 856, 856, 856, 1081, 1077, 856, + /* 240 */ 856, 856, 856, 856, 856, 856, 856, 856, 1087, 856, + /* 250 */ 856, 856, 856, 856, 856, 856, 856, 856, 991, 856, /* 260 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - /* 270 */ 1029, 856, 856, 856, 856, 856, 1041, 1040, 856, 856, - /* 280 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 1071, - /* 290 */ 856, 1063, 856, 856, 1003, 856, 856, 856, 856, 856, + /* 270 */ 856, 1029, 856, 856, 856, 856, 856, 1041, 1040, 856, + /* 280 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, + /* 290 */ 1071, 856, 1063, 856, 856, 1003, 856, 856, 856, 856, /* 300 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, /* 310 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - /* 320 */ 856, 856, 856, 856, 856, 856, 1144, 1139, 1140, 1137, - /* 330 */ 856, 856, 856, 1136, 1131, 1132, 856, 856, 856, 1129, - /* 340 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - /* 350 */ 856, 856, 856, 856, 856, 947, 856, 885, 883, 856, - /* 360 */ 874, 856, + /* 320 */ 856, 856, 856, 856, 856, 856, 856, 1144, 1139, 1140, + /* 330 */ 1137, 856, 856, 856, 1136, 1131, 1132, 856, 856, 856, + /* 340 */ 1129, 856, 856, 856, 856, 856, 856, 856, 856, 856, + /* 350 */ 856, 856, 856, 856, 856, 856, 947, 856, 885, 883, + /* 360 */ 856, 856, }; /********** End of lemon-generated parsing tables *****************************/ @@ -565,7 +578,6 @@ static const YYCODETYPE yyFallback[] = { 0, /* SCORES => nothing */ 0, /* GRANTS => nothing */ 0, /* VNODES => nothing */ - 1, /* IPTOKEN => ID */ 0, /* DOT => nothing */ 0, /* CREATE => nothing */ 0, /* TABLE => nothing */ @@ -690,6 +702,7 @@ static const YYCODETYPE yyFallback[] = { 1, /* STATEMENT => ID */ 1, /* TRIGGER => ID */ 1, /* VIEW => ID */ + 1, /* IPTOKEN => ID */ 1, /* SEMI => ID */ 1, /* NONE => ID */ 1, /* PREV => ID */ @@ -739,6 +752,7 @@ struct yyParser { int yyerrcnt; /* Shifts left before out of the error */ #endif ParseARG_SDECL /* A place to hold %extra_argument */ + ParseCTX_SDECL /* A place to hold %extra_context */ #if YYSTACKDEPTH<=0 int yystksz; /* Current side of the stack */ yyStackEntry *yystack; /* The parser's stack */ @@ -846,131 +860,131 @@ static const char *const yyTokenName[] = { /* 57 */ "SCORES", /* 58 */ "GRANTS", /* 59 */ "VNODES", - /* 60 */ "IPTOKEN", - /* 61 */ "DOT", - /* 62 */ "CREATE", - /* 63 */ "TABLE", - /* 64 */ "STABLE", - /* 65 */ "DATABASE", - /* 66 */ "TABLES", - /* 67 */ "STABLES", - /* 68 */ "VGROUPS", - /* 69 */ "DROP", - /* 70 */ "TOPIC", - /* 71 */ "FUNCTION", - /* 72 */ "DNODE", - /* 73 */ "USER", - /* 74 */ "ACCOUNT", - /* 75 */ "USE", - /* 76 */ "DESCRIBE", - /* 77 */ "ALTER", - /* 78 */ "PASS", - /* 79 */ "PRIVILEGE", - /* 80 */ "LOCAL", - /* 81 */ "COMPACT", - /* 82 */ "LP", - /* 83 */ "RP", - /* 84 */ "IF", - /* 85 */ "EXISTS", - /* 86 */ "AS", - /* 87 */ "OUTPUTTYPE", - /* 88 */ "AGGREGATE", - /* 89 */ "BUFSIZE", - /* 90 */ "PPS", - /* 91 */ "TSERIES", - /* 92 */ "DBS", - /* 93 */ "STORAGE", - /* 94 */ "QTIME", - /* 95 */ "CONNS", - /* 96 */ "STATE", - /* 97 */ "COMMA", - /* 98 */ "KEEP", - /* 99 */ "CACHE", - /* 100 */ "REPLICA", - /* 101 */ "QUORUM", - /* 102 */ "DAYS", - /* 103 */ "MINROWS", - /* 104 */ "MAXROWS", - /* 105 */ "BLOCKS", - /* 106 */ "CTIME", - /* 107 */ "WAL", - /* 108 */ "FSYNC", - /* 109 */ "COMP", - /* 110 */ "PRECISION", - /* 111 */ "UPDATE", - /* 112 */ "CACHELAST", - /* 113 */ "PARTITIONS", - /* 114 */ "UNSIGNED", - /* 115 */ "TAGS", - /* 116 */ "USING", - /* 117 */ "NULL", - /* 118 */ "NOW", - /* 119 */ "SELECT", - /* 120 */ "UNION", - /* 121 */ "ALL", - /* 122 */ "DISTINCT", - /* 123 */ "FROM", - /* 124 */ "VARIABLE", - /* 125 */ "INTERVAL", - /* 126 */ "SESSION", - /* 127 */ "STATE_WINDOW", - /* 128 */ "FILL", - /* 129 */ "SLIDING", - /* 130 */ "ORDER", - /* 131 */ "BY", - /* 132 */ "ASC", - /* 133 */ "DESC", - /* 134 */ "GROUP", - /* 135 */ "HAVING", - /* 136 */ "LIMIT", - /* 137 */ "OFFSET", - /* 138 */ "SLIMIT", - /* 139 */ "SOFFSET", - /* 140 */ "WHERE", - /* 141 */ "RESET", - /* 142 */ "QUERY", - /* 143 */ "SYNCDB", - /* 144 */ "ADD", - /* 145 */ "COLUMN", - /* 146 */ "MODIFY", - /* 147 */ "TAG", - /* 148 */ "CHANGE", - /* 149 */ "SET", - /* 150 */ "KILL", - /* 151 */ "CONNECTION", - /* 152 */ "STREAM", - /* 153 */ "COLON", - /* 154 */ "ABORT", - /* 155 */ "AFTER", - /* 156 */ "ATTACH", - /* 157 */ "BEFORE", - /* 158 */ "BEGIN", - /* 159 */ "CASCADE", - /* 160 */ "CLUSTER", - /* 161 */ "CONFLICT", - /* 162 */ "COPY", - /* 163 */ "DEFERRED", - /* 164 */ "DELIMITERS", - /* 165 */ "DETACH", - /* 166 */ "EACH", - /* 167 */ "END", - /* 168 */ "EXPLAIN", - /* 169 */ "FAIL", - /* 170 */ "FOR", - /* 171 */ "IGNORE", - /* 172 */ "IMMEDIATE", - /* 173 */ "INITIALLY", - /* 174 */ "INSTEAD", - /* 175 */ "MATCH", - /* 176 */ "KEY", - /* 177 */ "OF", - /* 178 */ "RAISE", - /* 179 */ "REPLACE", - /* 180 */ "RESTRICT", - /* 181 */ "ROW", - /* 182 */ "STATEMENT", - /* 183 */ "TRIGGER", - /* 184 */ "VIEW", + /* 60 */ "DOT", + /* 61 */ "CREATE", + /* 62 */ "TABLE", + /* 63 */ "STABLE", + /* 64 */ "DATABASE", + /* 65 */ "TABLES", + /* 66 */ "STABLES", + /* 67 */ "VGROUPS", + /* 68 */ "DROP", + /* 69 */ "TOPIC", + /* 70 */ "FUNCTION", + /* 71 */ "DNODE", + /* 72 */ "USER", + /* 73 */ "ACCOUNT", + /* 74 */ "USE", + /* 75 */ "DESCRIBE", + /* 76 */ "ALTER", + /* 77 */ "PASS", + /* 78 */ "PRIVILEGE", + /* 79 */ "LOCAL", + /* 80 */ "COMPACT", + /* 81 */ "LP", + /* 82 */ "RP", + /* 83 */ "IF", + /* 84 */ "EXISTS", + /* 85 */ "AS", + /* 86 */ "OUTPUTTYPE", + /* 87 */ "AGGREGATE", + /* 88 */ "BUFSIZE", + /* 89 */ "PPS", + /* 90 */ "TSERIES", + /* 91 */ "DBS", + /* 92 */ "STORAGE", + /* 93 */ "QTIME", + /* 94 */ "CONNS", + /* 95 */ "STATE", + /* 96 */ "COMMA", + /* 97 */ "KEEP", + /* 98 */ "CACHE", + /* 99 */ "REPLICA", + /* 100 */ "QUORUM", + /* 101 */ "DAYS", + /* 102 */ "MINROWS", + /* 103 */ "MAXROWS", + /* 104 */ "BLOCKS", + /* 105 */ "CTIME", + /* 106 */ "WAL", + /* 107 */ "FSYNC", + /* 108 */ "COMP", + /* 109 */ "PRECISION", + /* 110 */ "UPDATE", + /* 111 */ "CACHELAST", + /* 112 */ "PARTITIONS", + /* 113 */ "UNSIGNED", + /* 114 */ "TAGS", + /* 115 */ "USING", + /* 116 */ "NULL", + /* 117 */ "NOW", + /* 118 */ "SELECT", + /* 119 */ "UNION", + /* 120 */ "ALL", + /* 121 */ "DISTINCT", + /* 122 */ "FROM", + /* 123 */ "VARIABLE", + /* 124 */ "INTERVAL", + /* 125 */ "SESSION", + /* 126 */ "STATE_WINDOW", + /* 127 */ "FILL", + /* 128 */ "SLIDING", + /* 129 */ "ORDER", + /* 130 */ "BY", + /* 131 */ "ASC", + /* 132 */ "DESC", + /* 133 */ "GROUP", + /* 134 */ "HAVING", + /* 135 */ "LIMIT", + /* 136 */ "OFFSET", + /* 137 */ "SLIMIT", + /* 138 */ "SOFFSET", + /* 139 */ "WHERE", + /* 140 */ "RESET", + /* 141 */ "QUERY", + /* 142 */ "SYNCDB", + /* 143 */ "ADD", + /* 144 */ "COLUMN", + /* 145 */ "MODIFY", + /* 146 */ "TAG", + /* 147 */ "CHANGE", + /* 148 */ "SET", + /* 149 */ "KILL", + /* 150 */ "CONNECTION", + /* 151 */ "STREAM", + /* 152 */ "COLON", + /* 153 */ "ABORT", + /* 154 */ "AFTER", + /* 155 */ "ATTACH", + /* 156 */ "BEFORE", + /* 157 */ "BEGIN", + /* 158 */ "CASCADE", + /* 159 */ "CLUSTER", + /* 160 */ "CONFLICT", + /* 161 */ "COPY", + /* 162 */ "DEFERRED", + /* 163 */ "DELIMITERS", + /* 164 */ "DETACH", + /* 165 */ "EACH", + /* 166 */ "END", + /* 167 */ "EXPLAIN", + /* 168 */ "FAIL", + /* 169 */ "FOR", + /* 170 */ "IGNORE", + /* 171 */ "IMMEDIATE", + /* 172 */ "INITIALLY", + /* 173 */ "INSTEAD", + /* 174 */ "MATCH", + /* 175 */ "KEY", + /* 176 */ "OF", + /* 177 */ "RAISE", + /* 178 */ "REPLACE", + /* 179 */ "RESTRICT", + /* 180 */ "ROW", + /* 181 */ "STATEMENT", + /* 182 */ "TRIGGER", + /* 183 */ "VIEW", + /* 184 */ "IPTOKEN", /* 185 */ "SEMI", /* 186 */ "NONE", /* 187 */ "PREV", @@ -981,87 +995,86 @@ static const char *const yyTokenName[] = { /* 192 */ "INSERT", /* 193 */ "INTO", /* 194 */ "VALUES", - /* 195 */ "error", - /* 196 */ "program", - /* 197 */ "cmd", + /* 195 */ "program", + /* 196 */ "cmd", + /* 197 */ "ids", /* 198 */ "dbPrefix", - /* 199 */ "ids", - /* 200 */ "cpxName", - /* 201 */ "ifexists", - /* 202 */ "alter_db_optr", - /* 203 */ "alter_topic_optr", - /* 204 */ "acct_optr", - /* 205 */ "exprlist", - /* 206 */ "ifnotexists", - /* 207 */ "db_optr", - /* 208 */ "topic_optr", - /* 209 */ "typename", - /* 210 */ "bufsize", - /* 211 */ "pps", - /* 212 */ "tseries", - /* 213 */ "dbs", - /* 214 */ "streams", - /* 215 */ "storage", - /* 216 */ "qtime", - /* 217 */ "users", - /* 218 */ "conns", - /* 219 */ "state", - /* 220 */ "intitemlist", - /* 221 */ "intitem", - /* 222 */ "keep", - /* 223 */ "cache", - /* 224 */ "replica", - /* 225 */ "quorum", - /* 226 */ "days", - /* 227 */ "minrows", - /* 228 */ "maxrows", - /* 229 */ "blocks", - /* 230 */ "ctime", - /* 231 */ "wal", - /* 232 */ "fsync", - /* 233 */ "comp", - /* 234 */ "prec", - /* 235 */ "update", - /* 236 */ "cachelast", - /* 237 */ "partitions", - /* 238 */ "signed", - /* 239 */ "create_table_args", - /* 240 */ "create_stable_args", - /* 241 */ "create_table_list", - /* 242 */ "create_from_stable", - /* 243 */ "columnlist", - /* 244 */ "tagitemlist", - /* 245 */ "tagNamelist", - /* 246 */ "select", - /* 247 */ "column", - /* 248 */ "tagitem", - /* 249 */ "selcollist", - /* 250 */ "from", - /* 251 */ "where_opt", - /* 252 */ "interval_opt", - /* 253 */ "sliding_opt", - /* 254 */ "session_option", - /* 255 */ "windowstate_option", - /* 256 */ "fill_opt", - /* 257 */ "groupby_opt", - /* 258 */ "having_opt", - /* 259 */ "orderby_opt", - /* 260 */ "slimit_opt", - /* 261 */ "limit_opt", - /* 262 */ "union", - /* 263 */ "sclp", - /* 264 */ "distinct", - /* 265 */ "expr", - /* 266 */ "as", - /* 267 */ "tablelist", - /* 268 */ "sub", - /* 269 */ "tmvar", - /* 270 */ "sortlist", - /* 271 */ "sortitem", - /* 272 */ "item", - /* 273 */ "sortorder", - /* 274 */ "grouplist", - /* 275 */ "expritem", + /* 199 */ "cpxName", + /* 200 */ "ifexists", + /* 201 */ "alter_db_optr", + /* 202 */ "alter_topic_optr", + /* 203 */ "acct_optr", + /* 204 */ "exprlist", + /* 205 */ "ifnotexists", + /* 206 */ "db_optr", + /* 207 */ "topic_optr", + /* 208 */ "typename", + /* 209 */ "bufsize", + /* 210 */ "pps", + /* 211 */ "tseries", + /* 212 */ "dbs", + /* 213 */ "streams", + /* 214 */ "storage", + /* 215 */ "qtime", + /* 216 */ "users", + /* 217 */ "conns", + /* 218 */ "state", + /* 219 */ "intitemlist", + /* 220 */ "intitem", + /* 221 */ "keep", + /* 222 */ "cache", + /* 223 */ "replica", + /* 224 */ "quorum", + /* 225 */ "days", + /* 226 */ "minrows", + /* 227 */ "maxrows", + /* 228 */ "blocks", + /* 229 */ "ctime", + /* 230 */ "wal", + /* 231 */ "fsync", + /* 232 */ "comp", + /* 233 */ "prec", + /* 234 */ "update", + /* 235 */ "cachelast", + /* 236 */ "partitions", + /* 237 */ "signed", + /* 238 */ "create_table_args", + /* 239 */ "create_stable_args", + /* 240 */ "create_table_list", + /* 241 */ "create_from_stable", + /* 242 */ "columnlist", + /* 243 */ "tagitemlist", + /* 244 */ "tagNamelist", + /* 245 */ "select", + /* 246 */ "column", + /* 247 */ "tagitem", + /* 248 */ "selcollist", + /* 249 */ "from", + /* 250 */ "where_opt", + /* 251 */ "interval_opt", + /* 252 */ "sliding_opt", + /* 253 */ "session_option", + /* 254 */ "windowstate_option", + /* 255 */ "fill_opt", + /* 256 */ "groupby_opt", + /* 257 */ "having_opt", + /* 258 */ "orderby_opt", + /* 259 */ "slimit_opt", + /* 260 */ "limit_opt", + /* 261 */ "union", + /* 262 */ "sclp", + /* 263 */ "distinct", + /* 264 */ "expr", + /* 265 */ "as", + /* 266 */ "tablelist", + /* 267 */ "sub", + /* 268 */ "tmvar", + /* 269 */ "sortlist", + /* 270 */ "sortitem", + /* 271 */ "item", + /* 272 */ "sortorder", + /* 273 */ "grouplist", + /* 274 */ "expritem", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -1085,7 +1098,7 @@ static const char *const yyRuleName[] = { /* 13 */ "cmd ::= SHOW SCORES", /* 14 */ "cmd ::= SHOW GRANTS", /* 15 */ "cmd ::= SHOW VNODES", - /* 16 */ "cmd ::= SHOW VNODES IPTOKEN", + /* 16 */ "cmd ::= SHOW VNODES ids", /* 17 */ "dbPrefix ::=", /* 18 */ "dbPrefix ::= ids DOT", /* 19 */ "cpxName ::=", @@ -1406,28 +1419,29 @@ static int yyGrowStack(yyParser *p){ /* Initialize a new parser that has already been allocated. */ -void ParseInit(void *yypParser){ - yyParser *pParser = (yyParser*)yypParser; +void ParseInit(void *yypRawParser ParseCTX_PDECL){ + yyParser *yypParser = (yyParser*)yypRawParser; + ParseCTX_STORE #ifdef YYTRACKMAXSTACKDEPTH - pParser->yyhwm = 0; + yypParser->yyhwm = 0; #endif #if YYSTACKDEPTH<=0 - pParser->yytos = NULL; - pParser->yystack = NULL; - pParser->yystksz = 0; - if( yyGrowStack(pParser) ){ - pParser->yystack = &pParser->yystk0; - pParser->yystksz = 1; + yypParser->yytos = NULL; + yypParser->yystack = NULL; + yypParser->yystksz = 0; + if( yyGrowStack(yypParser) ){ + yypParser->yystack = &yypParser->yystk0; + yypParser->yystksz = 1; } #endif #ifndef YYNOERRORRECOVERY - pParser->yyerrcnt = -1; + yypParser->yyerrcnt = -1; #endif - pParser->yytos = pParser->yystack; - pParser->yystack[0].stateno = 0; - pParser->yystack[0].major = 0; + yypParser->yytos = yypParser->yystack; + yypParser->yystack[0].stateno = 0; + yypParser->yystack[0].major = 0; #if YYSTACKDEPTH>0 - pParser->yystackEnd = &pParser->yystack[YYSTACKDEPTH-1]; + yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; #endif } @@ -1444,11 +1458,14 @@ void ParseInit(void *yypParser){ ** A pointer to a parser. This pointer is used in subsequent calls ** to Parse and ParseFree. */ -void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ - yyParser *pParser; - pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); - if( pParser ) ParseInit(pParser); - return pParser; +void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) ParseCTX_PDECL){ + yyParser *yypParser; + yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); + if( yypParser ){ + ParseCTX_STORE + ParseInit(yypParser ParseCTX_PARAM); + } + return (void*)yypParser; } #endif /* Parse_ENGINEALWAYSONSTACK */ @@ -1465,7 +1482,8 @@ static void yy_destructor( YYCODETYPE yymajor, /* Type code for object to destroy */ YYMINORTYPE *yypminor /* The object to be destroyed */ ){ - ParseARG_FETCH; + ParseARG_FETCH + ParseCTX_FETCH switch( yymajor ){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen @@ -1478,60 +1496,76 @@ static void yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 205: /* exprlist */ - case 249: /* selcollist */ - case 263: /* sclp */ + case 204: /* exprlist */ + case 248: /* selcollist */ + case 262: /* sclp */ { -tSqlExprListDestroy((yypminor->yy525)); +#line 750 "sql.y" +tSqlExprListDestroy((yypminor->yy131)); +#line 1506 "sql.c" } break; - case 220: /* intitemlist */ - case 222: /* keep */ - case 243: /* columnlist */ - case 244: /* tagitemlist */ - case 245: /* tagNamelist */ - case 256: /* fill_opt */ - case 257: /* groupby_opt */ - case 259: /* orderby_opt */ - case 270: /* sortlist */ - case 274: /* grouplist */ + case 219: /* intitemlist */ + case 221: /* keep */ + case 242: /* columnlist */ + case 243: /* tagitemlist */ + case 244: /* tagNamelist */ + case 255: /* fill_opt */ + case 256: /* groupby_opt */ + case 258: /* orderby_opt */ + case 269: /* sortlist */ + case 273: /* grouplist */ { -taosArrayDestroy((yypminor->yy525)); +#line 253 "sql.y" +taosArrayDestroy((yypminor->yy131)); +#line 1522 "sql.c" } break; - case 241: /* create_table_list */ + case 240: /* create_table_list */ { -destroyCreateTableSql((yypminor->yy158)); +#line 361 "sql.y" +destroyCreateTableSql((yypminor->yy272)); +#line 1529 "sql.c" } break; - case 246: /* select */ + case 245: /* select */ { -destroySqlNode((yypminor->yy464)); +#line 481 "sql.y" +destroySqlNode((yypminor->yy256)); +#line 1536 "sql.c" } break; - case 250: /* from */ - case 267: /* tablelist */ - case 268: /* sub */ + case 249: /* from */ + case 266: /* tablelist */ + case 267: /* sub */ { -destroyRelationInfo((yypminor->yy412)); +#line 536 "sql.y" +destroyRelationInfo((yypminor->yy544)); +#line 1545 "sql.c" } break; - case 251: /* where_opt */ - case 258: /* having_opt */ - case 265: /* expr */ - case 275: /* expritem */ + case 250: /* where_opt */ + case 257: /* having_opt */ + case 264: /* expr */ + case 274: /* expritem */ { -tSqlExprDestroy((yypminor->yy370)); +#line 683 "sql.y" +tSqlExprDestroy((yypminor->yy46)); +#line 1555 "sql.c" } break; - case 262: /* union */ + case 261: /* union */ { -destroyAllSqlNode((yypminor->yy525)); +#line 489 "sql.y" +destroyAllSqlNode((yypminor->yy131)); +#line 1562 "sql.c" } break; - case 271: /* sortitem */ + case 270: /* sortitem */ { -tVariantDestroy(&(yypminor->yy506)); +#line 616 "sql.y" +tVariantDestroy(&(yypminor->yy516)); +#line 1569 "sql.c" } break; /********* End destructor definitions *****************************************/ @@ -1643,13 +1677,12 @@ int ParseCoverage(FILE *out){ ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. */ -static unsigned int yy_find_shift_action( - yyParser *pParser, /* The parser */ - YYCODETYPE iLookAhead /* The look-ahead token */ +static YYACTIONTYPE yy_find_shift_action( + YYCODETYPE iLookAhead, /* The look-ahead token */ + YYACTIONTYPE stateno /* Current state number */ ){ int i; - int stateno = pParser->yytos->stateno; - + if( stateno>YY_MAX_SHIFT ) return stateno; assert( stateno <= YY_SHIFT_COUNT ); #if defined(YYCOVERAGE) @@ -1657,15 +1690,19 @@ static unsigned int yy_find_shift_action( #endif do{ i = yy_shift_ofst[stateno]; - assert( i>=0 && i+YYNTOKEN<=sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) ); + assert( i>=0 ); + assert( i<=YY_ACTTAB_COUNT ); + assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); assert( iLookAhead!=YYNOCODE ); assert( iLookAhead < YYNTOKEN ); i += iLookAhead; + assert( i<(int)YY_NLOOKAHEAD ); if( yy_lookahead[i]!=iLookAhead ){ #ifdef YYFALLBACK YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", @@ -1680,15 +1717,8 @@ static unsigned int yy_find_shift_action( #ifdef YYWILDCARD { int j = i - iLookAhead + YYWILDCARD; - if( -#if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && -#endif -#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j0 - ){ + assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) ); + if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){ #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", @@ -1702,6 +1732,7 @@ static unsigned int yy_find_shift_action( #endif /* YYWILDCARD */ return yy_default[stateno]; }else{ + assert( i>=0 && iyytos; - yytos->stateno = (YYACTIONTYPE)yyNewState; - yytos->major = (YYCODETYPE)yyMajor; + yytos->stateno = yyNewState; + yytos->major = yyMajor; yytos->minor.yy0 = yyMinor; yyTraceShift(yypParser, yyNewState, "Shift"); } -/* The following table contains information about every rule that -** is used during the reduce. -*/ -static const struct { - YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ - signed char nrhs; /* Negative of the number of RHS symbols in the rule */ -} yyRuleInfo[] = { - { 196, -1 }, /* (0) program ::= cmd */ - { 197, -2 }, /* (1) cmd ::= SHOW DATABASES */ - { 197, -2 }, /* (2) cmd ::= SHOW TOPICS */ - { 197, -2 }, /* (3) cmd ::= SHOW FUNCTIONS */ - { 197, -2 }, /* (4) cmd ::= SHOW MNODES */ - { 197, -2 }, /* (5) cmd ::= SHOW DNODES */ - { 197, -2 }, /* (6) cmd ::= SHOW ACCOUNTS */ - { 197, -2 }, /* (7) cmd ::= SHOW USERS */ - { 197, -2 }, /* (8) cmd ::= SHOW MODULES */ - { 197, -2 }, /* (9) cmd ::= SHOW QUERIES */ - { 197, -2 }, /* (10) cmd ::= SHOW CONNECTIONS */ - { 197, -2 }, /* (11) cmd ::= SHOW STREAMS */ - { 197, -2 }, /* (12) cmd ::= SHOW VARIABLES */ - { 197, -2 }, /* (13) cmd ::= SHOW SCORES */ - { 197, -2 }, /* (14) cmd ::= SHOW GRANTS */ - { 197, -2 }, /* (15) cmd ::= SHOW VNODES */ - { 197, -3 }, /* (16) cmd ::= SHOW VNODES IPTOKEN */ - { 198, 0 }, /* (17) dbPrefix ::= */ - { 198, -2 }, /* (18) dbPrefix ::= ids DOT */ - { 200, 0 }, /* (19) cpxName ::= */ - { 200, -2 }, /* (20) cpxName ::= DOT ids */ - { 197, -5 }, /* (21) cmd ::= SHOW CREATE TABLE ids cpxName */ - { 197, -5 }, /* (22) cmd ::= SHOW CREATE STABLE ids cpxName */ - { 197, -4 }, /* (23) cmd ::= SHOW CREATE DATABASE ids */ - { 197, -3 }, /* (24) cmd ::= SHOW dbPrefix TABLES */ - { 197, -5 }, /* (25) cmd ::= SHOW dbPrefix TABLES LIKE ids */ - { 197, -3 }, /* (26) cmd ::= SHOW dbPrefix STABLES */ - { 197, -5 }, /* (27) cmd ::= SHOW dbPrefix STABLES LIKE ids */ - { 197, -3 }, /* (28) cmd ::= SHOW dbPrefix VGROUPS */ - { 197, -4 }, /* (29) cmd ::= SHOW dbPrefix VGROUPS ids */ - { 197, -5 }, /* (30) cmd ::= DROP TABLE ifexists ids cpxName */ - { 197, -5 }, /* (31) cmd ::= DROP STABLE ifexists ids cpxName */ - { 197, -4 }, /* (32) cmd ::= DROP DATABASE ifexists ids */ - { 197, -4 }, /* (33) cmd ::= DROP TOPIC ifexists ids */ - { 197, -3 }, /* (34) cmd ::= DROP FUNCTION ids */ - { 197, -3 }, /* (35) cmd ::= DROP DNODE ids */ - { 197, -3 }, /* (36) cmd ::= DROP USER ids */ - { 197, -3 }, /* (37) cmd ::= DROP ACCOUNT ids */ - { 197, -2 }, /* (38) cmd ::= USE ids */ - { 197, -3 }, /* (39) cmd ::= DESCRIBE ids cpxName */ - { 197, -5 }, /* (40) cmd ::= ALTER USER ids PASS ids */ - { 197, -5 }, /* (41) cmd ::= ALTER USER ids PRIVILEGE ids */ - { 197, -4 }, /* (42) cmd ::= ALTER DNODE ids ids */ - { 197, -5 }, /* (43) cmd ::= ALTER DNODE ids ids ids */ - { 197, -3 }, /* (44) cmd ::= ALTER LOCAL ids */ - { 197, -4 }, /* (45) cmd ::= ALTER LOCAL ids ids */ - { 197, -4 }, /* (46) cmd ::= ALTER DATABASE ids alter_db_optr */ - { 197, -4 }, /* (47) cmd ::= ALTER TOPIC ids alter_topic_optr */ - { 197, -4 }, /* (48) cmd ::= ALTER ACCOUNT ids acct_optr */ - { 197, -6 }, /* (49) cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ - { 197, -6 }, /* (50) cmd ::= COMPACT VNODES IN LP exprlist RP */ - { 199, -1 }, /* (51) ids ::= ID */ - { 199, -1 }, /* (52) ids ::= STRING */ - { 201, -2 }, /* (53) ifexists ::= IF EXISTS */ - { 201, 0 }, /* (54) ifexists ::= */ - { 206, -3 }, /* (55) ifnotexists ::= IF NOT EXISTS */ - { 206, 0 }, /* (56) ifnotexists ::= */ - { 197, -3 }, /* (57) cmd ::= CREATE DNODE ids */ - { 197, -6 }, /* (58) cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ - { 197, -5 }, /* (59) cmd ::= CREATE DATABASE ifnotexists ids db_optr */ - { 197, -5 }, /* (60) cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ - { 197, -8 }, /* (61) cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ - { 197, -9 }, /* (62) cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ - { 197, -5 }, /* (63) cmd ::= CREATE USER ids PASS ids */ - { 210, 0 }, /* (64) bufsize ::= */ - { 210, -2 }, /* (65) bufsize ::= BUFSIZE INTEGER */ - { 211, 0 }, /* (66) pps ::= */ - { 211, -2 }, /* (67) pps ::= PPS INTEGER */ - { 212, 0 }, /* (68) tseries ::= */ - { 212, -2 }, /* (69) tseries ::= TSERIES INTEGER */ - { 213, 0 }, /* (70) dbs ::= */ - { 213, -2 }, /* (71) dbs ::= DBS INTEGER */ - { 214, 0 }, /* (72) streams ::= */ - { 214, -2 }, /* (73) streams ::= STREAMS INTEGER */ - { 215, 0 }, /* (74) storage ::= */ - { 215, -2 }, /* (75) storage ::= STORAGE INTEGER */ - { 216, 0 }, /* (76) qtime ::= */ - { 216, -2 }, /* (77) qtime ::= QTIME INTEGER */ - { 217, 0 }, /* (78) users ::= */ - { 217, -2 }, /* (79) users ::= USERS INTEGER */ - { 218, 0 }, /* (80) conns ::= */ - { 218, -2 }, /* (81) conns ::= CONNS INTEGER */ - { 219, 0 }, /* (82) state ::= */ - { 219, -2 }, /* (83) state ::= STATE ids */ - { 204, -9 }, /* (84) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ - { 220, -3 }, /* (85) intitemlist ::= intitemlist COMMA intitem */ - { 220, -1 }, /* (86) intitemlist ::= intitem */ - { 221, -1 }, /* (87) intitem ::= INTEGER */ - { 222, -2 }, /* (88) keep ::= KEEP intitemlist */ - { 223, -2 }, /* (89) cache ::= CACHE INTEGER */ - { 224, -2 }, /* (90) replica ::= REPLICA INTEGER */ - { 225, -2 }, /* (91) quorum ::= QUORUM INTEGER */ - { 226, -2 }, /* (92) days ::= DAYS INTEGER */ - { 227, -2 }, /* (93) minrows ::= MINROWS INTEGER */ - { 228, -2 }, /* (94) maxrows ::= MAXROWS INTEGER */ - { 229, -2 }, /* (95) blocks ::= BLOCKS INTEGER */ - { 230, -2 }, /* (96) ctime ::= CTIME INTEGER */ - { 231, -2 }, /* (97) wal ::= WAL INTEGER */ - { 232, -2 }, /* (98) fsync ::= FSYNC INTEGER */ - { 233, -2 }, /* (99) comp ::= COMP INTEGER */ - { 234, -2 }, /* (100) prec ::= PRECISION STRING */ - { 235, -2 }, /* (101) update ::= UPDATE INTEGER */ - { 236, -2 }, /* (102) cachelast ::= CACHELAST INTEGER */ - { 237, -2 }, /* (103) partitions ::= PARTITIONS INTEGER */ - { 207, 0 }, /* (104) db_optr ::= */ - { 207, -2 }, /* (105) db_optr ::= db_optr cache */ - { 207, -2 }, /* (106) db_optr ::= db_optr replica */ - { 207, -2 }, /* (107) db_optr ::= db_optr quorum */ - { 207, -2 }, /* (108) db_optr ::= db_optr days */ - { 207, -2 }, /* (109) db_optr ::= db_optr minrows */ - { 207, -2 }, /* (110) db_optr ::= db_optr maxrows */ - { 207, -2 }, /* (111) db_optr ::= db_optr blocks */ - { 207, -2 }, /* (112) db_optr ::= db_optr ctime */ - { 207, -2 }, /* (113) db_optr ::= db_optr wal */ - { 207, -2 }, /* (114) db_optr ::= db_optr fsync */ - { 207, -2 }, /* (115) db_optr ::= db_optr comp */ - { 207, -2 }, /* (116) db_optr ::= db_optr prec */ - { 207, -2 }, /* (117) db_optr ::= db_optr keep */ - { 207, -2 }, /* (118) db_optr ::= db_optr update */ - { 207, -2 }, /* (119) db_optr ::= db_optr cachelast */ - { 208, -1 }, /* (120) topic_optr ::= db_optr */ - { 208, -2 }, /* (121) topic_optr ::= topic_optr partitions */ - { 202, 0 }, /* (122) alter_db_optr ::= */ - { 202, -2 }, /* (123) alter_db_optr ::= alter_db_optr replica */ - { 202, -2 }, /* (124) alter_db_optr ::= alter_db_optr quorum */ - { 202, -2 }, /* (125) alter_db_optr ::= alter_db_optr keep */ - { 202, -2 }, /* (126) alter_db_optr ::= alter_db_optr blocks */ - { 202, -2 }, /* (127) alter_db_optr ::= alter_db_optr comp */ - { 202, -2 }, /* (128) alter_db_optr ::= alter_db_optr update */ - { 202, -2 }, /* (129) alter_db_optr ::= alter_db_optr cachelast */ - { 203, -1 }, /* (130) alter_topic_optr ::= alter_db_optr */ - { 203, -2 }, /* (131) alter_topic_optr ::= alter_topic_optr partitions */ - { 209, -1 }, /* (132) typename ::= ids */ - { 209, -4 }, /* (133) typename ::= ids LP signed RP */ - { 209, -2 }, /* (134) typename ::= ids UNSIGNED */ - { 238, -1 }, /* (135) signed ::= INTEGER */ - { 238, -2 }, /* (136) signed ::= PLUS INTEGER */ - { 238, -2 }, /* (137) signed ::= MINUS INTEGER */ - { 197, -3 }, /* (138) cmd ::= CREATE TABLE create_table_args */ - { 197, -3 }, /* (139) cmd ::= CREATE TABLE create_stable_args */ - { 197, -3 }, /* (140) cmd ::= CREATE STABLE create_stable_args */ - { 197, -3 }, /* (141) cmd ::= CREATE TABLE create_table_list */ - { 241, -1 }, /* (142) create_table_list ::= create_from_stable */ - { 241, -2 }, /* (143) create_table_list ::= create_table_list create_from_stable */ - { 239, -6 }, /* (144) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ - { 240, -10 }, /* (145) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ - { 242, -10 }, /* (146) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ - { 242, -13 }, /* (147) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ - { 245, -3 }, /* (148) tagNamelist ::= tagNamelist COMMA ids */ - { 245, -1 }, /* (149) tagNamelist ::= ids */ - { 239, -5 }, /* (150) create_table_args ::= ifnotexists ids cpxName AS select */ - { 243, -3 }, /* (151) columnlist ::= columnlist COMMA column */ - { 243, -1 }, /* (152) columnlist ::= column */ - { 247, -2 }, /* (153) column ::= ids typename */ - { 244, -3 }, /* (154) tagitemlist ::= tagitemlist COMMA tagitem */ - { 244, -1 }, /* (155) tagitemlist ::= tagitem */ - { 248, -1 }, /* (156) tagitem ::= INTEGER */ - { 248, -1 }, /* (157) tagitem ::= FLOAT */ - { 248, -1 }, /* (158) tagitem ::= STRING */ - { 248, -1 }, /* (159) tagitem ::= BOOL */ - { 248, -1 }, /* (160) tagitem ::= NULL */ - { 248, -1 }, /* (161) tagitem ::= NOW */ - { 248, -2 }, /* (162) tagitem ::= MINUS INTEGER */ - { 248, -2 }, /* (163) tagitem ::= MINUS FLOAT */ - { 248, -2 }, /* (164) tagitem ::= PLUS INTEGER */ - { 248, -2 }, /* (165) tagitem ::= PLUS FLOAT */ - { 246, -14 }, /* (166) select ::= SELECT selcollist from where_opt interval_opt sliding_opt session_option windowstate_option fill_opt groupby_opt having_opt orderby_opt slimit_opt limit_opt */ - { 246, -3 }, /* (167) select ::= LP select RP */ - { 262, -1 }, /* (168) union ::= select */ - { 262, -4 }, /* (169) union ::= union UNION ALL select */ - { 197, -1 }, /* (170) cmd ::= union */ - { 246, -2 }, /* (171) select ::= SELECT selcollist */ - { 263, -2 }, /* (172) sclp ::= selcollist COMMA */ - { 263, 0 }, /* (173) sclp ::= */ - { 249, -4 }, /* (174) selcollist ::= sclp distinct expr as */ - { 249, -2 }, /* (175) selcollist ::= sclp STAR */ - { 266, -2 }, /* (176) as ::= AS ids */ - { 266, -1 }, /* (177) as ::= ids */ - { 266, 0 }, /* (178) as ::= */ - { 264, -1 }, /* (179) distinct ::= DISTINCT */ - { 264, 0 }, /* (180) distinct ::= */ - { 250, -2 }, /* (181) from ::= FROM tablelist */ - { 250, -2 }, /* (182) from ::= FROM sub */ - { 268, -3 }, /* (183) sub ::= LP union RP */ - { 268, -4 }, /* (184) sub ::= LP union RP ids */ - { 268, -6 }, /* (185) sub ::= sub COMMA LP union RP ids */ - { 267, -2 }, /* (186) tablelist ::= ids cpxName */ - { 267, -3 }, /* (187) tablelist ::= ids cpxName ids */ - { 267, -4 }, /* (188) tablelist ::= tablelist COMMA ids cpxName */ - { 267, -5 }, /* (189) tablelist ::= tablelist COMMA ids cpxName ids */ - { 269, -1 }, /* (190) tmvar ::= VARIABLE */ - { 252, -4 }, /* (191) interval_opt ::= INTERVAL LP tmvar RP */ - { 252, -6 }, /* (192) interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ - { 252, 0 }, /* (193) interval_opt ::= */ - { 254, 0 }, /* (194) session_option ::= */ - { 254, -7 }, /* (195) session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ - { 255, 0 }, /* (196) windowstate_option ::= */ - { 255, -4 }, /* (197) windowstate_option ::= STATE_WINDOW LP ids RP */ - { 256, 0 }, /* (198) fill_opt ::= */ - { 256, -6 }, /* (199) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ - { 256, -4 }, /* (200) fill_opt ::= FILL LP ID RP */ - { 253, -4 }, /* (201) sliding_opt ::= SLIDING LP tmvar RP */ - { 253, 0 }, /* (202) sliding_opt ::= */ - { 259, 0 }, /* (203) orderby_opt ::= */ - { 259, -3 }, /* (204) orderby_opt ::= ORDER BY sortlist */ - { 270, -4 }, /* (205) sortlist ::= sortlist COMMA item sortorder */ - { 270, -2 }, /* (206) sortlist ::= item sortorder */ - { 272, -2 }, /* (207) item ::= ids cpxName */ - { 273, -1 }, /* (208) sortorder ::= ASC */ - { 273, -1 }, /* (209) sortorder ::= DESC */ - { 273, 0 }, /* (210) sortorder ::= */ - { 257, 0 }, /* (211) groupby_opt ::= */ - { 257, -3 }, /* (212) groupby_opt ::= GROUP BY grouplist */ - { 274, -3 }, /* (213) grouplist ::= grouplist COMMA item */ - { 274, -1 }, /* (214) grouplist ::= item */ - { 258, 0 }, /* (215) having_opt ::= */ - { 258, -2 }, /* (216) having_opt ::= HAVING expr */ - { 261, 0 }, /* (217) limit_opt ::= */ - { 261, -2 }, /* (218) limit_opt ::= LIMIT signed */ - { 261, -4 }, /* (219) limit_opt ::= LIMIT signed OFFSET signed */ - { 261, -4 }, /* (220) limit_opt ::= LIMIT signed COMMA signed */ - { 260, 0 }, /* (221) slimit_opt ::= */ - { 260, -2 }, /* (222) slimit_opt ::= SLIMIT signed */ - { 260, -4 }, /* (223) slimit_opt ::= SLIMIT signed SOFFSET signed */ - { 260, -4 }, /* (224) slimit_opt ::= SLIMIT signed COMMA signed */ - { 251, 0 }, /* (225) where_opt ::= */ - { 251, -2 }, /* (226) where_opt ::= WHERE expr */ - { 265, -3 }, /* (227) expr ::= LP expr RP */ - { 265, -1 }, /* (228) expr ::= ID */ - { 265, -3 }, /* (229) expr ::= ID DOT ID */ - { 265, -3 }, /* (230) expr ::= ID DOT STAR */ - { 265, -1 }, /* (231) expr ::= INTEGER */ - { 265, -2 }, /* (232) expr ::= MINUS INTEGER */ - { 265, -2 }, /* (233) expr ::= PLUS INTEGER */ - { 265, -1 }, /* (234) expr ::= FLOAT */ - { 265, -2 }, /* (235) expr ::= MINUS FLOAT */ - { 265, -2 }, /* (236) expr ::= PLUS FLOAT */ - { 265, -1 }, /* (237) expr ::= STRING */ - { 265, -1 }, /* (238) expr ::= NOW */ - { 265, -1 }, /* (239) expr ::= VARIABLE */ - { 265, -2 }, /* (240) expr ::= PLUS VARIABLE */ - { 265, -2 }, /* (241) expr ::= MINUS VARIABLE */ - { 265, -1 }, /* (242) expr ::= BOOL */ - { 265, -1 }, /* (243) expr ::= NULL */ - { 265, -4 }, /* (244) expr ::= ID LP exprlist RP */ - { 265, -4 }, /* (245) expr ::= ID LP STAR RP */ - { 265, -3 }, /* (246) expr ::= expr IS NULL */ - { 265, -4 }, /* (247) expr ::= expr IS NOT NULL */ - { 265, -3 }, /* (248) expr ::= expr LT expr */ - { 265, -3 }, /* (249) expr ::= expr GT expr */ - { 265, -3 }, /* (250) expr ::= expr LE expr */ - { 265, -3 }, /* (251) expr ::= expr GE expr */ - { 265, -3 }, /* (252) expr ::= expr NE expr */ - { 265, -3 }, /* (253) expr ::= expr EQ expr */ - { 265, -5 }, /* (254) expr ::= expr BETWEEN expr AND expr */ - { 265, -3 }, /* (255) expr ::= expr AND expr */ - { 265, -3 }, /* (256) expr ::= expr OR expr */ - { 265, -3 }, /* (257) expr ::= expr PLUS expr */ - { 265, -3 }, /* (258) expr ::= expr MINUS expr */ - { 265, -3 }, /* (259) expr ::= expr STAR expr */ - { 265, -3 }, /* (260) expr ::= expr SLASH expr */ - { 265, -3 }, /* (261) expr ::= expr REM expr */ - { 265, -3 }, /* (262) expr ::= expr LIKE expr */ - { 265, -5 }, /* (263) expr ::= expr IN LP exprlist RP */ - { 205, -3 }, /* (264) exprlist ::= exprlist COMMA expritem */ - { 205, -1 }, /* (265) exprlist ::= expritem */ - { 275, -1 }, /* (266) expritem ::= expr */ - { 275, 0 }, /* (267) expritem ::= */ - { 197, -3 }, /* (268) cmd ::= RESET QUERY CACHE */ - { 197, -3 }, /* (269) cmd ::= SYNCDB ids REPLICA */ - { 197, -7 }, /* (270) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ - { 197, -7 }, /* (271) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ - { 197, -7 }, /* (272) cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist */ - { 197, -7 }, /* (273) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ - { 197, -7 }, /* (274) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ - { 197, -8 }, /* (275) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ - { 197, -9 }, /* (276) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ - { 197, -7 }, /* (277) cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist */ - { 197, -7 }, /* (278) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ - { 197, -7 }, /* (279) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ - { 197, -7 }, /* (280) cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist */ - { 197, -7 }, /* (281) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ - { 197, -7 }, /* (282) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ - { 197, -8 }, /* (283) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ - { 197, -9 }, /* (284) cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem */ - { 197, -7 }, /* (285) cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist */ - { 197, -3 }, /* (286) cmd ::= KILL CONNECTION INTEGER */ - { 197, -5 }, /* (287) cmd ::= KILL STREAM INTEGER COLON INTEGER */ - { 197, -5 }, /* (288) cmd ::= KILL QUERY INTEGER COLON INTEGER */ +/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side +** of that rule */ +static const YYCODETYPE yyRuleInfoLhs[] = { + 195, /* (0) program ::= cmd */ + 196, /* (1) cmd ::= SHOW DATABASES */ + 196, /* (2) cmd ::= SHOW TOPICS */ + 196, /* (3) cmd ::= SHOW FUNCTIONS */ + 196, /* (4) cmd ::= SHOW MNODES */ + 196, /* (5) cmd ::= SHOW DNODES */ + 196, /* (6) cmd ::= SHOW ACCOUNTS */ + 196, /* (7) cmd ::= SHOW USERS */ + 196, /* (8) cmd ::= SHOW MODULES */ + 196, /* (9) cmd ::= SHOW QUERIES */ + 196, /* (10) cmd ::= SHOW CONNECTIONS */ + 196, /* (11) cmd ::= SHOW STREAMS */ + 196, /* (12) cmd ::= SHOW VARIABLES */ + 196, /* (13) cmd ::= SHOW SCORES */ + 196, /* (14) cmd ::= SHOW GRANTS */ + 196, /* (15) cmd ::= SHOW VNODES */ + 196, /* (16) cmd ::= SHOW VNODES ids */ + 198, /* (17) dbPrefix ::= */ + 198, /* (18) dbPrefix ::= ids DOT */ + 199, /* (19) cpxName ::= */ + 199, /* (20) cpxName ::= DOT ids */ + 196, /* (21) cmd ::= SHOW CREATE TABLE ids cpxName */ + 196, /* (22) cmd ::= SHOW CREATE STABLE ids cpxName */ + 196, /* (23) cmd ::= SHOW CREATE DATABASE ids */ + 196, /* (24) cmd ::= SHOW dbPrefix TABLES */ + 196, /* (25) cmd ::= SHOW dbPrefix TABLES LIKE ids */ + 196, /* (26) cmd ::= SHOW dbPrefix STABLES */ + 196, /* (27) cmd ::= SHOW dbPrefix STABLES LIKE ids */ + 196, /* (28) cmd ::= SHOW dbPrefix VGROUPS */ + 196, /* (29) cmd ::= SHOW dbPrefix VGROUPS ids */ + 196, /* (30) cmd ::= DROP TABLE ifexists ids cpxName */ + 196, /* (31) cmd ::= DROP STABLE ifexists ids cpxName */ + 196, /* (32) cmd ::= DROP DATABASE ifexists ids */ + 196, /* (33) cmd ::= DROP TOPIC ifexists ids */ + 196, /* (34) cmd ::= DROP FUNCTION ids */ + 196, /* (35) cmd ::= DROP DNODE ids */ + 196, /* (36) cmd ::= DROP USER ids */ + 196, /* (37) cmd ::= DROP ACCOUNT ids */ + 196, /* (38) cmd ::= USE ids */ + 196, /* (39) cmd ::= DESCRIBE ids cpxName */ + 196, /* (40) cmd ::= ALTER USER ids PASS ids */ + 196, /* (41) cmd ::= ALTER USER ids PRIVILEGE ids */ + 196, /* (42) cmd ::= ALTER DNODE ids ids */ + 196, /* (43) cmd ::= ALTER DNODE ids ids ids */ + 196, /* (44) cmd ::= ALTER LOCAL ids */ + 196, /* (45) cmd ::= ALTER LOCAL ids ids */ + 196, /* (46) cmd ::= ALTER DATABASE ids alter_db_optr */ + 196, /* (47) cmd ::= ALTER TOPIC ids alter_topic_optr */ + 196, /* (48) cmd ::= ALTER ACCOUNT ids acct_optr */ + 196, /* (49) cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ + 196, /* (50) cmd ::= COMPACT VNODES IN LP exprlist RP */ + 197, /* (51) ids ::= ID */ + 197, /* (52) ids ::= STRING */ + 200, /* (53) ifexists ::= IF EXISTS */ + 200, /* (54) ifexists ::= */ + 205, /* (55) ifnotexists ::= IF NOT EXISTS */ + 205, /* (56) ifnotexists ::= */ + 196, /* (57) cmd ::= CREATE DNODE ids */ + 196, /* (58) cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ + 196, /* (59) cmd ::= CREATE DATABASE ifnotexists ids db_optr */ + 196, /* (60) cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ + 196, /* (61) cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ + 196, /* (62) cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ + 196, /* (63) cmd ::= CREATE USER ids PASS ids */ + 209, /* (64) bufsize ::= */ + 209, /* (65) bufsize ::= BUFSIZE INTEGER */ + 210, /* (66) pps ::= */ + 210, /* (67) pps ::= PPS INTEGER */ + 211, /* (68) tseries ::= */ + 211, /* (69) tseries ::= TSERIES INTEGER */ + 212, /* (70) dbs ::= */ + 212, /* (71) dbs ::= DBS INTEGER */ + 213, /* (72) streams ::= */ + 213, /* (73) streams ::= STREAMS INTEGER */ + 214, /* (74) storage ::= */ + 214, /* (75) storage ::= STORAGE INTEGER */ + 215, /* (76) qtime ::= */ + 215, /* (77) qtime ::= QTIME INTEGER */ + 216, /* (78) users ::= */ + 216, /* (79) users ::= USERS INTEGER */ + 217, /* (80) conns ::= */ + 217, /* (81) conns ::= CONNS INTEGER */ + 218, /* (82) state ::= */ + 218, /* (83) state ::= STATE ids */ + 203, /* (84) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ + 219, /* (85) intitemlist ::= intitemlist COMMA intitem */ + 219, /* (86) intitemlist ::= intitem */ + 220, /* (87) intitem ::= INTEGER */ + 221, /* (88) keep ::= KEEP intitemlist */ + 222, /* (89) cache ::= CACHE INTEGER */ + 223, /* (90) replica ::= REPLICA INTEGER */ + 224, /* (91) quorum ::= QUORUM INTEGER */ + 225, /* (92) days ::= DAYS INTEGER */ + 226, /* (93) minrows ::= MINROWS INTEGER */ + 227, /* (94) maxrows ::= MAXROWS INTEGER */ + 228, /* (95) blocks ::= BLOCKS INTEGER */ + 229, /* (96) ctime ::= CTIME INTEGER */ + 230, /* (97) wal ::= WAL INTEGER */ + 231, /* (98) fsync ::= FSYNC INTEGER */ + 232, /* (99) comp ::= COMP INTEGER */ + 233, /* (100) prec ::= PRECISION STRING */ + 234, /* (101) update ::= UPDATE INTEGER */ + 235, /* (102) cachelast ::= CACHELAST INTEGER */ + 236, /* (103) partitions ::= PARTITIONS INTEGER */ + 206, /* (104) db_optr ::= */ + 206, /* (105) db_optr ::= db_optr cache */ + 206, /* (106) db_optr ::= db_optr replica */ + 206, /* (107) db_optr ::= db_optr quorum */ + 206, /* (108) db_optr ::= db_optr days */ + 206, /* (109) db_optr ::= db_optr minrows */ + 206, /* (110) db_optr ::= db_optr maxrows */ + 206, /* (111) db_optr ::= db_optr blocks */ + 206, /* (112) db_optr ::= db_optr ctime */ + 206, /* (113) db_optr ::= db_optr wal */ + 206, /* (114) db_optr ::= db_optr fsync */ + 206, /* (115) db_optr ::= db_optr comp */ + 206, /* (116) db_optr ::= db_optr prec */ + 206, /* (117) db_optr ::= db_optr keep */ + 206, /* (118) db_optr ::= db_optr update */ + 206, /* (119) db_optr ::= db_optr cachelast */ + 207, /* (120) topic_optr ::= db_optr */ + 207, /* (121) topic_optr ::= topic_optr partitions */ + 201, /* (122) alter_db_optr ::= */ + 201, /* (123) alter_db_optr ::= alter_db_optr replica */ + 201, /* (124) alter_db_optr ::= alter_db_optr quorum */ + 201, /* (125) alter_db_optr ::= alter_db_optr keep */ + 201, /* (126) alter_db_optr ::= alter_db_optr blocks */ + 201, /* (127) alter_db_optr ::= alter_db_optr comp */ + 201, /* (128) alter_db_optr ::= alter_db_optr update */ + 201, /* (129) alter_db_optr ::= alter_db_optr cachelast */ + 202, /* (130) alter_topic_optr ::= alter_db_optr */ + 202, /* (131) alter_topic_optr ::= alter_topic_optr partitions */ + 208, /* (132) typename ::= ids */ + 208, /* (133) typename ::= ids LP signed RP */ + 208, /* (134) typename ::= ids UNSIGNED */ + 237, /* (135) signed ::= INTEGER */ + 237, /* (136) signed ::= PLUS INTEGER */ + 237, /* (137) signed ::= MINUS INTEGER */ + 196, /* (138) cmd ::= CREATE TABLE create_table_args */ + 196, /* (139) cmd ::= CREATE TABLE create_stable_args */ + 196, /* (140) cmd ::= CREATE STABLE create_stable_args */ + 196, /* (141) cmd ::= CREATE TABLE create_table_list */ + 240, /* (142) create_table_list ::= create_from_stable */ + 240, /* (143) create_table_list ::= create_table_list create_from_stable */ + 238, /* (144) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ + 239, /* (145) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ + 241, /* (146) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ + 241, /* (147) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ + 244, /* (148) tagNamelist ::= tagNamelist COMMA ids */ + 244, /* (149) tagNamelist ::= ids */ + 238, /* (150) create_table_args ::= ifnotexists ids cpxName AS select */ + 242, /* (151) columnlist ::= columnlist COMMA column */ + 242, /* (152) columnlist ::= column */ + 246, /* (153) column ::= ids typename */ + 243, /* (154) tagitemlist ::= tagitemlist COMMA tagitem */ + 243, /* (155) tagitemlist ::= tagitem */ + 247, /* (156) tagitem ::= INTEGER */ + 247, /* (157) tagitem ::= FLOAT */ + 247, /* (158) tagitem ::= STRING */ + 247, /* (159) tagitem ::= BOOL */ + 247, /* (160) tagitem ::= NULL */ + 247, /* (161) tagitem ::= NOW */ + 247, /* (162) tagitem ::= MINUS INTEGER */ + 247, /* (163) tagitem ::= MINUS FLOAT */ + 247, /* (164) tagitem ::= PLUS INTEGER */ + 247, /* (165) tagitem ::= PLUS FLOAT */ + 245, /* (166) select ::= SELECT selcollist from where_opt interval_opt sliding_opt session_option windowstate_option fill_opt groupby_opt having_opt orderby_opt slimit_opt limit_opt */ + 245, /* (167) select ::= LP select RP */ + 261, /* (168) union ::= select */ + 261, /* (169) union ::= union UNION ALL select */ + 196, /* (170) cmd ::= union */ + 245, /* (171) select ::= SELECT selcollist */ + 262, /* (172) sclp ::= selcollist COMMA */ + 262, /* (173) sclp ::= */ + 248, /* (174) selcollist ::= sclp distinct expr as */ + 248, /* (175) selcollist ::= sclp STAR */ + 265, /* (176) as ::= AS ids */ + 265, /* (177) as ::= ids */ + 265, /* (178) as ::= */ + 263, /* (179) distinct ::= DISTINCT */ + 263, /* (180) distinct ::= */ + 249, /* (181) from ::= FROM tablelist */ + 249, /* (182) from ::= FROM sub */ + 267, /* (183) sub ::= LP union RP */ + 267, /* (184) sub ::= LP union RP ids */ + 267, /* (185) sub ::= sub COMMA LP union RP ids */ + 266, /* (186) tablelist ::= ids cpxName */ + 266, /* (187) tablelist ::= ids cpxName ids */ + 266, /* (188) tablelist ::= tablelist COMMA ids cpxName */ + 266, /* (189) tablelist ::= tablelist COMMA ids cpxName ids */ + 268, /* (190) tmvar ::= VARIABLE */ + 251, /* (191) interval_opt ::= INTERVAL LP tmvar RP */ + 251, /* (192) interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ + 251, /* (193) interval_opt ::= */ + 253, /* (194) session_option ::= */ + 253, /* (195) session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ + 254, /* (196) windowstate_option ::= */ + 254, /* (197) windowstate_option ::= STATE_WINDOW LP ids RP */ + 255, /* (198) fill_opt ::= */ + 255, /* (199) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ + 255, /* (200) fill_opt ::= FILL LP ID RP */ + 252, /* (201) sliding_opt ::= SLIDING LP tmvar RP */ + 252, /* (202) sliding_opt ::= */ + 258, /* (203) orderby_opt ::= */ + 258, /* (204) orderby_opt ::= ORDER BY sortlist */ + 269, /* (205) sortlist ::= sortlist COMMA item sortorder */ + 269, /* (206) sortlist ::= item sortorder */ + 271, /* (207) item ::= ids cpxName */ + 272, /* (208) sortorder ::= ASC */ + 272, /* (209) sortorder ::= DESC */ + 272, /* (210) sortorder ::= */ + 256, /* (211) groupby_opt ::= */ + 256, /* (212) groupby_opt ::= GROUP BY grouplist */ + 273, /* (213) grouplist ::= grouplist COMMA item */ + 273, /* (214) grouplist ::= item */ + 257, /* (215) having_opt ::= */ + 257, /* (216) having_opt ::= HAVING expr */ + 260, /* (217) limit_opt ::= */ + 260, /* (218) limit_opt ::= LIMIT signed */ + 260, /* (219) limit_opt ::= LIMIT signed OFFSET signed */ + 260, /* (220) limit_opt ::= LIMIT signed COMMA signed */ + 259, /* (221) slimit_opt ::= */ + 259, /* (222) slimit_opt ::= SLIMIT signed */ + 259, /* (223) slimit_opt ::= SLIMIT signed SOFFSET signed */ + 259, /* (224) slimit_opt ::= SLIMIT signed COMMA signed */ + 250, /* (225) where_opt ::= */ + 250, /* (226) where_opt ::= WHERE expr */ + 264, /* (227) expr ::= LP expr RP */ + 264, /* (228) expr ::= ID */ + 264, /* (229) expr ::= ID DOT ID */ + 264, /* (230) expr ::= ID DOT STAR */ + 264, /* (231) expr ::= INTEGER */ + 264, /* (232) expr ::= MINUS INTEGER */ + 264, /* (233) expr ::= PLUS INTEGER */ + 264, /* (234) expr ::= FLOAT */ + 264, /* (235) expr ::= MINUS FLOAT */ + 264, /* (236) expr ::= PLUS FLOAT */ + 264, /* (237) expr ::= STRING */ + 264, /* (238) expr ::= NOW */ + 264, /* (239) expr ::= VARIABLE */ + 264, /* (240) expr ::= PLUS VARIABLE */ + 264, /* (241) expr ::= MINUS VARIABLE */ + 264, /* (242) expr ::= BOOL */ + 264, /* (243) expr ::= NULL */ + 264, /* (244) expr ::= ID LP exprlist RP */ + 264, /* (245) expr ::= ID LP STAR RP */ + 264, /* (246) expr ::= expr IS NULL */ + 264, /* (247) expr ::= expr IS NOT NULL */ + 264, /* (248) expr ::= expr LT expr */ + 264, /* (249) expr ::= expr GT expr */ + 264, /* (250) expr ::= expr LE expr */ + 264, /* (251) expr ::= expr GE expr */ + 264, /* (252) expr ::= expr NE expr */ + 264, /* (253) expr ::= expr EQ expr */ + 264, /* (254) expr ::= expr BETWEEN expr AND expr */ + 264, /* (255) expr ::= expr AND expr */ + 264, /* (256) expr ::= expr OR expr */ + 264, /* (257) expr ::= expr PLUS expr */ + 264, /* (258) expr ::= expr MINUS expr */ + 264, /* (259) expr ::= expr STAR expr */ + 264, /* (260) expr ::= expr SLASH expr */ + 264, /* (261) expr ::= expr REM expr */ + 264, /* (262) expr ::= expr LIKE expr */ + 264, /* (263) expr ::= expr IN LP exprlist RP */ + 204, /* (264) exprlist ::= exprlist COMMA expritem */ + 204, /* (265) exprlist ::= expritem */ + 274, /* (266) expritem ::= expr */ + 274, /* (267) expritem ::= */ + 196, /* (268) cmd ::= RESET QUERY CACHE */ + 196, /* (269) cmd ::= SYNCDB ids REPLICA */ + 196, /* (270) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ + 196, /* (271) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ + 196, /* (272) cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist */ + 196, /* (273) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ + 196, /* (274) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ + 196, /* (275) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ + 196, /* (276) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ + 196, /* (277) cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist */ + 196, /* (278) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ + 196, /* (279) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ + 196, /* (280) cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist */ + 196, /* (281) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ + 196, /* (282) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ + 196, /* (283) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ + 196, /* (284) cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem */ + 196, /* (285) cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist */ + 196, /* (286) cmd ::= KILL CONNECTION INTEGER */ + 196, /* (287) cmd ::= KILL STREAM INTEGER COLON INTEGER */ + 196, /* (288) cmd ::= KILL QUERY INTEGER COLON INTEGER */ +}; + +/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number +** of symbols on the right-hand side of that rule. */ +static const signed char yyRuleInfoNRhs[] = { + -1, /* (0) program ::= cmd */ + -2, /* (1) cmd ::= SHOW DATABASES */ + -2, /* (2) cmd ::= SHOW TOPICS */ + -2, /* (3) cmd ::= SHOW FUNCTIONS */ + -2, /* (4) cmd ::= SHOW MNODES */ + -2, /* (5) cmd ::= SHOW DNODES */ + -2, /* (6) cmd ::= SHOW ACCOUNTS */ + -2, /* (7) cmd ::= SHOW USERS */ + -2, /* (8) cmd ::= SHOW MODULES */ + -2, /* (9) cmd ::= SHOW QUERIES */ + -2, /* (10) cmd ::= SHOW CONNECTIONS */ + -2, /* (11) cmd ::= SHOW STREAMS */ + -2, /* (12) cmd ::= SHOW VARIABLES */ + -2, /* (13) cmd ::= SHOW SCORES */ + -2, /* (14) cmd ::= SHOW GRANTS */ + -2, /* (15) cmd ::= SHOW VNODES */ + -3, /* (16) cmd ::= SHOW VNODES ids */ + 0, /* (17) dbPrefix ::= */ + -2, /* (18) dbPrefix ::= ids DOT */ + 0, /* (19) cpxName ::= */ + -2, /* (20) cpxName ::= DOT ids */ + -5, /* (21) cmd ::= SHOW CREATE TABLE ids cpxName */ + -5, /* (22) cmd ::= SHOW CREATE STABLE ids cpxName */ + -4, /* (23) cmd ::= SHOW CREATE DATABASE ids */ + -3, /* (24) cmd ::= SHOW dbPrefix TABLES */ + -5, /* (25) cmd ::= SHOW dbPrefix TABLES LIKE ids */ + -3, /* (26) cmd ::= SHOW dbPrefix STABLES */ + -5, /* (27) cmd ::= SHOW dbPrefix STABLES LIKE ids */ + -3, /* (28) cmd ::= SHOW dbPrefix VGROUPS */ + -4, /* (29) cmd ::= SHOW dbPrefix VGROUPS ids */ + -5, /* (30) cmd ::= DROP TABLE ifexists ids cpxName */ + -5, /* (31) cmd ::= DROP STABLE ifexists ids cpxName */ + -4, /* (32) cmd ::= DROP DATABASE ifexists ids */ + -4, /* (33) cmd ::= DROP TOPIC ifexists ids */ + -3, /* (34) cmd ::= DROP FUNCTION ids */ + -3, /* (35) cmd ::= DROP DNODE ids */ + -3, /* (36) cmd ::= DROP USER ids */ + -3, /* (37) cmd ::= DROP ACCOUNT ids */ + -2, /* (38) cmd ::= USE ids */ + -3, /* (39) cmd ::= DESCRIBE ids cpxName */ + -5, /* (40) cmd ::= ALTER USER ids PASS ids */ + -5, /* (41) cmd ::= ALTER USER ids PRIVILEGE ids */ + -4, /* (42) cmd ::= ALTER DNODE ids ids */ + -5, /* (43) cmd ::= ALTER DNODE ids ids ids */ + -3, /* (44) cmd ::= ALTER LOCAL ids */ + -4, /* (45) cmd ::= ALTER LOCAL ids ids */ + -4, /* (46) cmd ::= ALTER DATABASE ids alter_db_optr */ + -4, /* (47) cmd ::= ALTER TOPIC ids alter_topic_optr */ + -4, /* (48) cmd ::= ALTER ACCOUNT ids acct_optr */ + -6, /* (49) cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ + -6, /* (50) cmd ::= COMPACT VNODES IN LP exprlist RP */ + -1, /* (51) ids ::= ID */ + -1, /* (52) ids ::= STRING */ + -2, /* (53) ifexists ::= IF EXISTS */ + 0, /* (54) ifexists ::= */ + -3, /* (55) ifnotexists ::= IF NOT EXISTS */ + 0, /* (56) ifnotexists ::= */ + -3, /* (57) cmd ::= CREATE DNODE ids */ + -6, /* (58) cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ + -5, /* (59) cmd ::= CREATE DATABASE ifnotexists ids db_optr */ + -5, /* (60) cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ + -8, /* (61) cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ + -9, /* (62) cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ + -5, /* (63) cmd ::= CREATE USER ids PASS ids */ + 0, /* (64) bufsize ::= */ + -2, /* (65) bufsize ::= BUFSIZE INTEGER */ + 0, /* (66) pps ::= */ + -2, /* (67) pps ::= PPS INTEGER */ + 0, /* (68) tseries ::= */ + -2, /* (69) tseries ::= TSERIES INTEGER */ + 0, /* (70) dbs ::= */ + -2, /* (71) dbs ::= DBS INTEGER */ + 0, /* (72) streams ::= */ + -2, /* (73) streams ::= STREAMS INTEGER */ + 0, /* (74) storage ::= */ + -2, /* (75) storage ::= STORAGE INTEGER */ + 0, /* (76) qtime ::= */ + -2, /* (77) qtime ::= QTIME INTEGER */ + 0, /* (78) users ::= */ + -2, /* (79) users ::= USERS INTEGER */ + 0, /* (80) conns ::= */ + -2, /* (81) conns ::= CONNS INTEGER */ + 0, /* (82) state ::= */ + -2, /* (83) state ::= STATE ids */ + -9, /* (84) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ + -3, /* (85) intitemlist ::= intitemlist COMMA intitem */ + -1, /* (86) intitemlist ::= intitem */ + -1, /* (87) intitem ::= INTEGER */ + -2, /* (88) keep ::= KEEP intitemlist */ + -2, /* (89) cache ::= CACHE INTEGER */ + -2, /* (90) replica ::= REPLICA INTEGER */ + -2, /* (91) quorum ::= QUORUM INTEGER */ + -2, /* (92) days ::= DAYS INTEGER */ + -2, /* (93) minrows ::= MINROWS INTEGER */ + -2, /* (94) maxrows ::= MAXROWS INTEGER */ + -2, /* (95) blocks ::= BLOCKS INTEGER */ + -2, /* (96) ctime ::= CTIME INTEGER */ + -2, /* (97) wal ::= WAL INTEGER */ + -2, /* (98) fsync ::= FSYNC INTEGER */ + -2, /* (99) comp ::= COMP INTEGER */ + -2, /* (100) prec ::= PRECISION STRING */ + -2, /* (101) update ::= UPDATE INTEGER */ + -2, /* (102) cachelast ::= CACHELAST INTEGER */ + -2, /* (103) partitions ::= PARTITIONS INTEGER */ + 0, /* (104) db_optr ::= */ + -2, /* (105) db_optr ::= db_optr cache */ + -2, /* (106) db_optr ::= db_optr replica */ + -2, /* (107) db_optr ::= db_optr quorum */ + -2, /* (108) db_optr ::= db_optr days */ + -2, /* (109) db_optr ::= db_optr minrows */ + -2, /* (110) db_optr ::= db_optr maxrows */ + -2, /* (111) db_optr ::= db_optr blocks */ + -2, /* (112) db_optr ::= db_optr ctime */ + -2, /* (113) db_optr ::= db_optr wal */ + -2, /* (114) db_optr ::= db_optr fsync */ + -2, /* (115) db_optr ::= db_optr comp */ + -2, /* (116) db_optr ::= db_optr prec */ + -2, /* (117) db_optr ::= db_optr keep */ + -2, /* (118) db_optr ::= db_optr update */ + -2, /* (119) db_optr ::= db_optr cachelast */ + -1, /* (120) topic_optr ::= db_optr */ + -2, /* (121) topic_optr ::= topic_optr partitions */ + 0, /* (122) alter_db_optr ::= */ + -2, /* (123) alter_db_optr ::= alter_db_optr replica */ + -2, /* (124) alter_db_optr ::= alter_db_optr quorum */ + -2, /* (125) alter_db_optr ::= alter_db_optr keep */ + -2, /* (126) alter_db_optr ::= alter_db_optr blocks */ + -2, /* (127) alter_db_optr ::= alter_db_optr comp */ + -2, /* (128) alter_db_optr ::= alter_db_optr update */ + -2, /* (129) alter_db_optr ::= alter_db_optr cachelast */ + -1, /* (130) alter_topic_optr ::= alter_db_optr */ + -2, /* (131) alter_topic_optr ::= alter_topic_optr partitions */ + -1, /* (132) typename ::= ids */ + -4, /* (133) typename ::= ids LP signed RP */ + -2, /* (134) typename ::= ids UNSIGNED */ + -1, /* (135) signed ::= INTEGER */ + -2, /* (136) signed ::= PLUS INTEGER */ + -2, /* (137) signed ::= MINUS INTEGER */ + -3, /* (138) cmd ::= CREATE TABLE create_table_args */ + -3, /* (139) cmd ::= CREATE TABLE create_stable_args */ + -3, /* (140) cmd ::= CREATE STABLE create_stable_args */ + -3, /* (141) cmd ::= CREATE TABLE create_table_list */ + -1, /* (142) create_table_list ::= create_from_stable */ + -2, /* (143) create_table_list ::= create_table_list create_from_stable */ + -6, /* (144) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ + -10, /* (145) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ + -10, /* (146) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ + -13, /* (147) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ + -3, /* (148) tagNamelist ::= tagNamelist COMMA ids */ + -1, /* (149) tagNamelist ::= ids */ + -5, /* (150) create_table_args ::= ifnotexists ids cpxName AS select */ + -3, /* (151) columnlist ::= columnlist COMMA column */ + -1, /* (152) columnlist ::= column */ + -2, /* (153) column ::= ids typename */ + -3, /* (154) tagitemlist ::= tagitemlist COMMA tagitem */ + -1, /* (155) tagitemlist ::= tagitem */ + -1, /* (156) tagitem ::= INTEGER */ + -1, /* (157) tagitem ::= FLOAT */ + -1, /* (158) tagitem ::= STRING */ + -1, /* (159) tagitem ::= BOOL */ + -1, /* (160) tagitem ::= NULL */ + -1, /* (161) tagitem ::= NOW */ + -2, /* (162) tagitem ::= MINUS INTEGER */ + -2, /* (163) tagitem ::= MINUS FLOAT */ + -2, /* (164) tagitem ::= PLUS INTEGER */ + -2, /* (165) tagitem ::= PLUS FLOAT */ + -14, /* (166) select ::= SELECT selcollist from where_opt interval_opt sliding_opt session_option windowstate_option fill_opt groupby_opt having_opt orderby_opt slimit_opt limit_opt */ + -3, /* (167) select ::= LP select RP */ + -1, /* (168) union ::= select */ + -4, /* (169) union ::= union UNION ALL select */ + -1, /* (170) cmd ::= union */ + -2, /* (171) select ::= SELECT selcollist */ + -2, /* (172) sclp ::= selcollist COMMA */ + 0, /* (173) sclp ::= */ + -4, /* (174) selcollist ::= sclp distinct expr as */ + -2, /* (175) selcollist ::= sclp STAR */ + -2, /* (176) as ::= AS ids */ + -1, /* (177) as ::= ids */ + 0, /* (178) as ::= */ + -1, /* (179) distinct ::= DISTINCT */ + 0, /* (180) distinct ::= */ + -2, /* (181) from ::= FROM tablelist */ + -2, /* (182) from ::= FROM sub */ + -3, /* (183) sub ::= LP union RP */ + -4, /* (184) sub ::= LP union RP ids */ + -6, /* (185) sub ::= sub COMMA LP union RP ids */ + -2, /* (186) tablelist ::= ids cpxName */ + -3, /* (187) tablelist ::= ids cpxName ids */ + -4, /* (188) tablelist ::= tablelist COMMA ids cpxName */ + -5, /* (189) tablelist ::= tablelist COMMA ids cpxName ids */ + -1, /* (190) tmvar ::= VARIABLE */ + -4, /* (191) interval_opt ::= INTERVAL LP tmvar RP */ + -6, /* (192) interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ + 0, /* (193) interval_opt ::= */ + 0, /* (194) session_option ::= */ + -7, /* (195) session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ + 0, /* (196) windowstate_option ::= */ + -4, /* (197) windowstate_option ::= STATE_WINDOW LP ids RP */ + 0, /* (198) fill_opt ::= */ + -6, /* (199) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ + -4, /* (200) fill_opt ::= FILL LP ID RP */ + -4, /* (201) sliding_opt ::= SLIDING LP tmvar RP */ + 0, /* (202) sliding_opt ::= */ + 0, /* (203) orderby_opt ::= */ + -3, /* (204) orderby_opt ::= ORDER BY sortlist */ + -4, /* (205) sortlist ::= sortlist COMMA item sortorder */ + -2, /* (206) sortlist ::= item sortorder */ + -2, /* (207) item ::= ids cpxName */ + -1, /* (208) sortorder ::= ASC */ + -1, /* (209) sortorder ::= DESC */ + 0, /* (210) sortorder ::= */ + 0, /* (211) groupby_opt ::= */ + -3, /* (212) groupby_opt ::= GROUP BY grouplist */ + -3, /* (213) grouplist ::= grouplist COMMA item */ + -1, /* (214) grouplist ::= item */ + 0, /* (215) having_opt ::= */ + -2, /* (216) having_opt ::= HAVING expr */ + 0, /* (217) limit_opt ::= */ + -2, /* (218) limit_opt ::= LIMIT signed */ + -4, /* (219) limit_opt ::= LIMIT signed OFFSET signed */ + -4, /* (220) limit_opt ::= LIMIT signed COMMA signed */ + 0, /* (221) slimit_opt ::= */ + -2, /* (222) slimit_opt ::= SLIMIT signed */ + -4, /* (223) slimit_opt ::= SLIMIT signed SOFFSET signed */ + -4, /* (224) slimit_opt ::= SLIMIT signed COMMA signed */ + 0, /* (225) where_opt ::= */ + -2, /* (226) where_opt ::= WHERE expr */ + -3, /* (227) expr ::= LP expr RP */ + -1, /* (228) expr ::= ID */ + -3, /* (229) expr ::= ID DOT ID */ + -3, /* (230) expr ::= ID DOT STAR */ + -1, /* (231) expr ::= INTEGER */ + -2, /* (232) expr ::= MINUS INTEGER */ + -2, /* (233) expr ::= PLUS INTEGER */ + -1, /* (234) expr ::= FLOAT */ + -2, /* (235) expr ::= MINUS FLOAT */ + -2, /* (236) expr ::= PLUS FLOAT */ + -1, /* (237) expr ::= STRING */ + -1, /* (238) expr ::= NOW */ + -1, /* (239) expr ::= VARIABLE */ + -2, /* (240) expr ::= PLUS VARIABLE */ + -2, /* (241) expr ::= MINUS VARIABLE */ + -1, /* (242) expr ::= BOOL */ + -1, /* (243) expr ::= NULL */ + -4, /* (244) expr ::= ID LP exprlist RP */ + -4, /* (245) expr ::= ID LP STAR RP */ + -3, /* (246) expr ::= expr IS NULL */ + -4, /* (247) expr ::= expr IS NOT NULL */ + -3, /* (248) expr ::= expr LT expr */ + -3, /* (249) expr ::= expr GT expr */ + -3, /* (250) expr ::= expr LE expr */ + -3, /* (251) expr ::= expr GE expr */ + -3, /* (252) expr ::= expr NE expr */ + -3, /* (253) expr ::= expr EQ expr */ + -5, /* (254) expr ::= expr BETWEEN expr AND expr */ + -3, /* (255) expr ::= expr AND expr */ + -3, /* (256) expr ::= expr OR expr */ + -3, /* (257) expr ::= expr PLUS expr */ + -3, /* (258) expr ::= expr MINUS expr */ + -3, /* (259) expr ::= expr STAR expr */ + -3, /* (260) expr ::= expr SLASH expr */ + -3, /* (261) expr ::= expr REM expr */ + -3, /* (262) expr ::= expr LIKE expr */ + -5, /* (263) expr ::= expr IN LP exprlist RP */ + -3, /* (264) exprlist ::= exprlist COMMA expritem */ + -1, /* (265) exprlist ::= expritem */ + -1, /* (266) expritem ::= expr */ + 0, /* (267) expritem ::= */ + -3, /* (268) cmd ::= RESET QUERY CACHE */ + -3, /* (269) cmd ::= SYNCDB ids REPLICA */ + -7, /* (270) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ + -7, /* (271) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ + -7, /* (272) cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist */ + -7, /* (273) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ + -7, /* (274) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ + -8, /* (275) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ + -9, /* (276) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ + -7, /* (277) cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist */ + -7, /* (278) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ + -7, /* (279) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ + -7, /* (280) cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist */ + -7, /* (281) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ + -7, /* (282) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ + -8, /* (283) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ + -9, /* (284) cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem */ + -7, /* (285) cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist */ + -3, /* (286) cmd ::= KILL CONNECTION INTEGER */ + -5, /* (287) cmd ::= KILL STREAM INTEGER COLON INTEGER */ + -5, /* (288) cmd ::= KILL QUERY INTEGER COLON INTEGER */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -2128,30 +2451,34 @@ static void yy_accept(yyParser*); /* Forward Declaration */ ** only called from one place, optimizing compilers will in-line it, which ** means that the extra parameters have no performance impact. */ -static void yy_reduce( +static YYACTIONTYPE yy_reduce( yyParser *yypParser, /* The parser */ unsigned int yyruleno, /* Number of the rule by which to reduce */ int yyLookahead, /* Lookahead token, or YYNOCODE if none */ ParseTOKENTYPE yyLookaheadToken /* Value of the lookahead token */ + ParseCTX_PDECL /* %extra_context */ ){ int yygoto; /* The next state */ - int yyact; /* The next action */ + YYACTIONTYPE yyact; /* The next action */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ - ParseARG_FETCH; + ParseARG_FETCH (void)yyLookahead; (void)yyLookaheadToken; yymsp = yypParser->yytos; #ifndef NDEBUG if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ - yysize = yyRuleInfo[yyruleno].nrhs; + yysize = yyRuleInfoNRhs[yyruleno]; if( yysize ){ - fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n", + fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n", yyTracePrompt, - yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno); + yyruleno, yyRuleName[yyruleno], + yyrulenoyytos - yypParser->yystack)>yypParser->yyhwm ){ yypParser->yyhwm++; @@ -2169,13 +2496,19 @@ static void yy_reduce( #if YYSTACKDEPTH>0 if( yypParser->yytos>=yypParser->yystackEnd ){ yyStackOverflow(yypParser); - return; + /* The call to yyStackOverflow() above pops the stack until it is + ** empty, causing the main parser loop to exit. So the return value + ** is never used and does not matter. */ + return 0; } #else if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){ if( yyGrowStack(yypParser) ){ yyStackOverflow(yypParser); - return; + /* The call to yyStackOverflow() above pops the stack until it is + ** empty, causing the main parser loop to exit. So the return value + ** is never used and does not matter. */ + return 0; } yymsp = yypParser->yytos; } @@ -2197,226 +2530,346 @@ static void yy_reduce( case 138: /* cmd ::= CREATE TABLE create_table_args */ yytestcase(yyruleno==138); case 139: /* cmd ::= CREATE TABLE create_stable_args */ yytestcase(yyruleno==139); case 140: /* cmd ::= CREATE STABLE create_stable_args */ yytestcase(yyruleno==140); +#line 63 "sql.y" {} +#line 2536 "sql.c" break; case 1: /* cmd ::= SHOW DATABASES */ +#line 66 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_DB, 0, 0);} +#line 2541 "sql.c" break; case 2: /* cmd ::= SHOW TOPICS */ +#line 67 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_TP, 0, 0);} +#line 2546 "sql.c" break; case 3: /* cmd ::= SHOW FUNCTIONS */ +#line 68 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_FUNCTION, 0, 0);} +#line 2551 "sql.c" break; case 4: /* cmd ::= SHOW MNODES */ +#line 69 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_MNODE, 0, 0);} +#line 2556 "sql.c" break; case 5: /* cmd ::= SHOW DNODES */ +#line 70 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_DNODE, 0, 0);} +#line 2561 "sql.c" break; case 6: /* cmd ::= SHOW ACCOUNTS */ +#line 71 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_ACCT, 0, 0);} +#line 2566 "sql.c" break; case 7: /* cmd ::= SHOW USERS */ +#line 72 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_USER, 0, 0);} +#line 2571 "sql.c" break; case 8: /* cmd ::= SHOW MODULES */ +#line 74 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_MODULE, 0, 0); } +#line 2576 "sql.c" break; case 9: /* cmd ::= SHOW QUERIES */ +#line 75 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_QUERIES, 0, 0); } +#line 2581 "sql.c" break; case 10: /* cmd ::= SHOW CONNECTIONS */ +#line 76 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_CONNS, 0, 0);} +#line 2586 "sql.c" break; case 11: /* cmd ::= SHOW STREAMS */ +#line 77 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_STREAMS, 0, 0); } +#line 2591 "sql.c" break; case 12: /* cmd ::= SHOW VARIABLES */ +#line 78 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_VARIABLES, 0, 0); } +#line 2596 "sql.c" break; case 13: /* cmd ::= SHOW SCORES */ +#line 79 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_SCORES, 0, 0); } +#line 2601 "sql.c" break; case 14: /* cmd ::= SHOW GRANTS */ +#line 80 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_GRANTS, 0, 0); } +#line 2606 "sql.c" break; case 15: /* cmd ::= SHOW VNODES */ +#line 82 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_VNODES, 0, 0); } +#line 2611 "sql.c" break; - case 16: /* cmd ::= SHOW VNODES IPTOKEN */ + case 16: /* cmd ::= SHOW VNODES ids */ +#line 83 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_VNODES, &yymsp[0].minor.yy0, 0); } +#line 2616 "sql.c" break; case 17: /* dbPrefix ::= */ +#line 87 "sql.y" {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.type = 0;} +#line 2621 "sql.c" break; case 18: /* dbPrefix ::= ids DOT */ +#line 88 "sql.y" {yylhsminor.yy0 = yymsp[-1].minor.yy0; } +#line 2626 "sql.c" yymsp[-1].minor.yy0 = yylhsminor.yy0; break; case 19: /* cpxName ::= */ +#line 91 "sql.y" {yymsp[1].minor.yy0.n = 0; } +#line 2632 "sql.c" break; case 20: /* cpxName ::= DOT ids */ +#line 92 "sql.y" {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n += 1; } +#line 2637 "sql.c" break; case 21: /* cmd ::= SHOW CREATE TABLE ids cpxName */ +#line 94 "sql.y" { yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_TABLE, 1, &yymsp[-1].minor.yy0); } +#line 2645 "sql.c" break; case 22: /* cmd ::= SHOW CREATE STABLE ids cpxName */ +#line 98 "sql.y" { yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_STABLE, 1, &yymsp[-1].minor.yy0); } +#line 2653 "sql.c" break; case 23: /* cmd ::= SHOW CREATE DATABASE ids */ +#line 103 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_DATABASE, 1, &yymsp[0].minor.yy0); } +#line 2660 "sql.c" break; case 24: /* cmd ::= SHOW dbPrefix TABLES */ +#line 107 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_TABLE, &yymsp[-1].minor.yy0, 0); } +#line 2667 "sql.c" break; case 25: /* cmd ::= SHOW dbPrefix TABLES LIKE ids */ +#line 111 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_TABLE, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); } +#line 2674 "sql.c" break; case 26: /* cmd ::= SHOW dbPrefix STABLES */ +#line 115 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_METRIC, &yymsp[-1].minor.yy0, 0); } +#line 2681 "sql.c" break; case 27: /* cmd ::= SHOW dbPrefix STABLES LIKE ids */ +#line 119 "sql.y" { SStrToken token; tSetDbName(&token, &yymsp[-3].minor.yy0); setShowOptions(pInfo, TSDB_MGMT_TABLE_METRIC, &token, &yymsp[0].minor.yy0); } +#line 2690 "sql.c" break; case 28: /* cmd ::= SHOW dbPrefix VGROUPS */ +#line 125 "sql.y" { SStrToken token; tSetDbName(&token, &yymsp[-1].minor.yy0); setShowOptions(pInfo, TSDB_MGMT_TABLE_VGROUP, &token, 0); } +#line 2699 "sql.c" break; case 29: /* cmd ::= SHOW dbPrefix VGROUPS ids */ +#line 131 "sql.y" { SStrToken token; tSetDbName(&token, &yymsp[-2].minor.yy0); setShowOptions(pInfo, TSDB_MGMT_TABLE_VGROUP, &token, &yymsp[0].minor.yy0); } +#line 2708 "sql.c" break; case 30: /* cmd ::= DROP TABLE ifexists ids cpxName */ +#line 138 "sql.y" { yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; setDropDbTableInfo(pInfo, TSDB_SQL_DROP_TABLE, &yymsp[-1].minor.yy0, &yymsp[-2].minor.yy0, -1, -1); } +#line 2716 "sql.c" break; case 31: /* cmd ::= DROP STABLE ifexists ids cpxName */ +#line 144 "sql.y" { yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; setDropDbTableInfo(pInfo, TSDB_SQL_DROP_TABLE, &yymsp[-1].minor.yy0, &yymsp[-2].minor.yy0, -1, TSDB_SUPER_TABLE); } +#line 2724 "sql.c" break; case 32: /* cmd ::= DROP DATABASE ifexists ids */ +#line 149 "sql.y" { setDropDbTableInfo(pInfo, TSDB_SQL_DROP_DB, &yymsp[0].minor.yy0, &yymsp[-1].minor.yy0, TSDB_DB_TYPE_DEFAULT, -1); } +#line 2729 "sql.c" break; case 33: /* cmd ::= DROP TOPIC ifexists ids */ +#line 150 "sql.y" { setDropDbTableInfo(pInfo, TSDB_SQL_DROP_DB, &yymsp[0].minor.yy0, &yymsp[-1].minor.yy0, TSDB_DB_TYPE_TOPIC, -1); } +#line 2734 "sql.c" break; case 34: /* cmd ::= DROP FUNCTION ids */ +#line 151 "sql.y" { setDropFuncInfo(pInfo, TSDB_SQL_DROP_FUNCTION, &yymsp[0].minor.yy0); } +#line 2739 "sql.c" break; case 35: /* cmd ::= DROP DNODE ids */ +#line 153 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_DROP_DNODE, 1, &yymsp[0].minor.yy0); } +#line 2744 "sql.c" break; case 36: /* cmd ::= DROP USER ids */ +#line 154 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_DROP_USER, 1, &yymsp[0].minor.yy0); } +#line 2749 "sql.c" break; case 37: /* cmd ::= DROP ACCOUNT ids */ +#line 155 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_DROP_ACCT, 1, &yymsp[0].minor.yy0); } +#line 2754 "sql.c" break; case 38: /* cmd ::= USE ids */ +#line 158 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_USE_DB, 1, &yymsp[0].minor.yy0);} +#line 2759 "sql.c" break; case 39: /* cmd ::= DESCRIBE ids cpxName */ +#line 161 "sql.y" { yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; setDCLSqlElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &yymsp[-1].minor.yy0); } +#line 2767 "sql.c" break; case 40: /* cmd ::= ALTER USER ids PASS ids */ +#line 167 "sql.y" { setAlterUserSql(pInfo, TSDB_ALTER_USER_PASSWD, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, NULL); } +#line 2772 "sql.c" break; case 41: /* cmd ::= ALTER USER ids PRIVILEGE ids */ +#line 168 "sql.y" { setAlterUserSql(pInfo, TSDB_ALTER_USER_PRIVILEGES, &yymsp[-2].minor.yy0, NULL, &yymsp[0].minor.yy0);} +#line 2777 "sql.c" break; case 42: /* cmd ::= ALTER DNODE ids ids */ +#line 169 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_CFG_DNODE, 2, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } +#line 2782 "sql.c" break; case 43: /* cmd ::= ALTER DNODE ids ids ids */ +#line 170 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_CFG_DNODE, 3, &yymsp[-2].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } +#line 2787 "sql.c" break; case 44: /* cmd ::= ALTER LOCAL ids */ +#line 171 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_CFG_LOCAL, 1, &yymsp[0].minor.yy0); } +#line 2792 "sql.c" break; case 45: /* cmd ::= ALTER LOCAL ids ids */ +#line 172 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_CFG_LOCAL, 2, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } +#line 2797 "sql.c" break; case 46: /* cmd ::= ALTER DATABASE ids alter_db_optr */ case 47: /* cmd ::= ALTER TOPIC ids alter_topic_optr */ yytestcase(yyruleno==47); -{ SStrToken t = {0}; setCreateDbInfo(pInfo, TSDB_SQL_ALTER_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy214, &t);} +#line 173 "sql.y" +{ SStrToken t = {0}; setCreateDbInfo(pInfo, TSDB_SQL_ALTER_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy42, &t);} +#line 2803 "sql.c" break; case 48: /* cmd ::= ALTER ACCOUNT ids acct_optr */ -{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-1].minor.yy0, NULL, &yymsp[0].minor.yy547);} +#line 176 "sql.y" +{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-1].minor.yy0, NULL, &yymsp[0].minor.yy341);} +#line 2808 "sql.c" break; case 49: /* 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.yy547);} +#line 177 "sql.y" +{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy341);} +#line 2813 "sql.c" break; case 50: /* cmd ::= COMPACT VNODES IN LP exprlist RP */ -{ setCompactVnodeSql(pInfo, TSDB_SQL_COMPACT_VNODE, yymsp[-1].minor.yy525);} +#line 181 "sql.y" +{ setCompactVnodeSql(pInfo, TSDB_SQL_COMPACT_VNODE, yymsp[-1].minor.yy131);} +#line 2818 "sql.c" break; case 51: /* ids ::= ID */ case 52: /* ids ::= STRING */ yytestcase(yyruleno==52); +#line 187 "sql.y" {yylhsminor.yy0 = yymsp[0].minor.yy0; } +#line 2824 "sql.c" yymsp[0].minor.yy0 = yylhsminor.yy0; break; case 53: /* ifexists ::= IF EXISTS */ +#line 191 "sql.y" { yymsp[-1].minor.yy0.n = 1;} +#line 2830 "sql.c" break; case 54: /* ifexists ::= */ case 56: /* ifnotexists ::= */ yytestcase(yyruleno==56); case 180: /* distinct ::= */ yytestcase(yyruleno==180); +#line 192 "sql.y" { yymsp[1].minor.yy0.n = 0;} +#line 2837 "sql.c" break; case 55: /* ifnotexists ::= IF NOT EXISTS */ +#line 195 "sql.y" { yymsp[-2].minor.yy0.n = 1;} +#line 2842 "sql.c" break; case 57: /* cmd ::= CREATE DNODE ids */ +#line 200 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_CREATE_DNODE, 1, &yymsp[0].minor.yy0);} +#line 2847 "sql.c" break; case 58: /* 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.yy547);} +#line 202 "sql.y" +{ setCreateAcctSql(pInfo, TSDB_SQL_CREATE_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy341);} +#line 2852 "sql.c" break; case 59: /* cmd ::= CREATE DATABASE ifnotexists ids db_optr */ case 60: /* cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ yytestcase(yyruleno==60); -{ setCreateDbInfo(pInfo, TSDB_SQL_CREATE_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy214, &yymsp[-2].minor.yy0);} +#line 203 "sql.y" +{ setCreateDbInfo(pInfo, TSDB_SQL_CREATE_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy42, &yymsp[-2].minor.yy0);} +#line 2858 "sql.c" break; case 61: /* cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ -{ setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &yymsp[-5].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy31, &yymsp[0].minor.yy0, 1);} +#line 205 "sql.y" +{ setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &yymsp[-5].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy163, &yymsp[0].minor.yy0, 1);} +#line 2863 "sql.c" break; case 62: /* cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ -{ setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &yymsp[-5].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy31, &yymsp[0].minor.yy0, 2);} +#line 206 "sql.y" +{ setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &yymsp[-5].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy163, &yymsp[0].minor.yy0, 2);} +#line 2868 "sql.c" break; case 63: /* cmd ::= CREATE USER ids PASS ids */ +#line 207 "sql.y" { setCreateUserSql(pInfo, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);} +#line 2873 "sql.c" break; case 64: /* bufsize ::= */ case 66: /* pps ::= */ yytestcase(yyruleno==66); @@ -2428,7 +2881,9 @@ static void yy_reduce( case 78: /* users ::= */ yytestcase(yyruleno==78); case 80: /* conns ::= */ yytestcase(yyruleno==80); case 82: /* state ::= */ yytestcase(yyruleno==82); +#line 209 "sql.y" { yymsp[1].minor.yy0.n = 0; } +#line 2887 "sql.c" break; case 65: /* bufsize ::= BUFSIZE INTEGER */ case 67: /* pps ::= PPS INTEGER */ yytestcase(yyruleno==67); @@ -2440,42 +2895,54 @@ static void yy_reduce( case 79: /* users ::= USERS INTEGER */ yytestcase(yyruleno==79); case 81: /* conns ::= CONNS INTEGER */ yytestcase(yyruleno==81); case 83: /* state ::= STATE ids */ yytestcase(yyruleno==83); +#line 210 "sql.y" { yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } +#line 2901 "sql.c" break; case 84: /* acct_optr ::= pps tseries storage streams qtime dbs users conns state */ +#line 240 "sql.y" { - yylhsminor.yy547.maxUsers = (yymsp[-2].minor.yy0.n>0)?atoi(yymsp[-2].minor.yy0.z):-1; - yylhsminor.yy547.maxDbs = (yymsp[-3].minor.yy0.n>0)?atoi(yymsp[-3].minor.yy0.z):-1; - yylhsminor.yy547.maxTimeSeries = (yymsp[-7].minor.yy0.n>0)?atoi(yymsp[-7].minor.yy0.z):-1; - yylhsminor.yy547.maxStreams = (yymsp[-5].minor.yy0.n>0)?atoi(yymsp[-5].minor.yy0.z):-1; - yylhsminor.yy547.maxPointsPerSecond = (yymsp[-8].minor.yy0.n>0)?atoi(yymsp[-8].minor.yy0.z):-1; - yylhsminor.yy547.maxStorage = (yymsp[-6].minor.yy0.n>0)?strtoll(yymsp[-6].minor.yy0.z, NULL, 10):-1; - yylhsminor.yy547.maxQueryTime = (yymsp[-4].minor.yy0.n>0)?strtoll(yymsp[-4].minor.yy0.z, NULL, 10):-1; - yylhsminor.yy547.maxConnections = (yymsp[-1].minor.yy0.n>0)?atoi(yymsp[-1].minor.yy0.z):-1; - yylhsminor.yy547.stat = yymsp[0].minor.yy0; + yylhsminor.yy341.maxUsers = (yymsp[-2].minor.yy0.n>0)?atoi(yymsp[-2].minor.yy0.z):-1; + yylhsminor.yy341.maxDbs = (yymsp[-3].minor.yy0.n>0)?atoi(yymsp[-3].minor.yy0.z):-1; + yylhsminor.yy341.maxTimeSeries = (yymsp[-7].minor.yy0.n>0)?atoi(yymsp[-7].minor.yy0.z):-1; + yylhsminor.yy341.maxStreams = (yymsp[-5].minor.yy0.n>0)?atoi(yymsp[-5].minor.yy0.z):-1; + yylhsminor.yy341.maxPointsPerSecond = (yymsp[-8].minor.yy0.n>0)?atoi(yymsp[-8].minor.yy0.z):-1; + yylhsminor.yy341.maxStorage = (yymsp[-6].minor.yy0.n>0)?strtoll(yymsp[-6].minor.yy0.z, NULL, 10):-1; + yylhsminor.yy341.maxQueryTime = (yymsp[-4].minor.yy0.n>0)?strtoll(yymsp[-4].minor.yy0.z, NULL, 10):-1; + yylhsminor.yy341.maxConnections = (yymsp[-1].minor.yy0.n>0)?atoi(yymsp[-1].minor.yy0.z):-1; + yylhsminor.yy341.stat = yymsp[0].minor.yy0; } - yymsp[-8].minor.yy547 = yylhsminor.yy547; +#line 2916 "sql.c" + yymsp[-8].minor.yy341 = yylhsminor.yy341; break; case 85: /* intitemlist ::= intitemlist COMMA intitem */ case 154: /* tagitemlist ::= tagitemlist COMMA tagitem */ yytestcase(yyruleno==154); -{ yylhsminor.yy525 = tVariantListAppend(yymsp[-2].minor.yy525, &yymsp[0].minor.yy506, -1); } - yymsp[-2].minor.yy525 = yylhsminor.yy525; +#line 256 "sql.y" +{ yylhsminor.yy131 = tVariantListAppend(yymsp[-2].minor.yy131, &yymsp[0].minor.yy516, -1); } +#line 2923 "sql.c" + yymsp[-2].minor.yy131 = yylhsminor.yy131; break; case 86: /* intitemlist ::= intitem */ case 155: /* tagitemlist ::= tagitem */ yytestcase(yyruleno==155); -{ yylhsminor.yy525 = tVariantListAppend(NULL, &yymsp[0].minor.yy506, -1); } - yymsp[0].minor.yy525 = yylhsminor.yy525; +#line 257 "sql.y" +{ yylhsminor.yy131 = tVariantListAppend(NULL, &yymsp[0].minor.yy516, -1); } +#line 2930 "sql.c" + yymsp[0].minor.yy131 = yylhsminor.yy131; break; case 87: /* intitem ::= INTEGER */ case 156: /* tagitem ::= INTEGER */ yytestcase(yyruleno==156); case 157: /* tagitem ::= FLOAT */ yytestcase(yyruleno==157); case 158: /* tagitem ::= STRING */ yytestcase(yyruleno==158); case 159: /* tagitem ::= BOOL */ yytestcase(yyruleno==159); -{ toTSDBType(yymsp[0].minor.yy0.type); tVariantCreate(&yylhsminor.yy506, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy506 = yylhsminor.yy506; +#line 259 "sql.y" +{ toTSDBType(yymsp[0].minor.yy0.type); tVariantCreate(&yylhsminor.yy516, &yymsp[0].minor.yy0); } +#line 2940 "sql.c" + yymsp[0].minor.yy516 = yylhsminor.yy516; break; case 88: /* keep ::= KEEP intitemlist */ -{ yymsp[-1].minor.yy525 = yymsp[0].minor.yy525; } +#line 263 "sql.y" +{ yymsp[-1].minor.yy131 = yymsp[0].minor.yy131; } +#line 2946 "sql.c" break; case 89: /* cache ::= CACHE INTEGER */ case 90: /* replica ::= REPLICA INTEGER */ yytestcase(yyruleno==90); @@ -2492,639 +2959,912 @@ static void yy_reduce( case 101: /* update ::= UPDATE INTEGER */ yytestcase(yyruleno==101); case 102: /* cachelast ::= CACHELAST INTEGER */ yytestcase(yyruleno==102); case 103: /* partitions ::= PARTITIONS INTEGER */ yytestcase(yyruleno==103); +#line 265 "sql.y" { yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } +#line 2965 "sql.c" break; case 104: /* db_optr ::= */ -{setDefaultCreateDbOption(&yymsp[1].minor.yy214); yymsp[1].minor.yy214.dbType = TSDB_DB_TYPE_DEFAULT;} +#line 282 "sql.y" +{setDefaultCreateDbOption(&yymsp[1].minor.yy42); yymsp[1].minor.yy42.dbType = TSDB_DB_TYPE_DEFAULT;} +#line 2970 "sql.c" break; case 105: /* db_optr ::= db_optr cache */ -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.cacheBlockSize = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 284 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.cacheBlockSize = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 2975 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 106: /* db_optr ::= db_optr replica */ case 123: /* alter_db_optr ::= alter_db_optr replica */ yytestcase(yyruleno==123); -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.replica = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 285 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.replica = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 2982 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 107: /* db_optr ::= db_optr quorum */ case 124: /* alter_db_optr ::= alter_db_optr quorum */ yytestcase(yyruleno==124); -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.quorum = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 286 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.quorum = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 2989 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 108: /* db_optr ::= db_optr days */ -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.daysPerFile = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 287 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.daysPerFile = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 2995 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 109: /* db_optr ::= db_optr minrows */ -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.minRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 288 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.minRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } +#line 3001 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 110: /* db_optr ::= db_optr maxrows */ -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.maxRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 289 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.maxRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } +#line 3007 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 111: /* db_optr ::= db_optr blocks */ case 126: /* alter_db_optr ::= alter_db_optr blocks */ yytestcase(yyruleno==126); -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.numOfBlocks = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 290 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.numOfBlocks = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3014 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 112: /* db_optr ::= db_optr ctime */ -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.commitTime = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 291 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.commitTime = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3020 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 113: /* db_optr ::= db_optr wal */ -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.walLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 292 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.walLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3026 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 114: /* db_optr ::= db_optr fsync */ -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.fsyncPeriod = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 293 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.fsyncPeriod = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3032 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 115: /* db_optr ::= db_optr comp */ case 127: /* alter_db_optr ::= alter_db_optr comp */ yytestcase(yyruleno==127); -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.compressionLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 294 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.compressionLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3039 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 116: /* db_optr ::= db_optr prec */ -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.precision = yymsp[0].minor.yy0; } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 295 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.precision = yymsp[0].minor.yy0; } +#line 3045 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 117: /* db_optr ::= db_optr keep */ case 125: /* alter_db_optr ::= alter_db_optr keep */ yytestcase(yyruleno==125); -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.keep = yymsp[0].minor.yy525; } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 296 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.keep = yymsp[0].minor.yy131; } +#line 3052 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 118: /* db_optr ::= db_optr update */ case 128: /* alter_db_optr ::= alter_db_optr update */ yytestcase(yyruleno==128); -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.update = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 297 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.update = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3059 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 119: /* db_optr ::= db_optr cachelast */ case 129: /* alter_db_optr ::= alter_db_optr cachelast */ yytestcase(yyruleno==129); -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.cachelast = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 298 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.cachelast = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3066 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 120: /* topic_optr ::= db_optr */ case 130: /* alter_topic_optr ::= alter_db_optr */ yytestcase(yyruleno==130); -{ yylhsminor.yy214 = yymsp[0].minor.yy214; yylhsminor.yy214.dbType = TSDB_DB_TYPE_TOPIC; } - yymsp[0].minor.yy214 = yylhsminor.yy214; +#line 302 "sql.y" +{ yylhsminor.yy42 = yymsp[0].minor.yy42; yylhsminor.yy42.dbType = TSDB_DB_TYPE_TOPIC; } +#line 3073 "sql.c" + yymsp[0].minor.yy42 = yylhsminor.yy42; break; case 121: /* topic_optr ::= topic_optr partitions */ case 131: /* alter_topic_optr ::= alter_topic_optr partitions */ yytestcase(yyruleno==131); -{ yylhsminor.yy214 = yymsp[-1].minor.yy214; yylhsminor.yy214.partitions = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy214 = yylhsminor.yy214; +#line 303 "sql.y" +{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.partitions = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3080 "sql.c" + yymsp[-1].minor.yy42 = yylhsminor.yy42; break; case 122: /* alter_db_optr ::= */ -{ setDefaultCreateDbOption(&yymsp[1].minor.yy214); yymsp[1].minor.yy214.dbType = TSDB_DB_TYPE_DEFAULT;} +#line 306 "sql.y" +{ setDefaultCreateDbOption(&yymsp[1].minor.yy42); yymsp[1].minor.yy42.dbType = TSDB_DB_TYPE_DEFAULT;} +#line 3086 "sql.c" break; case 132: /* typename ::= ids */ +#line 326 "sql.y" { yymsp[0].minor.yy0.type = 0; - tSetColumnType (&yylhsminor.yy31, &yymsp[0].minor.yy0); + tSetColumnType (&yylhsminor.yy163, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy31 = yylhsminor.yy31; +#line 3094 "sql.c" + yymsp[0].minor.yy163 = yylhsminor.yy163; break; case 133: /* typename ::= ids LP signed RP */ +#line 332 "sql.y" { - if (yymsp[-1].minor.yy501 <= 0) { + if (yymsp[-1].minor.yy459 <= 0) { yymsp[-3].minor.yy0.type = 0; - tSetColumnType(&yylhsminor.yy31, &yymsp[-3].minor.yy0); + tSetColumnType(&yylhsminor.yy163, &yymsp[-3].minor.yy0); } else { - yymsp[-3].minor.yy0.type = -yymsp[-1].minor.yy501; // negative value of name length - tSetColumnType(&yylhsminor.yy31, &yymsp[-3].minor.yy0); + yymsp[-3].minor.yy0.type = -yymsp[-1].minor.yy459; // negative value of name length + tSetColumnType(&yylhsminor.yy163, &yymsp[-3].minor.yy0); } } - yymsp[-3].minor.yy31 = yylhsminor.yy31; +#line 3108 "sql.c" + yymsp[-3].minor.yy163 = yylhsminor.yy163; break; case 134: /* typename ::= ids UNSIGNED */ +#line 343 "sql.y" { 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); - tSetColumnType (&yylhsminor.yy31, &yymsp[-1].minor.yy0); + tSetColumnType (&yylhsminor.yy163, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy31 = yylhsminor.yy31; +#line 3118 "sql.c" + yymsp[-1].minor.yy163 = yylhsminor.yy163; break; case 135: /* signed ::= INTEGER */ -{ yylhsminor.yy501 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[0].minor.yy501 = yylhsminor.yy501; +#line 350 "sql.y" +{ yylhsminor.yy459 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3124 "sql.c" + yymsp[0].minor.yy459 = yylhsminor.yy459; break; case 136: /* signed ::= PLUS INTEGER */ -{ yymsp[-1].minor.yy501 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 351 "sql.y" +{ yymsp[-1].minor.yy459 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3130 "sql.c" break; case 137: /* signed ::= MINUS INTEGER */ -{ yymsp[-1].minor.yy501 = -strtol(yymsp[0].minor.yy0.z, NULL, 10);} +#line 352 "sql.y" +{ yymsp[-1].minor.yy459 = -strtol(yymsp[0].minor.yy0.z, NULL, 10);} +#line 3135 "sql.c" break; case 141: /* cmd ::= CREATE TABLE create_table_list */ -{ pInfo->type = TSDB_SQL_CREATE_TABLE; pInfo->pCreateTableInfo = yymsp[0].minor.yy158;} +#line 358 "sql.y" +{ pInfo->type = TSDB_SQL_CREATE_TABLE; pInfo->pCreateTableInfo = yymsp[0].minor.yy272;} +#line 3140 "sql.c" break; case 142: /* create_table_list ::= create_from_stable */ +#line 362 "sql.y" { SCreateTableSql* pCreateTable = calloc(1, sizeof(SCreateTableSql)); pCreateTable->childTableInfo = taosArrayInit(4, sizeof(SCreatedTableInfo)); - taosArrayPush(pCreateTable->childTableInfo, &yymsp[0].minor.yy432); + taosArrayPush(pCreateTable->childTableInfo, &yymsp[0].minor.yy96); pCreateTable->type = TSQL_CREATE_TABLE_FROM_STABLE; - yylhsminor.yy158 = pCreateTable; + yylhsminor.yy272 = pCreateTable; } - yymsp[0].minor.yy158 = yylhsminor.yy158; +#line 3152 "sql.c" + yymsp[0].minor.yy272 = yylhsminor.yy272; break; case 143: /* create_table_list ::= create_table_list create_from_stable */ +#line 371 "sql.y" { - taosArrayPush(yymsp[-1].minor.yy158->childTableInfo, &yymsp[0].minor.yy432); - yylhsminor.yy158 = yymsp[-1].minor.yy158; + taosArrayPush(yymsp[-1].minor.yy272->childTableInfo, &yymsp[0].minor.yy96); + yylhsminor.yy272 = yymsp[-1].minor.yy272; } - yymsp[-1].minor.yy158 = yylhsminor.yy158; +#line 3161 "sql.c" + yymsp[-1].minor.yy272 = yylhsminor.yy272; break; case 144: /* create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ +#line 377 "sql.y" { - yylhsminor.yy158 = tSetCreateTableInfo(yymsp[-1].minor.yy525, NULL, NULL, TSQL_CREATE_TABLE); - setSqlInfo(pInfo, yylhsminor.yy158, NULL, TSDB_SQL_CREATE_TABLE); + yylhsminor.yy272 = tSetCreateTableInfo(yymsp[-1].minor.yy131, NULL, NULL, TSQL_CREATE_TABLE); + setSqlInfo(pInfo, yylhsminor.yy272, 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.yy158 = yylhsminor.yy158; +#line 3173 "sql.c" + yymsp[-5].minor.yy272 = yylhsminor.yy272; break; case 145: /* create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ +#line 387 "sql.y" { - yylhsminor.yy158 = tSetCreateTableInfo(yymsp[-5].minor.yy525, yymsp[-1].minor.yy525, NULL, TSQL_CREATE_STABLE); - setSqlInfo(pInfo, yylhsminor.yy158, NULL, TSDB_SQL_CREATE_TABLE); + yylhsminor.yy272 = tSetCreateTableInfo(yymsp[-5].minor.yy131, yymsp[-1].minor.yy131, NULL, TSQL_CREATE_STABLE); + setSqlInfo(pInfo, yylhsminor.yy272, 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.yy158 = yylhsminor.yy158; +#line 3185 "sql.c" + yymsp[-9].minor.yy272 = yylhsminor.yy272; break; case 146: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ +#line 398 "sql.y" { yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; - yylhsminor.yy432 = createNewChildTableInfo(&yymsp[-5].minor.yy0, NULL, yymsp[-1].minor.yy525, &yymsp[-8].minor.yy0, &yymsp[-9].minor.yy0); + yylhsminor.yy96 = createNewChildTableInfo(&yymsp[-5].minor.yy0, NULL, yymsp[-1].minor.yy131, &yymsp[-8].minor.yy0, &yymsp[-9].minor.yy0); } - yymsp[-9].minor.yy432 = yylhsminor.yy432; +#line 3195 "sql.c" + yymsp[-9].minor.yy96 = yylhsminor.yy96; break; case 147: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ +#line 404 "sql.y" { yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; yymsp[-11].minor.yy0.n += yymsp[-10].minor.yy0.n; - yylhsminor.yy432 = createNewChildTableInfo(&yymsp[-8].minor.yy0, yymsp[-5].minor.yy525, yymsp[-1].minor.yy525, &yymsp[-11].minor.yy0, &yymsp[-12].minor.yy0); + yylhsminor.yy96 = createNewChildTableInfo(&yymsp[-8].minor.yy0, yymsp[-5].minor.yy131, yymsp[-1].minor.yy131, &yymsp[-11].minor.yy0, &yymsp[-12].minor.yy0); } - yymsp[-12].minor.yy432 = yylhsminor.yy432; +#line 3205 "sql.c" + yymsp[-12].minor.yy96 = yylhsminor.yy96; break; case 148: /* tagNamelist ::= tagNamelist COMMA ids */ -{taosArrayPush(yymsp[-2].minor.yy525, &yymsp[0].minor.yy0); yylhsminor.yy525 = yymsp[-2].minor.yy525; } - yymsp[-2].minor.yy525 = yylhsminor.yy525; +#line 412 "sql.y" +{taosArrayPush(yymsp[-2].minor.yy131, &yymsp[0].minor.yy0); yylhsminor.yy131 = yymsp[-2].minor.yy131; } +#line 3211 "sql.c" + yymsp[-2].minor.yy131 = yylhsminor.yy131; break; case 149: /* tagNamelist ::= ids */ -{yylhsminor.yy525 = taosArrayInit(4, sizeof(SStrToken)); taosArrayPush(yylhsminor.yy525, &yymsp[0].minor.yy0);} - yymsp[0].minor.yy525 = yylhsminor.yy525; +#line 413 "sql.y" +{yylhsminor.yy131 = taosArrayInit(4, sizeof(SStrToken)); taosArrayPush(yylhsminor.yy131, &yymsp[0].minor.yy0);} +#line 3217 "sql.c" + yymsp[0].minor.yy131 = yylhsminor.yy131; break; case 150: /* create_table_args ::= ifnotexists ids cpxName AS select */ +#line 417 "sql.y" { - yylhsminor.yy158 = tSetCreateTableInfo(NULL, NULL, yymsp[0].minor.yy464, TSQL_CREATE_STREAM); - setSqlInfo(pInfo, yylhsminor.yy158, NULL, TSDB_SQL_CREATE_TABLE); + yylhsminor.yy272 = tSetCreateTableInfo(NULL, NULL, yymsp[0].minor.yy256, TSQL_CREATE_STREAM); + setSqlInfo(pInfo, yylhsminor.yy272, 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.yy158 = yylhsminor.yy158; +#line 3229 "sql.c" + yymsp[-4].minor.yy272 = yylhsminor.yy272; break; case 151: /* columnlist ::= columnlist COMMA column */ -{taosArrayPush(yymsp[-2].minor.yy525, &yymsp[0].minor.yy31); yylhsminor.yy525 = yymsp[-2].minor.yy525; } - yymsp[-2].minor.yy525 = yylhsminor.yy525; +#line 428 "sql.y" +{taosArrayPush(yymsp[-2].minor.yy131, &yymsp[0].minor.yy163); yylhsminor.yy131 = yymsp[-2].minor.yy131; } +#line 3235 "sql.c" + yymsp[-2].minor.yy131 = yylhsminor.yy131; break; case 152: /* columnlist ::= column */ -{yylhsminor.yy525 = taosArrayInit(4, sizeof(TAOS_FIELD)); taosArrayPush(yylhsminor.yy525, &yymsp[0].minor.yy31);} - yymsp[0].minor.yy525 = yylhsminor.yy525; +#line 429 "sql.y" +{yylhsminor.yy131 = taosArrayInit(4, sizeof(TAOS_FIELD)); taosArrayPush(yylhsminor.yy131, &yymsp[0].minor.yy163);} +#line 3241 "sql.c" + yymsp[0].minor.yy131 = yylhsminor.yy131; break; case 153: /* column ::= ids typename */ +#line 433 "sql.y" { - tSetColumnInfo(&yylhsminor.yy31, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy31); + tSetColumnInfo(&yylhsminor.yy163, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy163); } - yymsp[-1].minor.yy31 = yylhsminor.yy31; +#line 3249 "sql.c" + yymsp[-1].minor.yy163 = yylhsminor.yy163; break; case 160: /* tagitem ::= NULL */ -{ yymsp[0].minor.yy0.type = 0; tVariantCreate(&yylhsminor.yy506, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy506 = yylhsminor.yy506; +#line 448 "sql.y" +{ yymsp[0].minor.yy0.type = 0; tVariantCreate(&yylhsminor.yy516, &yymsp[0].minor.yy0); } +#line 3255 "sql.c" + yymsp[0].minor.yy516 = yylhsminor.yy516; break; case 161: /* tagitem ::= NOW */ -{ yymsp[0].minor.yy0.type = TSDB_DATA_TYPE_TIMESTAMP; tVariantCreate(&yylhsminor.yy506, &yymsp[0].minor.yy0);} - yymsp[0].minor.yy506 = yylhsminor.yy506; +#line 449 "sql.y" +{ yymsp[0].minor.yy0.type = TSDB_DATA_TYPE_TIMESTAMP; tVariantCreate(&yylhsminor.yy516, &yymsp[0].minor.yy0);} +#line 3261 "sql.c" + yymsp[0].minor.yy516 = yylhsminor.yy516; break; case 162: /* tagitem ::= MINUS INTEGER */ case 163: /* tagitem ::= MINUS FLOAT */ yytestcase(yyruleno==163); case 164: /* tagitem ::= PLUS INTEGER */ yytestcase(yyruleno==164); case 165: /* tagitem ::= PLUS FLOAT */ yytestcase(yyruleno==165); +#line 451 "sql.y" { 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.yy506, &yymsp[-1].minor.yy0); + tVariantCreate(&yylhsminor.yy516, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy506 = yylhsminor.yy506; +#line 3275 "sql.c" + yymsp[-1].minor.yy516 = yylhsminor.yy516; break; case 166: /* select ::= SELECT selcollist from where_opt interval_opt sliding_opt session_option windowstate_option fill_opt groupby_opt having_opt orderby_opt slimit_opt limit_opt */ +#line 482 "sql.y" { - yylhsminor.yy464 = tSetQuerySqlNode(&yymsp[-13].minor.yy0, yymsp[-12].minor.yy525, yymsp[-11].minor.yy412, yymsp[-10].minor.yy370, yymsp[-4].minor.yy525, yymsp[-2].minor.yy525, &yymsp[-9].minor.yy520, &yymsp[-7].minor.yy259, &yymsp[-6].minor.yy144, &yymsp[-8].minor.yy0, yymsp[-5].minor.yy525, &yymsp[0].minor.yy126, &yymsp[-1].minor.yy126, yymsp[-3].minor.yy370); + yylhsminor.yy256 = tSetQuerySqlNode(&yymsp[-13].minor.yy0, yymsp[-12].minor.yy131, yymsp[-11].minor.yy544, yymsp[-10].minor.yy46, yymsp[-4].minor.yy131, yymsp[-2].minor.yy131, &yymsp[-9].minor.yy530, &yymsp[-7].minor.yy39, &yymsp[-6].minor.yy538, &yymsp[-8].minor.yy0, yymsp[-5].minor.yy131, &yymsp[0].minor.yy284, &yymsp[-1].minor.yy284, yymsp[-3].minor.yy46); } - yymsp[-13].minor.yy464 = yylhsminor.yy464; +#line 3283 "sql.c" + yymsp[-13].minor.yy256 = yylhsminor.yy256; break; case 167: /* select ::= LP select RP */ -{yymsp[-2].minor.yy464 = yymsp[-1].minor.yy464;} +#line 486 "sql.y" +{yymsp[-2].minor.yy256 = yymsp[-1].minor.yy256;} +#line 3289 "sql.c" break; case 168: /* union ::= select */ -{ yylhsminor.yy525 = setSubclause(NULL, yymsp[0].minor.yy464); } - yymsp[0].minor.yy525 = yylhsminor.yy525; +#line 490 "sql.y" +{ yylhsminor.yy131 = setSubclause(NULL, yymsp[0].minor.yy256); } +#line 3294 "sql.c" + yymsp[0].minor.yy131 = yylhsminor.yy131; break; case 169: /* union ::= union UNION ALL select */ -{ yylhsminor.yy525 = appendSelectClause(yymsp[-3].minor.yy525, yymsp[0].minor.yy464); } - yymsp[-3].minor.yy525 = yylhsminor.yy525; +#line 491 "sql.y" +{ yylhsminor.yy131 = appendSelectClause(yymsp[-3].minor.yy131, yymsp[0].minor.yy256); } +#line 3300 "sql.c" + yymsp[-3].minor.yy131 = yylhsminor.yy131; break; case 170: /* cmd ::= union */ -{ setSqlInfo(pInfo, yymsp[0].minor.yy525, NULL, TSDB_SQL_SELECT); } +#line 493 "sql.y" +{ setSqlInfo(pInfo, yymsp[0].minor.yy131, NULL, TSDB_SQL_SELECT); } +#line 3306 "sql.c" break; case 171: /* select ::= SELECT selcollist */ +#line 500 "sql.y" { - yylhsminor.yy464 = tSetQuerySqlNode(&yymsp[-1].minor.yy0, yymsp[0].minor.yy525, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + yylhsminor.yy256 = tSetQuerySqlNode(&yymsp[-1].minor.yy0, yymsp[0].minor.yy131, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } - yymsp[-1].minor.yy464 = yylhsminor.yy464; +#line 3313 "sql.c" + yymsp[-1].minor.yy256 = yylhsminor.yy256; break; case 172: /* sclp ::= selcollist COMMA */ -{yylhsminor.yy525 = yymsp[-1].minor.yy525;} - yymsp[-1].minor.yy525 = yylhsminor.yy525; +#line 512 "sql.y" +{yylhsminor.yy131 = yymsp[-1].minor.yy131;} +#line 3319 "sql.c" + yymsp[-1].minor.yy131 = yylhsminor.yy131; break; case 173: /* sclp ::= */ case 203: /* orderby_opt ::= */ yytestcase(yyruleno==203); -{yymsp[1].minor.yy525 = 0;} +#line 513 "sql.y" +{yymsp[1].minor.yy131 = 0;} +#line 3326 "sql.c" break; case 174: /* selcollist ::= sclp distinct expr as */ +#line 514 "sql.y" { - yylhsminor.yy525 = tSqlExprListAppend(yymsp[-3].minor.yy525, yymsp[-1].minor.yy370, yymsp[-2].minor.yy0.n? &yymsp[-2].minor.yy0:0, yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0); + yylhsminor.yy131 = tSqlExprListAppend(yymsp[-3].minor.yy131, yymsp[-1].minor.yy46, yymsp[-2].minor.yy0.n? &yymsp[-2].minor.yy0:0, yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0); } - yymsp[-3].minor.yy525 = yylhsminor.yy525; +#line 3333 "sql.c" + yymsp[-3].minor.yy131 = yylhsminor.yy131; break; case 175: /* selcollist ::= sclp STAR */ +#line 518 "sql.y" { tSqlExpr *pNode = tSqlExprCreateIdValue(NULL, TK_ALL); - yylhsminor.yy525 = tSqlExprListAppend(yymsp[-1].minor.yy525, pNode, 0, 0); + yylhsminor.yy131 = tSqlExprListAppend(yymsp[-1].minor.yy131, pNode, 0, 0); } - yymsp[-1].minor.yy525 = yylhsminor.yy525; +#line 3342 "sql.c" + yymsp[-1].minor.yy131 = yylhsminor.yy131; break; case 176: /* as ::= AS ids */ +#line 526 "sql.y" { yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } +#line 3348 "sql.c" break; case 177: /* as ::= ids */ +#line 527 "sql.y" { yylhsminor.yy0 = yymsp[0].minor.yy0; } +#line 3353 "sql.c" yymsp[0].minor.yy0 = yylhsminor.yy0; break; case 178: /* as ::= */ +#line 528 "sql.y" { yymsp[1].minor.yy0.n = 0; } +#line 3359 "sql.c" break; case 179: /* distinct ::= DISTINCT */ +#line 531 "sql.y" { yylhsminor.yy0 = yymsp[0].minor.yy0; } +#line 3364 "sql.c" yymsp[0].minor.yy0 = yylhsminor.yy0; break; case 181: /* from ::= FROM tablelist */ case 182: /* from ::= FROM sub */ yytestcase(yyruleno==182); -{yymsp[-1].minor.yy412 = yymsp[0].minor.yy412;} +#line 537 "sql.y" +{yymsp[-1].minor.yy544 = yymsp[0].minor.yy544;} +#line 3371 "sql.c" break; case 183: /* sub ::= LP union RP */ -{yymsp[-2].minor.yy412 = addSubqueryElem(NULL, yymsp[-1].minor.yy525, NULL);} +#line 542 "sql.y" +{yymsp[-2].minor.yy544 = addSubqueryElem(NULL, yymsp[-1].minor.yy131, NULL);} +#line 3376 "sql.c" break; case 184: /* sub ::= LP union RP ids */ -{yymsp[-3].minor.yy412 = addSubqueryElem(NULL, yymsp[-2].minor.yy525, &yymsp[0].minor.yy0);} +#line 543 "sql.y" +{yymsp[-3].minor.yy544 = addSubqueryElem(NULL, yymsp[-2].minor.yy131, &yymsp[0].minor.yy0);} +#line 3381 "sql.c" break; case 185: /* sub ::= sub COMMA LP union RP ids */ -{yylhsminor.yy412 = addSubqueryElem(yymsp[-5].minor.yy412, yymsp[-2].minor.yy525, &yymsp[0].minor.yy0);} - yymsp[-5].minor.yy412 = yylhsminor.yy412; +#line 544 "sql.y" +{yylhsminor.yy544 = addSubqueryElem(yymsp[-5].minor.yy544, yymsp[-2].minor.yy131, &yymsp[0].minor.yy0);} +#line 3386 "sql.c" + yymsp[-5].minor.yy544 = yylhsminor.yy544; break; case 186: /* tablelist ::= ids cpxName */ +#line 548 "sql.y" { yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - yylhsminor.yy412 = setTableNameList(NULL, &yymsp[-1].minor.yy0, NULL); + yylhsminor.yy544 = setTableNameList(NULL, &yymsp[-1].minor.yy0, NULL); } - yymsp[-1].minor.yy412 = yylhsminor.yy412; +#line 3395 "sql.c" + yymsp[-1].minor.yy544 = yylhsminor.yy544; break; case 187: /* tablelist ::= ids cpxName ids */ +#line 553 "sql.y" { yymsp[-2].minor.yy0.n += yymsp[-1].minor.yy0.n; - yylhsminor.yy412 = setTableNameList(NULL, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); + yylhsminor.yy544 = setTableNameList(NULL, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy412 = yylhsminor.yy412; +#line 3404 "sql.c" + yymsp[-2].minor.yy544 = yylhsminor.yy544; break; case 188: /* tablelist ::= tablelist COMMA ids cpxName */ +#line 558 "sql.y" { yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - yylhsminor.yy412 = setTableNameList(yymsp[-3].minor.yy412, &yymsp[-1].minor.yy0, NULL); + yylhsminor.yy544 = setTableNameList(yymsp[-3].minor.yy544, &yymsp[-1].minor.yy0, NULL); } - yymsp[-3].minor.yy412 = yylhsminor.yy412; +#line 3413 "sql.c" + yymsp[-3].minor.yy544 = yylhsminor.yy544; break; case 189: /* tablelist ::= tablelist COMMA ids cpxName ids */ +#line 563 "sql.y" { yymsp[-2].minor.yy0.n += yymsp[-1].minor.yy0.n; - yylhsminor.yy412 = setTableNameList(yymsp[-4].minor.yy412, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); + yylhsminor.yy544 = setTableNameList(yymsp[-4].minor.yy544, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } - yymsp[-4].minor.yy412 = yylhsminor.yy412; +#line 3422 "sql.c" + yymsp[-4].minor.yy544 = yylhsminor.yy544; break; case 190: /* tmvar ::= VARIABLE */ +#line 570 "sql.y" {yylhsminor.yy0 = yymsp[0].minor.yy0;} +#line 3428 "sql.c" yymsp[0].minor.yy0 = yylhsminor.yy0; break; case 191: /* interval_opt ::= INTERVAL LP tmvar RP */ -{yymsp[-3].minor.yy520.interval = yymsp[-1].minor.yy0; yymsp[-3].minor.yy520.offset.n = 0;} +#line 573 "sql.y" +{yymsp[-3].minor.yy530.interval = yymsp[-1].minor.yy0; yymsp[-3].minor.yy530.offset.n = 0;} +#line 3434 "sql.c" break; case 192: /* interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP */ -{yymsp[-5].minor.yy520.interval = yymsp[-3].minor.yy0; yymsp[-5].minor.yy520.offset = yymsp[-1].minor.yy0;} +#line 574 "sql.y" +{yymsp[-5].minor.yy530.interval = yymsp[-3].minor.yy0; yymsp[-5].minor.yy530.offset = yymsp[-1].minor.yy0;} +#line 3439 "sql.c" break; case 193: /* interval_opt ::= */ -{memset(&yymsp[1].minor.yy520, 0, sizeof(yymsp[1].minor.yy520));} +#line 575 "sql.y" +{memset(&yymsp[1].minor.yy530, 0, sizeof(yymsp[1].minor.yy530));} +#line 3444 "sql.c" break; case 194: /* session_option ::= */ -{yymsp[1].minor.yy259.col.n = 0; yymsp[1].minor.yy259.gap.n = 0;} +#line 578 "sql.y" +{yymsp[1].minor.yy39.col.n = 0; yymsp[1].minor.yy39.gap.n = 0;} +#line 3449 "sql.c" break; case 195: /* session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ +#line 579 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - yymsp[-6].minor.yy259.col = yymsp[-4].minor.yy0; - yymsp[-6].minor.yy259.gap = yymsp[-1].minor.yy0; + yymsp[-6].minor.yy39.col = yymsp[-4].minor.yy0; + yymsp[-6].minor.yy39.gap = yymsp[-1].minor.yy0; } +#line 3458 "sql.c" break; case 196: /* windowstate_option ::= */ -{ yymsp[1].minor.yy144.col.n = 0; yymsp[1].minor.yy144.col.z = NULL;} +#line 585 "sql.y" +{ yymsp[1].minor.yy538.col.n = 0; yymsp[1].minor.yy538.col.z = NULL;} +#line 3463 "sql.c" break; case 197: /* windowstate_option ::= STATE_WINDOW LP ids RP */ -{ yymsp[-3].minor.yy144.col = yymsp[-1].minor.yy0; } +#line 586 "sql.y" +{ yymsp[-3].minor.yy538.col = yymsp[-1].minor.yy0; } +#line 3468 "sql.c" break; case 198: /* fill_opt ::= */ -{ yymsp[1].minor.yy525 = 0; } +#line 590 "sql.y" +{ yymsp[1].minor.yy131 = 0; } +#line 3473 "sql.c" break; case 199: /* fill_opt ::= FILL LP ID COMMA tagitemlist RP */ +#line 591 "sql.y" { tVariant A = {0}; toTSDBType(yymsp[-3].minor.yy0.type); tVariantCreate(&A, &yymsp[-3].minor.yy0); - tVariantListInsert(yymsp[-1].minor.yy525, &A, -1, 0); - yymsp[-5].minor.yy525 = yymsp[-1].minor.yy525; + tVariantListInsert(yymsp[-1].minor.yy131, &A, -1, 0); + yymsp[-5].minor.yy131 = yymsp[-1].minor.yy131; } +#line 3485 "sql.c" break; case 200: /* fill_opt ::= FILL LP ID RP */ +#line 600 "sql.y" { toTSDBType(yymsp[-1].minor.yy0.type); - yymsp[-3].minor.yy525 = tVariantListAppendToken(NULL, &yymsp[-1].minor.yy0, -1); + yymsp[-3].minor.yy131 = tVariantListAppendToken(NULL, &yymsp[-1].minor.yy0, -1); } +#line 3493 "sql.c" break; case 201: /* sliding_opt ::= SLIDING LP tmvar RP */ +#line 606 "sql.y" {yymsp[-3].minor.yy0 = yymsp[-1].minor.yy0; } +#line 3498 "sql.c" break; case 202: /* sliding_opt ::= */ +#line 607 "sql.y" {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = NULL; yymsp[1].minor.yy0.type = 0; } +#line 3503 "sql.c" break; case 204: /* orderby_opt ::= ORDER BY sortlist */ -{yymsp[-2].minor.yy525 = yymsp[0].minor.yy525;} +#line 619 "sql.y" +{yymsp[-2].minor.yy131 = yymsp[0].minor.yy131;} +#line 3508 "sql.c" break; case 205: /* sortlist ::= sortlist COMMA item sortorder */ +#line 621 "sql.y" { - yylhsminor.yy525 = tVariantListAppend(yymsp[-3].minor.yy525, &yymsp[-1].minor.yy506, yymsp[0].minor.yy52); + yylhsminor.yy131 = tVariantListAppend(yymsp[-3].minor.yy131, &yymsp[-1].minor.yy516, yymsp[0].minor.yy43); } - yymsp[-3].minor.yy525 = yylhsminor.yy525; +#line 3515 "sql.c" + yymsp[-3].minor.yy131 = yylhsminor.yy131; break; case 206: /* sortlist ::= item sortorder */ +#line 625 "sql.y" { - yylhsminor.yy525 = tVariantListAppend(NULL, &yymsp[-1].minor.yy506, yymsp[0].minor.yy52); + yylhsminor.yy131 = tVariantListAppend(NULL, &yymsp[-1].minor.yy516, yymsp[0].minor.yy43); } - yymsp[-1].minor.yy525 = yylhsminor.yy525; +#line 3523 "sql.c" + yymsp[-1].minor.yy131 = yylhsminor.yy131; break; case 207: /* item ::= ids cpxName */ +#line 630 "sql.y" { toTSDBType(yymsp[-1].minor.yy0.type); yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - tVariantCreate(&yylhsminor.yy506, &yymsp[-1].minor.yy0); + tVariantCreate(&yylhsminor.yy516, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy506 = yylhsminor.yy506; +#line 3534 "sql.c" + yymsp[-1].minor.yy516 = yylhsminor.yy516; break; case 208: /* sortorder ::= ASC */ -{ yymsp[0].minor.yy52 = TSDB_ORDER_ASC; } +#line 638 "sql.y" +{ yymsp[0].minor.yy43 = TSDB_ORDER_ASC; } +#line 3540 "sql.c" break; case 209: /* sortorder ::= DESC */ -{ yymsp[0].minor.yy52 = TSDB_ORDER_DESC;} +#line 639 "sql.y" +{ yymsp[0].minor.yy43 = TSDB_ORDER_DESC;} +#line 3545 "sql.c" break; case 210: /* sortorder ::= */ -{ yymsp[1].minor.yy52 = TSDB_ORDER_ASC; } +#line 640 "sql.y" +{ yymsp[1].minor.yy43 = TSDB_ORDER_ASC; } +#line 3550 "sql.c" break; case 211: /* groupby_opt ::= */ -{ yymsp[1].minor.yy525 = 0;} +#line 648 "sql.y" +{ yymsp[1].minor.yy131 = 0;} +#line 3555 "sql.c" break; case 212: /* groupby_opt ::= GROUP BY grouplist */ -{ yymsp[-2].minor.yy525 = yymsp[0].minor.yy525;} +#line 649 "sql.y" +{ yymsp[-2].minor.yy131 = yymsp[0].minor.yy131;} +#line 3560 "sql.c" break; case 213: /* grouplist ::= grouplist COMMA item */ +#line 651 "sql.y" { - yylhsminor.yy525 = tVariantListAppend(yymsp[-2].minor.yy525, &yymsp[0].minor.yy506, -1); + yylhsminor.yy131 = tVariantListAppend(yymsp[-2].minor.yy131, &yymsp[0].minor.yy516, -1); } - yymsp[-2].minor.yy525 = yylhsminor.yy525; +#line 3567 "sql.c" + yymsp[-2].minor.yy131 = yylhsminor.yy131; break; case 214: /* grouplist ::= item */ +#line 655 "sql.y" { - yylhsminor.yy525 = tVariantListAppend(NULL, &yymsp[0].minor.yy506, -1); + yylhsminor.yy131 = tVariantListAppend(NULL, &yymsp[0].minor.yy516, -1); } - yymsp[0].minor.yy525 = yylhsminor.yy525; +#line 3575 "sql.c" + yymsp[0].minor.yy131 = yylhsminor.yy131; break; case 215: /* having_opt ::= */ case 225: /* where_opt ::= */ yytestcase(yyruleno==225); case 267: /* expritem ::= */ yytestcase(yyruleno==267); -{yymsp[1].minor.yy370 = 0;} +#line 662 "sql.y" +{yymsp[1].minor.yy46 = 0;} +#line 3583 "sql.c" break; case 216: /* having_opt ::= HAVING expr */ case 226: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==226); -{yymsp[-1].minor.yy370 = yymsp[0].minor.yy370;} +#line 663 "sql.y" +{yymsp[-1].minor.yy46 = yymsp[0].minor.yy46;} +#line 3589 "sql.c" break; case 217: /* limit_opt ::= */ case 221: /* slimit_opt ::= */ yytestcase(yyruleno==221); -{yymsp[1].minor.yy126.limit = -1; yymsp[1].minor.yy126.offset = 0;} +#line 667 "sql.y" +{yymsp[1].minor.yy284.limit = -1; yymsp[1].minor.yy284.offset = 0;} +#line 3595 "sql.c" break; case 218: /* limit_opt ::= LIMIT signed */ case 222: /* slimit_opt ::= SLIMIT signed */ yytestcase(yyruleno==222); -{yymsp[-1].minor.yy126.limit = yymsp[0].minor.yy501; yymsp[-1].minor.yy126.offset = 0;} +#line 668 "sql.y" +{yymsp[-1].minor.yy284.limit = yymsp[0].minor.yy459; yymsp[-1].minor.yy284.offset = 0;} +#line 3601 "sql.c" break; case 219: /* limit_opt ::= LIMIT signed OFFSET signed */ -{ yymsp[-3].minor.yy126.limit = yymsp[-2].minor.yy501; yymsp[-3].minor.yy126.offset = yymsp[0].minor.yy501;} +#line 670 "sql.y" +{ yymsp[-3].minor.yy284.limit = yymsp[-2].minor.yy459; yymsp[-3].minor.yy284.offset = yymsp[0].minor.yy459;} +#line 3606 "sql.c" break; case 220: /* limit_opt ::= LIMIT signed COMMA signed */ -{ yymsp[-3].minor.yy126.limit = yymsp[0].minor.yy501; yymsp[-3].minor.yy126.offset = yymsp[-2].minor.yy501;} +#line 672 "sql.y" +{ yymsp[-3].minor.yy284.limit = yymsp[0].minor.yy459; yymsp[-3].minor.yy284.offset = yymsp[-2].minor.yy459;} +#line 3611 "sql.c" break; case 223: /* slimit_opt ::= SLIMIT signed SOFFSET signed */ -{yymsp[-3].minor.yy126.limit = yymsp[-2].minor.yy501; yymsp[-3].minor.yy126.offset = yymsp[0].minor.yy501;} +#line 678 "sql.y" +{yymsp[-3].minor.yy284.limit = yymsp[-2].minor.yy459; yymsp[-3].minor.yy284.offset = yymsp[0].minor.yy459;} +#line 3616 "sql.c" break; case 224: /* slimit_opt ::= SLIMIT signed COMMA signed */ -{yymsp[-3].minor.yy126.limit = yymsp[0].minor.yy501; yymsp[-3].minor.yy126.offset = yymsp[-2].minor.yy501;} +#line 680 "sql.y" +{yymsp[-3].minor.yy284.limit = yymsp[0].minor.yy459; yymsp[-3].minor.yy284.offset = yymsp[-2].minor.yy459;} +#line 3621 "sql.c" break; case 227: /* expr ::= LP expr RP */ -{yylhsminor.yy370 = yymsp[-1].minor.yy370; yylhsminor.yy370->exprToken.z = yymsp[-2].minor.yy0.z; yylhsminor.yy370->exprToken.n = (yymsp[0].minor.yy0.z - yymsp[-2].minor.yy0.z + 1);} - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 693 "sql.y" +{yylhsminor.yy46 = yymsp[-1].minor.yy46; yylhsminor.yy46->exprToken.z = yymsp[-2].minor.yy0.z; yylhsminor.yy46->exprToken.n = (yymsp[0].minor.yy0.z - yymsp[-2].minor.yy0.z + 1);} +#line 3626 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 228: /* expr ::= ID */ -{ yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_ID);} - yymsp[0].minor.yy370 = yylhsminor.yy370; +#line 695 "sql.y" +{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_ID);} +#line 3632 "sql.c" + yymsp[0].minor.yy46 = yylhsminor.yy46; break; case 229: /* expr ::= ID DOT ID */ -{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[-2].minor.yy0, TK_ID);} - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 696 "sql.y" +{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[-2].minor.yy0, TK_ID);} +#line 3638 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 230: /* expr ::= ID DOT STAR */ -{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[-2].minor.yy0, TK_ALL);} - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 697 "sql.y" +{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[-2].minor.yy0, TK_ALL);} +#line 3644 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 231: /* expr ::= INTEGER */ -{ yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_INTEGER);} - yymsp[0].minor.yy370 = yylhsminor.yy370; +#line 699 "sql.y" +{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_INTEGER);} +#line 3650 "sql.c" + yymsp[0].minor.yy46 = yylhsminor.yy46; break; case 232: /* expr ::= MINUS INTEGER */ case 233: /* expr ::= PLUS INTEGER */ yytestcase(yyruleno==233); -{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_INTEGER; yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_INTEGER);} - yymsp[-1].minor.yy370 = yylhsminor.yy370; +#line 700 "sql.y" +{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_INTEGER; yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_INTEGER);} +#line 3657 "sql.c" + yymsp[-1].minor.yy46 = yylhsminor.yy46; break; case 234: /* expr ::= FLOAT */ -{ yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_FLOAT);} - yymsp[0].minor.yy370 = yylhsminor.yy370; +#line 702 "sql.y" +{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_FLOAT);} +#line 3663 "sql.c" + yymsp[0].minor.yy46 = yylhsminor.yy46; break; case 235: /* expr ::= MINUS FLOAT */ case 236: /* expr ::= PLUS FLOAT */ yytestcase(yyruleno==236); -{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_FLOAT; yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_FLOAT);} - yymsp[-1].minor.yy370 = yylhsminor.yy370; +#line 703 "sql.y" +{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_FLOAT; yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_FLOAT);} +#line 3670 "sql.c" + yymsp[-1].minor.yy46 = yylhsminor.yy46; break; case 237: /* expr ::= STRING */ -{ yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_STRING);} - yymsp[0].minor.yy370 = yylhsminor.yy370; +#line 705 "sql.y" +{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_STRING);} +#line 3676 "sql.c" + yymsp[0].minor.yy46 = yylhsminor.yy46; break; case 238: /* expr ::= NOW */ -{ yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_NOW); } - yymsp[0].minor.yy370 = yylhsminor.yy370; +#line 706 "sql.y" +{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_NOW); } +#line 3682 "sql.c" + yymsp[0].minor.yy46 = yylhsminor.yy46; break; case 239: /* expr ::= VARIABLE */ -{ yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_VARIABLE);} - yymsp[0].minor.yy370 = yylhsminor.yy370; +#line 707 "sql.y" +{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_VARIABLE);} +#line 3688 "sql.c" + yymsp[0].minor.yy46 = yylhsminor.yy46; break; case 240: /* expr ::= PLUS VARIABLE */ case 241: /* expr ::= MINUS VARIABLE */ yytestcase(yyruleno==241); -{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_VARIABLE; yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_VARIABLE);} - yymsp[-1].minor.yy370 = yylhsminor.yy370; +#line 708 "sql.y" +{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_VARIABLE; yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_VARIABLE);} +#line 3695 "sql.c" + yymsp[-1].minor.yy46 = yylhsminor.yy46; break; case 242: /* expr ::= BOOL */ -{ yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_BOOL);} - yymsp[0].minor.yy370 = yylhsminor.yy370; +#line 710 "sql.y" +{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_BOOL);} +#line 3701 "sql.c" + yymsp[0].minor.yy46 = yylhsminor.yy46; break; case 243: /* expr ::= NULL */ -{ yylhsminor.yy370 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_NULL);} - yymsp[0].minor.yy370 = yylhsminor.yy370; +#line 711 "sql.y" +{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_NULL);} +#line 3707 "sql.c" + yymsp[0].minor.yy46 = yylhsminor.yy46; break; case 244: /* expr ::= ID LP exprlist RP */ -{ tStrTokenAppend(pInfo->funcs, &yymsp[-3].minor.yy0); yylhsminor.yy370 = tSqlExprCreateFunction(yymsp[-1].minor.yy525, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } - yymsp[-3].minor.yy370 = yylhsminor.yy370; +#line 714 "sql.y" +{ tStrTokenAppend(pInfo->funcs, &yymsp[-3].minor.yy0); yylhsminor.yy46 = tSqlExprCreateFunction(yymsp[-1].minor.yy131, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } +#line 3713 "sql.c" + yymsp[-3].minor.yy46 = yylhsminor.yy46; break; case 245: /* expr ::= ID LP STAR RP */ -{ tStrTokenAppend(pInfo->funcs, &yymsp[-3].minor.yy0); yylhsminor.yy370 = tSqlExprCreateFunction(NULL, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } - yymsp[-3].minor.yy370 = yylhsminor.yy370; +#line 717 "sql.y" +{ tStrTokenAppend(pInfo->funcs, &yymsp[-3].minor.yy0); yylhsminor.yy46 = tSqlExprCreateFunction(NULL, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } +#line 3719 "sql.c" + yymsp[-3].minor.yy46 = yylhsminor.yy46; break; case 246: /* expr ::= expr IS NULL */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, NULL, TK_ISNULL);} - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 720 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, NULL, TK_ISNULL);} +#line 3725 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 247: /* expr ::= expr IS NOT NULL */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-3].minor.yy370, NULL, TK_NOTNULL);} - yymsp[-3].minor.yy370 = yylhsminor.yy370; +#line 721 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-3].minor.yy46, NULL, TK_NOTNULL);} +#line 3731 "sql.c" + yymsp[-3].minor.yy46 = yylhsminor.yy46; break; case 248: /* expr ::= expr LT expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_LT);} - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 724 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_LT);} +#line 3737 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 249: /* expr ::= expr GT expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_GT);} - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 725 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_GT);} +#line 3743 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 250: /* expr ::= expr LE expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_LE);} - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 726 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_LE);} +#line 3749 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 251: /* expr ::= expr GE expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_GE);} - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 727 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_GE);} +#line 3755 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 252: /* expr ::= expr NE expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_NE);} - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 728 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_NE);} +#line 3761 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 253: /* expr ::= expr EQ expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_EQ);} - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 729 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_EQ);} +#line 3767 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 254: /* expr ::= expr BETWEEN expr AND expr */ -{ tSqlExpr* X2 = tSqlExprClone(yymsp[-4].minor.yy370); yylhsminor.yy370 = tSqlExprCreate(tSqlExprCreate(yymsp[-4].minor.yy370, yymsp[-2].minor.yy370, TK_GE), tSqlExprCreate(X2, yymsp[0].minor.yy370, TK_LE), TK_AND);} - yymsp[-4].minor.yy370 = yylhsminor.yy370; +#line 731 "sql.y" +{ tSqlExpr* X2 = tSqlExprClone(yymsp[-4].minor.yy46); yylhsminor.yy46 = tSqlExprCreate(tSqlExprCreate(yymsp[-4].minor.yy46, yymsp[-2].minor.yy46, TK_GE), tSqlExprCreate(X2, yymsp[0].minor.yy46, TK_LE), TK_AND);} +#line 3773 "sql.c" + yymsp[-4].minor.yy46 = yylhsminor.yy46; break; case 255: /* expr ::= expr AND expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_AND);} - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 733 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_AND);} +#line 3779 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 256: /* expr ::= expr OR expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_OR); } - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 734 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_OR); } +#line 3785 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 257: /* expr ::= expr PLUS expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_PLUS); } - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 737 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_PLUS); } +#line 3791 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 258: /* expr ::= expr MINUS expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_MINUS); } - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 738 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_MINUS); } +#line 3797 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 259: /* expr ::= expr STAR expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_STAR); } - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 739 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_STAR); } +#line 3803 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 260: /* expr ::= expr SLASH expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_DIVIDE);} - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 740 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_DIVIDE);} +#line 3809 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 261: /* expr ::= expr REM expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_REM); } - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 741 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_REM); } +#line 3815 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 262: /* expr ::= expr LIKE expr */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-2].minor.yy370, yymsp[0].minor.yy370, TK_LIKE); } - yymsp[-2].minor.yy370 = yylhsminor.yy370; +#line 744 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_LIKE); } +#line 3821 "sql.c" + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; case 263: /* expr ::= expr IN LP exprlist RP */ -{yylhsminor.yy370 = tSqlExprCreate(yymsp[-4].minor.yy370, (tSqlExpr*)yymsp[-1].minor.yy525, TK_IN); } - yymsp[-4].minor.yy370 = yylhsminor.yy370; +#line 747 "sql.y" +{yylhsminor.yy46 = tSqlExprCreate(yymsp[-4].minor.yy46, (tSqlExpr*)yymsp[-1].minor.yy131, TK_IN); } +#line 3827 "sql.c" + yymsp[-4].minor.yy46 = yylhsminor.yy46; break; case 264: /* exprlist ::= exprlist COMMA expritem */ -{yylhsminor.yy525 = tSqlExprListAppend(yymsp[-2].minor.yy525,yymsp[0].minor.yy370,0, 0);} - yymsp[-2].minor.yy525 = yylhsminor.yy525; +#line 755 "sql.y" +{yylhsminor.yy131 = tSqlExprListAppend(yymsp[-2].minor.yy131,yymsp[0].minor.yy46,0, 0);} +#line 3833 "sql.c" + yymsp[-2].minor.yy131 = yylhsminor.yy131; break; case 265: /* exprlist ::= expritem */ -{yylhsminor.yy525 = tSqlExprListAppend(0,yymsp[0].minor.yy370,0, 0);} - yymsp[0].minor.yy525 = yylhsminor.yy525; +#line 756 "sql.y" +{yylhsminor.yy131 = tSqlExprListAppend(0,yymsp[0].minor.yy46,0, 0);} +#line 3839 "sql.c" + yymsp[0].minor.yy131 = yylhsminor.yy131; break; case 266: /* expritem ::= expr */ -{yylhsminor.yy370 = yymsp[0].minor.yy370;} - yymsp[0].minor.yy370 = yylhsminor.yy370; +#line 757 "sql.y" +{yylhsminor.yy46 = yymsp[0].minor.yy46;} +#line 3845 "sql.c" + yymsp[0].minor.yy46 = yylhsminor.yy46; break; case 268: /* cmd ::= RESET QUERY CACHE */ +#line 761 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_RESET_CACHE, 0);} +#line 3851 "sql.c" break; case 269: /* cmd ::= SYNCDB ids REPLICA */ +#line 764 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_SYNC_DB_REPLICA, 1, &yymsp[-1].minor.yy0);} +#line 3856 "sql.c" break; case 270: /* cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ +#line 767 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy525, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } +#line 3865 "sql.c" break; case 271: /* cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ +#line 773 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; @@ -3134,22 +3874,28 @@ static void yy_reduce( SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } +#line 3878 "sql.c" break; case 272: /* cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist */ +#line 783 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy525, NULL, TSDB_ALTER_TABLE_CHANGE_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_CHANGE_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } +#line 3887 "sql.c" break; case 273: /* cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ +#line 790 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy525, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } +#line 3896 "sql.c" break; case 274: /* cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ +#line 795 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; @@ -3159,8 +3905,10 @@ static void yy_reduce( SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, NULL, A, TSDB_ALTER_TABLE_DROP_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } +#line 3909 "sql.c" break; case 275: /* cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ +#line 805 "sql.y" { yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; @@ -3173,34 +3921,42 @@ static void yy_reduce( SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-5].minor.yy0, NULL, A, TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } +#line 3925 "sql.c" break; case 276: /* cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ +#line 818 "sql.y" { 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.yy506, -1); + A = tVariantListAppend(A, &yymsp[0].minor.yy516, -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); } +#line 3939 "sql.c" break; case 277: /* cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist */ +#line 829 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy525, NULL, TSDB_ALTER_TABLE_MODIFY_TAG_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_MODIFY_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } +#line 3948 "sql.c" break; case 278: /* cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ +#line 836 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy525, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } +#line 3957 "sql.c" break; case 279: /* cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ +#line 842 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; @@ -3210,22 +3966,28 @@ static void yy_reduce( 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); } +#line 3970 "sql.c" break; case 280: /* cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist */ +#line 852 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy525, NULL, TSDB_ALTER_TABLE_CHANGE_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_CHANGE_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } +#line 3979 "sql.c" break; case 281: /* cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ +#line 859 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy525, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } +#line 3988 "sql.c" break; case 282: /* cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ +#line 864 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; @@ -3235,8 +3997,10 @@ static void yy_reduce( 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); } +#line 4001 "sql.c" break; case 283: /* cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ +#line 874 "sql.y" { yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; @@ -3249,42 +4013,53 @@ static void yy_reduce( 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); } +#line 4017 "sql.c" break; case 284: /* cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem */ +#line 887 "sql.y" { 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.yy506, -1); + A = tVariantListAppend(A, &yymsp[0].minor.yy516, -1); SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-6].minor.yy0, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_VAL, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } +#line 4031 "sql.c" break; case 285: /* cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist */ +#line 898 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy525, NULL, TSDB_ALTER_TABLE_MODIFY_TAG_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_MODIFY_TAG_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } +#line 4040 "sql.c" break; case 286: /* cmd ::= KILL CONNECTION INTEGER */ +#line 905 "sql.y" {setKillSql(pInfo, TSDB_SQL_KILL_CONNECTION, &yymsp[0].minor.yy0);} +#line 4045 "sql.c" break; case 287: /* cmd ::= KILL STREAM INTEGER COLON INTEGER */ +#line 906 "sql.y" {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);} +#line 4050 "sql.c" break; case 288: /* cmd ::= KILL QUERY INTEGER COLON INTEGER */ +#line 907 "sql.y" {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);} +#line 4055 "sql.c" break; default: break; /********** End reduce actions ************************************************/ }; - assert( yyrulenostateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; yyTraceShift(yypParser, yyact, "... then shift"); + return yyact; } /* @@ -3308,7 +4084,8 @@ static void yy_reduce( static void yy_parse_failed( yyParser *yypParser /* The parser */ ){ - ParseARG_FETCH; + ParseARG_FETCH + ParseCTX_FETCH #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); @@ -3319,7 +4096,8 @@ static void yy_parse_failed( ** parser fails */ /************ Begin %parse_failure code ***************************************/ /************ End %parse_failure code *****************************************/ - ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ + ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ + ParseCTX_STORE } #endif /* YYNOERRORRECOVERY */ @@ -3331,9 +4109,11 @@ static void yy_syntax_error( int yymajor, /* The major type of the error token */ ParseTOKENTYPE yyminor /* The minor type of the error token */ ){ - ParseARG_FETCH; + ParseARG_FETCH + ParseCTX_FETCH #define TOKEN yyminor /************ Begin %syntax_error code ****************************************/ +#line 37 "sql.y" pInfo->valid = false; int32_t outputBufLen = tListLen(pInfo->msg); @@ -3356,8 +4136,10 @@ static void yy_syntax_error( } assert(len <= outputBufLen); +#line 4140 "sql.c" /************ End %syntax_error code ******************************************/ - ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ + ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ + ParseCTX_STORE } /* @@ -3366,7 +4148,8 @@ static void yy_syntax_error( static void yy_accept( yyParser *yypParser /* The parser */ ){ - ParseARG_FETCH; + ParseARG_FETCH + ParseCTX_FETCH #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); @@ -3379,9 +4162,11 @@ static void yy_accept( /* Here code is inserted which will be executed whenever the ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ - +#line 61 "sql.y" +#line 4167 "sql.c" /*********** End %parse_accept code *******************************************/ - ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ + ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ + ParseCTX_STORE } /* The main parser program. @@ -3410,45 +4195,47 @@ void Parse( ParseARG_PDECL /* Optional %extra_argument parameter */ ){ YYMINORTYPE yyminorunion; - unsigned int yyact; /* The parser action. */ + YYACTIONTYPE yyact; /* The parser action. */ #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) int yyendofinput; /* True if we are at the end of input */ #endif #ifdef YYERRORSYMBOL int yyerrorhit = 0; /* True if yymajor has invoked an error */ #endif - yyParser *yypParser; /* The parser */ + yyParser *yypParser = (yyParser*)yyp; /* The parser */ + ParseCTX_FETCH + ParseARG_STORE - yypParser = (yyParser*)yyp; assert( yypParser->yytos!=0 ); #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) yyendofinput = (yymajor==0); #endif - ParseARG_STORE; + yyact = yypParser->yytos->stateno; #ifndef NDEBUG if( yyTraceFILE ){ - int stateno = yypParser->yytos->stateno; - if( stateno < YY_MIN_REDUCE ){ + if( yyact < YY_MIN_REDUCE ){ fprintf(yyTraceFILE,"%sInput '%s' in state %d\n", - yyTracePrompt,yyTokenName[yymajor],stateno); + yyTracePrompt,yyTokenName[yymajor],yyact); }else{ fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n", - yyTracePrompt,yyTokenName[yymajor],stateno-YY_MIN_REDUCE); + yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE); } } #endif do{ - yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); + assert( yyact==yypParser->yytos->stateno ); + yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact); if( yyact >= YY_MIN_REDUCE ){ - yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,yyminor); + yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor, + yyminor ParseCTX_PARAM); }else if( yyact <= YY_MAX_SHIFTREDUCE ){ - yy_shift(yypParser,yyact,yymajor,yyminor); + yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt--; #endif - yymajor = YYNOCODE; + break; }else if( yyact==YY_ACCEPT_ACTION ){ yypParser->yytos--; yy_accept(yypParser); @@ -3499,10 +4286,9 @@ void Parse( yymajor = YYNOCODE; }else{ while( yypParser->yytos >= yypParser->yystack - && yymx != YYERRORSYMBOL && (yyact = yy_find_reduce_action( yypParser->yytos->stateno, - YYERRORSYMBOL)) >= YY_MIN_REDUCE + YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE ){ yy_pop_parser_stack(yypParser); } @@ -3519,6 +4305,8 @@ void Parse( } yypParser->yyerrcnt = 3; yyerrorhit = 1; + if( yymajor==YYNOCODE ) break; + yyact = yypParser->yytos->stateno; #elif defined(YYNOERRORRECOVERY) /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to ** do any kind of error recovery. Instead, simply invoke the syntax @@ -3529,8 +4317,7 @@ void Parse( */ yy_syntax_error(yypParser,yymajor, yyminor); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - yymajor = YYNOCODE; - + break; #else /* YYERRORSYMBOL is not defined */ /* This is what we do if the grammar does not define ERROR: ** @@ -3552,10 +4339,10 @@ void Parse( yypParser->yyerrcnt = -1; #endif } - yymajor = YYNOCODE; + break; #endif } - }while( yymajor!=YYNOCODE && yypParser->yytos>yypParser->yystack ); + }while( yypParser->yytos>yypParser->yystack ); #ifndef NDEBUG if( yyTraceFILE ){ yyStackEntry *i; @@ -3570,3 +4357,17 @@ void Parse( #endif return; } + +/* +** Return the fallback token corresponding to canonical token iToken, or +** 0 if iToken has no fallback. +*/ +int ParseFallback(int iToken){ +#ifdef YYFALLBACK + assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); + return yyFallback[iToken]; +#else + (void)iToken; + return 0; +#endif +} diff --git a/src/query/tests/CMakeLists.txt b/src/query/tests/CMakeLists.txt index cc4b607bb4..349d511f15 100644 --- a/src/query/tests/CMakeLists.txt +++ b/src/query/tests/CMakeLists.txt @@ -27,3 +27,4 @@ SET_SOURCE_FILES_PROPERTIES(./percentileTest.cpp PROPERTIES COMPILE_FLAGS -w) SET_SOURCE_FILES_PROPERTIES(./resultBufferTest.cpp PROPERTIES COMPILE_FLAGS -w) SET_SOURCE_FILES_PROPERTIES(./tsBufTest.cpp PROPERTIES COMPILE_FLAGS -w) SET_SOURCE_FILES_PROPERTIES(./unitTest.cpp PROPERTIES COMPILE_FLAGS -w) +SET_SOURCE_FILES_PROPERTIES(./rangeMergeTest.cpp PROPERTIES COMPILE_FLAGS -w) diff --git a/src/query/tests/rangeMergeTest.cpp b/src/query/tests/rangeMergeTest.cpp new file mode 100644 index 0000000000..e65508a300 --- /dev/null +++ b/src/query/tests/rangeMergeTest.cpp @@ -0,0 +1,367 @@ +#include +#include + +#include "qResultbuf.h" +#include "taos.h" +#include "taosdef.h" + +#include "qFilter.h" + +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" + +extern "C" { + extern void* filterInitRangeCtx(int32_t type, int32_t options); + extern int32_t filterGetRangeNum(void* h, int32_t* num); + extern int32_t filterGetRangeRes(void* h, SFilterRange *ra); + extern int32_t filterFreeRangeCtx(void* h); + extern int32_t filterAddRange(void* h, SFilterRange* ra, int32_t optr); +} + +namespace { + + +void intDataTest() { + printf("running %s\n", __FUNCTION__); + int32_t asize = 0; + SFilterRange ra[10] = {0}; + int64_t *s =NULL; + int64_t *e =NULL; + int64_t s0[3] = {-100, 1, 3}; + int64_t e0[3] = {0 , 2, 4}; + int64_t s1[3] = {INT64_MIN, 0 , 3}; + int64_t e1[3] = {100 , 50, 4}; + int64_t s2[5] = {1 , 3 , 10,30,70}; + int64_t e2[5] = {10, 100, 20,50,120}; + int64_t s3[3] = {1 , 20 , 5}; + int64_t e3[3] = {10, 100, 25}; + int64_t s4[2] = {10, 0}; + int64_t e4[2] = {20, 5}; + int64_t s5[3] = {0, 6 ,7}; + int64_t e5[3] = {4, 10,20}; + + int64_t rs[10]; + int64_t re[10]; + + int32_t num = 0; + void *h = NULL; + + s = s0; + e = e0; + asize = sizeof(s0)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + filterAddRange(h, ra, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 3); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, -100); + ASSERT_EQ(ra[0].e, 0); + ASSERT_EQ(ra[1].s, 1); + ASSERT_EQ(ra[1].e, 2); + ASSERT_EQ(ra[2].s, 3); + ASSERT_EQ(ra[2].e, 4); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, FI_OPTION_TIMESTAMP); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, -100); + ASSERT_EQ(ra[0].e, 4); + filterFreeRangeCtx(h); + + + s = s1; + e = e1; + asize = sizeof(s1)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 3); + ASSERT_EQ(ra[0].e, 4); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, INT64_MIN); + ASSERT_EQ(ra[0].e, 100); + filterFreeRangeCtx(h); + + + + s = s2; + e = e2; + asize = sizeof(s2)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 1); + ASSERT_EQ(ra[0].e, 120); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, i % 2 ? TSDB_RELATION_OR : TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, i % 2 ? TSDB_RELATION_AND : TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 70); + ASSERT_EQ(ra[0].e, 120); + filterFreeRangeCtx(h); + + + s = s3; + e = e3; + asize = sizeof(s3)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 1); + ASSERT_EQ(ra[0].e, 100); + filterFreeRangeCtx(h); + + + + + s = s4; + e = e4; + asize = sizeof(s4)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 2); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 0); + ASSERT_EQ(ra[0].e, 5); + ASSERT_EQ(ra[1].s, 10); + ASSERT_EQ(ra[1].e, 20); + filterFreeRangeCtx(h); + + + s = s5; + e = e5; + asize = sizeof(s5)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 2); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 0); + ASSERT_EQ(ra[0].e, 4); + ASSERT_EQ(ra[1].s, 6); + ASSERT_EQ(ra[1].e, 20); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, (i == (asize -1)) ? TSDB_RELATION_AND : TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 7); + ASSERT_EQ(ra[0].e, 10); + filterFreeRangeCtx(h); + + + + int64_t s6[2] = {0, 4}; + int64_t e6[2] = {4, 6}; + s = s6; + e = e6; + asize = sizeof(s6)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].eflag = 1; + ra[1].sflag = 4; + + ra[i].s = s[i]; + ra[i].e = e[i]; + + filterAddRange(h, ra + i, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].eflag = 1; + ra[1].sflag = 1; + + ra[i].s = s[i]; + ra[i].e = e[i]; + + filterAddRange(h, ra + i, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 2); + ASSERT_EQ(ra[0].s, 0); + ASSERT_EQ(ra[0].e, 4); + ASSERT_EQ(ra[0].eflag, 1); + ASSERT_EQ(ra[1].s, 4); + ASSERT_EQ(ra[1].e, 6); + ASSERT_EQ(ra[1].sflag, 1); + filterFreeRangeCtx(h); + +} + + +} // namespace + +TEST(testCase, rangeMergeTest) { + intDataTest(); + +} diff --git a/src/query/tests/unitTest.cpp b/src/query/tests/unitTest.cpp index 2338adc2c5..1ed4cde406 100644 --- a/src/query/tests/unitTest.cpp +++ b/src/query/tests/unitTest.cpp @@ -405,11 +405,56 @@ TEST(testCase, parse_time) { taosParseTime(t41, &time, strlen(t41), TSDB_TIME_PRECISION_MILLI, 0); EXPECT_EQ(time, 852048000999); - int64_t k = timezone; char t42[] = "1997-1-1T0:0:0.999999999Z"; taosParseTime(t42, &time, strlen(t42), TSDB_TIME_PRECISION_MILLI, 0); EXPECT_EQ(time, 852048000999 - timezone * MILLISECOND_PER_SECOND); + // "%Y-%m-%d %H:%M:%S" format with TimeZone appendix is also treated as legal + // and TimeZone will be processed + char t60[] = "2017-4-3 1:1:2.980"; + char t61[] = "2017-4-3 2:1:2.98+9:00"; + taosParseTime(t60, &time, strlen(t60), TSDB_TIME_PRECISION_MILLI, 0); + taosParseTime(t61, &time1, strlen(t61), TSDB_TIME_PRECISION_MILLI, 0); + EXPECT_EQ(time, time1); + + char t62[] = "2017-4-3 2:1:2.98+09:00"; + taosParseTime(t62, &time, strlen(t62), TSDB_TIME_PRECISION_MILLI, 0); + taosParseTime(t61, &time1, strlen(t61), TSDB_TIME_PRECISION_MILLI, 0); + EXPECT_EQ(time, time1); + + char t63[] = "2017-4-3 2:1:2.98+0900"; + taosParseTime(t63, &time, strlen(t63), TSDB_TIME_PRECISION_MILLI, 0); + taosParseTime(t62, &time1, strlen(t62), TSDB_TIME_PRECISION_MILLI, 0); + EXPECT_EQ(time, time1); + + char t64[] = "2017-4-2 17:1:2.98Z"; + taosParseTime(t63, &time, strlen(t63), TSDB_TIME_PRECISION_MILLI, 0); + taosParseTime(t64, &time1, strlen(t64), TSDB_TIME_PRECISION_MILLI, 0); + EXPECT_EQ(time, time1); + + // "%Y-%m-%d%H:%M:%S" format with TimeZone appendix is also treated as legal + // and TimeZone will be processed + char t80[] = "2017-4-51:1:2.980"; + char t81[] = "2017-4-52:1:2.98+9:00"; + taosParseTime(t80, &time, strlen(t80), TSDB_TIME_PRECISION_MILLI, 0); + taosParseTime(t81, &time1, strlen(t81), TSDB_TIME_PRECISION_MILLI, 0); + EXPECT_EQ(time, time1); + + char t82[] = "2017-4-52:1:2.98+09:00"; + taosParseTime(t82, &time, strlen(t82), TSDB_TIME_PRECISION_MILLI, 0); + taosParseTime(t81, &time1, strlen(t81), TSDB_TIME_PRECISION_MILLI, 0); + EXPECT_EQ(time, time1); + + char t83[] = "2017-4-52:1:2.98+0900"; + taosParseTime(t83, &time, strlen(t83), TSDB_TIME_PRECISION_MILLI, 0); + taosParseTime(t82, &time1, strlen(t82), TSDB_TIME_PRECISION_MILLI, 0); + EXPECT_EQ(time, time1); + + char t84[] = "2017-4-417:1:2.98Z"; + taosParseTime(t83, &time, strlen(t83), TSDB_TIME_PRECISION_MILLI, 0); + taosParseTime(t84, &time1, strlen(t84), TSDB_TIME_PRECISION_MILLI, 0); + EXPECT_EQ(time, time1); + //////////////////////////////////////////////////////////////////// // illegal timestamp format char t15[] = "2017-12-33 0:0:0"; @@ -428,8 +473,7 @@ TEST(testCase, parse_time) { EXPECT_EQ(taosParseTime(t19, &time, strlen(t19), TSDB_TIME_PRECISION_MILLI, 0), -1); char t20[] = "2017-12-31 9:0:0.1+12:99"; - EXPECT_EQ(taosParseTime(t20, &time, strlen(t20), TSDB_TIME_PRECISION_MILLI, 0), 0); - EXPECT_EQ(time, 1514682000100); + EXPECT_EQ(taosParseTime(t20, &time, strlen(t20), TSDB_TIME_PRECISION_MILLI, 0), -1); char t21[] = "2017-12-31T9:0:0.1+12:99"; EXPECT_EQ(taosParseTime(t21, &time, strlen(t21), TSDB_TIME_PRECISION_MILLI, 0), -1); @@ -439,8 +483,103 @@ TEST(testCase, parse_time) { char t23[] = "2017-12-31T9:0:0.1+13:1"; EXPECT_EQ(taosParseTime(t23, &time, strlen(t23), TSDB_TIME_PRECISION_MILLI, 0), 0); + + char t24[] = "2017-12-31T9:0:0.1+13:001"; + EXPECT_EQ(taosParseTime(t24, &time, strlen(t24), TSDB_TIME_PRECISION_MILLI, 0), -1); + + char t25[] = "2017-12-31T9:0:0.1+13:00abc"; + EXPECT_EQ(taosParseTime(t25, &time, strlen(t25), TSDB_TIME_PRECISION_MILLI, 0), -1); + + char t26[] = "2017-12-31T9:0:0.1+13001"; + EXPECT_EQ(taosParseTime(t26, &time, strlen(t26), TSDB_TIME_PRECISION_MILLI, 0), -1); + + char t27[] = "2017-12-31T9:0:0.1+1300abc"; + EXPECT_EQ(taosParseTime(t27, &time, strlen(t27), TSDB_TIME_PRECISION_MILLI, 0), -1); + + char t28[] = "2017-12-31T9:0:0Z+12:00"; + EXPECT_EQ(taosParseTime(t28, &time, strlen(t28), TSDB_TIME_PRECISION_MILLI, 0), -1); + + char t29[] = "2017-12-31T9:0:0.123Z+12:00"; + EXPECT_EQ(taosParseTime(t29, &time, strlen(t29), TSDB_TIME_PRECISION_MILLI, 0), -1); + + char t65[] = "2017-12-31 9:0:0.1+13:001"; + EXPECT_EQ(taosParseTime(t65, &time, strlen(t65), TSDB_TIME_PRECISION_MILLI, 0), -1); + + char t66[] = "2017-12-31 9:0:0.1+13:00abc"; + EXPECT_EQ(taosParseTime(t66, &time, strlen(t66), TSDB_TIME_PRECISION_MILLI, 0), -1); + + char t67[] = "2017-12-31 9:0:0.1+13001"; + EXPECT_EQ(taosParseTime(t67, &time, strlen(t67), TSDB_TIME_PRECISION_MILLI, 0), -1); + + char t68[] = "2017-12-31 9:0:0.1+1300abc"; + EXPECT_EQ(taosParseTime(t68, &time, strlen(t68), TSDB_TIME_PRECISION_MILLI, 0), -1); + + char t69[] = "2017-12-31 9:0:0Z+12:00"; + EXPECT_EQ(taosParseTime(t69, &time, strlen(t69), TSDB_TIME_PRECISION_MILLI, 0), -1); + + char t70[] = "2017-12-31 9:0:0.123Z+12:00"; + EXPECT_EQ(taosParseTime(t70, &time, strlen(t70), TSDB_TIME_PRECISION_MILLI, 0), -1); + } +/* test parse time profiling */ +TEST(testCase, parse_time_profile) { + taos_options(TSDB_OPTION_TIMEZONE, "GMT-8"); + char t1[] = "2018-1-8 1:1:1.952"; + char t2[] = "2018-1-8T1:1:1.952+0800"; + char t3[] = "2018-1-8 1:1:1.952+0800"; + char t4[] = "2018-1-81:1:1.952+0800"; + + char t5[] = "2018-1-8 1:1:1.952"; + char t6[] = "2018-1-8T1:1:1.952+08:00"; + char t7[] = "2018-1-8 1:1:1.952+08:00"; + char t8[] = "2018-1-81:1:1.952+08:00"; + + char t9[] = "2018-1-8 1:1:1.952"; + char t10[] = "2018-1-8T1:1:1.952Z"; + char t11[] = "2018-1-8 1:1:1.952z"; + char t12[] = "2018-1-81:1:1.952Z"; + + struct timeval start, end; + int64_t time = 0, time1 = 0; + + int32_t total_run = 100000000; + long total_time_us; + + gettimeofday(&start, NULL); + for (int i = 0; i < total_run; ++i) { + taosParseTime(t1, &time, strlen(t1), TSDB_TIME_PRECISION_MILLI, 0); + } + gettimeofday(&end, NULL); + total_time_us = ((end.tv_sec - start.tv_sec)* 1000000) + (end.tv_usec - start.tv_usec); + printf("[t1] The elapsed time is %f seconds in %d run, average:%fns\n", total_time_us/1000000.0, total_run, 1000*(float)total_time_us/(float)total_run); + + gettimeofday(&start, NULL); + for (int i = 0; i < total_run; ++i) { + taosParseTime(t2, &time, strlen(t2), TSDB_TIME_PRECISION_MILLI, 0); + } + gettimeofday(&end, NULL); + total_time_us = ((end.tv_sec - start.tv_sec)* 1000000) + (end.tv_usec - start.tv_usec); + printf("[t2] The elapsed time is %f seconds in %d run, average:%fns\n", total_time_us/1000000.0, total_run, 1000*(float)total_time_us/(float)total_run); + + gettimeofday(&start, NULL); + for (int i = 0; i < total_run; ++i) { + taosParseTime(t3, &time, strlen(t3), TSDB_TIME_PRECISION_MILLI, 0); + } + gettimeofday(&end, NULL); + total_time_us = ((end.tv_sec - start.tv_sec)* 1000000) + (end.tv_usec - start.tv_usec); + printf("[t3] The elapsed time is %f seconds in %d run, average:%fns\n", total_time_us/1000000.0, total_run, 1000*(float)total_time_us/(float)total_run); + + gettimeofday(&start, NULL); + for (int i = 0; i < total_run; ++i) { + taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI, 0); + } + gettimeofday(&end, NULL); + total_time_us = ((end.tv_sec - start.tv_sec)* 1000000) + (end.tv_usec - start.tv_usec); + printf("[t4] The elapsed time is %f seconds in %d run, average:%fns\n", total_time_us/1000000.0, total_run, 1000*(float)total_time_us/(float)total_run); +} + + TEST(testCase, tvariant_convert) { // 1. bool data to all other data types tVariant t = {0}; diff --git a/src/tfs/src/tfs.c b/src/tfs/src/tfs.c index 9dc68dcdfd..61fbc61448 100644 --- a/src/tfs/src/tfs.c +++ b/src/tfs/src/tfs.c @@ -261,11 +261,20 @@ int tfsMkdirRecurAt(const char *rname, int level, int id) { // Try to create upper char *s = strdup(rname); - if (tfsMkdirRecurAt(dirname(s), level, id) < 0) { - tfree(s); + // Make a copy of dirname(s) because the implementation of 'dirname' differs on different platforms. + // Some platform may modify the contents of the string passed into dirname(). Others may return a pointer to + // internal static storage space that will be overwritten by next call. For case like that, we should not use + // the pointer directly in this recursion. + // See https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dirname.3.html + char *dir = strdup(dirname(s)); + + if (tfsMkdirRecurAt(dir, level, id) < 0) { + free(s); + free(dir); return -1; } - tfree(s); + free(s); + free(dir); if (tfsMkdirAt(rname, level, id) < 0) { return -1; diff --git a/src/tsdb/src/tsdbCommit.c b/src/tsdb/src/tsdbCommit.c index 6c98283189..8f5f885d69 100644 --- a/src/tsdb/src/tsdbCommit.c +++ b/src/tsdb/src/tsdbCommit.c @@ -722,7 +722,7 @@ static int tsdbInitCommitH(SCommitH *pCommith, STsdbRepo *pRepo) { return -1; } - pCommith->pDataCols = tdNewDataCols(0, 0, pCfg->maxRowsPerFileBlock); + pCommith->pDataCols = tdNewDataCols(0, pCfg->maxRowsPerFileBlock); if (pCommith->pDataCols == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; tsdbDestroyCommitH(pCommith); @@ -920,7 +920,6 @@ int tsdbWriteBlockImpl(STsdbRepo *pRepo, STable *pTable, SDFile *pDFile, SDataCo SDataCol * pDataCol = pDataCols->cols + ncol; SBlockCol *pBlockCol = pBlockData->cols + nColsNotAllNull; - // if (isNEleNull(pDataCol, rowsToWrite)) { // all data to commit are NULL, just ignore it if (isAllRowsNull(pDataCol)) { // all data to commit are NULL, just ignore it continue; } @@ -1277,6 +1276,7 @@ static void tsdbLoadAndMergeFromCache(SDataCols *pDataCols, int *iter, SCommitIt if (key1 < key2) { for (int i = 0; i < pDataCols->numOfCols; i++) { + //TODO: dataColAppendVal may fail dataColAppendVal(pTarget->cols + i, tdGetColDataOfRow(pDataCols->cols + i, *iter), pTarget->numOfRows, pTarget->maxPoints); } @@ -1308,6 +1308,7 @@ static void tsdbLoadAndMergeFromCache(SDataCols *pDataCols, int *iter, SCommitIt ASSERT(!isRowDel); for (int i = 0; i < pDataCols->numOfCols; i++) { + //TODO: dataColAppendVal may fail dataColAppendVal(pTarget->cols + i, tdGetColDataOfRow(pDataCols->cols + i, *iter), pTarget->numOfRows, pTarget->maxPoints); } diff --git a/src/tsdb/src/tsdbCompact.c b/src/tsdb/src/tsdbCompact.c index 62f9e41119..5ccb9e90f2 100644 --- a/src/tsdb/src/tsdbCompact.c +++ b/src/tsdb/src/tsdbCompact.c @@ -296,7 +296,7 @@ static int tsdbCompactMeta(STsdbRepo *pRepo) { return -1; } - pComph->pDataCols = tdNewDataCols(0, 0, pCfg->maxRowsPerFileBlock); + pComph->pDataCols = tdNewDataCols(0, pCfg->maxRowsPerFileBlock); if (pComph->pDataCols == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; tsdbDestroyCompactH(pComph); diff --git a/src/tsdb/src/tsdbMemTable.c b/src/tsdb/src/tsdbMemTable.c index 8bb2d1c44e..e766d97a97 100644 --- a/src/tsdb/src/tsdbMemTable.c +++ b/src/tsdb/src/tsdbMemTable.c @@ -702,11 +702,12 @@ static int tsdbScanAndConvertSubmitMsg(STsdbRepo *pRepo, SSubmitMsg *pMsg) { } //row1 has higher priority -static SMemRow tsdbInsertDupKeyMerge(SMemRow row1, SMemRow row2, STsdbRepo* pRepo, STSchema **ppSchema1, STSchema **ppSchema2, STable* pTable, int32_t* pAffectedRows, int64_t* pPoints, SMemRow* pLastRow) { +static SMemRow tsdbInsertDupKeyMerge(SMemRow row1, SMemRow row2, STsdbRepo* pRepo, + STSchema **ppSchema1, STSchema **ppSchema2, + STable* pTable, int32_t* pPoints, SMemRow* pLastRow) { //for compatiblity, duplicate key inserted when update=0 should be also calculated as affected rows! if(row1 == NULL && row2 == NULL && pRepo->config.update == TD_ROW_DISCARD_UPDATE) { - (*pAffectedRows)++; (*pPoints)++; return NULL; } @@ -715,7 +716,6 @@ static SMemRow tsdbInsertDupKeyMerge(SMemRow row1, SMemRow row2, STsdbRepo* pRep void* pMem = tsdbAllocBytes(pRepo, memRowTLen(row1)); if(pMem == NULL) return NULL; memRowCpy(pMem, row1); - (*pAffectedRows)++; (*pPoints)++; *pLastRow = pMem; return pMem; @@ -750,18 +750,16 @@ static SMemRow tsdbInsertDupKeyMerge(SMemRow row1, SMemRow row2, STsdbRepo* pRep if(pMem == NULL) return NULL; memRowCpy(pMem, tmp); - (*pAffectedRows)++; (*pPoints)++; - *pLastRow = pMem; return pMem; } static void* tsdbInsertDupKeyMergePacked(void** args) { - return tsdbInsertDupKeyMerge(args[0], args[1], args[2], (STSchema**)&args[3], (STSchema**)&args[4], args[5], args[6], args[7], args[8]); + return tsdbInsertDupKeyMerge(args[0], args[1], args[2], (STSchema**)&args[3], (STSchema**)&args[4], args[5], args[6], args[7]); } -static void tsdbSetupSkipListHookFns(SSkipList* pSkipList, STsdbRepo *pRepo, STable *pTable, int32_t* pAffectedRows, int64_t* pPoints, SMemRow* pLastRow) { +static void tsdbSetupSkipListHookFns(SSkipList* pSkipList, STsdbRepo *pRepo, STable *pTable, int32_t* pPoints, SMemRow* pLastRow) { if(pSkipList->insertHandleFn == NULL) { tGenericSavedFunc *dupHandleSavedFunc = genericSavedFuncInit((GenericVaFunc)&tsdbInsertDupKeyMergePacked, 9); @@ -769,17 +767,16 @@ static void tsdbSetupSkipListHookFns(SSkipList* pSkipList, STsdbRepo *pRepo, STa dupHandleSavedFunc->args[3] = NULL; dupHandleSavedFunc->args[4] = NULL; dupHandleSavedFunc->args[5] = pTable; - dupHandleSavedFunc->args[6] = pAffectedRows; - dupHandleSavedFunc->args[7] = pPoints; - dupHandleSavedFunc->args[8] = pLastRow; pSkipList->insertHandleFn = dupHandleSavedFunc; } + pSkipList->insertHandleFn->args[6] = pPoints; + pSkipList->insertHandleFn->args[7] = pLastRow; } static int tsdbInsertDataToTable(STsdbRepo* pRepo, SSubmitBlk* pBlock, int32_t *pAffectedRows) { STsdbMeta *pMeta = pRepo->tsdbMeta; - int64_t points = 0; + int32_t points = 0; STable *pTable = NULL; SSubmitBlkIter blkIter = {0}; SMemTable *pMemTable = NULL; @@ -830,9 +827,10 @@ static int tsdbInsertDataToTable(STsdbRepo* pRepo, SSubmitBlk* pBlock, int32_t * SMemRow lastRow = NULL; int64_t osize = SL_SIZE(pTableData->pData); - tsdbSetupSkipListHookFns(pTableData->pData, pRepo, pTable, pAffectedRows, &points, &lastRow); + tsdbSetupSkipListHookFns(pTableData->pData, pRepo, pTable, &points, &lastRow); tSkipListPutBatchByIter(pTableData->pData, &blkIter, (iter_next_fn_t)tsdbGetSubmitBlkNext); int64_t dsize = SL_SIZE(pTableData->pData) - osize; + (*pAffectedRows) += points; if(lastRow != NULL) { diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index 619b32b3d9..21150c66e2 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -17,7 +17,6 @@ #define TSDB_SUPER_TABLE_SL_LEVEL 5 #define DEFAULT_TAG_INDEX_COLUMN 0 -static int tsdbCompareSchemaVersion(const void *key1, const void *key2); static char * getTagIndexKey(const void *pData); static STable *tsdbNewTable(); static STable *tsdbCreateTableFromCfg(STableCfg *pCfg, bool isSuper, STable *pSTable); diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index c578555df2..716f82d154 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -466,7 +466,7 @@ static STsdbQueryHandle* tsdbQueryTablesImpl(STsdbRepo* tsdb, STsdbQueryCond* pC STsdbMeta* pMeta = tsdbGetMeta(tsdb); assert(pMeta != NULL); - pQueryHandle->pDataCols = tdNewDataCols(pMeta->maxRowBytes, pMeta->maxCols, pQueryHandle->pTsdb->config.maxRowsPerFileBlock); + pQueryHandle->pDataCols = tdNewDataCols(pMeta->maxCols, pQueryHandle->pTsdb->config.maxRowsPerFileBlock); if (pQueryHandle->pDataCols == NULL) { tsdbError("%p failed to malloc buf for pDataCols, %"PRIu64, pQueryHandle, pQueryHandle->qId); terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; @@ -1446,7 +1446,7 @@ static int doBinarySearchKey(char* pValue, int num, TSKEY key, int order) { return midPos; } -int32_t doCopyRowsFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t capacity, int32_t numOfRows, int32_t start, int32_t end) { +static int32_t doCopyRowsFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t capacity, int32_t numOfRows, int32_t start, int32_t end) { char* pData = NULL; int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1 : -1; @@ -1481,7 +1481,7 @@ int32_t doCopyRowsFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t capacity pData = (char*)pColInfo->pData + (capacity - numOfRows - num) * pColInfo->info.bytes; } - if (pColInfo->info.colId == src->colId) { + if (!isAllRowsNull(src) && pColInfo->info.colId == src->colId) { 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 diff --git a/src/tsdb/src/tsdbReadImpl.c b/src/tsdb/src/tsdbReadImpl.c index 711c32535b..74d41cce19 100644 --- a/src/tsdb/src/tsdbReadImpl.c +++ b/src/tsdb/src/tsdbReadImpl.c @@ -42,14 +42,14 @@ int tsdbInitReadH(SReadH *pReadh, STsdbRepo *pRepo) { return -1; } - pReadh->pDCols[0] = tdNewDataCols(0, 0, pCfg->maxRowsPerFileBlock); + pReadh->pDCols[0] = tdNewDataCols(0, pCfg->maxRowsPerFileBlock); if (pReadh->pDCols[0] == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; tsdbDestroyReadH(pReadh); return -1; } - pReadh->pDCols[1] = tdNewDataCols(0, 0, pCfg->maxRowsPerFileBlock); + pReadh->pDCols[1] = tdNewDataCols(0, pCfg->maxRowsPerFileBlock); if (pReadh->pDCols[1] == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; tsdbDestroyReadH(pReadh); @@ -463,7 +463,7 @@ static int tsdbLoadBlockDataImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDat SDataCol *pDataCol = &(pDataCols->cols[dcol]); if (dcol != 0 && ccol >= pBlockData->numOfCols) { // Set current column as NULL and forward - dataColSetNEleNull(pDataCol, pBlock->numOfRows, pDataCols->maxPoints); + dataColReset(pDataCol); dcol++; continue; } @@ -503,7 +503,7 @@ static int tsdbLoadBlockDataImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDat ccol++; } else { // Set current column as NULL and forward - dataColSetNEleNull(pDataCol, pBlock->numOfRows, pDataCols->maxPoints); + dataColReset(pDataCol); dcol++; } } @@ -608,7 +608,7 @@ static int tsdbLoadBlockDataColsImpl(SReadH *pReadh, SBlock *pBlock, SDataCols * } if (pBlockCol == NULL) { - dataColSetNEleNull(pDataCol, pBlock->numOfRows, pDataCols->maxPoints); + dataColReset(pDataCol); continue; } diff --git a/src/util/inc/hash.h b/src/util/inc/hash.h index 6c4145810b..7a93745dc8 100644 --- a/src/util/inc/hash.h +++ b/src/util/inc/hash.h @@ -42,7 +42,7 @@ typedef struct SHashNode { #define GET_HASH_NODE_KEY(_n) ((char*)(_n) + sizeof(SHashNode) + (_n)->dataLen) #define GET_HASH_NODE_DATA(_n) ((char*)(_n) + sizeof(SHashNode)) -#define GET_HASH_PNODE(_n) ((char*)(_n) - sizeof(SHashNode)); +#define GET_HASH_PNODE(_n) ((SHashNode *)((char*)(_n) - sizeof(SHashNode))) typedef enum SHashLockTypeE { HASH_NO_LOCK = 0, @@ -170,6 +170,10 @@ void *taosHashIterate(SHashObj *pHashObj, void *p); void taosHashCancelIterate(SHashObj *pHashObj, void *p); +void *taosHashGetDataKey(SHashObj *pHashObj, void *data); + +uint32_t taosHashGetDataKeyLen(SHashObj *pHashObj, void *data); + #ifdef __cplusplus } #endif diff --git a/src/util/inc/tcompare.h b/src/util/inc/tcompare.h index 4861779acd..d1760ab28c 100644 --- a/src/util/inc/tcompare.h +++ b/src/util/inc/tcompare.h @@ -25,7 +25,7 @@ extern "C" { #define TSDB_PATTERN_MATCH 0 #define TSDB_PATTERN_NOMATCH 1 #define TSDB_PATTERN_NOWILDCARDMATCH 2 -#define TSDB_PATTERN_STRING_MAX_LEN 20 +#define TSDB_PATTERN_STRING_MAX_LEN 100 #define FLT_COMPAR_TOL_FACTOR 4 #define FLT_EQUAL(_x, _y) (fabs((_x) - (_y)) <= (FLT_COMPAR_TOL_FACTOR * FLT_EPSILON)) @@ -53,6 +53,38 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr); int32_t taosArrayCompareString(const void* a, const void* b); +int32_t setCompareBytes1(const void *pLeft, const void *pRight); + +int32_t setCompareBytes2(const void *pLeft, const void *pRight); + +int32_t setCompareBytes4(const void *pLeft, const void *pRight); +int32_t setCompareBytes8(const void *pLeft, const void *pRight); + +int32_t compareInt32Val(const void *pLeft, const void *pRight); +int32_t compareInt64Val(const void *pLeft, const void *pRight); + +int32_t compareInt16Val(const void *pLeft, const void *pRight); + +int32_t compareInt8Val(const void *pLeft, const void *pRight); + +int32_t compareUint32Val(const void *pLeft, const void *pRight); +int32_t compareUint64Val(const void *pLeft, const void *pRight); + +int32_t compareUint16Val(const void *pLeft, const void *pRight); + +int32_t compareUint8Val(const void* pLeft, const void* pRight); + +int32_t compareFloatVal(const void *pLeft, const void *pRight); + +int32_t compareDoubleVal(const void *pLeft, const void *pRight); + +int32_t compareLenPrefixedStr(const void *pLeft, const void *pRight); + +int32_t compareLenPrefixedWStr(const void *pLeft, const void *pRight); +int32_t compareStrPatternComp(const void* pLeft, const void* pRight); +int32_t compareFindItemInSet(const void *pLeft, const void* pRight); +int32_t compareWStrPatternComp(const void* pLeft, const void* pRight); + #ifdef __cplusplus } #endif diff --git a/src/util/src/hash.c b/src/util/src/hash.c index 6118aa7bef..a22ce34a0e 100644 --- a/src/util/src/hash.c +++ b/src/util/src/hash.c @@ -776,6 +776,17 @@ size_t taosHashGetMemSize(const SHashObj *pHashObj) { return (pHashObj->capacity * (sizeof(SHashEntry) + POINTER_BYTES)) + sizeof(SHashNode) * taosHashGetSize(pHashObj) + sizeof(SHashObj); } +FORCE_INLINE void *taosHashGetDataKey(SHashObj *pHashObj, void *data) { + SHashNode * node = GET_HASH_PNODE(data); + return GET_HASH_NODE_KEY(node); +} + +FORCE_INLINE uint32_t taosHashGetDataKeyLen(SHashObj *pHashObj, void *data) { + SHashNode * node = GET_HASH_PNODE(data); + return node->keyLen; +} + + // release the pNode, return next pNode, and lock the current entry static void *taosHashReleaseNode(SHashObj *pHashObj, void *p, int *slot) { diff --git a/src/util/src/tcompare.c b/src/util/src/tcompare.c index 57689b7269..0b046ecb84 100644 --- a/src/util/src/tcompare.c +++ b/src/util/src/tcompare.c @@ -18,6 +18,22 @@ #include "tcompare.h" #include "hash.h" +int32_t setCompareBytes1(const void *pLeft, const void *pRight) { + return NULL != taosHashGet((SHashObj *)pRight, pLeft, 1) ? 1 : 0; +} + +int32_t setCompareBytes2(const void *pLeft, const void *pRight) { + return NULL != taosHashGet((SHashObj *)pRight, pLeft, 2) ? 1 : 0; +} + +int32_t setCompareBytes4(const void *pLeft, const void *pRight) { + return NULL != taosHashGet((SHashObj *)pRight, pLeft, 4) ? 1 : 0; +} + +int32_t setCompareBytes8(const void *pLeft, const void *pRight) { + return NULL != taosHashGet((SHashObj *)pRight, pLeft, 8) ? 1 : 0; +} + int32_t compareInt8Val(const void *pLeft, const void *pRight) { int8_t left = GET_INT8_VAL(pLeft), right = GET_INT8_VAL(pRight); if (left > right) return 1; @@ -63,7 +79,7 @@ int32_t compareInt64ValDesc(const void* pLeft, const void* pRight) { } int32_t compareUint32Val(const void *pLeft, const void *pRight) { - int32_t left = GET_UINT32_VAL(pLeft), right = GET_UINT32_VAL(pRight); + uint32_t left = GET_UINT32_VAL(pLeft), right = GET_UINT32_VAL(pRight); if (left > right) return 1; if (left < right) return -1; return 0; @@ -74,7 +90,7 @@ int32_t compareUint32ValDesc(const void* pLeft, const void* pRight) { } int32_t compareUint64Val(const void *pLeft, const void *pRight) { - int64_t left = GET_UINT64_VAL(pLeft), right = GET_UINT64_VAL(pRight); + uint64_t left = GET_UINT64_VAL(pLeft), right = GET_UINT64_VAL(pRight); if (left > right) return 1; if (left < right) return -1; return 0; @@ -85,7 +101,7 @@ int32_t compareUint64ValDesc(const void* pLeft, const void* pRight) { } int32_t compareUint16Val(const void *pLeft, const void *pRight) { - int16_t left = GET_UINT16_VAL(pLeft), right = GET_UINT16_VAL(pRight); + uint16_t left = GET_UINT16_VAL(pLeft), right = GET_UINT16_VAL(pRight); if (left > right) return 1; if (left < right) return -1; return 0; @@ -309,7 +325,7 @@ int WCSPatternMatch(const wchar_t *patterStr, const wchar_t *str, size_t size, c return (str[j] == 0 || j >= size) ? TSDB_PATTERN_MATCH : TSDB_PATTERN_NOMATCH; } -static int32_t compareStrPatternComp(const void* pLeft, const void* pRight) { +int32_t compareStrPatternComp(const void* pLeft, const void* pRight) { SPatternCompareInfo pInfo = {'%', '_'}; char pattern[128] = {0}; @@ -333,11 +349,11 @@ int32_t taosArrayCompareString(const void* a, const void* b) { return compareLenPrefixedStr(x, y); } -static int32_t compareFindItemInSet(const void *pLeft, const void* pRight) { +int32_t compareFindItemInSet(const void *pLeft, const void* pRight) { return NULL != taosHashGet((SHashObj *)pRight, varDataVal(pLeft), varDataLen(pLeft)) ? 1 : 0; } -static int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) { +int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) { SPatternCompareInfo pInfo = {'%', '_'}; wchar_t pattern[128] = {0}; @@ -352,7 +368,30 @@ static int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) { __compar_fn_t getComparFunc(int32_t type, int32_t optr) { __compar_fn_t comparFn = NULL; - + + if (optr == TSDB_RELATION_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR)) { + switch (type) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_UTINYINT: + return setCompareBytes1; + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_USMALLINT: + return setCompareBytes2; + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_FLOAT: + return setCompareBytes4; + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_DOUBLE: + case TSDB_DATA_TYPE_TIMESTAMP: + return setCompareBytes8; + default: + assert(0); + } + } + switch (type) { case TSDB_DATA_TYPE_BOOL: case TSDB_DATA_TYPE_TINYINT: comparFn = compareInt8Val; break; @@ -377,6 +416,8 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr) { case TSDB_DATA_TYPE_NCHAR: { if (optr == TSDB_RELATION_LIKE) { comparFn = compareWStrPatternComp; + } else if (optr == TSDB_RELATION_IN) { + comparFn = compareFindItemInSet; } else { comparFn = compareLenPrefixedWStr; } diff --git a/src/util/src/terror.c b/src/util/src/terror.c index 42fc76e6c9..49e46cdde8 100644 --- a/src/util/src/terror.c +++ b/src/util/src/terror.c @@ -280,6 +280,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_QRY_IN_EXEC, "Multiple retrieval of TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW, "Too many time window in query") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_NOT_ENOUGH_BUFFER, "Query buffer limit has reached") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_INCONSISTAN, "File inconsistance in replica") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_INVALID_TIME_CONDITION, "One valid time range condition expected") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_SYS_ERROR, "System error") diff --git a/tests/comparisonTest/influxdb/main.go b/tests/comparisonTest/influxdb/main.go index 2fb16fad89..043dfbf96d 100644 --- a/tests/comparisonTest/influxdb/main.go +++ b/tests/comparisonTest/influxdb/main.go @@ -1,3 +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 . + */ + package main import ( diff --git a/tests/gotest/case001/case001.go b/tests/gotest/case001/case001.go index fb94f566dd..9e912aab99 100644 --- a/tests/gotest/case001/case001.go +++ b/tests/gotest/case001/case001.go @@ -12,6 +12,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ + package main import ( diff --git a/tests/pytest/TimeZone/TestCaseTimeZone.py b/tests/pytest/TimeZone/TestCaseTimeZone.py new file mode 100644 index 0000000000..0bad52ef98 --- /dev/null +++ b/tests/pytest/TimeZone/TestCaseTimeZone.py @@ -0,0 +1,176 @@ +################################################################### +# 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 +import subprocess +import time +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import * +import datetime + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + 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/" + + tdSql.execute("create database timezone") + tdSql.execute("use timezone") + tdSql.execute("create stable st (ts timestamp, id int ) tags (index int)") + + tdSql.execute("insert into tb0 using st tags (1) values ('2021-07-01 00:00:00.000',0)") + tdSql.query("select ts from tb0") + tdSql.checkData(0, 0, "2021-07-01 00:00:00.000") + + tdSql.execute("insert into tb1 using st tags (1) values ('2021-07-01T00:00:00.000+07:50',1)") + tdSql.query("select ts from tb1") + tdSql.checkData(0, 0, "2021-07-01 00:10:00.000") + + tdSql.execute("insert into tb2 using st tags (1) values ('2021-07-01T00:00:00.000+08:00',2)") + tdSql.query("select ts from tb2") + tdSql.checkData(0, 0, "2021-07-01 00:00:00.000") + + tdSql.execute("insert into tb3 using st tags (1) values ('2021-07-01T00:00:00.000Z',3)") + tdSql.query("select ts from tb3") + tdSql.checkData(0, 0, "2021-07-01 08:00:00.000") + + tdSql.execute("insert into tb4 using st tags (1) values ('2021-07-01 00:00:00.000+07:50',4)") + tdSql.query("select ts from tb4") + tdSql.checkData(0, 0, "2021-07-01 00:10:00.000") + + tdSql.execute("insert into tb5 using st tags (1) values ('2021-07-01 00:00:00.000Z',5)") + tdSql.query("select ts from tb5") + tdSql.checkData(0, 0, "2021-07-01 08:00:00.000") + + tdSql.execute("insert into tb6 using st tags (1) values ('2021-07-01T00:00:00.000+0800',6)") + tdSql.query("select ts from tb6") + tdSql.checkData(0, 0, "2021-07-01 00:00:00.000") + + tdSql.execute("insert into tb7 using st tags (1) values ('2021-07-01 00:00:00.000+0800',7)") + tdSql.query("select ts from tb7") + tdSql.checkData(0, 0, "2021-07-01 00:00:00.000") + + tdSql.execute("insert into tb8 using st tags (1) values ('2021-07-0100:00:00.000',8)") + tdSql.query("select ts from tb8") + tdSql.checkData(0, 0, "2021-07-01 00:00:00.000") + + tdSql.execute("insert into tb9 using st tags (1) values ('2021-07-0100:00:00.000+0800',9)") + tdSql.query("select ts from tb9") + tdSql.checkData(0, 0, "2021-07-01 00:00:00.000") + + tdSql.execute("insert into tb10 using st tags (1) values ('2021-07-0100:00:00.000+08:00',10)") + tdSql.query("select ts from tb10") + tdSql.checkData(0, 0, "2021-07-01 00:00:00.000") + + tdSql.execute("insert into tb11 using st tags (1) values ('2021-07-0100:00:00.000+07:00',11)") + tdSql.query("select ts from tb11") + tdSql.checkData(0, 0, "2021-07-01 01:00:00.000") + + tdSql.execute("insert into tb12 using st tags (1) values ('2021-07-0100:00:00.000+0700',12)") + tdSql.query("select ts from tb12") + tdSql.checkData(0, 0, "2021-07-01 01:00:00.000") + + tdSql.execute("insert into tb13 using st tags (1) values ('2021-07-0100:00:00.000+07:12',13)") + tdSql.query("select ts from tb13") + tdSql.checkData(0, 0, "2021-07-01 00:48:00.000") + + tdSql.execute("insert into tb14 using st tags (1) values ('2021-07-0100:00:00.000+712',14)") + tdSql.query("select ts from tb14") + tdSql.checkData(0, 0, "2021-06-28 08:58:00.000") + + tdSql.execute("insert into tb15 using st tags (1) values ('2021-07-0100:00:00.000Z',15)") + tdSql.query("select ts from tb15") + tdSql.checkData(0, 0, "2021-07-01 08:00:00.000") + + tdSql.execute("insert into tb16 using st tags (1) values ('2021-7-1 00:00:00.000Z',16)") + tdSql.query("select ts from tb16") + tdSql.checkData(0, 0, "2021-07-01 08:00:00.000") + + tdSql.execute("insert into tb17 using st tags (1) values ('2021-07-0100:00:00.000+0750',17)") + tdSql.query("select ts from tb17") + tdSql.checkData(0, 0, "2021-07-01 00:10:00.000") + + tdSql.execute("insert into tb18 using st tags (1) values ('2021-07-0100:00:00.000+0752',18)") + tdSql.query("select ts from tb18") + tdSql.checkData(0, 0, "2021-07-01 00:08:00.000") + + tdSql.execute("insert into tb19 using st tags (1) values ('2021-07-0100:00:00.000+075',19)") + tdSql.query("select ts from tb19") + tdSql.checkData(0, 0, "2021-07-01 00:55:00.000") + + tdSql.execute("insert into tb20 using st tags (1) values ('2021-07-0100:00:00.000+75',20)") + tdSql.query("select ts from tb20") + tdSql.checkData(0, 0, "2021-06-28 05:00:00.000") + + tdSql.execute("insert into tb21 using st tags (1) values ('2021-7-1 1:1:1.234+075',21)") + tdSql.query("select ts from tb21") + tdSql.checkData(0, 0, "2021-07-01 01:56:01.234") + + tdSql.execute("insert into tb22 using st tags (1) values ('2021-7-1T1:1:1.234+075',22)") + tdSql.query("select ts from tb22") + tdSql.checkData(0, 0, "2021-07-01 01:56:01.234") + + tdSql.execute("insert into tb23 using st tags (1) values ('2021-7-131:1:1.234+075',22)") + tdSql.query("select ts from tb23") + tdSql.checkData(0, 0, "2021-07-13 01:56:01.234") + + + tdSql.error("insert into tberror using st tags (1) values ('20210701 00:00:00.000+0800',0)") + tdSql.error("insert into tberror using st tags (1) values ('2021070100:00:00.000+0800',0)") + tdSql.error("insert into tberror using st tags (1) values ('202171 00:00:00.000+0800',0)") + tdSql.error("insert into tberror using st tags (1) values ('2021 07 01 00:00:00.000+0800',0)") + tdSql.error("insert into tberror using st tags (1) values ('2021 -07-0100:00:00.000+0800',0)") + tdSql.error("insert into tberror using st tags (1) values ('2021-7-11:1:1.234+075',0)") + + os.system("rm -rf ./TimeZone/*.py.sql") + + + + + + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/ZoneTimeTest.py b/tests/pytest/ZoneTimeTest.py new file mode 100644 index 0000000000..0e33f1887d --- /dev/null +++ b/tests/pytest/ZoneTimeTest.py @@ -0,0 +1,174 @@ +################################################################### +# 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 datetime + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + def checkCommunity(self): + selfPath = os.path.dirname(os.path.realpath(__file__)) + if ("community" in selfPath): + return False + else: + return True + + 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 ("taosdump" 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): + + # clear envs + + tdSql.execute(" create database ZoneTime precision 'us' ") + tdSql.execute(" use ZoneTime ") + tdSql.execute(" create stable st (ts timestamp , id int , val float) tags (tag1 timestamp ,tag2 int) ") + + # standard case for Timestamp + + tdSql.execute(" insert into tb1 using st tags (\"2021-07-01 00:00:00.000\" , 2) values( \"2021-07-01 00:00:00.000\" , 1 , 1.0 ) ") + case1 = (tdSql.getResult("select * from tb1")) + print(case1) + if case1 == [(datetime.datetime(2021, 7, 1, 0, 0), 1, 1.0)]: + print ("check pass! ") + else: + print ("check failed about timestamp '2021-07-01 00:00:00.000' ") + + # RCF-3339 : it allows "T" is replaced by " " + + tdSql.execute(" insert into tb2 using st tags (\"2021-07-01T00:00:00.000+07:50\" , 2) values( \"2021-07-01T00:00:00.000+07:50\" , 2 , 2.0 ) ") + case2 = (tdSql.getResult("select * from tb2")) + print(case2) + if case2 == [(datetime.datetime(2021, 7, 1, 0, 10), 2, 2.0)]: + print ("check pass! ") + else: + print ("check failed about timestamp '2021-07-01T00:00:00.000+07:50'! ") + + tdSql.execute(" insert into tb3 using st tags (\"2021-07-01T00:00:00.000+08:00\" , 3) values( \"2021-07-01T00:00:00.000+08:00\" , 3 , 3.0 ) ") + case3 = (tdSql.getResult("select * from tb3")) + print(case3) + if case3 == [(datetime.datetime(2021, 7, 1, 0, 0), 3, 3.0)]: + print ("check pass! ") + else: + print ("check failed about timestamp '2021-07-01T00:00:00.000+08:00'! ") + + tdSql.execute(" insert into tb4 using st tags (\"2021-07-01T00:00:00.000Z\" , 4) values( \"2021-07-01T00:00:00.000Z\" , 4 , 4.0 ) ") + case4 = (tdSql.getResult("select * from tb4")) + print(case4) + if case4 == [(datetime.datetime(2021, 7, 1, 8, 0), 4, 4.0)]: + print ("check pass! ") + else: + print ("check failed about timestamp '2021-07-01T00:00:00.000Z'! ") + + tdSql.execute(" insert into tb5 using st tags (\"2021-07-01 00:00:00.000+07:50\" , 5) values( \"2021-07-01 00:00:00.000+07:50\" , 5 , 5.0 ) ") + case5 = (tdSql.getResult("select * from tb5")) + print(case5) + if case5 == [(datetime.datetime(2021, 7, 1, 0, 10), 5, 5.0)]: + print ("check pass! ") + else: + print ("check failed about timestamp '2021-07-01 00:00:00.000+08:00 ") + + tdSql.execute(" insert into tb6 using st tags (\"2021-07-01 00:00:00.000Z\" , 6) values( \"2021-07-01 00:00:00.000Z\" , 6 , 6.0 ) ") + case6 = (tdSql.getResult("select * from tb6")) + print(case6) + if case6 == [(datetime.datetime(2021, 7, 1, 8, 0), 6, 6.0)]: + print ("check pass! ") + else: + print ("check failed about timestamp '2021-07-01 00:00:00.000Z'! ") + + # ISO 8610 timestamp format , time days and hours must be split by "T" + + tdSql.execute(" insert into tb7 using st tags (\"2021-07-01T00:00:00.000+0800\" , 7) values( \"2021-07-01T00:00:00.000+0800\" , 7 , 7.0 ) ") + case7 = (tdSql.getResult("select * from tb7")) + print(case7) + if case7 == [(datetime.datetime(2021, 7, 1, 0, 0), 7, 7.0)]: + print ("check pass! ") + else: + print ("check failed about timestamp '2021-07-01T00:00:00.000+0800'! ") + + tdSql.execute(" insert into tb8 using st tags (\"2021-07-01T00:00:00.000+08\" , 8) values( \"2021-07-01T00:00:00.000+08\" , 8 , 8.0 ) ") + case8 = (tdSql.getResult("select * from tb8")) + print(case8) + if case8 == [(datetime.datetime(2021, 7, 1, 0, 0), 8, 8.0)]: + print ("check pass! ") + else: + print ("check failed about timestamp '2021-07-01T00:00:00.000+08'! ") + + # Non-standard case for Timestamp + + tdSql.execute(" insert into tb9 using st tags (\"2021-07-01 00:00:00.000+0800\" , 9) values( \"2021-07-01 00:00:00.000+0800\" , 9 , 9.0 ) ") + case9 = (tdSql.getResult("select * from tb9")) + print(case9) + + tdSql.execute(" insert into tb10 using st tags (\"2021-07-0100:00:00.000\" , 10) values( \"2021-07-0100:00:00.000\" , 10 , 10.0 ) ") + case10 = (tdSql.getResult("select * from tb10")) + print(case10) + + tdSql.execute(" insert into tb11 using st tags (\"2021-07-0100:00:00.000+0800\" , 11) values( \"2021-07-0100:00:00.000+0800\" , 11 , 11.0 ) ") + case11 = (tdSql.getResult("select * from tb11")) + print(case11) + + tdSql.execute(" insert into tb12 using st tags (\"2021-07-0100:00:00.000+08:00\" , 12) values( \"2021-07-0100:00:00.000+08:00\" , 12 , 12.0 ) ") + case12 = (tdSql.getResult("select * from tb12")) + print(case12) + + tdSql.execute(" insert into tb13 using st tags (\"2021-07-0100:00:00.000Z\" , 13) values( \"2021-07-0100:00:00.000Z\" , 13 , 13.0 ) ") + case13 = (tdSql.getResult("select * from tb13")) + print(case13) + + tdSql.execute(" insert into tb14 using st tags (\"2021-07-0100:00:00.000Z\" , 14) values( \"2021-07-0100:00:00.000Z\" , 14 , 14.0 ) ") + case14 = (tdSql.getResult("select * from tb14")) + print(case14) + + tdSql.execute(" insert into tb15 using st tags (\"2021-07-0100:00:00.000+08\" , 15) values( \"2021-07-0100:00:00.000+08\" , 15 , 15.0 ) ") + case15 = (tdSql.getResult("select * from tb15")) + print(case15) + + tdSql.execute(" insert into tb16 using st tags (\"2021-07-0100:00:00.000+07:50\" , 16) values( \"2021-07-0100:00:00.000+07:50\" , 16 , 16.0 ) ") + case16 = (tdSql.getResult("select * from tb16")) + print(case16) + + os.system("rm -rf *.py.sql") + + + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/client/client.py b/tests/pytest/client/client.py index b40511094b..c559860d3c 100644 --- a/tests/pytest/client/client.py +++ b/tests/pytest/client/client.py @@ -16,6 +16,7 @@ from util.log import * from util.cases import * from util.sql import * +from datetime import timedelta class TDTestCase: def init(self, conn, logSql): @@ -36,15 +37,36 @@ class TDTestCase: ret = tdSql.query('show dnodes') - ret = tdSql.execute('alter dnode "%s" debugFlag 135' % tdSql.getData(0,0)) - tdLog.info('alter dnode "%s" debugFlag 135 -> ret: %d' % (tdSql.getData(0, 0), ret)) + dnodeId = tdSql.getData(0, 0); + dnodeEndpoint = tdSql.getData(0, 1); + + ret = tdSql.execute('alter dnode "%s" debugFlag 135' % dnodeId) + tdLog.info('alter dnode "%s" debugFlag 135 -> ret: %d' % (dnodeId, ret)) + ret = tdSql.query('show mnodes') tdSql.checkRows(1) + tdSql.checkData(0, 2, "master") + + role_time = tdSql.getData(0, 3) + create_time = tdSql.getData(0, 4) + time_delta = timedelta(milliseconds=100) + + if create_time-time_delta < role_time < create_time+time_delta: + tdLog.info("role_time {} and create_time {} expected within range".format(role_time, create_time)) + else: + tdLog.exit("role_time {} and create_time {} not expected within range".format(role_time, create_time)) ret = tdSql.query('show vgroups') tdSql.checkRows(0) + tdSql.execute('create stable st (ts timestamp, f int) tags(t int)') + tdSql.execute('create table ct1 using st tags(1)'); + tdSql.execute('create table ct2 using st tags(2)'); + ret = tdSql.query('show vnodes "{}"'.format(dnodeEndpoint)) + tdSql.checkRows(1) + tdSql.checkData(0, 0, 2) + tdSql.checkData(0, 1, "master") def stop(self): tdSql.close() diff --git a/tests/pytest/fulltest.sh b/tests/pytest/fulltest.sh index 9f67dfda8f..6d7f1d00bf 100755 --- a/tests/pytest/fulltest.sh +++ b/tests/pytest/fulltest.sh @@ -29,6 +29,10 @@ python3 ./test.py -f insert/in_function.py python3 ./test.py -f insert/modify_column.py python3 ./test.py -f insert/line_insert.py +# timezone + +python3 ./test.py -f TimeZone/TestCaseTimeZone.py + #table python3 ./test.py -f table/alter_wal0.py python3 ./test.py -f table/column_name.py @@ -167,11 +171,11 @@ python3 test.py -f tools/taosdemoTestInterlace.py python3 test.py -f tools/taosdemoTestQuery.py # nano support -python3 test.py -f tools/taosdemoAllTest/taosdemoTestSupportNanoInsert.py -python3 test.py -f tools/taosdemoAllTest/taosdemoTestSupportNanoQuery.py -python3 test.py -f tools/taosdemoAllTest/taosdemoTestSupportNanosubscribe.py -python3 test.py -f tools/taosdemoAllTest/taosdemoTestInsertTime_step.py -python3 test.py -f tools/taosdumpTestNanoSupport.py +python3 test.py -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoInsert.py +python3 test.py -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuery.py +python3 test.py -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanosubscribe.py +python3 test.py -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestInsertTime_step.py +python3 test.py -f tools/taosdemoAllTest/NanoTestCase/taosdumpTestNanoSupport.py # update python3 ./test.py -f update/allow_update.py @@ -257,7 +261,7 @@ python3 ./test.py -f query/nestedQuery/queryWithOrderLimit.py python3 ./test.py -f query/nestquery_last_row.py python3 ./test.py -f query/queryCnameDisplay.py python3 ./test.py -f query/operator_cost.py -python3 ./test.py -f query/long_where_query.py +# python3 ./test.py -f query/long_where_query.py python3 test.py -f query/nestedQuery/queryWithSpread.py #stream @@ -383,7 +387,7 @@ python3 ./test.py -f insert/flushwhiledrop.py python3 ./test.py -f insert/schemalessInsert.py #======================p4-end=============== -python3 test.py -f tools/taosdemoAllTest/pytest.py + diff --git a/tests/pytest/functions/showOfflineThresholdIs864000.py b/tests/pytest/functions/showOfflineThresholdIs864000.py index a7a1c2bf3f..57d0b1921b 100644 --- a/tests/pytest/functions/showOfflineThresholdIs864000.py +++ b/tests/pytest/functions/showOfflineThresholdIs864000.py @@ -25,7 +25,7 @@ class TDTestCase: def run(self): tdSql.query("show variables") - tdSql.checkData(53, 1, 864000) + tdSql.checkData(54, 1, 864000) def stop(self): tdSql.close() diff --git a/tests/pytest/insert/line_insert.py b/tests/pytest/insert/line_insert.py index 53eaa55aa5..92fdd0f28e 100644 --- a/tests/pytest/insert/line_insert.py +++ b/tests/pytest/insert/line_insert.py @@ -42,18 +42,18 @@ class TDTestCase: "stf,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933641000000ns" ] - code = self._conn.insertLines(lines) - print("insertLines result {}".format(code)) + code = self._conn.insert_lines(lines) + print("insert_lines result {}".format(code)) lines2 = [ "stg,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000ns", "stg,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000ns" ] - code = self._conn.insertLines([ lines2[0] ]) - print("insertLines result {}".format(code)) + code = self._conn.insert_lines([ lines2[0] ]) + print("insert_lines result {}".format(code)) - self._conn.insertLines([ lines2[1] ]) - print("insertLines result {}".format(code)) + self._conn.insert_lines([ lines2[1] ]) + print("insert_lines result {}".format(code)) tdSql.query("select * from st") tdSql.checkRows(4) @@ -73,7 +73,7 @@ class TDTestCase: tdSql.query("describe stf") tdSql.checkData(2, 2, 14) - self._conn.insertLines([ + self._conn.insert_lines([ "sth,t1=4i64,t2=5f64,t4=5f64,ID=\"childtable\" c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933641ms", "sth,t1=4i64,t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933654ms" ]) diff --git a/tests/pytest/insert/schemalessInsert.py b/tests/pytest/insert/schemalessInsert.py index 5c93095a1e..49c3223588 100644 --- a/tests/pytest/insert/schemalessInsert.py +++ b/tests/pytest/insert/schemalessInsert.py @@ -11,8 +11,10 @@ # -*- coding: utf-8 -*- +import traceback import random import string +from taos.error import LinesError import time from copy import deepcopy import numpy as np @@ -292,7 +294,7 @@ class TDTestCase: def resCmp(self, input_sql, stb_name, query_sql="select * from", condition="", ts=None, id=True, none_check_tag=None): expect_list = self.inputHandle(input_sql) - self._conn.insertLines([input_sql]) + self._conn.insert_lines([input_sql]) query_sql = f"{query_sql} {stb_name} {condition}" res_row_list, res_field_list_without_ts, res_type_list = self.resHandle(query_sql, True) if ts == 0: @@ -312,7 +314,9 @@ class TDTestCase: expect_list[0].pop(j) tdSql.checkEqual(res_row_list[0], expect_list[0]) tdSql.checkEqual(res_field_list_without_ts, expect_list[1]) - tdSql.checkEqual(res_type_list, expect_list[2]) + for i in range(len(res_type_list)): + tdSql.checkEqual(res_type_list[i], expect_list[2][i]) + # tdSql.checkEqual(res_type_list, expect_list[2]) def cleanStb(self): query_sql = "show stables" @@ -405,13 +409,14 @@ class TDTestCase: """ for input_sql in [self.genLongSql(128, 1)[0], self.genLongSql(1, 4094)[0]]: self.cleanStb() - code = self._conn.insertLines([input_sql]) - tdSql.checkEqual(code, 0) + self._conn.insert_lines([input_sql]) for input_sql in [self.genLongSql(129, 1)[0], self.genLongSql(1, 4095)[0]]: self.cleanStb() - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) - + try: + self._conn.insert_lines([input_sql]) + except LinesError: + pass + def idIllegalNameCheckCase(self): """ test illegal id name @@ -421,8 +426,10 @@ class TDTestCase: rstr = list("`~!@#$¥%^&*()-+={}|[]、「」【】\:;《》<>?") for i in rstr: input_sql = self.genFullTypeSql(tb_name=f"\"aaa{i}bbb\"")[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + except LinesError: + pass def idStartWithNumCheckCase(self): """ @@ -430,8 +437,10 @@ class TDTestCase: """ self.cleanStb() input_sql = self.genFullTypeSql(tb_name=f"\"1aaabbb\"")[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + except LinesError: + pass def nowTsCheckCase(self): """ @@ -439,8 +448,10 @@ class TDTestCase: """ self.cleanStb() input_sql = self.genFullTypeSql(ts="now")[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + except LinesError: + pass def dateFormatTsCheckCase(self): """ @@ -448,8 +459,10 @@ class TDTestCase: """ self.cleanStb() input_sql = self.genFullTypeSql(ts="2021-07-21\ 19:01:46.920")[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + except LinesError: + pass def illegalTsCheckCase(self): """ @@ -457,8 +470,10 @@ class TDTestCase: """ self.cleanStb() input_sql = self.genFullTypeSql(ts="16260068336390us19")[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + except LinesError: + pass def tagValueLengthCheckCase(self): """ @@ -471,8 +486,10 @@ class TDTestCase: self.resCmp(input_sql, stb_name) for t1 in ["-128i8", "128i8"]: input_sql = self.genFullTypeSql(t1=t1)[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + except LinesError: + pass #i16 for t2 in ["-32767i16", "32767i16"]: @@ -480,8 +497,10 @@ class TDTestCase: self.resCmp(input_sql, stb_name) for t2 in ["-32768i16", "32768i16"]: input_sql = self.genFullTypeSql(t2=t2)[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + except LinesError: + pass #i32 for t3 in ["-2147483647i32", "2147483647i32"]: @@ -489,8 +508,10 @@ class TDTestCase: self.resCmp(input_sql, stb_name) for t3 in ["-2147483648i32", "2147483648i32"]: input_sql = self.genFullTypeSql(t3=t3)[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + except LinesError: + pass #i64 for t4 in ["-9223372036854775807i64", "9223372036854775807i64"]: @@ -498,8 +519,10 @@ class TDTestCase: self.resCmp(input_sql, stb_name) for t4 in ["-9223372036854775808i64", "9223372036854775808i64"]: input_sql = self.genFullTypeSql(t4=t4)[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + except LinesError: + pass # f32 for t5 in [f"{-3.4028234663852885981170418348451692544*(10**38)}f32", f"{3.4028234663852885981170418348451692544*(10**38)}f32"]: @@ -508,8 +531,12 @@ class TDTestCase: # * limit set to 4028234664*(10**38) for t5 in [f"{-3.4028234664*(10**38)}f32", f"{3.4028234664*(10**38)}f32"]: input_sql = self.genFullTypeSql(t5=t5)[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) + # f64 for t6 in [f'{-1.79769*(10**308)}f64', f'{-1.79769*(10**308)}f64']: @@ -518,27 +545,36 @@ class TDTestCase: # * limit set to 1.797693134862316*(10**308) for c6 in [f'{-1.797693134862316*(10**308)}f64', f'{-1.797693134862316*(10**308)}f64']: input_sql = self.genFullTypeSql(c6=c6)[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) # binary stb_name = self.getLongName(7, "letters") input_sql = f'{stb_name},t0=t,t1="{self.getLongName(16374, "letters")}" c0=f 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkEqual(code, 0) + self._conn.insert_lines([input_sql]) + input_sql = f'{stb_name},t0=t,t1="{self.getLongName(16375, "letters")}" c0=f 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + pass # nchar # * legal nchar could not be larger than 16374/4 stb_name = self.getLongName(7, "letters") input_sql = f'{stb_name},t0=t,t1=L"{self.getLongName(4093, "letters")}" c0=f 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkEqual(code, 0) + self._conn.insert_lines([input_sql]) + input_sql = f'{stb_name},t0=t,t1=L"{self.getLongName(4094, "letters")}" c0=f 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) def colValueLengthCheckCase(self): """ @@ -552,16 +588,22 @@ class TDTestCase: for c1 in ["-128i8", "128i8"]: input_sql = self.genFullTypeSql(c1=c1)[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) # i16 for c2 in ["-32767i16"]: input_sql, stb_name = self.genFullTypeSql(c2=c2) self.resCmp(input_sql, stb_name) for c2 in ["-32768i16", "32768i16"]: input_sql = self.genFullTypeSql(c2=c2)[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) # i32 for c3 in ["-2147483647i32"]: @@ -569,8 +611,11 @@ class TDTestCase: self.resCmp(input_sql, stb_name) for c3 in ["-2147483648i32", "2147483648i32"]: input_sql = self.genFullTypeSql(c3=c3)[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) # i64 for c4 in ["-9223372036854775807i64"]: @@ -578,8 +623,11 @@ class TDTestCase: self.resCmp(input_sql, stb_name) for c4 in ["-9223372036854775808i64", "9223372036854775808i64"]: input_sql = self.genFullTypeSql(c4=c4)[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) # f32 for c5 in [f"{-3.4028234663852885981170418348451692544*(10**38)}f32", f"{3.4028234663852885981170418348451692544*(10**38)}f32"]: @@ -588,8 +636,11 @@ class TDTestCase: # * limit set to 4028234664*(10**38) for c5 in [f"{-3.4028234664*(10**38)}f32", f"{3.4028234664*(10**38)}f32"]: input_sql = self.genFullTypeSql(c5=c5)[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) # f64 for c6 in [f'{-1.79769313486231570814527423731704356798070567525844996598917476803157260780*(10**308)}f64', f'{-1.79769313486231570814527423731704356798070567525844996598917476803157260780*(10**308)}f64']: @@ -598,27 +649,36 @@ class TDTestCase: # * limit set to 1.797693134862316*(10**308) for c6 in [f'{-1.797693134862316*(10**308)}f64', f'{-1.797693134862316*(10**308)}f64']: input_sql = self.genFullTypeSql(c6=c6)[0] - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) # # binary stb_name = self.getLongName(7, "letters") input_sql = f'{stb_name},t0=t c0=f,c1="{self.getLongName(16374, "letters")}" 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkEqual(code, 0) + self._conn.insert_lines([input_sql]) + input_sql = f'{stb_name},t0=t c0=f,c1="{self.getLongName(16375, "letters")}" 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) # nchar # * legal nchar could not be larger than 16374/4 stb_name = self.getLongName(7, "letters") input_sql = f'{stb_name},t0=t c0=f,c1=L"{self.getLongName(4093, "letters")}" 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkEqual(code, 0) + self._conn.insert_lines([input_sql]) + input_sql = f'{stb_name},t0=t c0=f,c1=L"{self.getLongName(4094, "letters")}" 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) def tagColIllegalValueCheckCase(self): @@ -629,11 +689,17 @@ class TDTestCase: # bool for i in ["TrUe", "tRue", "trUe", "truE", "FalsE", "fAlse", "faLse", "falSe", "falsE"]: input_sql1 = self.genFullTypeSql(t0=i)[0] - code = self._conn.insertLines([input_sql1]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql1]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) input_sql2 = self.genFullTypeSql(c0=i)[0] - code = self._conn.insertLines([input_sql2]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql2]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) # i8 i16 i32 i64 f32 f64 for input_sql in [ @@ -651,8 +717,11 @@ class TDTestCase: self.genFullTypeSql(c6="11.1s45f64")[0], self.genFullTypeSql(c9="1s1u64")[0] ]: - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) # check binary and nchar blank stb_name = self.getLongName(7, "letters") @@ -661,18 +730,19 @@ class TDTestCase: input_sql3 = f'{stb_name},t0=t,t1="abc aaa" c0=f 1626006833639000000ns' input_sql4 = f'{stb_name},t0=t,t1=L"abc aaa" c0=f 1626006833639000000ns' for input_sql in [input_sql1, input_sql2, input_sql3, input_sql4]: - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) # check accepted binary and nchar symbols # # * ~!@#$¥%^&*()-+={}|[]、「」:; for symbol in list('~!@#$¥%^&*()-+={}|[]、「」:;'): input_sql1 = f'{stb_name},t0=t c0=f,c1="abc{symbol}aaa" 1626006833639000000ns' input_sql2 = f'{stb_name},t0=t,t1="abc{symbol}aaa" c0=f 1626006833639000000ns' - code = self._conn.insertLines([input_sql1]) - tdSql.checkEqual(code, 0) - code = self._conn.insertLines([input_sql2]) - tdSql.checkEqual(code, 0) + self._conn.insert_lines([input_sql1]) + self._conn.insert_lines([input_sql2]) def duplicateIdTagColInsertCheckCase(self): @@ -681,23 +751,35 @@ class TDTestCase: """ self.cleanStb() input_sql_id = self.genFullTypeSql(id_double_tag=True)[0] - code = self._conn.insertLines([input_sql_id]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql_id]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) input_sql = self.genFullTypeSql()[0] input_sql_tag = input_sql.replace("t5", "t6") - code = self._conn.insertLines([input_sql_tag]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql_tag]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) input_sql = self.genFullTypeSql()[0] input_sql_col = input_sql.replace("c5", "c6") - code = self._conn.insertLines([input_sql_col]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql_col]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) input_sql = self.genFullTypeSql()[0] input_sql_col = input_sql.replace("c5", "C6") - code = self._conn.insertLines([input_sql_col]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql_col]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) ##### stb exist ##### def noIdStbExistCheckCase(self): @@ -705,7 +787,7 @@ class TDTestCase: case no id when stb exist """ self.cleanStb() - input_sql, stb_name = self.genFullTypeSql(t0="f", c0="f") + input_sql, stb_name = self.genFullTypeSql(tb_name="sub_table_0123456", t0="f", c0="f") self.resCmp(input_sql, stb_name) input_sql, stb_name = self.genFullTypeSql(stb_name=stb_name, id_noexist_tag=True, t0="f", c0="f") self.resCmp(input_sql, stb_name, condition='where tbname like "t_%"') @@ -720,8 +802,7 @@ class TDTestCase: self.cleanStb() input_sql, stb_name = self.genFullTypeSql() self.resCmp(input_sql, stb_name) - code = self._conn.insertLines([input_sql]) - tdSql.checkEqual(code, 0) + self._conn.insert_lines([input_sql]) self.resCmp(input_sql, stb_name) def tagColBinaryNcharLengthCheckCase(self): @@ -788,7 +869,7 @@ class TDTestCase: tdSql.checkRows(1) tdSql.checkEqual(tb_name1, tb_name2) input_sql, stb_name = self.genFullTypeSql(stb_name=stb_name, t0="f", c0="f", id_noexist_tag=True, ct_add_tag=True) - self._conn.insertLines([input_sql]) + self._conn.insert_lines([input_sql]) tb_name3 = self.getNoIdTbName(stb_name) tdSql.query(f"select * from {stb_name}") tdSql.checkRows(2) @@ -803,29 +884,35 @@ class TDTestCase: stb_name = self.getLongName(7, "letters") tb_name = f'{stb_name}_1' input_sql = f'{stb_name},id="{tb_name}",t0=t c0=f 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) + self._conn.insert_lines([input_sql]) # * every binary and nchar must be length+2, so here is two tag, max length could not larger than 16384-2*2 input_sql = f'{stb_name},t0=t,t1="{self.getLongName(16374, "letters")}",t2="{self.getLongName(5, "letters")}" c0=f 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkEqual(code, 0) + self._conn.insert_lines([input_sql]) + tdSql.query(f"select * from {stb_name}") tdSql.checkRows(2) input_sql = f'{stb_name},t0=t,t1="{self.getLongName(16374, "letters")}",t2="{self.getLongName(6, "letters")}" c0=f 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError: + pass tdSql.query(f"select * from {stb_name}") tdSql.checkRows(2) # # * check col,col+ts max in describe ---> 16143 input_sql = f'{stb_name},t0=t c0=f,c1="{self.getLongName(16374, "letters")}",c2="{self.getLongName(16374, "letters")}",c3="{self.getLongName(16374, "letters")}",c4="{self.getLongName(12, "letters")}" 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkEqual(code, 0) + self._conn.insert_lines([input_sql]) + tdSql.query(f"select * from {stb_name}") tdSql.checkRows(3) input_sql = f'{stb_name},t0=t c0=f,c1="{self.getLongName(16374, "letters")}",c2="{self.getLongName(16374, "letters")}",c3="{self.getLongName(16374, "letters")}",c4="{self.getLongName(13, "letters")}" 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) tdSql.query(f"select * from {stb_name}") tdSql.checkRows(3) @@ -838,28 +925,32 @@ class TDTestCase: stb_name = self.getLongName(7, "letters") tb_name = f'{stb_name}_1' input_sql = f'{stb_name},id="{tb_name}",t0=t c0=f 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) + code = self._conn.insert_lines([input_sql]) # * legal nchar could not be larger than 16374/4 input_sql = f'{stb_name},t0=t,t1=L"{self.getLongName(4093, "letters")}",t2=L"{self.getLongName(1, "letters")}" c0=f 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkEqual(code, 0) + self._conn.insert_lines([input_sql]) tdSql.query(f"select * from {stb_name}") tdSql.checkRows(2) input_sql = f'{stb_name},t0=t,t1=L"{self.getLongName(4093, "letters")}",t2=L"{self.getLongName(2, "letters")}" c0=f 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) tdSql.query(f"select * from {stb_name}") tdSql.checkRows(2) input_sql = f'{stb_name},t0=t c0=f,c1=L"{self.getLongName(4093, "letters")}",c2=L"{self.getLongName(4093, "letters")}",c3=L"{self.getLongName(4093, "letters")}",c4=L"{self.getLongName(4, "letters")}" 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkEqual(code, 0) + self._conn.insert_lines([input_sql]) tdSql.query(f"select * from {stb_name}") tdSql.checkRows(3) input_sql = f'{stb_name},t0=t c0=f,c1=L"{self.getLongName(4093, "letters")}",c2=L"{self.getLongName(4093, "letters")}",c3=L"{self.getLongName(4093, "letters")}",c4=L"{self.getLongName(5, "letters")}" 1626006833639000000ns' - code = self._conn.insertLines([input_sql]) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) tdSql.query(f"select * from {stb_name}") tdSql.checkRows(3) @@ -880,8 +971,7 @@ class TDTestCase: "st123456,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64,c6=7u64 1626006933640000000ns", "st123456,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933641000000ns" ] - code = self._conn.insertLines(lines) - tdSql.checkEqual(code, 0) + self._conn.insert_lines(lines) def multiInsertCheckCase(self, count): """ @@ -894,8 +984,7 @@ class TDTestCase: for i in range(count): input_sql = self.genFullTypeSql(stb_name=stb_name, t7=f'"{self.getLongName(8, "letters")}"', c7=f'"{self.getLongName(8, "letters")}"', id_noexist_tag=True)[0] sql_list.append(input_sql) - code = self._conn.insertLines(sql_list) - tdSql.checkEqual(code, 0) + self._conn.insert_lines(sql_list) def batchErrorInsertCheckCase(self): """ @@ -905,8 +994,11 @@ class TDTestCase: stb_name = self.getLongName(8, "letters") lines = ["st123456,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000ns", f"{stb_name},t2=5f64,t3=L\"ste\" c1=tRue,c2=4i64,c3=\"iam\" 1626056811823316532ns"] - code = self._conn.insertLines(lines) - tdSql.checkNotEqual(code, 0) + try: + self._conn.insert_lines(lines) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) def genSqlList(self, count=5, stb_name="", tb_name=""): """ @@ -957,7 +1049,7 @@ class TDTestCase: def genMultiThreadSeq(self, sql_list): tlist = list() for insert_sql in sql_list: - t = threading.Thread(target=self._conn.insertLines,args=([insert_sql[0]],)) + t = threading.Thread(target=self._conn.insert_lines,args=([insert_sql[0]],)) tlist.append(t) return tlist @@ -1155,16 +1247,18 @@ class TDTestCase: def test(self): input_sql1 = "rfasta,id=\"rfasta_1\",t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"ddzhiksj\",t8=L\"ncharTagValue\" c0=True,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"bnhwlgvj\",c8=L\"ncharTagValue\",c9=7u64 1626006933640000000ns" input_sql2 = "rfasta,id=\"rfasta_1\",t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64 c0=True,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64 1626006933640000000ns" - code = self._conn.insertLines([input_sql1]) - code = self._conn.insertLines([input_sql2]) - print(code) - # self._conn.insertLines([input_sql2]) + try: + self._conn.insert_lines([input_sql1]) + self._conn.insert_lines([input_sql2]) + except LinesError as err: + print(err.errno) + # self._conn.insert_lines([input_sql2]) # input_sql3 = f'abcd,id="cc¥Ec",t0=True,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7="ndsfdrum",t8=L"ncharTagValue" c0=f,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7="igwoehkm",c8=L"ncharColValue",c9=7u64 0' # print(input_sql3) # input_sql4 = 'hmemeb,id="kilrcrldgf",t0=F,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7="fysodjql",t8=L"ncharTagValue" c0=True,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7="waszbfvc",c8=L"ncharColValue",c9=7u64 0' - # code = self._conn.insertLines([input_sql3]) + # code = self._conn.insert_lines([input_sql3]) # print(code) - # self._conn.insertLines([input_sql4]) + # self._conn.insert_lines([input_sql4]) def runAll(self): self.initCheckCase() @@ -1222,7 +1316,11 @@ class TDTestCase: def run(self): print("running {}".format(__file__)) self.createDb() - self.runAll() + try: + self.runAll() + except Exception as err: + print(''.join(traceback.format_exception(None, err, err.__traceback__))) + raise err # self.tagColIllegalValueCheckCase() # self.test() diff --git a/tests/pytest/manualTest/cal_unavaliable_time_kill.py b/tests/pytest/manualTest/cal_unavaliable_time_kill.py new file mode 100644 index 0000000000..a4ffc2506f --- /dev/null +++ b/tests/pytest/manualTest/cal_unavaliable_time_kill.py @@ -0,0 +1,50 @@ +# -*-coding: utf-8-*- +# for TD-5159 +import time +import taos +import sys, time, os, re, platform +from RemoteModule import RemoteModule +class Cal(): + def __init__(self): + master_ip = "192.168.1.189" + master_ssh_port = "22" + ssh_user = "root" + ssh_passwd = "tbase125!" + log_dir = "" + remote_dir = "" + self.RM_master = RemoteModule(master_ip, master_ssh_port, ssh_user, ssh_passwd, log_dir, remote_dir) + + def execShellCmd(self, shell_cmd): + result = os.popen(shell_cmd).read().strip() + return result + + def caltimeFromKill(self): + try: + conn = taos.connect(host="127.0.0.1", user="root", password="taosdata", config="/home/ubuntu/abt_taos") + while "failed" in str(conn): + conn = taos.connect(host="127.0.0.1", user="root", password="taosdata", config="/home/ubuntu/abt_taos") + if "failed" not in str(conn): + break + c1 = conn.cursor() + c1.execute("use test") + insert_tag = 0 + times = 0 + self.RM_master.exec_cmd('ps -ef | grep taosd | grep -v grep | awk \'{print $2}\' | xargs sudo kill -9') + start_time = time.time() + while insert_tag == 0 and times < 10: + insert_res = c1.execute('insert into stb_22 values (now,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)') + if insert_res == 1: + insert_tag = 1 + end_time = time.time() + break + else: + times += 1 + use_time = end_time - start_time + print(use_time) + return use_time + except Exception: + print("last failed") +if __name__ == '__main__': + cal = Cal() + cal.caltimeFromKill() + diff --git a/tests/pytest/manualTest/cal_unavaliable_time_stop.py b/tests/pytest/manualTest/cal_unavaliable_time_stop.py new file mode 100644 index 0000000000..2c60bb69fb --- /dev/null +++ b/tests/pytest/manualTest/cal_unavaliable_time_stop.py @@ -0,0 +1,47 @@ +# -*-coding: utf-8-*- +# for TD-5159 +import time +import taos +import sys, time, os, re, platform +from RemoteModule import RemoteModule +class Cal(): + def __init__(self): + master_ip = "192.168.1.189" + master_ssh_port = "22" + #ssh_user = "ubuntu" + ssh_user = "root" + #ssh_passwd = "1" + ssh_passwd = "tbase125!" + log_dir = "" + remote_dir = "" + self.RM_master = RemoteModule(master_ip, master_ssh_port, ssh_user, ssh_passwd, log_dir, remote_dir) + + def execShellCmd(self, shell_cmd): + result = os.popen(shell_cmd).read().strip() + return result + + def caltimeFromKill(self): + try: + self.RM_master.exec_cmd('screen -d -m systemctl stop taosd') + start_time = time.time() + res = self.execShellCmd('taos -c /home/ubuntu/abt_taos -s "use test; insert into stb_22 values (now,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);"') + while "failed" in str(res): + start_time_shell = time.time() + res = self.execShellCmd('taos -c /home/ubuntu/abt_taos -s "use test; insert into stb_22 values (now,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);"') + end_time_shell = time.time() + shell_time = end_time_shell - start_time_shell + if "failed" not in str(res): + break + print(f'shell_time --- {shell_time}') + sql_time = str(res).split("database")[-1].replace('(', "").replace(')', "").replace('s', "").strip() + print(f'sql_time----{sql_time}') + end_time = time.time() + use_time = end_time - start_time - float(shell_time) + float(sql_time) + print(f'use_time---{use_time}') + return use_time + except Exception: + print("failed") +if __name__ == '__main__': + cal = Cal() + cal.caltimeFromKill() + diff --git a/tests/pytest/query/queryBetweenAnd.py b/tests/pytest/query/queryBetweenAnd.py index cd4320f523..3d038b3d2f 100644 --- a/tests/pytest/query/queryBetweenAnd.py +++ b/tests/pytest/query/queryBetweenAnd.py @@ -101,7 +101,7 @@ class TDTestCase: # tdSql.query(f"select * from t1 where c2 between {pow(10,38)*3.4} and {pow(10,38)*3.4+1}") # tdSql.checkRows(1) tdSql.query(f"select * from t2 where c2 between {-3.4*10**38-1} and {-3.4*10**38}") - tdSql.checkRows(0) + tdSql.checkRows(2) tdSql.error(f"select * from t2 where c2 between null and {-3.4*10**38}") # tdSql.checkRows(3) @@ -203,4 +203,4 @@ class TDTestCase: tdLog.success(f"{__file__} successfully executed") tdCases.addLinux(__file__, TDTestCase()) -tdCases.addWindows(__file__, TDTestCase()) \ No newline at end of file +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/pytest/query/queryPerformance.py b/tests/pytest/query/queryPerformance.py index 1d4e6a2f0f..81103252d8 100644 --- a/tests/pytest/query/queryPerformance.py +++ b/tests/pytest/query/queryPerformance.py @@ -31,7 +31,7 @@ class taosdemoQueryPerformace: self.host = "127.0.0.1" self.user = "root" self.password = "taosdata" - self.config = "/etc/taosperf" + self.config = "/etc/perf" self.conn = taos.connect( self.host, self.user, diff --git a/tests/pytest/query/queryWildcardLength.py b/tests/pytest/query/queryWildcardLength.py new file mode 100644 index 0000000000..d15085f751 --- /dev/null +++ b/tests/pytest/query/queryWildcardLength.py @@ -0,0 +1,217 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- +from copy import deepcopy +import string +import random +from util.log import tdLog +from util.cases import tdCases +from util.sql import tdSql + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + def cleanTb(self): + query_sql = "show stables" + res_row_list = tdSql.query(query_sql, True) + stb_list = map(lambda x: x[0], res_row_list) + for stb in stb_list: + tdSql.execute(f'drop table if exists {stb}') + + query_sql = "show tables" + res_row_list = tdSql.query(query_sql, True) + tb_list = map(lambda x: x[0], res_row_list) + for tb in tb_list: + tdSql.execute(f'drop table if exists {tb}') + + def getLongWildcardStr(self, len=None): + """ + generate long wildcard str + """ + maxWildCardsLength = int(tdSql.getVariable('maxWildCardsLength')[0]) + if len: + chars = ''.join(random.choice(string.ascii_letters.lower()) for i in range(len)) + else: + chars = ''.join(random.choice(string.ascii_letters.lower()) for i in range(maxWildCardsLength+1)) + return chars + + def genTableName(self): + ''' + generate table name + hp_name--->'%str' + lp_name--->'str%' + ul_name--->'st_r' + ''' + table_name = self.getLongWildcardStr() + table_name_list = list(table_name) + table_name_list.pop(-1) + + if len(table_name_list) > 1: + lp_name = deepcopy(table_name_list) + lp_name[-1] = '%' + lp_name = ''.join(lp_name) + + ul_name = list(lp_name) + ul_name[int(len(ul_name)/2)] = '_' + ul_name = ''.join(ul_name) + + table_name_list = list(table_name) + hp_name = deepcopy(table_name_list) + hp_name.pop(1) + hp_name[0] = '%' + hp_name = ''.join(hp_name) + else: + hp_name = '%' + lp_name = '%' + ul_name = '_' + return table_name, hp_name, lp_name, ul_name + + def checkRegularTableWildcardLength(self): + ''' + check regular table wildcard length with % and _ + ''' + self.cleanTb() + table_name, hp_name, lp_name, ul_name = self.genTableName() + tdSql.execute(f"CREATE TABLE {table_name} (ts timestamp, a1 int)") + sql_list = [f'show tables like "{hp_name}"', f'show tables like "{lp_name}"', f'show tables like "{ul_name}"'] + for sql in sql_list: + tdSql.query(sql) + if len(table_name) >= 1: + tdSql.checkRows(1) + else: + tdSql.error(sql) + + exceed_sql_list = [f'show tables like "%{hp_name}"', f'show tables like "{lp_name}%"', f'show tables like "{ul_name}%"'] + for sql in exceed_sql_list: + tdSql.error(sql) + + def checkSuperTableWildcardLength(self): + ''' + check super table wildcard length with % and _ + ''' + self.cleanTb() + table_name, hp_name, lp_name, ul_name = self.genTableName() + tdSql.execute(f"CREATE TABLE {table_name} (ts timestamp, c1 int) tags (t1 int)") + sql_list = [f'show stables like "{hp_name}"', f'show stables like "{lp_name}"', f'show stables like "{ul_name}"'] + for sql in sql_list: + tdSql.query(sql) + if len(table_name) >= 1: + tdSql.checkRows(1) + else: + tdSql.error(sql) + + exceed_sql_list = [f'show stables like "%{hp_name}"', f'show stables like "{lp_name}%"', f'show stables like "{ul_name}%"'] + for sql in exceed_sql_list: + tdSql.error(sql) + + def checkRegularWildcardSelectLength(self): + ''' + check regular table wildcard select length with % and _ + ''' + self.cleanTb() + table_name, hp_name, lp_name, ul_name = self.genTableName() + tdSql.execute(f"CREATE TABLE {table_name} (ts timestamp, bi1 binary(200), nc1 nchar(200))") + tdSql.execute(f'insert into {table_name} values (now, "{table_name}", "{table_name}")') + sql_list = [f'select * from {table_name} where bi1 like "{hp_name}"', + f'select * from {table_name} where bi1 like "{lp_name}"', + f'select * from {table_name} where bi1 like "{ul_name}"', + f'select * from {table_name} where nc1 like "{hp_name}"', + f'select * from {table_name} where nc1 like "{lp_name}"', + f'select * from {table_name} where nc1 like "{ul_name}"'] + for sql in sql_list: + tdSql.query(sql) + if len(table_name) >= 1: + tdSql.checkRows(1) + else: + tdSql.error(sql) + + exceed_sql_list = [f'select * from {table_name} where bi1 like "%{hp_name}"', + f'select * from {table_name} where bi1 like "{lp_name}%"', + f'select * from {table_name} where bi1 like "{ul_name}%"', + f'select * from {table_name} where nc1 like "%{hp_name}"', + f'select * from {table_name} where nc1 like "{lp_name}%"', + f'select * from {table_name} where nc1 like "{ul_name}%"'] + for sql in exceed_sql_list: + tdSql.error(sql) + + def checkStbWildcardSelectLength(self): + ''' + check stb wildcard select length with % and _ + ''' + self.cleanTb() + table_name, hp_name, lp_name, ul_name = self.genTableName() + + tdSql.execute(f'CREATE TABLE {table_name} (ts timestamp, bi1 binary(200), nc1 nchar(200)) tags (si1 binary(200), sc1 nchar(200))') + tdSql.execute(f'create table {table_name}_sub1 using {table_name} tags ("{table_name}", "{table_name}")') + tdSql.execute(f'insert into {table_name}_sub1 values (now, "{table_name}", "{table_name}");') + + # TODO sc1 leave a bug ---> TD-5918 + # sql_list = [f'select * from {table_name} where bi1 like "{hp_name}"', + # f'select * from {table_name} where bi1 like "{lp_name}"', + # f'select * from {table_name} where bi1 like "{ul_name}"', + # f'select * from {table_name} where nc1 like "{hp_name}"', + # f'select * from {table_name} where nc1 like "{lp_name}"', + # f'select * from {table_name} where nc1 like "{ul_name}"', + # f'select * from {table_name} where si1 like "{hp_name}"', + # f'select * from {table_name} where si1 like "{lp_name}"', + # f'select * from {table_name} where si1 like "{ul_name}"', + # f'select * from {table_name} where sc1 like "{hp_name}"', + # f'select * from {table_name} where sc1 like "{lp_name}"', + # f'select * from {table_name} where sc1 like "{ul_name}"'] + sql_list = [f'select * from {table_name} where bi1 like "{hp_name}"', + f'select * from {table_name} where bi1 like "{lp_name}"', + f'select * from {table_name} where bi1 like "{ul_name}"', + f'select * from {table_name} where nc1 like "{hp_name}"', + f'select * from {table_name} where nc1 like "{lp_name}"', + f'select * from {table_name} where nc1 like "{ul_name}"', + f'select * from {table_name} where si1 like "{hp_name}"', + f'select * from {table_name} where si1 like "{lp_name}"', + f'select * from {table_name} where si1 like "{ul_name}"'] + for sql in sql_list: + tdSql.query(sql) + if len(table_name) >= 1: + tdSql.checkRows(1) + else: + tdSql.error(sql) + exceed_sql_list = [f'select * from {table_name} where bi1 like "%{hp_name}"', + f'select * from {table_name} where bi1 like "{lp_name}%"', + f'select * from {table_name} where bi1 like "{ul_name}%"', + f'select * from {table_name} where nc1 like "%{hp_name}"', + f'select * from {table_name} where nc1 like "{lp_name}%"', + f'select * from {table_name} where nc1 like "{ul_name}%"', + f'select * from {table_name} where si1 like "%{hp_name}"', + f'select * from {table_name} where si1 like "{lp_name}%"', + f'select * from {table_name} where si1 like "{ul_name}%"', + f'select * from {table_name} where sc1 like "%{hp_name}"', + f'select * from {table_name} where sc1 like "{lp_name}%"', + f'select * from {table_name} where sc1 like "{ul_name}%"'] + for sql in exceed_sql_list: + tdSql.error(sql) + + def run(self): + tdSql.prepare() + self.checkRegularTableWildcardLength() + self.checkSuperTableWildcardLength() + self.checkRegularWildcardSelectLength() + self.checkStbWildcardSelectLength() + + 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/taosdemoAllTest/NanoTestCase/nano_samples.csv b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/nano_samples.csv new file mode 100644 index 0000000000..5fc779b41b --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/nano_samples.csv @@ -0,0 +1,100 @@ +8.855,"binary_str0" ,1626870128248246976 +8.75,"binary_str1" ,1626870128249060032 +5.44,"binary_str2" ,1626870128249067968 +8.45,"binary_str3" ,1626870128249072064 +4.07,"binary_str4" ,1626870128249075904 +6.97,"binary_str5" ,1626870128249078976 +6.86,"binary_str6" ,1626870128249082048 +1.585,"binary_str7" ,1626870128249085120 +1.4,"binary_str8" ,1626870128249087936 +5.135,"binary_str9" ,1626870128249092032 +3.15,"binary_str10" ,1626870128249095104 +1.765,"binary_str11" ,1626870128249097920 +7.71,"binary_str12" ,1626870128249100992 +3.91,"binary_str13" ,1626870128249104064 +5.615,"binary_str14" ,1626870128249106880 +9.495,"binary_str15" ,1626870128249109952 +3.825,"binary_str16" ,1626870128249113024 +1.94,"binary_str17" ,1626870128249117120 +5.385,"binary_str18" ,1626870128249119936 +7.075,"binary_str19" ,1626870128249123008 +5.715,"binary_str20" ,1626870128249126080 +1.83,"binary_str21" ,1626870128249128896 +6.365,"binary_str22" ,1626870128249131968 +6.55,"binary_str23" ,1626870128249135040 +6.315,"binary_str24" ,1626870128249138112 +3.82,"binary_str25" ,1626870128249140928 +2.455,"binary_str26" ,1626870128249145024 +7.795,"binary_str27" ,1626870128249148096 +2.47,"binary_str28" ,1626870128249150912 +1.37,"binary_str29" ,1626870128249155008 +5.39,"binary_str30" ,1626870128249158080 +5.13,"binary_str31" ,1626870128249160896 +4.09,"binary_str32" ,1626870128249163968 +5.855,"binary_str33" ,1626870128249167040 +0.17,"binary_str34" ,1626870128249170112 +1.955,"binary_str35" ,1626870128249173952 +0.585,"binary_str36" ,1626870128249178048 +0.33,"binary_str37" ,1626870128249181120 +7.925,"binary_str38" ,1626870128249183936 +9.685,"binary_str39" ,1626870128249187008 +2.6,"binary_str40" ,1626870128249191104 +5.705,"binary_str41" ,1626870128249193920 +3.965,"binary_str42" ,1626870128249196992 +4.43,"binary_str43" ,1626870128249200064 +8.73,"binary_str44" ,1626870128249202880 +3.105,"binary_str45" ,1626870128249205952 +9.39,"binary_str46" ,1626870128249209024 +2.825,"binary_str47" ,1626870128249212096 +9.675,"binary_str48" ,1626870128249214912 +9.99,"binary_str49" ,1626870128249217984 +4.51,"binary_str50" ,1626870128249221056 +4.94,"binary_str51" ,1626870128249223872 +7.72,"binary_str52" ,1626870128249226944 +4.135,"binary_str53" ,1626870128249231040 +2.325,"binary_str54" ,1626870128249234112 +4.585,"binary_str55" ,1626870128249236928 +8.76,"binary_str56" ,1626870128249240000 +4.715,"binary_str57" ,1626870128249243072 +0.56,"binary_str58" ,1626870128249245888 +5.35,"binary_str59" ,1626870128249249984 +5.075,"binary_str60" ,1626870128249253056 +6.665,"binary_str61" ,1626870128249256128 +7.13,"binary_str62" ,1626870128249258944 +2.775,"binary_str63" ,1626870128249262016 +5.775,"binary_str64" ,1626870128249265088 +1.62,"binary_str65" ,1626870128249267904 +1.625,"binary_str66" ,1626870128249270976 +8.15,"binary_str67" ,1626870128249274048 +0.75,"binary_str68" ,1626870128249277120 +3.265,"binary_str69" ,1626870128249280960 +8.585,"binary_str70" ,1626870128249284032 +1.88,"binary_str71" ,1626870128249287104 +8.44,"binary_str72" ,1626870128249289920 +5.12,"binary_str73" ,1626870128249295040 +2.58,"binary_str74" ,1626870128249298112 +9.42,"binary_str75" ,1626870128249300928 +1.765,"binary_str76" ,1626870128249304000 +2.66,"binary_str77" ,1626870128249308096 +1.405,"binary_str78" ,1626870128249310912 +5.595,"binary_str79" ,1626870128249315008 +2.28,"binary_str80" ,1626870128249318080 +9.24,"binary_str81" ,1626870128249320896 +9.03,"binary_str82" ,1626870128249323968 +6.055,"binary_str83" ,1626870128249327040 +1.74,"binary_str84" ,1626870128249330112 +5.77,"binary_str85" ,1626870128249332928 +1.97,"binary_str86" ,1626870128249336000 +0.3,"binary_str87" ,1626870128249339072 +7.145,"binary_str88" ,1626870128249342912 +0.88,"binary_str89" ,1626870128249345984 +8.025,"binary_str90" ,1626870128249349056 +4.81,"binary_str91" ,1626870128249351872 +0.725,"binary_str92" ,1626870128249355968 +3.85,"binary_str93" ,1626870128249359040 +9.455,"binary_str94" ,1626870128249362112 +2.265,"binary_str95" ,1626870128249364928 +3.985,"binary_str96" ,1626870128249368000 +9.375,"binary_str97" ,1626870128249371072 +0.2,"binary_str98" ,1626870128249373888 +6.95,"binary_str99" ,1626870128249377984 diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/nano_sampletags.csv b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/nano_sampletags.csv new file mode 100644 index 0000000000..18fb855d6d --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/nano_sampletags.csv @@ -0,0 +1,100 @@ +"string0",7,8.615 +"string1",4,9.895 +"string2",3,2.92 +"string3",3,5.62 +"string4",7,1.615 +"string5",6,1.45 +"string6",5,7.48 +"string7",7,3.01 +"string8",5,4.76 +"string9",10,7.09 +"string10",2,8.38 +"string11",7,8.65 +"string12",5,5.025 +"string13",10,5.765 +"string14",2,4.57 +"string15",2,1.03 +"string16",7,6.98 +"string17",10,0.23 +"string18",7,5.815 +"string19",1,2.37 +"string20",10,8.865 +"string21",3,1.235 +"string22",2,8.62 +"string23",9,1.045 +"string24",8,4.34 +"string25",1,5.455 +"string26",2,4.475 +"string27",1,6.95 +"string28",2,3.39 +"string29",3,6.79 +"string30",7,9.735 +"string31",1,9.79 +"string32",10,9.955 +"string33",1,5.095 +"string34",3,3.86 +"string35",9,5.105 +"string36",10,4.22 +"string37",1,2.78 +"string38",9,6.345 +"string39",1,0.975 +"string40",5,6.16 +"string41",4,7.735 +"string42",5,6.6 +"string43",8,2.845 +"string44",1,0.655 +"string45",3,2.995 +"string46",9,3.6 +"string47",8,3.47 +"string48",3,7.98 +"string49",6,2.225 +"string50",9,5.44 +"string51",4,6.335 +"string52",3,2.955 +"string53",1,0.565 +"string54",6,5.575 +"string55",6,9.905 +"string56",9,6.025 +"string57",8,0.94 +"string58",10,0.15 +"string59",8,1.555 +"string60",4,2.28 +"string61",2,8.29 +"string62",9,6.22 +"string63",6,3.35 +"string64",10,6.7 +"string65",3,9.345 +"string66",7,9.815 +"string67",1,5.365 +"string68",10,3.81 +"string69",1,6.405 +"string70",8,2.715 +"string71",3,8.58 +"string72",8,6.34 +"string73",2,7.49 +"string74",4,8.64 +"string75",3,8.995 +"string76",7,3.465 +"string77",1,7.64 +"string78",6,3.65 +"string79",6,1.4 +"string80",6,5.875 +"string81",2,1.22 +"string82",5,7.87 +"string83",9,8.41 +"string84",9,8.9 +"string85",9,3.89 +"string86",2,5.0 +"string87",2,4.495 +"string88",4,2.835 +"string89",3,5.895 +"string90",7,8.41 +"string91",5,5.125 +"string92",7,9.165 +"string93",5,8.315 +"string94",10,7.485 +"string95",7,4.635 +"string96",2,6.015 +"string97",8,0.595 +"string98",3,8.79 +"string99",4,1.72 diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoInsertMSDB.json b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoInsertMSDB.json new file mode 100644 index 0000000000..8bd5ddbae8 --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoInsertMSDB.json @@ -0,0 +1,63 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 10, + "thread_count_create_tbl": 10, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 100, + "num_of_records_per_req": 1000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "testdb3", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ms", + "keep": 3600, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 100, + "childtable_prefix": "tb0_", + "auto_create_table": "no", + "batch_create_tbl_num": 20, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 100, + "childtable_offset":0, + "multi_thread_write_one_tbl": "no", + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1000, + "start_timestamp": "2021-07-01 00:00:00.000", + "sample_format": "", + "sample_file": "", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":3}, {"type": "BINARY", "len": 16, "count":2}, {"type": "BINARY", "len": 32, "count":2}, + {"type": "TIMESTAMP"}, {"type": "BIGINT", "count":3},{"type": "FLOAT", "count":1},{"type": "SMALLINT", "count":1},{"type": "TINYINT", "count":1}, + {"type": "BOOL"},{"type": "NCHAR","len":16}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":5},{"type": "NCHAR","len":16, "count":1}] + }] + }] +} + diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoInsertNanoDB.json b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoInsertNanoDB.json new file mode 100644 index 0000000000..5408a9841a --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoInsertNanoDB.json @@ -0,0 +1,63 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 10, + "thread_count_create_tbl": 10, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 100, + "num_of_records_per_req": 1000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "testdb1", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ns", + "keep": 3600, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 100, + "childtable_prefix": "tb0_", + "auto_create_table": "no", + "batch_create_tbl_num": 20, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 100, + "childtable_offset":0, + "multi_thread_write_one_tbl": "no", + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1000, + "start_timestamp": "2021-07-01 00:00:00.000", + "sample_format": "", + "sample_file": "", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":3}, {"type": "BINARY", "len": 16, "count":2}, {"type": "BINARY", "len": 32, "count":2}, + {"type": "TIMESTAMP"}, {"type": "BIGINT", "count":3},{"type": "FLOAT", "count":1},{"type": "SMALLINT", "count":1},{"type": "TINYINT", "count":1}, + {"type": "BOOL"},{"type": "NCHAR","len":16}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":5},{"type": "NCHAR","len":16, "count":1}] + }] + }] +} + diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoInsertUSDB.json b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoInsertUSDB.json new file mode 100644 index 0000000000..13eb80f3cf --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoInsertUSDB.json @@ -0,0 +1,63 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 10, + "thread_count_create_tbl": 10, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 100, + "num_of_records_per_req": 1000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "testdb2", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "us", + "keep": 3600, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 100, + "childtable_prefix": "tb0_", + "auto_create_table": "no", + "batch_create_tbl_num": 20, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 100, + "childtable_offset":0, + "multi_thread_write_one_tbl": "no", + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1000, + "start_timestamp": "2021-07-01 00:00:00.000", + "sample_format": "", + "sample_file": "", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":3}, {"type": "BINARY", "len": 16, "count":2}, {"type": "BINARY", "len": 32, "count":2}, + {"type": "TIMESTAMP"}, {"type": "BIGINT", "count":3},{"type": "FLOAT", "count":1},{"type": "SMALLINT", "count":1},{"type": "TINYINT", "count":1}, + {"type": "BOOL"},{"type": "NCHAR","len":16}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":5},{"type": "NCHAR","len":16, "count":1}] + }] + }] +} + diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestInsertTime_step.py b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestInsertTime_step.py new file mode 100644 index 0000000000..b248eda6b0 --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestInsertTime_step.py @@ -0,0 +1,115 @@ +################################################################### +# 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) + + 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): + buildPath = self.getBuildPath() + if (buildPath == ""): + tdLog.exit("taosd not found!") + else: + tdLog.info("taosd found in %s" % buildPath) + binPath = buildPath+ "/build/bin/" + + # insert: create one or mutiple tables per sql and insert multiple rows per sql + + # check the params of taosdemo about time_step is nano + os.system("%staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoInsertNanoDB.json -y " % binPath) + tdSql.execute("use testdb1") + tdSql.query("show stables") + tdSql.checkData(0, 4, 100) + tdSql.query("select count (tbname) from stb0") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from tb0_0") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from stb0") + tdSql.checkData(0, 0, 10000) + tdSql.query("describe stb0") + tdSql.getData(9, 1) + tdSql.checkDataType(9, 1,"TIMESTAMP") + tdSql.query("select last(ts) from stb0") + tdSql.checkData(0, 0,"2021-07-01 00:00:00.000099000") + + # check the params of taosdemo about time_step is us + os.system("%staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoInsertUSDB.json -y " % binPath) + tdSql.execute("use testdb2") + tdSql.query("show stables") + tdSql.checkData(0, 4, 100) + tdSql.query("select count (tbname) from stb0") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from tb0_0") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from stb0") + tdSql.checkData(0, 0, 10000) + tdSql.query("describe stb0") + tdSql.getData(9, 1) + tdSql.checkDataType(9, 1,"TIMESTAMP") + tdSql.query("select last(ts) from stb0") + tdSql.checkData(0, 0,"2021-07-01 00:00:00.099000") + + # check the params of taosdemo about time_step is ms + os.system("%staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoInsertMSDB.json -y " % binPath) + tdSql.execute("use testdb3") + tdSql.query("show stables") + tdSql.checkData(0, 4, 100) + tdSql.query("select count (tbname) from stb0") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from tb0_0") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from stb0") + tdSql.checkData(0, 0, 10000) + tdSql.query("describe stb0") + tdSql.checkDataType(9, 1,"TIMESTAMP") + tdSql.query("select last(ts) from stb0") + tdSql.checkData(0, 0,"2021-07-01 00:01:39.000") + + + os.system("rm -rf ./res.txt") + os.system("rm -rf ./*.py.sql") + + + + 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/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabase.json b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabase.json new file mode 100644 index 0000000000..38ac666fac --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabase.json @@ -0,0 +1,88 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 10, + "thread_count_create_tbl": 10, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 100, + "num_of_records_per_req": 1000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "nsdb", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ns", + "keep": 3600, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 100, + "childtable_prefix": "tb0_", + "auto_create_table": "no", + "batch_create_tbl_num": 20, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 100, + "childtable_offset":0, + "multi_thread_write_one_tbl": "no", + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 10000000, + "start_timestamp": "2021-07-01 00:00:00.000", + "sample_format": "", + "sample_file": "", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":3}, {"type": "BINARY", "len": 16, "count":2}, {"type": "BINARY", "len": 32, "count":2}, + {"type": "TIMESTAMP"}, {"type": "BIGINT", "count":3},{"type": "FLOAT", "count":1},{"type": "SMALLINT", "count":1},{"type": "TINYINT", "count":1}, + {"type": "BOOL"},{"type": "NCHAR","len":16}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":5},{"type": "NCHAR","len":16, "count":1}] + }, + { + "name": "stb1", + "child_table_exists":"no", + "childtable_count": 100, + "childtable_prefix": "tb1_", + "auto_create_table": "no", + "batch_create_tbl_num": 20, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 100, + "childtable_offset":0, + "multi_thread_write_one_tbl": "no", + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 10, + "disorder_range": 1000, + "timestamp_step": 10000000, + "start_timestamp": "2021-07-01 00:00:00.000", + "sample_format": "", + "sample_file": "", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":3}, {"type": "BINARY", "len": 16, "count":2}, {"type": "BINARY", "len": 32, "count":2}, + {"type": "TIMESTAMP"}, {"type": "BIGINT", "count":3},{"type": "FLOAT", "count":1},{"type": "SMALLINT", "count":1},{"type": "TINYINT", "count":1}, + {"type": "BOOL"},{"type": "NCHAR","len":16}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":5},{"type": "NCHAR","len":16, "count":1}] + }] + }] +} diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabaseInsertForSub.json b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabaseInsertForSub.json new file mode 100644 index 0000000000..9ef4a0af66 --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabaseInsertForSub.json @@ -0,0 +1,84 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 10, + "thread_count_create_tbl": 10, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 100, + "num_of_records_per_req": 1000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "subnsdb", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ns", + "keep": 3600, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 10, + "childtable_prefix": "tb0_", + "auto_create_table": "no", + "batch_create_tbl_num": 20, + "data_source": "samples", + "insert_mode": "taosc", + "insert_rows": 10, + "childtable_offset":0, + "multi_thread_write_one_tbl": "no", + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 10000000, + "start_timestamp": "2021-07-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./tools/taosdemoAllTest/NanoTestCase/nano_samples.csv", + "tags_file": "./tools/taosdemoAllTest/NanoTestCase/nano_sampletags.csv", + "columns": [{"type": "DOUBLE"}, {"type": "BINARY", "len": 64, "count":1}, {"type": "TIMESTAMP", "count":1}], + "tags": [{"type": "BINARY", "len": 16, "count":1},{"type": "INT"},{"type": "DOUBLE"}] + }, + { + "name": "stb1", + "child_table_exists":"no", + "childtable_count": 10, + "childtable_prefix": "tb1_", + "auto_create_table": "no", + "batch_create_tbl_num": 20, + "data_source": "samples", + "insert_mode": "taosc", + "insert_rows": 10, + "childtable_offset":0, + "multi_thread_write_one_tbl": "no", + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 10, + "disorder_range": 1000, + "timestamp_step": 10000000, + "start_timestamp": "2021-07-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./tools/taosdemoAllTest/NanoTestCase/nano_samples.csv", + "tags_file": "./tools/taosdemoAllTest/NanoTestCase/nano_sampletags.csv", + "columns": [{"type": "DOUBLE"}, {"type": "BINARY", "len": 64, "count":1}, {"type": "TIMESTAMP", "count":1}], + "tags": [{"type": "BINARY", "len": 16, "count":1},{"type": "INT"},{"type": "DOUBLE"}] + }] + }] +} diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabaseNow.json b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabaseNow.json new file mode 100644 index 0000000000..a09dec21fa --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabaseNow.json @@ -0,0 +1,62 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 10, + "thread_count_create_tbl": 10, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 100, + "num_of_records_per_req": 1000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "nsdb2", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ns", + "keep": 3600, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 100, + "childtable_prefix": "tb0_", + "auto_create_table": "no", + "batch_create_tbl_num": 20, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 100, + "childtable_offset":0, + "multi_thread_write_one_tbl": "no", + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 10, + "start_timestamp": "now", + "sample_format": "", + "sample_file": "", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":3}, {"type": "BINARY", "len": 16, "count":2}, {"type": "BINARY", "len": 32, "count":2}, + {"type": "TIMESTAMP"}, {"type": "BIGINT", "count":3},{"type": "FLOAT", "count":1},{"type": "SMALLINT", "count":1},{"type": "TINYINT", "count":1}, + {"type": "BOOL"},{"type": "NCHAR","len":16}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":5},{"type": "NCHAR","len":16, "count":1}] + }] + }] +} diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabasecsv.json b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabasecsv.json new file mode 100644 index 0000000000..e99c528c6d --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabasecsv.json @@ -0,0 +1,84 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 10, + "thread_count_create_tbl": 10, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 100, + "num_of_records_per_req": 1000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "nsdbcsv", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ns", + "keep": 3600, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 100, + "childtable_prefix": "tb0_", + "auto_create_table": "no", + "batch_create_tbl_num": 20, + "data_source": "samples", + "insert_mode": "taosc", + "insert_rows": 100, + "childtable_offset":0, + "multi_thread_write_one_tbl": "no", + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 10000000, + "start_timestamp": "2021-07-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./tools/taosdemoAllTest/NanoTestCase/nano_samples.csv", + "tags_file": "./tools/taosdemoAllTest/NanoTestCase/nano_sampletags.csv", + "columns": [{"type": "DOUBLE"}, {"type": "BINARY", "len": 64, "count":1}, {"type": "TIMESTAMP", "count":1}], + "tags": [{"type": "BINARY", "len": 16, "count":1},{"type": "INT"},{"type": "DOUBLE"}] + }, + { + "name": "stb1", + "child_table_exists":"no", + "childtable_count": 100, + "childtable_prefix": "tb1_", + "auto_create_table": "no", + "batch_create_tbl_num": 20, + "data_source": "samples", + "insert_mode": "taosc", + "insert_rows": 100, + "childtable_offset":0, + "multi_thread_write_one_tbl": "no", + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 10, + "disorder_range": 1000, + "timestamp_step": 10000000, + "start_timestamp": "2021-07-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./tools/taosdemoAllTest/NanoTestCase/nano_samples.csv", + "tags_file": "./tools/taosdemoAllTest/NanoTestCase/nano_sampletags.csv", + "columns": [{"type": "DOUBLE"}, {"type": "BINARY", "len": 64, "count":1}, {"type": "TIMESTAMP", "count":1}], + "tags": [{"type": "BINARY", "len": 16, "count":1},{"type": "INT"},{"type": "DOUBLE"}] + }] + }] +} diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoInsert.py b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoInsert.py new file mode 100644 index 0000000000..f069bb8f70 --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoInsert.py @@ -0,0 +1,169 @@ +################################################################### +# 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) + + 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): + buildPath = self.getBuildPath() + if (buildPath == ""): + tdLog.exit("taosd not found!") + else: + tdLog.info("taosd found in %s" % buildPath) + binPath = buildPath + "/build/bin/" + + # insert: create one or mutiple tables per sql and insert multiple rows per sql + # insert data from a special timestamp + # check stable stb0 + + os.system( + "%staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabase.json -y " % + binPath) + tdSql.execute("use nsdb") + tdSql.query("show stables") + tdSql.checkData(0, 4, 100) + tdSql.query("select count (tbname) from stb0") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from tb0_0") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from stb0") + tdSql.checkData(0, 0, 10000) + tdSql.query("describe stb0") + tdSql.checkDataType(9, 1, "TIMESTAMP") + tdSql.query("select last(ts) from stb0") + tdSql.checkData(0, 0, "2021-07-01 00:00:00.990000000") + + # check stable stb1 which is insert with disord + + tdSql.query("select count (tbname) from stb1") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from tb1_0") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from stb1") + tdSql.checkData(0, 0, 10000) + # check c8 is an nano timestamp + tdSql.query("describe stb1") + tdSql.checkDataType(9, 1, "TIMESTAMP") + # check insert timestamp_step is nano_second + tdSql.query("select last(ts) from stb1") + tdSql.checkData(0, 0, "2021-07-01 00:00:00.990000000") + + # insert data from now time + + # check stable stb0 + os.system( + "%staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabaseNow.json -y " % + binPath) + + tdSql.execute("use nsdb2") + tdSql.query("show stables") + tdSql.checkData(0, 4, 100) + tdSql.query("select count (tbname) from stb0") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from tb0_0") + tdSql.checkData(0, 0, 100) + tdSql.query("select count(*) from stb0") + tdSql.checkData(0, 0, 10000) + # check c8 is an nano timestamp + tdSql.query("describe stb0") + tdSql.checkDataType(9, 1, "TIMESTAMP") + + # insert by csv files and timetamp is long int , strings in ts and + # cols + + os.system( + "%staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabasecsv.json -y " % + binPath) + tdSql.execute("use nsdbcsv") + tdSql.query("show stables") + tdSql.checkData(0, 4, 100) + tdSql.query("select count(*) from stb0") + tdSql.checkData(0, 0, 10000) + tdSql.query("describe stb0") + tdSql.checkDataType(3, 1, "TIMESTAMP") + tdSql.query( + "select count(*) from stb0 where ts > \"2021-07-01 00:00:00.490000000\"") + tdSql.checkData(0, 0, 5000) + tdSql.query("select count(*) from stb0 where ts < 1626918583000000000") + tdSql.checkData(0, 0, 10000) + + os.system("rm -rf ./insert_res.txt") + os.system( + "rm -rf tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNano*.py.sql") + + # taosdemo test insert with command and parameter , detals show + # taosdemo --help + os.system( + "%staosdemo -u root -ptaosdata -P 6030 -a 1 -m pre -n 10 -T 20 -t 60 -o res.txt -y " % + binPath) + tdSql.query("select count(*) from test.meters") + tdSql.checkData(0, 0, 600) + # check taosdemo -s + + sqls_ls = [ + 'drop database if exists nsdbsql;', + 'create database nsdbsql precision "ns" keep 3600 days 6 update 1;', + 'use nsdbsql;', + 'CREATE STABLE meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupdId int);', + 'CREATE TABLE d1001 USING meters TAGS ("Beijing.Chaoyang", 2);', + 'INSERT INTO d1001 USING METERS TAGS ("Beijng.Chaoyang", 2) VALUES (now, 10.2, 219, 0.32);', + 'INSERT INTO d1001 USING METERS TAGS ("Beijng.Chaoyang", 2) VALUES (now, 85, 32, 0.76);'] + + with open("./taosdemoTestNanoCreateDB.sql", mode="a") as sql_files: + for sql in sqls_ls: + sql_files.write(sql + "\n") + sql_files.close() + + sleep(10) + + os.system("%staosdemo -s taosdemoTestNanoCreateDB.sql -y " % binPath) + tdSql.query("select count(*) from nsdbsql.meters") + tdSql.checkData(0, 0, 2) + + os.system("rm -rf ./res.txt") + os.system("rm -rf ./*.py.sql") + os.system("rm -rf ./taosdemoTestNanoCreateDB.sql") + + 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/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuery.json b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuery.json new file mode 100644 index 0000000000..fff1017588 --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuery.json @@ -0,0 +1,92 @@ +{ + "filetype": "query", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "confirm_parameter_prompt": "no", + "databases": "nsdb", + "query_times": 10, + "query_mode": "taosc", + "specified_table_query": { + "query_interval": 1, + "concurrent": 2, + "sqls": [ + { + "sql": "select count(*) from stb0 where ts>\"2021-07-01 00:01:00.000000000 \" ;", + "result": "./query_res0.txt" + }, + { + "sql": "select count(*) from stb0 where ts>\"2021-07-01 00:01:00.000000000\" and ts <=\"2021-07-01 00:01:10.000000000\" ;", + "result": "./query_res1.txt" + }, + { + "sql": "select count(*) from stb0 where ts>now-20d ;", + "result": "./query_res2.txt" + }, + { + "sql": "select max(c10) from stb0;", + "result": "./query_res3.txt" + }, + { + "sql": "select min(c1) from stb0;", + "result": "./query_res4.txt" + }, + { + "sql": "select avg(c1) from stb0;", + "result": "./query_res5.txt" + }, + { + "sql":"select count(*) from stb0 group by tbname;", + "result":"./query_res6.txt" + } + + ] + }, + "super_table_query": { + "stblname": "stb0", + "query_interval": 0, + "threads": 4, + "sqls": [ + { + "sql": "select count(*) from xxxx where ts>\"2021-07-01 00:01:00.000000000 \" ;", + "result": "./query_res_tb0.txt" + }, + { + "sql":"select count(*) from xxxx where ts>\"2021-07-01 00:01:00.000000000\" and ts <=\"2021-07-01 00:01:10.000000000\" ;", + "result": "./query_res_tb1.txt" + }, + { + "sql":"select first(*) from xxxx ;", + "result": "./query_res_tb2.txt" + }, + { + "sql":"select last(*) from xxxx;", + "result": "./query_res_tb3.txt" + + }, + { + "sql":"select last_row(*) from xxxx ;", + "result": "./query_res_tb4.txt" + + }, + { + "sql":"select max(c10) from xxxx ;", + "result": "./query_res_tb5.txt" + + }, + { + "sql":"select min(c1) from xxxx ;", + "result": "./query_res_tb6.txt" + + }, + { + "sql":"select avg(c10) from xxxx ;", + "result": "./query_res_tb7.txt" + + } + + ] + } + } \ No newline at end of file diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuery.py b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuery.py new file mode 100644 index 0000000000..6c3e4d6c8a --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuery.py @@ -0,0 +1,157 @@ +################################################################### +# 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) + + 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): + buildPath = self.getBuildPath() + if (buildPath == ""): + tdLog.exit("taosd not found!") + else: + tdLog.info("taosd found in %s" % buildPath) + binPath = buildPath+ "/build/bin/" + + # query: query test for nanoSecond with where and max min groupby order + os.system("%staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabase.json -y " % binPath) + + tdSql.execute("use nsdb") + + # use where to filter + + tdSql.query("select count(*) from stb0 where ts>\"2021-07-01 00:00:00.590000000 \" ") + tdSql.checkData(0, 0, 4000) + tdSql.query("select count(*) from stb0 where ts>\"2021-07-01 00:00:00.000000000\" and ts <=\"2021-07-01 00:00:00.590000000\" ") + tdSql.checkData(0, 0, 5900) + + tdSql.query("select count(*) from tb0_0 where ts>\"2021-07-01 00:00:00.590000000 \" ;") + tdSql.checkData(0, 0, 40) + tdSql.query("select count(*) from tb0_0 where ts>\"2021-07-01 00:00:00.000000000\" and ts <=\"2021-07-01 00:00:00.590000000\" ") + tdSql.checkData(0, 0, 59) + + + # select max min avg from special col + tdSql.query("select max(c10) from stb0;") + print("select max(c10) from stb0 : " , tdSql.getData(0, 0)) + + tdSql.query("select max(c10) from tb0_0;") + print("select max(c10) from tb0_0 : " , tdSql.getData(0, 0)) + + + tdSql.query("select min(c1) from stb0;") + print( "select min(c1) from stb0 : " , tdSql.getData(0, 0)) + + tdSql.query("select min(c1) from tb0_0;") + print( "select min(c1) from tb0_0 : " , tdSql.getData(0, 0)) + + tdSql.query("select avg(c1) from stb0;") + print( "select avg(c1) from stb0 : " , tdSql.getData(0, 0)) + + tdSql.query("select avg(c1) from tb0_0;") + print( "select avg(c1) from tb0_0 : " , tdSql.getData(0, 0)) + + tdSql.query("select count(*) from stb0 group by tbname;") + tdSql.checkData(0, 0, 100) + tdSql.checkData(10, 0, 100) + + # query : query above sqls by taosdemo and continuously + + os.system("%staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuery.json -y " % binPath) + + + os.system("%staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabasecsv.json -y " % binPath) + tdSql.execute("use nsdbcsv") + tdSql.query("show stables") + tdSql.checkData(0, 4, 100) + tdSql.query("select count(*) from stb0") + tdSql.checkData(0, 0, 10000) + tdSql.query("describe stb0") + tdSql.checkDataType(3, 1, "TIMESTAMP") + tdSql.query("select count(*) from stb0 where ts >\"2021-07-01 00:00:00.490000000\"") + tdSql.checkData(0, 0, 5000) + tdSql.query("select count(*) from stb0 where ts 162687012800000000') + tdSql.execute('select count(*) from stb0 where c2 < 162687012800000000') + tdSql.execute('select count(*) from stb0 where c2 = 162687012800000000') + tdSql.execute('select count(*) from stb0 where c2 != 162687012800000000') + tdSql.execute('select count(*) from stb0 where c2 <> 162687012800000000') + tdSql.execute('select count(*) from stb0 where c2 > "2021-07-21 20:22:08.248246976"') + tdSql.execute('select count(*) from stb0 where c2 < "2021-07-21 20:22:08.248246976"') + tdSql.execute('select count(*) from stb0 where c2 = "2021-07-21 20:22:08.248246976"') + tdSql.execute('select count(*) from stb0 where c2 != "2021-07-21 20:22:08.248246976"') + tdSql.execute('select count(*) from stb0 where c2 <> "2021-07-21 20:22:08.248246976"') + tdSql.execute('select count(*) from stb0 where ts between "2021-07-01 00:00:00.000000000" and "2021-07-01 00:00:00.990000000"') + tdSql.execute('select count(*) from stb0 where ts between 1625068800000000000 and 1625068801000000000') + tdSql.query('select avg(c0) from stb0 interval(5000000000b)') + tdSql.checkRows(1) + + tdSql.query('select avg(c0) from stb0 interval(100000000b)') + tdSql.checkRows(10) + + tdSql.error('select avg(c0) from stb0 interval(1b)') + tdSql.error('select avg(c0) from stb0 interval(999b)') + + tdSql.query('select avg(c0) from stb0 interval(1000b)') + tdSql.checkRows(100) + + tdSql.query('select avg(c0) from stb0 interval(1u)') + tdSql.checkRows(100) + + tdSql.query('select avg(c0) from stb0 interval(100000000b) sliding (100000000b)') + tdSql.checkRows(10) + + # query : query above sqls by taosdemo and continuously + os.system("%staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuerycsv.json -y " % binPath) + + os.system("rm -rf ./query_res*.txt*") + os.system("rm -rf tools/taosdemoAllTest/NanoTestCase/*.py.sql") + + + + + 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/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuerycsv.json b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuerycsv.json new file mode 100644 index 0000000000..2323b0f370 --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuerycsv.json @@ -0,0 +1,110 @@ +{ + "filetype": "query", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "confirm_parameter_prompt": "no", + "databases": "nsdbcsv", + "query_times": 10, + "query_mode": "taosc", + "specified_table_query": { + "query_interval": 1, + "concurrent": 2, + "sqls": [ + { + "sql": "select count(*) from stb0 where ts> \"2021-07-01 00:00:00.490000000\" ;", + "result": "./query_res0.txt" + }, + { + "sql": "select count(*) from stb0 where ts < now -22d-1h-3s ;", + "result": "./query_res1.txt" + }, + { + "sql": "select count(*) from stb0 where ts < 1626918583000000000 ;", + "result": "./query_res2.txt" + }, + { + "sql": "select count(*) from stb0 where c2 <> 162687012800000000;", + "result": "./query_res3.txt" + }, + { + "sql": "select count(*) from stb0 where c2 != \"2021-07-21 20:22:08.248246976\";", + "result": "./query_res4.txt" + }, + { + "sql": "select count(*) from stb0 where ts between \"2021-07-01 00:00:00.000000000\" and \"2021-07-01 00:00:00.990000000\";", + "result": "./query_res5.txt" + }, + { + "sql":"select count(*) from stb0 group by tbname;", + "result":"./query_res6.txt" + }, + { + "sql":"select count(*) from stb0 where ts between 1625068800000000000 and 1625068801000000000;", + "result":"./query_res7.txt" + }, + { + "sql":"select avg(c0) from stb0 interval(5000000000b);", + "result":"./query_res8.txt" + }, + { + "sql":"select avg(c0) from stb0 interval(100000000b) sliding (100000000b);", + "result":"./query_res9.txt" + } + + ] + }, + "super_table_query": { + "stblname": "stb0", + "query_interval": 0, + "threads": 4, + "sqls": [ + { + "sql": "select count(*) from xxxx where ts > \"2021-07-01 00:00:00.490000000\" ;", + "result": "./query_res_tb0.txt" + }, + { + "sql":"select count(*) from xxxx where ts between \"2021-07-01 00:00:00.000000000\" and \"2021-07-01 00:00:00.990000000\" ;", + "result": "./query_res_tb1.txt" + }, + { + "sql":"select first(*) from xxxx ;", + "result": "./query_res_tb2.txt" + }, + { + "sql":"select last(*) from xxxx;", + "result": "./query_res_tb3.txt" + + }, + { + "sql":"select last_row(*) from xxxx ;", + "result": "./query_res_tb4.txt" + + }, + { + "sql":"select max(c0) from xxxx ;", + "result": "./query_res_tb5.txt" + + }, + { + "sql":"select min(c0) from xxxx ;", + "result": "./query_res_tb6.txt" + + }, + { + "sql":"select avg(c0) from xxxx ;", + "result": "./query_res_tb7.txt" + + }, + { + "sql":"select avg(c0) from xxxx interval(100000000b) sliding (100000000b) ;", + "result": "./query_res_tb8.txt" + + } + + + ] + } + } \ No newline at end of file diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoSubscribe.json b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoSubscribe.json new file mode 100644 index 0000000000..1cc834164e --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoSubscribe.json @@ -0,0 +1,32 @@ +{ + "filetype":"subscribe", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "databases": "subnsdb", + "confirm_parameter_prompt": "no", + "specified_table_query": + { + "concurrent":2, + "mode":"sync", + "interval":10000, + "restart":"yes", + "keepProgress":"yes", + "sqls": [ + { + "sql": "select * from stb0 where ts>= \"2021-07-01 00:00:00.000000000\" ;", + "result": "./subscribe_res0.txt" + }, + { + "sql": "select * from stb0 where ts < now -2d-1h-3s ;", + "result": "./subscribe_res1.txt" + }, + { + "sql": "select * from stb0 where ts < 1626918583000000000 ;", + "result": "./subscribe_res2.txt" + }] + + } +} diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanosubscribe.py b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanosubscribe.py new file mode 100644 index 0000000000..95c1a731bc --- /dev/null +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanosubscribe.py @@ -0,0 +1,125 @@ +################################################################### +# 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 time +from datetime import datetime +import subprocess + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + 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 + + # get the number of subscriptions + def subTimes(self,filename): + self.filename = filename + command = 'cat %s |wc -l'% filename + times = int(subprocess.getstatusoutput(command)[1]) + return times + + # assert results + def assertCheck(self,filename,subResult,expectResult): + self.filename = filename + self.subResult = subResult + self.expectResult = expectResult + args0 = (filename, subResult, expectResult) + assert subResult == expectResult , "Queryfile:%s ,result is %s != expect: %s" % args0 + + def run(self): + buildPath = self.getBuildPath() + if (buildPath == ""): + tdLog.exit("taosd not found!") + else: + tdLog.info("taosd found in %s" % buildPath) + binPath = buildPath+ "/build/bin/" + + # clear env + os.system("ps -ef |grep 'taosdemoAllTest/taosdemoTestSupportNanoSubscribe.json' |grep -v 'grep' |awk '{print $2}'|xargs kill -9") + os.system("rm -rf ./subscribe_res*") + os.system("rm -rf ./all_subscribe_res*") + + + # insert data + os.system("%staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabaseInsertForSub.json" % binPath) + os.system("nohup %staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoSubscribe.json &" % binPath) + query_pid = int(subprocess.getstatusoutput('ps aux|grep "taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoSubscribe.json" |grep -v "grep"|awk \'{print $2}\'')[1]) + + + # merge result files + sleep(5) + os.system("cat subscribe_res0.txt* > all_subscribe_res0.txt") + os.system("cat subscribe_res1.txt* > all_subscribe_res1.txt") + os.system("cat subscribe_res2.txt* > all_subscribe_res2.txt") + + + # correct subscribeTimes testcase + subTimes0 = self.subTimes("all_subscribe_res0.txt") + self.assertCheck("all_subscribe_res0.txt",subTimes0 ,200) + + subTimes1 = self.subTimes("all_subscribe_res1.txt") + self.assertCheck("all_subscribe_res1.txt",subTimes1 ,200) + + subTimes2 = self.subTimes("all_subscribe_res2.txt") + self.assertCheck("all_subscribe_res2.txt",subTimes2 ,200) + + + # insert extral data + tdSql.execute("use subnsdb") + tdSql.execute("insert into tb0_0 values(now,100.1000,'subtest1',now-1s)") + sleep(15) + + os.system("cat subscribe_res0.txt* > all_subscribe_res0.txt") + subTimes0 = self.subTimes("all_subscribe_res0.txt") + print("pass") + self.assertCheck("all_subscribe_res0.txt",subTimes0 ,202) + + + + # correct data testcase + os.system("kill -9 %d" % query_pid) + sleep(3) + os.system("rm -rf ./subscribe_res*") + os.system("rm -rf ./all_subscribe*") + os.system("rm -rf ./*.py.sql") + + + + 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/taosdumpTestNanoSupport.py b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdumpTestNanoSupport.py similarity index 100% rename from tests/pytest/tools/taosdumpTestNanoSupport.py rename to tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdumpTestNanoSupport.py diff --git a/tests/pytest/tools/taosdemoAllTest/taosdemoTestSupportNanoInsert.py b/tests/pytest/tools/taosdemoAllTest/taosdemoTestSupportNanoInsert.py index 266a8fa712..c3fdff00ec 100644 --- a/tests/pytest/tools/taosdemoAllTest/taosdemoTestSupportNanoInsert.py +++ b/tests/pytest/tools/taosdemoAllTest/taosdemoTestSupportNanoInsert.py @@ -120,7 +120,7 @@ class TDTestCase: os.system("rm -rf tools/taosdemoAllTest/taosdemoTestSupportNano*.py.sql") # taosdemo test insert with command and parameter , detals show taosdemo --help - os.system("%staosdemo -u root -P taosdata -p 6030 -a 1 -m pre -n 10 -T 20 -t 60 -o res.txt -y " % binPath) + os.system("%staosdemo -u root -ptaosdata -P 6030 -a 1 -m pre -n 10 -T 20 -t 60 -o res.txt -y " % binPath) tdSql.query("select count(*) from test.meters") tdSql.checkData(0, 0, 600) # check taosdemo -s diff --git a/tests/pytest/tools/taosdemoPerformance.py b/tests/pytest/tools/taosdemoPerformance.py index 9d9b29c017..6b5681dfbc 100644 --- a/tests/pytest/tools/taosdemoPerformance.py +++ b/tests/pytest/tools/taosdemoPerformance.py @@ -16,8 +16,7 @@ import pandas as pd import argparse import os.path import json -from util.log import tdLog -from util.sql import tdSql +import sys class taosdemoPerformace: def __init__(self, commitID, dbName, branch, type): @@ -132,7 +131,9 @@ class taosdemoPerformace: def insertData(self): buildPath = self.getBuildPath() if (buildPath == ""): - tdLog.exit("taosdemo not found!") + print("taosdemo not found!") + sys.exit(1) + binPath = buildPath + "/build/bin/" os.system( diff --git a/tests/pytest/tools/taosdemoTestInterlace.py b/tests/pytest/tools/taosdemoTestInterlace.py index 4c551f327a..30c04729b7 100644 --- a/tests/pytest/tools/taosdemoTestInterlace.py +++ b/tests/pytest/tools/taosdemoTestInterlace.py @@ -49,7 +49,7 @@ class TDTestCase: 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 + 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)) diff --git a/tests/pytest/util/sql.py b/tests/pytest/util/sql.py index b42af27d06..dfe1e4a582 100644 --- a/tests/pytest/util/sql.py +++ b/tests/pytest/util/sql.py @@ -81,6 +81,22 @@ class TDSql: return self.queryResult return self.queryRows + def getVariable(self, search_attr): + ''' + get variable of search_attr access "show variables" + ''' + try: + sql = 'show variables' + param_list = self.query(sql, row_tag=True) + for param in param_list: + if param[0] == search_attr: + return param[1], param_list + except Exception as e: + caller = inspect.getframeinfo(inspect.stack()[1][0]) + args = (caller.filename, caller.lineno, sql, repr(e)) + tdLog.notice("%s(%d) failed: sql:%s, %s" % args) + raise Exception(repr(e)) + def getColNameList(self, sql, col_tag=None): self.sql = sql try: diff --git a/tests/pytest/util/sub.py b/tests/pytest/util/sub.py index 2e3c2a96b7..664d830b86 100644 --- a/tests/pytest/util/sub.py +++ b/tests/pytest/util/sub.py @@ -29,9 +29,10 @@ class TDSub: self.sub.close(keepProgress) def consume(self): - self.data = self.sub.consume() - self.consumedRows = len(self.data) - self.consumedCols = len(self.sub.fields) + self.result = self.sub.consume() + self.result.fetch_all() + self.consumedRows = self.result.row_count + self.consumedCols = self.result.field_count return self.consumedRows def checkRows(self, expectRows): diff --git a/tests/script/general/http/bug.go b/tests/script/general/http/bug.go index 61991f4d02..9455a48c56 100644 --- a/tests/script/general/http/bug.go +++ b/tests/script/general/http/bug.go @@ -1,3 +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 . + */ + package main import ( @@ -184,7 +199,7 @@ func exec(client *http.Client, sql string) { if (request < 103) { return } - + atomic.AddInt64(&period, spend) if request%5000 == 0 && request != 0 { requestAvg := float64(period) / float64(1000000) / float64(request) @@ -204,7 +219,7 @@ func insertTable(conn int) { tbStart := conn*config.TablePerConn + config.TableStart tmStart := config.DataBegin - + for j := 0; j < config.DataNum; j++ { for i := 0; i < config.TablePerConn; i++ { tmVal := int64(j)*int64(config.DataInterval) + tmStart + 1 @@ -214,7 +229,7 @@ func insertTable(conn int) { if config.DataRandom { dataVal = rand.Intn(1000) } - + sql := fmt.Sprintf("import into %s.%s%d values(%d, %d)", config.DbName, config.TablePrefix, tbIndex, tmVal, dataVal) exec(client, sql) time.Sleep(time.Millisecond * time.Duration(10)) @@ -282,7 +297,7 @@ func selectData(wg *sync.WaitGroup, conn int) { client := &http.Client{} - + tbStart := conn*config.TablePerConn + config.TableStart for j := 0; j < config.DataNum; j++ { tbIndex := 0 + tbStart @@ -292,10 +307,10 @@ func selectData(wg *sync.WaitGroup, conn int) { sql += fmt.Sprintf(",'%s%d'", config.TablePrefix, tbIndex) } sql += ") group by orgno" - + //sql := fmt.Sprintf("select count(*) from db.mt") //sql := fmt.Sprintf("select max(i),min(i) from db.mt", config.TablePrefix, tbIndex) - + exec(client, sql) time.Sleep(time.Millisecond * time.Duration(10)) } @@ -303,17 +318,17 @@ func selectData(wg *sync.WaitGroup, conn int) { func main() { filename := flag.String("config", "taos_cloud.json", "config file name") - + flag.Parse() - + readFile(*filename) - + fmt.Println("\n================http test start======================") var wg sync.WaitGroup fmt.Println("\n================select data ========================") - + for i := 0; i < config.ConnNum; i++ { wg.Add(1) diff --git a/tests/script/general/http/httpTestNew.go b/tests/script/general/http/httpTestNew.go index 7947f0a20a..9ca7733d44 100644 --- a/tests/script/general/http/httpTestNew.go +++ b/tests/script/general/http/httpTestNew.go @@ -1,3 +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 . + */ + package main import ( diff --git a/tests/script/general/http/httpTest_cloud.go b/tests/script/general/http/httpTest_cloud.go index feb3f1450b..1d849a245f 100644 --- a/tests/script/general/http/httpTest_cloud.go +++ b/tests/script/general/http/httpTest_cloud.go @@ -1,3 +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 . + */ + package main import ( @@ -184,7 +199,7 @@ func exec(client *http.Client, sql string) { if (request < 103) { return } - + atomic.AddInt64(&period, spend) if request%5000 == 0 && request != 0 { requestAvg := float64(period) / float64(1000000) / float64(request) @@ -333,11 +348,11 @@ func selectData(wg *sync.WaitGroup, conn int) { func main() { filename := flag.String("config", "taos_cloud.json", "config file name") - + flag.Parse() - + readFile(*filename) - + fmt.Println("\n================http test start======================") var wg sync.WaitGroup diff --git a/tests/script/general/http/httpTest_private.go b/tests/script/general/http/httpTest_private.go index 907b6c1d62..66f19ec896 100644 --- a/tests/script/general/http/httpTest_private.go +++ b/tests/script/general/http/httpTest_private.go @@ -1,3 +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 . + */ + package main import ( @@ -184,7 +199,7 @@ func exec(client *http.Client, sql string) { if (request < 103) { return } - + atomic.AddInt64(&period, spend) if request%5000 == 0 && request != 0 { requestAvg := float64(period) / float64(1000000) / float64(request) @@ -256,7 +271,7 @@ func insertTable(conn int) { sql += fmt.Sprintf("(%d, %d)", tmVal, dataVal) } - + exec(client, sql) if config.WaitTime != 0 { time.Sleep(time.Millisecond * time.Duration(config.WaitTime)) @@ -333,11 +348,11 @@ func selectData(wg *sync.WaitGroup, conn int) { func main() { filename := flag.String("config", "taos_cloud.json", "config file name") - + flag.Parse() - + readFile(*filename) - + fmt.Println("\n================http test start======================") var wg sync.WaitGroup diff --git a/tests/script/general/http/telegrafTest.go b/tests/script/general/http/telegrafTest.go index b8cbb43ce8..caa6493c82 100644 --- a/tests/script/general/http/telegrafTest.go +++ b/tests/script/general/http/telegrafTest.go @@ -1,3 +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 . + */ + package main import ( @@ -68,7 +83,7 @@ func readConf(filename string) { fmt.Println("LoopNum:", config.LoopNum) fmt.Println("dbName:", config.DbName) fmt.Println("dataBegin:", config.DataBegin) - + fmt.Println("================http token=============================") token, err = getToken() url = fmt.Sprintf("http://%s:%d/telegraf/%s", config.HostIp, 6020, config.DbName) @@ -90,9 +105,9 @@ func readReq(filename string) { defer file.Close() data, _ := ioutil.ReadAll(file) - + template = string(data[:]) - + //fmt.Println(template) } @@ -154,13 +169,13 @@ func exec(client *http.Client, sql string) { var jsonResult JsonResult err = json.Unmarshal(data, &jsonResult) if err != nil { - fmt.Println("parse json error: ", string(data[:])) + fmt.Println("parse json error: ", string(data[:])) resp.Body.Close() continue } - - atomic.AddInt64(&request, 1) + + atomic.AddInt64(&request, 1) atomic.AddInt64(&period, spend) if request%1000 == 0 && request != 0 { @@ -179,16 +194,16 @@ func exec(client *http.Client, sql string) { func writeData(wg *sync.WaitGroup, tbIndex int) { defer wg.Done() client := &http.Client{} - + tbName := fmt.Sprintf("t%d", tbIndex) - + for j := 0; j < config.LoopNum; j++ { tmVal := fmt.Sprintf("%d", int64(j)*int64(10000) + config.DataBegin) //fmt.Println(tmVal) req1 := strings.Replace(template, "panshi-gsl", tbName, -1) req2 := strings.Replace(req1, "1536750390000", tmVal, -1) - + //fmt.Println(req2) exec(client, req2) } @@ -196,17 +211,17 @@ func writeData(wg *sync.WaitGroup, tbIndex int) { func main() { filename := flag.String("config", "telegraf.json", "config file name") - + flag.Parse() - + readReq("telegraf.req") - + readConf(*filename) - + fmt.Println("\n================telegraf test start======================") var wg sync.WaitGroup - + for i := 0; i < config.MachineNum; i++ { wg.Add(1) go writeData(&wg, i) diff --git a/tests/script/general/parser/condition.sim b/tests/script/general/parser/condition.sim new file mode 100644 index 0000000000..56706467f1 --- /dev/null +++ b/tests/script/general/parser/condition.sim @@ -0,0 +1,111 @@ +system sh/stop_dnodes.sh + +system sh/deploy.sh -n dnode1 -i 1 +system sh/cfg.sh -n dnode1 -c walLevel -v 1 +system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 +system sh/exec.sh -n dnode1 -s start + +sleep 100 +sql connect + +sql drop database if exists cdb +sql create database if not exists cdb +sql use cdb +sql create table stb1 (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(10), t3 double) + +sql create table tb1 using stb1 tags(1,'1',1.0) +sql create table tb2 using stb1 tags(2,'2',2.0) +sql create table tb3 using stb1 tags(3,'3',3.0) +sql create table tb4 using stb1 tags(4,'4',4.0) +sql create table tb5 using stb1 tags(5,'5',5.0) +sql create table tb6 using stb1 tags(6,'6',6.0) + +sql insert into tb1 values ('2021-05-05 18:19:00',1,1.0,1,1,1,1.0,true ,'1','1') +sql insert into tb1 values ('2021-05-05 18:19:01',2,2.0,2,2,2,2.0,true ,'2','2') +sql insert into tb1 values ('2021-05-05 18:19:02',3,3.0,3,3,3,3.0,false,'3','3') +sql insert into tb1 values ('2021-05-05 18:19:03',4,4.0,4,4,4,4.0,false,'4','4') +sql insert into tb1 values ('2021-05-05 18:19:04',11,11.0,11,11,11,11.0,true ,'11','11') +sql insert into tb1 values ('2021-05-05 18:19:05',12,12.0,12,12,12,12.0,true ,'12','12') +sql insert into tb1 values ('2021-05-05 18:19:06',13,13.0,13,13,13,13.0,false,'13','13') +sql insert into tb1 values ('2021-05-05 18:19:07',14,14.0,14,14,14,14.0,false,'14','14') +sql insert into tb2 values ('2021-05-05 18:19:08',21,21.0,21,21,21,21.0,true ,'21','21') +sql insert into tb2 values ('2021-05-05 18:19:09',22,22.0,22,22,22,22.0,true ,'22','22') +sql insert into tb2 values ('2021-05-05 18:19:10',23,23.0,23,23,23,23.0,false,'23','23') +sql insert into tb2 values ('2021-05-05 18:19:11',24,24.0,24,24,24,24.0,false,'24','24') +sql insert into tb3 values ('2021-05-05 18:19:12',31,31.0,31,31,31,31.0,true ,'31','31') +sql insert into tb3 values ('2021-05-05 18:19:13',32,32.0,32,32,32,32.0,true ,'32','32') +sql insert into tb3 values ('2021-05-05 18:19:14',33,33.0,33,33,33,33.0,false,'33','33') +sql insert into tb3 values ('2021-05-05 18:19:15',34,34.0,34,34,34,34.0,false,'34','34') +sql insert into tb4 values ('2021-05-05 18:19:16',41,41.0,41,41,41,41.0,true ,'41','41') +sql insert into tb4 values ('2021-05-05 18:19:17',42,42.0,42,42,42,42.0,true ,'42','42') +sql insert into tb4 values ('2021-05-05 18:19:18',43,43.0,43,43,43,43.0,false,'43','43') +sql insert into tb4 values ('2021-05-05 18:19:19',44,44.0,44,44,44,44.0,false,'44','44') +sql insert into tb5 values ('2021-05-05 18:19:20',51,51.0,51,51,51,51.0,true ,'51','51') +sql insert into tb5 values ('2021-05-05 18:19:21',52,52.0,52,52,52,52.0,true ,'52','52') +sql insert into tb5 values ('2021-05-05 18:19:22',53,53.0,53,53,53,53.0,false,'53','53') +sql insert into tb5 values ('2021-05-05 18:19:23',54,54.0,54,54,54,54.0,false,'54','54') +sql insert into tb6 values ('2021-05-05 18:19:24',61,61.0,61,61,61,61.0,true ,'61','61') +sql insert into tb6 values ('2021-05-05 18:19:25',62,62.0,62,62,62,62.0,true ,'62','62') +sql insert into tb6 values ('2021-05-05 18:19:26',63,63.0,63,63,63,63.0,false,'63','63') +sql insert into tb6 values ('2021-05-05 18:19:27',64,64.0,64,64,64,64.0,false,'64','64') +sql insert into tb6 values ('2021-05-05 18:19:28',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL) + +sql create table stb2 (ts timestamp, u1 int unsigned, u2 bigint unsigned, u3 smallint unsigned, u4 tinyint unsigned, ts2 timestamp) TAGS(t1 int unsigned, t2 bigint unsigned, t3 timestamp, t4 int) + +sql create table tb2_1 using stb2 tags(1,1,'2021-05-05 18:38:38',1) +sql create table tb2_2 using stb2 tags(2,2,'2021-05-05 18:58:58',2) + +sql insert into tb2_1 values ('2021-05-05 18:19:00',1,2,3,4,'2021-05-05 18:28:01') +sql insert into tb2_1 values ('2021-05-05 18:19:01',5,6,7,8,'2021-05-05 18:28:02') +sql insert into tb2_1 values ('2021-05-05 18:19:02',2,2,3,4,'2021-05-05 18:28:03') +sql insert into tb2_1 values ('2021-05-05 18:19:03',5,6,7,8,'2021-05-05 18:28:04') +sql insert into tb2_1 values ('2021-05-05 18:19:04',3,2,3,4,'2021-05-05 18:28:05') +sql insert into tb2_1 values ('2021-05-05 18:19:05',5,6,7,8,'2021-05-05 18:28:06') +sql insert into tb2_1 values ('2021-05-05 18:19:06',4,2,3,4,'2021-05-05 18:28:07') +sql insert into tb2_1 values ('2021-05-05 18:19:07',5,6,7,8,'2021-05-05 18:28:08') +sql insert into tb2_1 values ('2021-05-05 18:19:08',5,2,3,4,'2021-05-05 18:28:09') +sql insert into tb2_1 values ('2021-05-05 18:19:09',5,6,7,8,'2021-05-05 18:28:10') +sql insert into tb2_1 values ('2021-05-05 18:19:10',6,2,3,4,'2021-05-05 18:28:11') +sql insert into tb2_2 values ('2021-05-05 18:19:11',5,6,7,8,'2021-05-05 18:28:12') +sql insert into tb2_2 values ('2021-05-05 18:19:12',7,2,3,4,'2021-05-05 18:28:13') +sql insert into tb2_2 values ('2021-05-05 18:19:13',5,6,7,8,'2021-05-05 18:28:14') +sql insert into tb2_2 values ('2021-05-05 18:19:14',8,2,3,4,'2021-05-05 18:28:15') +sql insert into tb2_2 values ('2021-05-05 18:19:15',5,6,7,8,'2021-05-05 18:28:16') + +sql create table stb3 (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(10), t3 double) + +sql create table tb3_1 using stb3 tags(1,'1',1.0) +sql create table tb3_2 using stb3 tags(2,'2',2.0) + +sql insert into tb3_1 values ('2021-01-05 18:19:00',1,1.0,1,1,1,1.0,true ,'1','1') +sql insert into tb3_1 values ('2021-02-05 18:19:01',2,2.0,2,2,2,2.0,true ,'2','2') +sql insert into tb3_1 values ('2021-03-05 18:19:02',3,3.0,3,3,3,3.0,false,'3','3') +sql insert into tb3_1 values ('2021-04-05 18:19:03',4,4.0,4,4,4,4.0,false,'4','4') +sql insert into tb3_1 values ('2021-05-05 18:19:28',5,NULL,5,NULL,5,NULL,true,NULL,'5') +sql insert into tb3_1 values ('2021-06-05 18:19:28',NULL,6.0,NULL,6,NULL,6.0,NULL,'6',NULL) +sql insert into tb3_1 values ('2021-07-05 18:19:28',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL) + +sql insert into tb3_2 values ('2021-01-06 18:19:00',11,11.0,11,11,11,11.0,true ,'11','11') +sql insert into tb3_2 values ('2021-02-06 18:19:01',12,12.0,12,12,12,12.0,true ,'12','12') +sql insert into tb3_2 values ('2021-03-06 18:19:02',13,13.0,13,13,13,13.0,false,'13','13') +sql insert into tb3_2 values ('2021-04-06 18:19:03',14,14.0,14,14,14,14.0,false,'14','14') +sql insert into tb3_2 values ('2021-05-06 18:19:28',15,NULL,15,NULL,15,NULL,true,NULL,'15') +sql insert into tb3_2 values ('2021-06-06 18:19:28',NULL,16.0,NULL,16,NULL,16.0,NULL,'16',NULL) +sql insert into tb3_2 values ('2021-07-06 18:19:28',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL) + +sleep 100 + +sql connect + +run general/parser/condition_query.sim + +print ================== restart server to commit data into disk +system sh/exec.sh -n dnode1 -s stop -x SIGINT +sleep 100 +system sh/exec.sh -n dnode1 -s start +print ================== server restart completed +sql connect +sleep 100 + +run general/parser/condition_query.sim + diff --git a/tests/script/general/parser/condition_query.sim b/tests/script/general/parser/condition_query.sim new file mode 100644 index 0000000000..7600e510d3 --- /dev/null +++ b/tests/script/general/parser/condition_query.sim @@ -0,0 +1,2628 @@ + +sql use cdb; + +print "column test" +sql select * from stb1 +if $rows != 29 then + return -1 +endi +sql select * from stb1 where c1 > 0 +if $rows != 28 then + return -1 +endi + +sql_error select * from stb1 where c8 > 0 +sql_error select * from stb1 where c7 in (0,2,3,1); +sql_error select * from stb1 where c8 in (true); +sql_error select * from stb1 where c8 in (1,2); +sql_error select * from stb1 where t2 in (3.0); +sql_error select ts,c1,c7 from stb1 where c7 > false +sql_error select * from stb1 where c1 > NULL; +sql_error select * from stb1 where c1 = NULL; +sql_error select * from stb1 where c1 LIKE '%1'; +sql_error select * from stb1 where c2 LIKE '%1'; +sql_error select * from stb1 where c3 LIKE '%1'; +sql_error select * from stb1 where c4 LIKE '%1'; +sql_error select * from stb1 where c5 LIKE '%1'; +sql_error select * from stb1 where c6 LIKE '%1'; +sql_error select * from stb1 where c7 LIKE '%1'; +sql_error select * from stb1 where c1 = 'NULL'; +sql_error select * from stb1 where c2 > 'NULL'; +sql_error select * from stb1 where c3 <> 'NULL'; +sql_error select * from stb1 where c4 != 'null'; +sql_error select * from stb1 where c5 >= 'null'; +sql_error select * from stb1 where c6 <= 'null'; +sql_error select * from stb1 where c7 < 'nuLl'; +sql_error select * from stb1 where c8 < 'nuLl'; +sql_error select * from stb1 where c9 > 'nuLl'; +sql_error select * from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b; +sql_error select a.ts,a.c1,a.c8 from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b where a.ts=b.ts and a.c1 > 50 or b.c1 < 60; +sql_error select a.ts,a.c1,a.c8 from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b where a.ts=b.ts and ((a.c1 > 50 and a.c1 < 60) or (b.c2 > 60)); +sql_error select * from stb1 where 'c2' is null; +sql_error select * from stb1 where 'c2' is not null; + +sql select * from stb1 where c2 > 3.0 or c2 < 60; +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c2 > 3.0 or c2 < 60 and c2 > 50; +if $rows != 25 then + return -1 +endi +sql select * from stb1 where (c2 > 3.0 or c2 < 60) and c2 > 50; +if $rows != 8 then + return -1 +endi + +sql select * from stb1 where (c2 > 3.0 or c2 < 60) and c2 > 50 and (c2 != 53 and c2 != 63); +if $rows != 6 then + return -1 +endi + +sql select * from stb1 where (c2 > 3.0 or c2 < 60) and c2 > 50 and (c2 != 53 or c2 != 63); +if $rows != 8 then + return -1 +endi + +sql select * from stb1 where (c3 > 3.0 or c3 < 60) and c3 > 50 and (c3 != 53 or c3 != 63); +if $rows != 8 then + return -1 +endi + +sql select * from stb1 where (c4 > 3.0 or c4 < 60) and c4 > 50 and (c4 != 53 or c4 != 63); +if $rows != 8 then + return -1 +endi + +sql select * from stb1 where (c5 > 3.0 or c5 < 60) and c5 > 50 and (c5 != 53 or c5 != 63); +if $rows != 8 then + return -1 +endi + +sql select * from stb1 where (c6 > 3.0 or c6 < 60) and c6 > 50 and (c6 != 53 or c6 != 63); +if $rows != 8 then + return -1 +endi + +sql select * from stb1 where c8 = '51'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi + +sql select * from stb1 where c8 != '51'; +if $rows != 27 then + return -1 +endi + +#xxx +sql select * from stb1 where c8 = '51' and c8 != '51'; +if $rows != 0 then + return -1 +endi + +#xxx +sql select * from stb1 where c8 = '51' or c8 != '51'; +if $rows != 28 then + return -1 +endi + +sql select * from stb1 where c9 = '51'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi + +sql select * from stb1 where c9 != '51'; +if $rows != 27 then + return -1 +endi + +sql select * from stb1 where c9 = '51' and c9 != '51'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c9 = '51' or c9 != '51'; +if $rows != 28 then + return -1 +endi + +sql select ts,c1,c7 from stb1 where c7 = false +if $rows != 14 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data01 != 3 then + return -1 +endi +if $data02 != 0 then + return -1 +endi +if $data10 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data11 != 4 then + return -1 +endi +if $data12 != 0 then + return -1 +endi +if $data20 != @21-05-05 18:19:06.000@ then + return -1 +endi +if $data21 != 13 then + return -1 +endi +if $data22 != 0 then + return -1 +endi +if $data30 != @21-05-05 18:19:07.000@ then + return -1 +endi +if $data31 != 14 then + return -1 +endi +if $data32 != 0 then + return -1 +endi + + +sql select ts,c1,c7 from stb1 where c7 = true +if $rows != 14 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +if $data02 != 1 then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data11 != 2 then + return -1 +endi +if $data12 != 1 then + return -1 +endi +if $data20 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data21 != 11 then + return -1 +endi +if $data22 != 1 then + return -1 +endi +if $data30 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data31 != 12 then + return -1 +endi +if $data32 != 1 then + return -1 +endi + + +sql select * from stb1 where c8 = '51' or c8 = '4' +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data01 != 4 then + return -1 +endi +if $data10 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data11 != 51 then + return -1 +endi + + +sql select * from stb1 where c1 > 50 and c1 > 53 +if $rows != 5 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 +if $rows != 8 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 and c1 < 52 +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 or c1 < 51 +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 or c1 < 51 +if $rows != 25 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 and c1 < 51 +if $rows != 8 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 and c1 > 51 and c1 > 54 +if $rows != 4 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 and c1 > 51 or c1 > 54 +if $rows != 5 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 and c1 < 51 or c1 > 54 +if $rows != 4 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 or c1 < 51 and c1 > 54 +if $rows != 5 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 or c1 > 51 and c1 < 54 +if $rows != 7 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 and c1 < 51 and c1 > 54 +if $rows != 8 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 or c1 < 51 or c1 > 54 +if $rows != 25 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 and c1 < 51 or c1 > 54 +if $rows != 8 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 or c1 < 51 and c1 > 54 +if $rows != 8 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 or c1 > 51 and c1 > 54 +if $rows != 8 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 or c1 < 51 or c1 > 54 +if $rows != 28 then + return -1 +endi + +sql select * from stb1 where (c1 > 50 and c1 > 53) and c1 < 52 +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 and c1 < 52) +if $rows != 0 then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53) or c1 < 51 +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 or c1 < 51) +if $rows != 28 then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53) or c1 < 51 +if $rows != 25 then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 or c1 < 51) +if $rows != 5 then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53) and c1 < 51 +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 and c1 < 51) +if $rows != 8 then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53) and (c1 < 51 and c1 > 54) +if $rows != 0 then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53 and c1 < 51) and c1 > 54 +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 and c1 < 51) and c1 > 54 +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 and c1 < 51 or c1 > 54) +if $rows != 4 then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53) or (c1 < 51 and c1 > 54) +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 or c1 < 51) and c1 > 54 +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53 or c1 < 51) and c1 > 54 +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 or c1 < 51 and c1 > 54) +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53) and (c1 < 51 and c1 > 54) +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 and c1 < 51 and c1 > 54) +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53 and c1 < 51) and c1 > 54 +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 and c1 < 51) and c1 > 54 +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53) or (c1 < 51 or c1 > 54) +if $rows != 25 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 or c1 < 51 or c1 > 54) +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53 or c1 < 51) or c1 > 54 +if $rows != 25 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 or c1 < 51) or c1 > 54 +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53) and (c1 < 51 or c1 > 54) +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 and c1 < 51 or c1 > 54) +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53 and c1 < 51) or c1 > 54 +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 and c1 < 51) or c1 > 54 +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53) or (c1 < 51 and c1 > 54) +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53 or c1 < 51) and c1 > 54 +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 or c1 < 51 and c1 > 54) +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 or c1 < 51) and c1 > 54 +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where c1 > 62 or (c1 > 53 or c1 < 51) and c1 > 54 +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53) or (c1 < 51 or c1 > 54) +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 or c1 < 51 or c1 > 54) +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53 or c1 < 51) or c1 > 54 +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 or c1 < 51) or c1 > 54 +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +sql select ts,c1 from stb1 where (c1 > 60 or c1 < 10 or (c1 > 20 and c1 < 30)) and ts > '2021-05-05 18:19:00.000' and ts < '2021-05-05 18:19:25.000' and c1 != 21 and c1 != 22 +if $rows != 6 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data11 != 3 then + return -1 +endi +if $data20 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data21 != 4 then + return -1 +endi +if $data30 != @21-05-05 18:19:10.000@ then + return -1 +endi +if $data31 != 23 then + return -1 +endi +if $data40 != @21-05-05 18:19:11.000@ then + return -1 +endi +if $data41 != 24 then + return -1 +endi +if $data50 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data51 != 61 then + return -1 +endi + + +sql select * from stb1 where (c1 > 40 or c1 < 20) and (c2 < 53 or c2 >= 63) and c3 > 1 and c3 < 5 +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data11 != 3 then + return -1 +endi +if $data20 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data21 != 4 then + return -1 +endi + +sql select * from stb1 where (c1 > 52 or c1 < 10) and (c2 > 1 and c2 < 61) +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data11 != 3 then + return -1 +endi +if $data20 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data21 != 4 then + return -1 +endi +if $data30 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data31 != 53 then + return -1 +endi +if $data40 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data41 != 54 then + return -1 +endi + +sql select * from stb1 where (c3 > 52 or c3 < 10) and (c4 > 1 and c4 < 61) and (c5 = 2 or c6 = 3.0 or c6 = 4.0 or c6 = 53); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data11 != 3 then + return -1 +endi +if $data20 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data21 != 4 then + return -1 +endi +if $data30 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data31 != 53 then + return -1 +endi + +sql select * from stb1 where c1 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c2 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c3 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c4 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c5 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c6 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c7 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c8 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi + +#xxx +sql select * from stb1 where c8 like '1'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi + +#xxx +sql select * from stb1 where c8 like '1%' and c8 like '%1'; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:04.000@ then + return -1 +endi + +#xxx +sql select * from stb1 where c8 like '1' and c8 like '2'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c9 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi + +sql select * from stb1 where c1 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c2 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c3 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c4 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c5 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c6 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c7 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c8 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c9 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c1 > 63 or c1 is null; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:27.000@ then + return -1 +endi +if $data01 != 64 then + return -1 +endi +if $data10 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data11 != NULL then + return -1 +endi +sql select * from stb1 where c1 is null and c2 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c1 is null and c2 is null and c3 is not null; +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 is null and c2 is null and ts > '2021-05-05 18:19:00.000' and ts < '2021-05-05 18:19:28.000'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c1 is null and c1 > 0; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c1 is null or c1 is not null or c1 > 1; +if $rows != 29 then + return -1 +endi + +sql select * from stb1 where (c1 is null or c1 > 40) and c1 < 44; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:16.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:17.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:18.000@ then + return -1 +endi + +sql select * from stb1 where c1 in (11,21,31,41) and c1 in (11,42); +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi + +sql select * from stb1 where c8 in ('11','21','31','41') and c8 in ('11','42'); +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi + +sql select * from stb1 where (c1 > 60 and c2 > 40) or (c1 > 62 and c2 > 50); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where c1 = 3 or c1 = 5 or c1 >= 44 and c1 <= 52; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:19.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:21.000@ then + return -1 +endi + +sql select * from stb1 where c8 LIKE '%1'; +if $rows != 7 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:08.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:12.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:16.000@ then + return -1 +endi +if $data50 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data60 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where c9 LIKE '%1'; +if $rows != 7 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:08.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:12.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:16.000@ then + return -1 +endi +if $data50 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data60 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where (c8 LIKE '%1' or c9 like '_2') and (c5 > 50 or c6 > 30) and ( c8 like '3_' or c9 like '4_') and (c4 <= 31 or c4 >= 42); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:12.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:17.000@ then + return -1 +endi + +sql select * from stb1 where c1 in (1,3); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi + +sql select * from stb1 where c3 in (11,22); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:09.000@ then + return -1 +endi + +sql select * from stb1 where c4 in (3,33); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:14.000@ then + return -1 +endi + +sql select * from stb1 where c5 in (3,33) and c8 in ('22','55'); +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c5 in (3,33) and c8 in ('33','54'); +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:14.000@ then + return -1 +endi + +sql select * from stb1 where c5 in (3,33) or c8 in ('22','54'); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:09.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:14.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi + +sql select * from stb1 where (c9 in ('3','1','2','4','5') or c9 in ('33','11','22','44','55')) and c9 in ('1','3','11','13'); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:04.000@ then + return -1 +endi + +sql select * from stb2 where (u1 in (1) or u2 in (5,6)) and (u3 in (3,6) or u4 in (7,8)) and ts2 in ('2021-05-05 18:28:02.000','2021-05-05 18:28:15.000','2021-05-05 18:28:01.000'); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi + +sql select * from stb2 where u2 in (2) and u3 in (1,2,3) and u4 in (1,2,4,5) and u1 > 3 and u1 < 6 and u1 != 4; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:08.000@ then + return -1 +endi + +sql select avg(c1) from tb1 where (c1 > 12 or c2 > 10) and (c3 < 12 or c3 > 13); +if $rows != 1 then + return -1 +endi +if $data00 != 12.500000000 then + return -1 +endi + +sql select count(c1),sum(c3) from tb1 where ((c7 = true and c6 > 2) or (c1 > 10 or c3 < 3)) and ((c8 like '1%') or (c9 like '%2' or c9 like '%3')) interval(5s); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 3 then + return -1 +endi +if $data02 != 14 then + return -1 +endi +if $data10 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data11 != 3 then + return -1 +endi +if $data12 != 39 then + return -1 +endi + +sql select * from stb1 where c8 = 'null'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c8 = 'NULL'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c9 = 'null'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c9 = 'NULL'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c2 in (0,1); +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +sql select * from stb1 where c6 in (0,2,3,1); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +sql select ts,c1 from (select * from stb1 where (c1 > 60 or c1 < 10) and (c7 = true or c5 > 2 and c5 < 63)) where (c3 > 61 or c3 < 3); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:25.000@ then + return -1 +endi + +#sql select a.* from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b where a.ts=b.ts and a.c1 > 50; +sql select a.ts from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b where a.ts=b.ts and a.c1 > 50; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:25.000@ then + return -1 +endi + +#sql select a.ts,a.c1,a.c8,a.c9 from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b where a.ts=b.ts and a.c1 > 50 and b.c1 < 60; +sql select a.ts,a.c1,a.c8 from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b where a.ts=b.ts and a.c1 > 50 and b.c1 < 60; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi + +sql select a.ts,b.ts,a.c1,b.u1,b.u2 from (select * from stb1) a, (select * from stb2) b where a.ts=b.ts and (a.c1 < 10 or a.c1 > 30) and (b.u1 < 5 or b.u1 > 5); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:12.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:14.000@ then + return -1 +endi + +sql select a.ts,b.ts,a.c1,b.u1,b.u2 from (select * from stb1) a, (select * from stb2) b where a.ts=b.ts and a.c1 < 30 and b.u1 > 1 and a.c1 > 10 and b.u1 < 8 and b.u1<>5; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:06.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:10.000@ then + return -1 +endi + +sql select * from stb1 where c1 is null and c1 is not null; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c1 is null or c1 is not null; +if $rows != 29 then + return -1 +endi +sql select * from stb1 where c1 is null or c1 > 20 or c1 < 25; +if $rows != 29 then + return -1 +endi +sql select * from stb1 where (c1 > 20 or c1 < 25) and c1 is null; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where (c1 > 20 or c1 < 25) and (c1 > 62 or c1 < 3); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 11 and c1 != 11 and c1 != 14 and c1 < 14; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:06.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 60 or c1 < 4 or c1 > 10 and c1 < 20 and c1 != 13 or c1 < 2 or c1 > 50) +if $rows != 14 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:04.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 62 or c1 >= 62; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 62 and c1 >= 62; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where c1 >= 62 and c1 != 62; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where c1 >= 62 or c1 != 62; +if $rows != 28 then + return -1 +endi + +sql select * from stb1 where c1 >= 62 and c1 = 62; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:25.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 62 and c1 != 62; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 62 and c1 = 62; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c1 is not null and c1 is not null; +if $rows != 28 then + return -1 +endi + +sql select * from stb1 where c1 is not null or c1 is not null; +if $rows != 28 then + return -1 +endi + +sql select * from stb1 where c1 is null and c1 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi + +sql select * from stb1 where c1 is null or c1 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi + +sql select * from stb1 where c2 > 3 and c2 < 3; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c2 = 3; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi + +sql select * from stb1 where c2 > 3 and c2 <= 3; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c2 >= 3 and c2 <= 3; +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi + +sql select * from stb1 where (c2 in (1,2,3,4) or c2 in (11,12,13,14)) and c2 != 11 and c2 >2 and c2 != 14; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:06.000@ then + return -1 +endi + +sql select * from stb1 where (c1 > 60 or c1 < 4 or c1 > 10 and c1 < 20 and c1 != 13 or c1 < 2 or c1 > 50) and (c1 != 51 and c1 <= 54 and c1 != 54 and c1 >=1 and c1 != 1) and (c1 >= 11 and c1 <=52 and c1 != 52 and c1 != 11); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:07.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 1 and c1 is not null and c1 < 5; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:03.000@ then + return -1 +endi + +sql select * from (select * from stb1 where c2 > 10 and c6 < 40) where c9 in ('11','21','31'); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:08.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:12.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 40 and c2 > 50 and c3 > 62 or c1 < 2 and c2 < 3; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where (c1 > 3 and c2 > 4) or (c1 < 60 and c2 < 30); +if $rows != 28 then + return -1 +endi + +sql select * from stb1 where (c1 > 3 and c2 > 4) or (c1 < 60 and c2 < 30) or (c1 is null and c2 is null); +if $rows != 29 then + return -1 +endi + +sql select * from stb1 where (c1 > 3 and c2 > 4) or (c1 < 60 and c3 < 30) or (c1 is null and c2 is null); +if $rows != 29 then + return -1 +endi + +sql select * from stb1 where (c1 > 60 and c2 < 63) or (c1 >62 and c3 < 30) or (c1 is null and c2 is null); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:28.000@ then + return -1 +endi + +sql select * from stb1 where c1 between 60 and 9999999999; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where c1 > 9999999999; +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 < 9999999999; +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c1 = 9999999999; +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 <> 9999999999; +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c4 < -9999999999; +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c4 > -9999999999; +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c4 = -9999999999; +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c4 <> -9999999999; +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c5 in (-9999999999); +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c5 in (9999999999); +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c5 in (-9999999999,3,4,9999999999); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:03.000@ then + return -1 +endi + +sql select * from stb3 where c1 > 3 and c1 < 2; +if $rows != 0 then + return -1 +endi + +sql select * from stb3 where c1 is null order by ts; +if $rows != 4 then + return -1 +endi +if $data00 != @21-06-05 18:19:28.000@ then + return -1 +endi +if $data10 != @21-06-06 18:19:28.000@ then + return -1 +endi +if $data20 != @21-07-05 18:19:28.000@ then + return -1 +endi +if $data30 != @21-07-06 18:19:28.000@ then + return -1 +endi + +sql select * from stb3 where c1 is not null order by ts; +if $rows != 10 then + return -1 +endi +if $data00 != @21-01-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-01-06 18:19:00.000@ then + return -1 +endi +if $data20 != @21-02-05 18:19:01.000@ then + return -1 +endi +if $data30 != @21-02-06 18:19:01.000@ then + return -1 +endi +if $data40 != @21-03-05 18:19:02.000@ then + return -1 +endi +if $data50 != @21-03-06 18:19:02.000@ then + return -1 +endi +if $data60 != @21-04-05 18:19:03.000@ then + return -1 +endi +if $data70 != @21-04-06 18:19:03.000@ then + return -1 +endi + + +sql select * from stb3 where c1 > 11; +if $rows != 4 then + return -1 +endi +if $data00 != @21-02-06 18:19:01.000@ then + return -1 +endi +if $data10 != @21-03-06 18:19:02.000@ then + return -1 +endi +if $data20 != @21-04-06 18:19:03.000@ then + return -1 +endi +if $data30 != @21-05-06 18:19:28.000@ then + return -1 +endi + +sql select * from stb3 where c1 is not null or c1 is null; +if $rows != 14 then + return -1 +endi + + + +print "ts test" +sql_error select ts,c1,c7 from stb1 where ts != '2021-05-05 18:19:27' +sql_error select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:03.000' or ts < '2021-05-05 18:19:02.000'; +sql_error select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:03.000' and ts > '2021-05-05 18:19:20.000' and ts != '2021-05-05 18:19:22.000'; +sql_error select * from stb1 where ts2 like '2021-05-05%'; +sql_error select ts,c1,c2 from stb1 where (ts > '2021-05-05 18:19:25.000' or ts < '2021-05-05 18:19:05.000') and ts > '2021-05-05 18:19:01.000' and ts < '2021-05-05 18:19:27.000'; +sql_error select ts,c1,c2 from stb1 where (ts > '2021-05-05 18:19:20.000' or ts < '2021-05-05 18:19:05.000') and ts != '2021-05-05 18:19:25.000'; +sql_error select ts,c1,c2 from stb1 where ((ts >= '2021-05-05 18:19:05.000' and ts <= '2021-05-05 18:19:10.000') or (ts >= '2021-05-05 18:19:15.000' and ts <= '2021-05-05 18:19:20.000') or (ts >= '2021-05-05 18:19:11.000' and ts <= '2021-05-05 18:19:14.000')); +sql_error select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' or ts < '2021-05-05 18:19:24.000'; +sql select * from stb1 where ts is null; +if $rows != 0 then + return -1 +endi +sql select * from stb1 where ts is not null and ts is null; +if $rows != 0 then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' and ts < '2021-05-05 18:19:10.000'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where ts > '2021-05-05 18:19:03.000' and ts < '2021-05-05 18:19:02'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where ts is not null; +if $rows != 29 then + return -1 +endi + +sql select * from stb1 where ts is not null or ts is null; +if $rows != 29 then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' or ts < '2021-05-05 18:19:25.000'; +if $rows != 29 then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' and ts < '2021-05-05 18:19:26.000'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:25.000@ then + return -1 +endi +sql select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' or ts < '2021-05-05 18:19:28.000'; +if $rows != 29 then + return -1 +endi +sql select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' or ts > '2021-05-05 18:19:27.000'; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:27.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:28.000@ then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ts > '2021-05-05 18:19:20.000' or ts < '2021-05-05 18:19:05.000' or ts != '2021-05-05 18:19:25.000'; +if $rows != 29 then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' or ts <> '2021-05-05 18:19:25.000'; +if $rows != 29 then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ((ts >= '2021-05-05 18:19:05.000' and ts <= '2021-05-05 18:19:10.999') or (ts >= '2021-05-05 18:19:15.000' and ts <= '2021-05-05 18:19:20.000') or (ts >= '2021-05-05 18:19:11.000' and ts <= '2021-05-05 18:19:14.999')); +if $rows != 16 then + return -1 +endi +if $data00 != @21-05-05 18:19:05.000@ then + return -1 +endi + +sql select ts,c1,c2 from stb1 where (ts >= '2021-05-05 18:19:05.000' and ts <= '2021-05-05 18:19:10.000') or (ts >= '2021-05-05 18:19:12.000' and ts <= '2021-05-05 18:19:14.000') or (ts >= '2021-05-05 18:19:08.000' and ts <= '2021-05-05 18:19:17.000'); +if $rows != 13 then + return -1 +endi +if $data00 != @21-05-05 18:19:05.000@ then + return -1 +endi + +sql select ts,c1,c2 from stb1 where (ts >= '2021-05-05 18:19:05.000' and ts <= '2021-05-05 18:19:10.000') or (ts >= '2021-05-05 18:19:02.000' and ts <= '2021-05-05 18:19:03.000') or (ts >= '2021-05-05 18:19:01.000' and ts <= '2021-05-05 18:19:08.000'); +if $rows != 10 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ((ts >= '2021-05-05 18:19:08.000' and ts <= '2021-05-05 18:19:10.000') or (ts >= '2021-05-05 18:19:02.000' and ts <= '2021-05-05 18:19:03.000') or (ts >= '2021-05-05 18:19:05.000' and ts <= '2021-05-05 18:19:06.000') or (ts >= '2021-05-05 18:19:03.000' and ts <= '2021-05-05 18:19:12.000')) and (ts >= '2021-05-05 18:19:10.000'); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:10.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:11.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:12.000@ then + return -1 +endi + +sql select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:25.000' and ts != '2021-05-05 18:19:18'; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:27.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:28.000@ then + return -1 +endi + + +sql select * from stb1 where ts > '2021-05-05 18:19:03.000' and ts > '2021-05-05 18:19:25'; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:27.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:28.000@ then + return -1 +endi + +sql select * from stb1 where ts < '2021-05-05 18:19:03.000' and ts < '2021-05-05 18:19:25'; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi + +sql select * from stb1 where ts > '2021-05-05 18:19:23.000' and ts < '2021-05-05 18:19:25'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi + +sql select * from stb1 where ts > '2021-05-05 18:19:03.000' or ts > '2021-05-05 18:19:25'; +if $rows != 25 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:06.000@ then + return -1 +endi + +sql select * from stb1 where ts < '2021-05-05 18:19:03.000' or ts < '2021-05-05 18:19:25'; +if $rows != 25 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi + +sql select * from stb1 where ts > '2021-05-05 18:19:23.000' or ts < '2021-05-05 18:19:25'; +if $rows != 29 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi + +sql select * from stb1 where (ts > '2021-05-05 18:19:23.000' or ts < '2021-05-05 18:19:25') and (ts > '2021-05-05 18:19:23.000' and ts < '2021-05-05 18:19:26'); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi + +sql select * from stb1 where (ts > '2021-05-05 18:19:23.000' or ts < '2021-05-05 18:19:25') and (ts > '2021-05-05 18:19:23.000' or ts > '2021-05-05 18:19:26'); +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:28.000@ then + return -1 +endi + + +sql select * from stb2 where ts2 in ('2021-05-05 18:28:03','2021-05-05 18:28:05','2021-05-05 18:28:08'); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:07.000@ then + return -1 +endi + +sql select * from stb2 where t3 in ('2021-05-05 18:38:38','2021-05-05 18:38:28','2021-05-05 18:38:08') and ts2 in ('2021-05-05 18:28:04','2021-05-05 18:28:04','2021-05-05 18:28:03'); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:03.000@ then + return -1 +endi + +sql select a.ts,b.ts,a.c1,b.u1,b.u2 from (select * from stb1) a, (select * from stb2) b where a.ts=b.ts and (a.ts < '2021-05-05 18:19:03.000' or a.ts >= '2021-05-05 18:19:13.000') and (b.ts >= '2021-05-05 18:19:01.000' and b.ts <= '2021-05-05 18:19:14.000'); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:13.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:14.000@ then + return -1 +endi + +sql select a.ts,c.ts,b.c1,c.u1,c.u2 from (select * from stb1) a, (select * from stb1) b, (select * from stb2) c where a.ts=b.ts and b.ts=c.ts and a.ts <= '2021-05-05 18:19:12.000' and b.ts >= '2021-05-05 18:19:06.000' and c.ts >= '2021-05-05 18:19:08.000' and c.ts <= '2021-05-05 18:19:11.000' and a.ts != '2021-05-05 18:19:10.000'; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:08.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:09.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:11.000@ then + return -1 +endi + +sql select ts,c1,c2,c8 from (select * from stb1) where (ts <= '2021-05-05 18:19:06.000' or ts >= '2021-05-05 18:19:13.000') and (ts >= '2021-05-05 18:19:02.000' and ts <= '2021-05-05 18:19:14.000') and ts != '2021-05-05 18:19:04.000'; +if $rows != 6 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:06.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:13.000@ then + return -1 +endi +if $data50 != @21-05-05 18:19:14.000@ then + return -1 +endi + +sql select ts,c1,c2,c8 from (select * from stb1) where (ts <= '2021-05-05 18:19:03.000' or ts > '2021-05-05 18:19:26.000' or ts = '2021-05-05 18:19:26.000') and ts != '2021-05-05 18:19:03.000' and ts != '2021-05-05 18:19:26.000'; +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:28.000@ then + return -1 +endi + +print "tbname test" +sql_error select * from stb1 where tbname like '%3' and tbname like '%4'; + +sql select * from stb1 where tbname like 'tb%'; +if $rows != 29 then + return -1 +endi + +sql select * from stb1 where tbname like '%2'; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:08.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:09.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:10.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:11.000@ then + return -1 +endi + +print "tag test" +sql select * from stb1 where t1 in (1,2) and t1 in (2,3); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:08.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:09.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:10.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:11.000@ then + return -1 +endi + +sql select * from stb2 where t1 in (1,2) and t2 in (2) and t3 in ('2021-05-05 18:58:57.000'); +if $rows != 0 then + return -1 +endi + +print "join test" +sql_error select * from tb1, tb2_1 where tb1.ts=tb2_1.ts or tb1.ts =tb2_1.ts; +sql select tb1.ts from tb1, tb2_1 where tb1.ts=tb2_1.ts and tb1.ts > '2021-05-05 18:19:03.000' and tb2_1.ts < '2021-05-05 18:19:06.000'; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:05.000@ then + return -1 +endi +sql select tb1.ts,tb1.*,tb2_1.* from tb1, tb2_1 where tb1.ts=tb2_1.ts and tb1.ts > '2021-05-05 18:19:03.000' and tb2_1.u1 < 5; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:06.000@ then + return -1 +endi + +sql select tb1.ts,tb1.*,tb2_1.* from tb1, tb2_1 where tb1.ts=tb2_1.ts and tb1.ts >= '2021-05-05 18:19:03.000' and tb1.c7=false and tb2_1.u3>4; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:07.000@ then + return -1 +endi + +sql select stb1.ts,stb1.c1,stb1.t1,stb2.ts,stb2.u1,stb2.t4 from stb1, stb2 where stb1.ts=stb2.ts and stb1.t1 = stb2.t4; +if $rows != 9 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data50 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data60 != @21-05-05 18:19:06.000@ then + return -1 +endi +if $data70 != @21-05-05 18:19:07.000@ then + return -1 +endi +if $data80 != @21-05-05 18:19:11.000@ then + return -1 +endi + +sql select stb1.ts,stb1.c1,stb1.t1,stb2.ts,stb2.u1,stb2.t4 from stb1, stb2 where stb1.ts=stb2.ts and stb1.t1 = stb2.t4 and stb1.c1 > 2 and stb2.u1 <=4; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:06.000@ then + return -1 +endi + +print "column&ts test" +sql_error select count(*) from stb1 where ts > 0 or c1 > 0; +sql select * from stb1 where ts > '2021-05-05 18:19:03.000' and ts < '2021-05-05 18:19:20.000' and (c1 > 23 or c1 < 14) and c7 in (true) and c8 like '%2'; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:13.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:17.000@ then + return -1 +endi + +print "column&tbname test" +sql_error select count(*) from stb1 where tbname like 'tb%' or c1 > 0; +sql select * from stb1 where tbname like '%3' and c6 < 34 and c5 != 33 and c4 > 31; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:13.000@ then + return -1 +endi + +print "column&tag test" +sql_error select * from stb1 where t1 > 0 or c1 > 0 +sql_error select * from stb1 where c1 > 0 or t1 > 0 +sql_error select * from stb1 where t1 > 0 or c1 > 0 or t1 > 1 +sql_error select * from stb1 where c1 > 0 or t1 > 0 or c1 > 1 +sql_error select * from stb1 where t1 > 0 and c1 > 0 or t1 > 1 +sql_error select * from stb1 where c1 > 0 or t1 > 0 and c1 > 1 +sql_error select * from stb1 where c1 > 0 or t1 > 0 and c1 > 1 +sql_error select * from stb1 where t1 > 0 or t1 > 0 and c1 > 1 +sql_error select * from stb1 where (c1 > 0 and t1 > 0 ) or (t1 > 1 and c1 > 3) +sql_error select * from stb1 where (c1 > 0 and t1 > 0 ) or t1 > 1 +sql_error select a.ts,b.ts,a.c1,b.u1,b.u2 from (select * from stb1) a, (select * from stb2) b where a.ts=b.ts and a.t1=b.t1; + +sql select * from stb1 where c1 < 63 and t1 > 5 +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +sql select * from stb1 where t1 > 3 and t1 < 5 and c1 != 42 and c1 != 44; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:16.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:18.000@ then + return -1 +endi +sql select * from stb1 where t1 > 1 and c1 > 21 and t1 < 3 and c1 < 24 and t1 != 3 and c1 != 23; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:09.000@ then + return -1 +endi +sql select * from stb1 where c1 > 1 and (t1 > 3 or t1 < 2) and (c2 > 2 and c2 < 62 and t1 != 4) and (t1 > 2 and t1 < 6) and c7 = true and c8 like '%2'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:21.000@ then + return -1 +endi + +sql select * from stb1 where c1!=31 and c1 !=32 and c1 <> 63 and c1 <>1 and c1 <> 21 and c1 <> 2 and c7 <> true and c8 <> '3' and c9 <> '4' and c2<>13 and c3 <> 23 and c4 <> 33 and c5 <> 34 and c6 <> 43 and c2 <> 53 and t1 <> 5 and t2 <>4; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:07.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:11.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:27.000@ then + return -1 +endi + + +print "column&join test" +sql_error select tb1.ts,tb1.c1,tb2_1.u1 from tb1, tb2_1 where tb1.ts=tb2_1.ts or tb1.c1 > 0; + + +print "ts&tbname test" +sql_error select count(*) from stb1 where ts > 0 or tbname like 'tb%'; + +print "ts&tag test" +sql_error select count(*) from stb1 where ts > 0 or t1 > 0; + +sql select * from stb2 where t1!=1 and t2=2 and t3 in ('2021-05-05 18:58:58.000') and ts < '2021-05-05 18:19:13.000'; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:11.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:12.000@ then + return -1 +endi + +print "ts&join test" +sql_error select tb1.ts,tb1.c1,tb2_1.u1 from tb1, tb2_1 where tb1.ts=tb2_1.ts or tb1.ts > 0; +sql select tb1.ts,tb1.c1,tb2_1.u1 from tb1, tb2_1 where tb1.ts=tb2_1.ts and (tb1.ts > '2021-05-05 18:19:05.000' or tb1.ts < '2021-05-05 18:19:03.000' or tb1.ts > 0); + + +print "tbname&tag test" +sql select * from stb1 where tbname like 'tb%' and (t1=1 or t2=2 or t3=3) and t1 > 2; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:12.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:13.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:14.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:15.000@ then + return -1 +endi + +print "tbname&join test" + +print "tag&join test" + + + + + +print "column&ts&tbname test" +sql_error select count(*) from stb1 where tbname like 'tb%' or c1 > 0 or ts > 0; + +print "column&ts&tag test" +sql_error select count(*) from stb1 where t1 > 0 or c1 > 0 or ts > 0; +sql_error select count(*) from stb1 where c1 > 0 or t1 > 0 or ts > 0; + +sql select * from stb1 where (t1 > 0 or t1 > 2 ) and ts > '2021-05-05 18:19:10.000' and (c1 > 1 or c1 > 3) and (c6 > 40 or c6 < 30) and (c8 like '%3' or c8 like '_4') and (c9 like '1%' or c9 like '6%' or (c9 like '%3' and c9 != '23')) and ts > '2021-05-05 18:19:22.000' and ts <= '2021-05-05 18:19:26.000'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:26.000@ then + return -1 +endi +sql select * from stb1 where ts > '2021-05-05 18:19:00.000' and c1 > 2 and t1 != 1 and c2 >= 23 and t2 >= 3 and c3 < 63 and c7 = false and t3 > 3 and t3 < 6 and c8 like '4%' and ts < '2021-05-05 18:19:19.000' and c2 > 40 and c3 != 42; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:18.000@ then + return -1 +endi +print "column&ts&join test" + +print "column&tbname&tag test" +sql_error select count(*) from stb1 where c1 > 0 or tbname in ('tb1') or t1 > 0; + +print "column&tbname&join test" +print "column&tag&join test" +print "ts&tbname&tag test" +sql_error select count(*) from stb1 where ts > 0 or tbname in ('tb1') or t1 > 0; + +print "ts&tbname&join test" +print "ts&tag&join test" +print "tbname&tag&join test" + + + + +print "column&ts&tbname&tag test" +sql_error select * from stb1 where (tbname like 'tb%' or ts > '2021-05-05 18:19:01.000') and (t1 > 5 or t1 < 4) and c1 > 0; +sql_error select * from stb1 where (ts > '2021-05-05 18:19:01.000') and (ts > '2021-05-05 18:19:02.000' or t1 > 3) and (t1 > 5 or t1 < 4) and c1 > 0; +sql_error select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:03.000' or ts > '2021-05-05 18:19:20.000' and col > 0 and t1 > 0; + + +print "column&ts&tbname&join test" +print "column&ts&tag&join test" +print "column&tbname&tag&join test" +print "ts&tbname&tag&join test" + + +print "column&ts&tbname&tag&join test" + +#system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/general/parser/set_tag_vals.sim b/tests/script/general/parser/set_tag_vals.sim index 74184f94d4..4a63f9c6f1 100644 --- a/tests/script/general/parser/set_tag_vals.sim +++ b/tests/script/general/parser/set_tag_vals.sim @@ -83,10 +83,7 @@ while $i < $tbNum endw print ================== all tags have been changed! -sql select tbname from $stb where t3 = 'NULL' -if $rows != 0 then - return -1 -endi +sql_error select tbname from $stb where t3 = 'NULL' print ================== set tag to NULL sql create table stb1_tg (ts timestamp, c1 int) tags(t1 int,t2 bigint,t3 double,t4 float,t5 smallint,t6 tinyint) @@ -227,4 +224,4 @@ if $data04 != NULL then return -1 endi -system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/general/parser/where.sim b/tests/script/general/parser/where.sim index 781b2725b5..6b789de490 100644 --- a/tests/script/general/parser/where.sim +++ b/tests/script/general/parser/where.sim @@ -65,7 +65,14 @@ $tb = $tbPrefix . $i sql_error select * from $tb where c7 # TBASE-654 : invalid filter expression cause server crashed -sql_error select count(*) from $tb where c1<10 and c1<>2 +sql select count(*) from $tb where c1<10 and c1<>2 +if $rows != 1 then + return -1 +endi +if $data00 != 900 then + return -1 +endi + sql select * from $tb where c7 = false $val = $rowNum / 100 @@ -253,30 +260,11 @@ sql insert into tb_where_NULL values ('2019-01-01 09:00:02.000', 2, 'val2') sql_error select * from tb_where_NULL where c1 = NULL sql_error select * from tb_where_NULL where c1 <> NULL sql_error select * from tb_where_NULL where c1 < NULL -sql select * from tb_where_NULL where c1 = "NULL" -if $rows != 0 then - return -1 -endi - -sql select * from tb_where_NULL where c1 <> "NULL" -if $rows != 2 then - return -1 -endi -sql select * from tb_where_NULL where c1 <> "nulL" -if $rows != 2 then - return -1 -endi - -sql select * from tb_where_NULL where c1 > "NULL" -if $rows != 0 then - return -1 -endi - -sql select * from tb_where_NULL where c1 >= "NULL" -if $rows != 0 then - return -1 -endi - +sql_error select * from tb_where_NULL where c1 = "NULL" +sql_error select * from tb_where_NULL where c1 <> "NULL" +sql_error select * from tb_where_NULL where c1 <> "nulL" +sql_error select * from tb_where_NULL where c1 > "NULL" +sql_error select * from tb_where_NULL where c1 >= "NULL" sql select * from tb_where_NULL where c2 = "NULL" if $rows != 0 then return -1 diff --git a/tests/script/test.sh b/tests/script/test.sh index 29a15db4dc..f2dc578987 100755 --- a/tests/script/test.sh +++ b/tests/script/test.sh @@ -121,6 +121,7 @@ echo "rpcDebugFlag 143" >> $TAOS_CFG echo "tmrDebugFlag 131" >> $TAOS_CFG echo "cDebugFlag 143" >> $TAOS_CFG echo "udebugFlag 143" >> $TAOS_CFG +echo "debugFlag 143" >> $TAOS_CFG echo "wal 0" >> $TAOS_CFG echo "asyncLog 0" >> $TAOS_CFG echo "locale en_US.UTF-8" >> $TAOS_CFG diff --git a/tests/stress/main.go b/tests/stress/main.go index c3b9290a37..3056ee97f6 100644 --- a/tests/stress/main.go +++ b/tests/stress/main.go @@ -1,3 +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 . + */ + package main import (